├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── .npmignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENCE ├── README.md ├── _config.yml ├── codecov.yml ├── common ├── config │ └── rush │ │ ├── .npmrc │ │ ├── command-line.json │ │ ├── common-versions.json │ │ ├── npm-shrinkwrap.json │ │ └── version-policies.json └── scripts │ ├── install-run-rush.js │ ├── install-run-rushx.js │ └── install-run.js ├── packages ├── specron-cli │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── README.md │ ├── bin │ │ └── specron │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── commands │ │ │ ├── compile.ts │ │ │ ├── flatten.ts │ │ │ ├── init.ts │ │ │ ├── sandbox.ts │ │ │ └── test.ts │ │ ├── index.ts │ │ ├── lib │ │ │ └── env.ts │ │ └── tests │ │ │ ├── assets │ │ │ ├── invalid.hay.ts │ │ │ ├── token-a.sol │ │ │ ├── token-b.sol │ │ │ └── valid.hay.ts │ │ │ ├── index.test.ts │ │ │ └── lib │ │ │ └── env.test.ts │ └── tsconfig.json ├── specron-compiler │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── README.md │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── core │ │ │ ├── compiler.ts │ │ │ └── reporter.ts │ │ ├── index.ts │ │ ├── lib │ │ │ └── solc.ts │ │ └── tests │ │ │ ├── assets │ │ │ ├── foo.js │ │ │ ├── interface.sol │ │ │ ├── token-a.sol │ │ │ ├── token-b.sol │ │ │ └── token-c.sol │ │ │ ├── compiler.test.ts │ │ │ └── index.test.ts │ └── tsconfig.json ├── specron-flattener │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── README.md │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── core │ │ │ ├── flattener.ts │ │ │ └── reporter.ts │ │ ├── index.ts │ │ └── tests │ │ │ ├── assets │ │ │ ├── token-a.sol │ │ │ ├── token-b.sol │ │ │ └── token-c.sol │ │ │ ├── flattener.test.ts │ │ │ └── index.test.ts │ └── tsconfig.json ├── specron-init │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── README.md │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── core │ │ │ ├── generator.ts │ │ │ └── structure.ts │ │ ├── index.ts │ │ └── tests │ │ │ ├── generator.test.ts │ │ │ └── index.test.ts │ └── tsconfig.json ├── specron-sandbox │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── README.md │ ├── nodemon.json │ ├── package.json │ ├── src │ │ ├── core │ │ │ └── sandbox.ts │ │ ├── index.ts │ │ └── tests │ │ │ ├── core │ │ │ └── sandbox.test.ts │ │ │ └── index.test.ts │ └── tsconfig.json └── specron-spec │ ├── CHANGELOG.json │ ├── CHANGELOG.md │ ├── README.md │ ├── nodemon.json │ ├── package.json │ ├── src │ ├── asserts │ │ └── reverts.ts │ ├── core │ │ ├── context.ts │ │ ├── reporter.ts │ │ ├── runner.ts │ │ ├── spec.ts │ │ ├── stage.ts │ │ └── types.ts │ ├── index.ts │ ├── methods │ │ ├── deploy.ts │ │ ├── sign.ts │ │ └── tuple.ts │ └── tests │ │ ├── asserts │ │ └── reverts.test.ts │ │ ├── assets │ │ ├── Scaffold.hay.ts │ │ ├── scaffold-a.json │ │ ├── scaffold-b.json │ │ └── scaffold-ecrecover.json │ │ ├── core │ │ ├── context.test.ts │ │ ├── runner.test.ts │ │ └── stage.test.ts │ │ ├── index.test.ts │ │ └── methods │ │ ├── deploy.test.ts │ │ ├── sign.test.ts │ │ └── tuple.test.ts │ └── tsconfig.json └── rush.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # Don't allow people to merge changes to these generated files, because the result 2 | # may be invalid. You need to run "rush update" again. 3 | shrinkwrap.yaml merge=binary 4 | npm-shrinkwrap.json merge=binary 5 | yarn.lock merge=binary 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [xpepermint] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | *.log 3 | npm-debug.log* 4 | yarn-debug.log* 5 | yarn-error.log* 6 | 7 | # Runtime data 8 | *.pid 9 | *.seed 10 | *.pid.lock 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # nyc test coverage 19 | .nyc_output 20 | 21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 22 | .grunt 23 | 24 | # Bower dependency directory (https://bower.io/) 25 | bower_components 26 | 27 | # node-waf configuration 28 | .lock-wscript 29 | 30 | # Compiled binary addons (https://nodejs.org/api/addons.html) 31 | build/Release 32 | 33 | # Dependency directories 34 | node_modules/ 35 | jspm_packages/ 36 | 37 | # Optional npm cache directory 38 | .npm 39 | 40 | # Optional eslint cache 41 | .eslintcache 42 | 43 | # Optional REPL history 44 | .node_repl_history 45 | 46 | # Output of 'npm pack' 47 | *.tgz 48 | 49 | # Yarn Integrity file 50 | .yarn-integrity 51 | 52 | # dotenv environment variables file 53 | .env 54 | 55 | # next.js build output 56 | .next 57 | 58 | # Common toolchain intermediate files 59 | temp 60 | 61 | # Rush files 62 | common/temp/** 63 | package-deps.json 64 | 65 | # OSx environment 66 | .DS_Store 67 | 68 | # Compiled data 69 | build 70 | **/dist/* 71 | !dist/* -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .nyc_output 4 | node_modules 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: node_js 3 | node_js: 4 | - 11 5 | script: 6 | # use latest npm to work on node9 7 | - npm install -g npm 8 | # install required global npm packages 9 | - npm install -g codecov 10 | - npm install -g @microsoft/rush 11 | # testing 12 | - rush update --full 13 | - rush rebuild 14 | - rush test 15 | after_success: 16 | # code coverage & codecov upload 17 | - rm -Rf .nyc_output && mkdir -p .nyc_output 18 | - find packages/**/.nyc_output -type f -name '*.json' -not -path 'packages/**/.nyc_output/processinfo/*' -exec cp '{}' .nyc_output \; 19 | - npx nyc report --extension=.ts --reporter=text-lcov > .nyc_output/coverage.lcov 20 | - codecov 21 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Issues 4 | 5 | We use GitHub issues to track public bugs. Please ensure your description is clear and has sufficient instructions to be able to reproduce the issue. 6 | 7 | ## Pull Requests 8 | 9 | * Fork the repo and create your branch from master. 10 | * If you've added code that should be tested, add tests. 11 | * Ensure the test suite passes. 12 | 13 | ## Coding Style 14 | 15 | Please follow the [TypeScript coding guidelines](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines). 16 | 17 | ## Development 18 | 19 | * https://gist.github.com/xpepermint/eecfc6ad6cd7c9f5dcda381aa255738d 20 | 21 | ## Release process 22 | 23 | The release manager will publish packages to NPM using these commands. 24 | 25 | ``` 26 | $ rush version --bump --override-bump minor 27 | $ rush update --full 28 | $ rush rebuild 29 | $ rush test 30 | $ rush publish --publish --include-all 31 | ``` 32 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2017-2018 Xpepermint. 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Specron Framework 2 | 3 | [![Build Status](https://travis-ci.org/specron/framework.svg?branch=master)](https://travis-ci.org/specron/framework) [![codecov](https://codecov.io/gh/specron/framework/branch/master/graph/badge.svg)](https://codecov.io/gh/specron/framework) 4 | 5 | Specron is a lightweight, open source, magic-free framework for testing smart contracts written in [Solidity](https://solidity.readthedocs.io/). The testing suite is built on top of the [Hayspec framework](https://github.com/hayspec/framework) thus using [TypeScript](https://www.typescriptlang.org/) is supported. 6 | 7 | Specron provides development environment for the Ethereum blockchain and includes useful tools which enable developers to easily write tests for smart contracts. 8 | 9 | The source code is available on [GitHub](https://github.com/specron/framework) where you can also find our [issue tracker](https://github.com/specron/framework/issues). 10 | 11 | ## Installation 12 | 13 | Start by installing the Specron command-line tool. 14 | 15 | ```bash 16 | $ npm install -g @specron/cli web3 solc 17 | ``` 18 | 19 | Specron depends on the latest [web3](https://www.npmjs.com/package/web3) and [solc](https://www.npmjs.com/package/solc) packages, so make sure you have them globally installed. Specron also uses promises thus you need to use [Promise polyfill](https://github.com/taylorhakes/promise-polyfill) when promises are not supported. 20 | 21 | ## Getting started 22 | 23 | Specron automates the testing process of your Solidity code. It doesn't require you to install certain applications in order to get started. 24 | 25 | The Specron interface is designed to fully support the power of [TypeScript](https://www.typescriptlang.org/) when writing tests. It is magic-free which means you have a complete control and visibility of what the code does and how tests are executed. The testing flow should look familiar to any JavaScript or TypeScript developer. 26 | 27 | ### Project initialization 28 | 29 | Start by creating a new project folder. 30 | 31 | ```bash 32 | $ mkdir myproject 33 | $ cd myproject 34 | ``` 35 | 36 | Initialize the project and install the dependencies. 37 | 38 | ```bash 39 | $ specron init 40 | $ npm install 41 | ``` 42 | 43 | Run tests to verify everything works as expected. 44 | 45 | ```bash 46 | $ npm test 47 | ``` 48 | 49 | ### Writing tests 50 | 51 | The core test functionality is provided by the `@specron/spec` module which is automatically attached to your project at initialization. Here we explain some of the main framework features but please explore the source code to find out all the possibilities. 52 | 53 | #### Initializing specs 54 | 55 | The framework provides a `Spec` class which holds basically the whole testing power. You start your test by creating an instance of that class. 56 | 57 | ```ts 58 | import { Spec } from '@specron/spec'; 59 | 60 | const spec = new Spec(); 61 | ``` 62 | 63 | #### Testing features 64 | 65 | The Spec instance provides methods that you can use when writing tests. Most of the time you will use the `test` method which performs the test you write. 66 | 67 | ```ts 68 | spec.test('is true', async (ctx) => { // promise | function 69 | ctx.true(true); 70 | }); 71 | ``` 72 | 73 | There is also the `skip` method which prevents a test to be performed, and the `only` method which includes itself into the test process but excludes all other tests. 74 | 75 | #### Nested specs 76 | 77 | Tests can be nested using the `spec` method. 78 | 79 | ```ts 80 | const colors = new Spec(); 81 | ... 82 | spec.spec('colors', colors); 83 | ``` 84 | 85 | #### Using callbacks 86 | 87 | The framework provides `before` and `after` methods which are execute at the beginning and at the end of the spec case. 88 | 89 | ```ts 90 | spec.before((stage) => { 91 | // execute before all tests 92 | }); 93 | ... 94 | spec.after((stage) => { 95 | // execute after all tests 96 | }); 97 | ``` 98 | 99 | These methods have access to the `stage` of the spec instance. The stage is global to the whole spec stack which means that all settings are always preserved. 100 | 101 | There are also the `beforeEach` and `afterEach` methods which are triggered before and after each test. These methods have access to the `context` and `stage` of the spec. The context represents a copy of a stage and is preserved between `beforeEach`, `test` and `afterEach` methods. This allows for testing atomic tests where a fresh context is always created for each test. 102 | 103 | ```ts 104 | spec.beforeEach((context, stage) => { 105 | // execute before all tests 106 | }); 107 | ... 108 | spec.afterEach((context, stage) => { 109 | // execute after all tests 110 | }); 111 | ``` 112 | Callback functions can be called multiple times and the execution will happen in a defined sequence. 113 | 114 | #### Shared data 115 | 116 | The `context` and the `stage` both provide a way to `set` and `get` values with proper TypeScript types. 117 | 118 | ```ts 119 | interface Data { 120 | id: number; 121 | name: string; 122 | } 123 | 124 | const spec = new Spec(); 125 | 126 | spec.beforeEach((ctx) => { 127 | ctx.set('id', 100); 128 | ctx.set('name', 'John'); 129 | }) 130 | 131 | spec.test('is John with id=100', (ctx) => { 132 | const id = ctx.get('id'); 133 | const name = ctx.get('name'); 134 | ctx.is(id, 100); 135 | ctx.is(name, 'John'); 136 | }) 137 | ``` 138 | 139 | Values set inside the `before` and `after` blocks are available to all `spec` methods. Values set in the `beforeEach` and `afterEach` blocks are available only on the context stack of each test. 140 | 141 | #### Contract deployment 142 | 143 | Stage and context both provide a series of different helper methods. 144 | 145 | A very important method is the `deploy()` method which deploys a contract to a local blockchain process in the background and returns a contract instance. 146 | 147 | ```ts 148 | const { instance, receipt } = await ctx.deploy({ 149 | src: './contracts.json', 150 | contract: 'Main', 151 | }); 152 | ``` 153 | 154 | ### Using CLI 155 | 156 | The `@specron/cli` module is automatically installed when you initialize the project. You can interact with the utility using the `npx specron` command in your terminal. 157 | 158 | To get a list of available features use the `--help` flag. 159 | 160 | ``` 161 | $ npx specron --help 162 | ``` 163 | 164 | #### Running tests 165 | 166 | Every test file must export the `spec` instance for the CLI to be able to detect the test. 167 | 168 | ```ts 169 | export default spec; 170 | ``` 171 | 172 | Run the `specron test` command to run tests. Customize the files search by using the `--match` flag. 173 | 174 | ``` 175 | $ npx specron test --match ./**/*.test.* 176 | ``` 177 | 178 | #### TypeScript support 179 | 180 | Install the [ts-node](https://www.npmjs.com/package/ts-node) NPM package then use the `--require` flag to enable [TypeScript](https://www.typescriptlang.org/) support. 181 | 182 | ``` 183 | specron --require ts-node/register 184 | ``` 185 | 186 | #### Project configuration 187 | 188 | Specron configuration options can be saved inside the package.json file under the the `specron` key. 189 | 190 | ```json 191 | { 192 | "specron": { 193 | "compiler": { 194 | "build": "./build", 195 | "match": [ 196 | "./src/**/*.sol" 197 | ], 198 | "severities": [ 199 | "error", 200 | "warning" 201 | ], 202 | "evmVersion": "byzantium" 203 | }, 204 | "flattener": { 205 | "build": "./build", 206 | "match": [ 207 | "./src/**/*.sol" 208 | ], 209 | "severities": [ 210 | "error", 211 | "warning" 212 | ] 213 | }, 214 | "sandbox": { 215 | "port": 8545, 216 | "host": "localhost" 217 | }, 218 | "test": { 219 | "server": true, 220 | "port": 8545, 221 | "host": "localhost", 222 | "match": [ 223 | "./src/**/*.test.*" 224 | ] 225 | }, 226 | "require": [ 227 | "ts-node/register" 228 | ] 229 | } 230 | } 231 | ``` 232 | 233 | Note that these options can be overriden by providing CLI arguments. 234 | 235 | ### Using continuous integration 236 | 237 | For a full example of a Solidity contract repository including continuous integration using Travis and Specron, see https://github.com/xpepermint/specron-example. 238 | 239 | ## Packages 240 | 241 | | Package | Description | Version 242 | |-|-|- 243 | | [@specron/cli](https://github.com/specron/framework/tree/master/packages/specron-cli) | Command-line interface. | [![NPM Version](https://badge.fury.io/js/@specron%2Fcli.svg)](https://badge.fury.io/js/%40specron%2Fcli) 244 | | [@specron/compiler](https://github.com/specron/framework/tree/master/packages/specron-compiler) | Smart contracts compiler. | [![NPM Version](https://badge.fury.io/js/@specron%2Fcompiler.svg)](https://badge.fury.io/js/%40specron%2Fcompiler) 245 | | [@specron/flattener](https://github.com/specron/framework/tree/master/packages/specron-flattener) | Smart contracts flattener. | [![NPM Version](https://badge.fury.io/js/@specron%2Fflattener.svg)](https://badge.fury.io/js/%40specron%2Fflattener) 246 | | [@specron/init](https://github.com/specron/framework/tree/master/packages/specron-init) | Project structure initializer. | [![NPM Version](https://badge.fury.io/js/@specron%2Finit.svg)](https://badge.fury.io/js/%40specron%2Finit) 247 | | [@specron/sandbox](https://github.com/specron/framework/tree/master/packages/specron-sandbox) | Ethereum sandbox server. | [![NPM Version](https://badge.fury.io/js/@specron%2Fsandbox.svg)](https://badge.fury.io/js/%40specron%2Fsandbox) 248 | | [@specron/spec](https://github.com/specron/framework/tree/master/packages/specron-spec) | Core test suite. | [![NPM Version](https://badge.fury.io/js/@specron%2Fspec.svg)](https://badge.fury.io/js/%40specron%2Fspec) 249 | 250 | ## Contributing 251 | 252 | See [CONTRIBUTING.md](https://github.com/specron/framework/blob/master/CONTRIBUTING.md) for how to help out. 253 | 254 | ## Licence 255 | 256 | See [LICENSE](https://github.com/specron/framework/blob/master/LICENCE) for details. 257 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | title: specron 2 | heading: a lightweight, open source and magic-free framework for testing Solidity smart contracts. 3 | logo: /assets/images/specron.svg 4 | email: info@specron.org 5 | google_analytics: 6 | 7 | menu: 8 | - url: '#specron-framework' 9 | title: What is Specron 10 | - url: '#installation' 11 | title: Getting started 12 | 13 | remote_theme: specron/gp-theme 14 | plugins: 15 | - jekyll-remote-theme 16 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | fixes: 2 | - "specron/framework::/" # travis path to match github repo paths 3 | comment: 4 | layout: "reach, diff, flags, files" 5 | behavior: default 6 | require_changes: false # if true: only post the comment if coverage changes 7 | require_base: no # [yes :: must have a base report to post] 8 | require_head: yes # [yes :: must have a head report to post] 9 | branches: null 10 | coverage: 11 | status: 12 | project: 13 | default: 14 | # basic 15 | target: auto 16 | threshold: null 17 | base: auto 18 | # advanced 19 | branches: null 20 | if_no_uploads: error 21 | if_not_found: success 22 | if_ci_failed: error 23 | only_pulls: false 24 | flags: null 25 | paths: null 26 | -------------------------------------------------------------------------------- /common/config/rush/.npmrc: -------------------------------------------------------------------------------- 1 | # Rush uses this file to configure the package registry, regardless of whether the 2 | # package manager is PNPM, NPM, or Yarn. Prior to invoking the package manager, 3 | # Rush will always copy this file to the folder where installation is performed. 4 | # When NPM is the package manager, Rush works around NPM's processing of 5 | # undefined environment variables by deleting any lines that reference undefined 6 | # environment variables. 7 | # 8 | # DO NOT SPECIFY AUTHENTICATION CREDENTIALS IN THIS FILE. It should only be used 9 | # to configure registry sources. 10 | 11 | registry=https://registry.npmjs.org/ 12 | always-auth=false 13 | -------------------------------------------------------------------------------- /common/config/rush/command-line.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", 3 | "commands": [ 4 | { 5 | "commandKind": "bulk", 6 | "name": "test", 7 | "summary": "Test packages.", 8 | "description": "Executes automated tests.", 9 | "enableParallelism": true 10 | } 11 | ], 12 | "parameters": [] 13 | } 14 | -------------------------------------------------------------------------------- /common/config/rush/common-versions.json: -------------------------------------------------------------------------------- 1 | /** 2 | * This configuration file specifies NPM dependency version selections that affect all projects 3 | * in a Rush repo. For full documentation, please see https://rushjs.io 4 | */ 5 | { 6 | "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/common-versions.schema.json", 7 | 8 | /** 9 | * A table that specifies a "preferred version" for a dependency package. The "preferred version" 10 | * is typically used to hold an indirect dependency back to a specific version, however generally 11 | * it can be any SemVer range specifier (e.g. "~1.2.3"), and it will narrow any (compatible) 12 | * SemVer range specifier. See the Rush documentation for details about this feature. 13 | */ 14 | "preferredVersions": { 15 | 16 | /** 17 | * When someone asks for "^1.0.0" make sure they get "1.2.3" when working in this repo, 18 | * instead of the latest version. 19 | */ 20 | // "some-library": "1.2.3" 21 | }, 22 | 23 | /** 24 | * The "rush check" command can be used to enforce that every project in the repo must specify 25 | * the same SemVer range for a given dependency. However, sometimes exceptions are needed. 26 | * The allowedAlternativeVersions table allows you to list other SemVer ranges that will be 27 | * accepted by "rush check" for a given dependency. 28 | * 29 | * IMPORTANT: THIS TABLE IS FOR *ADDITIONAL* VERSION RANGES THAT ARE ALTERNATIVES TO THE 30 | * USUAL VERSION (WHICH IS INFERRED BY LOOKING AT ALL PROJECTS IN THE REPO). 31 | * This design avoids unnecessary churn in this file. 32 | */ 33 | "allowedAlternativeVersions": { 34 | 35 | /** 36 | * For example, allow some projects to use an older TypeScript compiler 37 | * (in addition to whatever "usual" version is being used by other projects in the repo): 38 | */ 39 | // "typescript": [ 40 | // "~2.4.0" 41 | // ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /common/config/rush/version-policies.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "policyName": "patchAll", 4 | "definitionName": "lockStepVersion", 5 | "version": "0.17.6", 6 | "nextBump": "patch" 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /common/scripts/install-run-rush.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | // See the @microsoft/rush package's LICENSE file for license information. 4 | Object.defineProperty(exports, "__esModule", { value: true }); 5 | // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. 6 | // 7 | // This script is intended for usage in an automated build environment where the Rush command may not have 8 | // been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush 9 | // specified in the rush.json configuration file (if not already installed), and then pass a command-line to it. 10 | // An example usage would be: 11 | // 12 | // node common/scripts/install-run-rush.js install 13 | // 14 | // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ 15 | const path = require("path"); 16 | const fs = require("fs"); 17 | const install_run_1 = require("./install-run"); 18 | const PACKAGE_NAME = '@microsoft/rush'; 19 | const RUSH_PREVIEW_VERSION = 'RUSH_PREVIEW_VERSION'; 20 | function _getRushVersion() { 21 | const rushPreviewVersion = process.env[RUSH_PREVIEW_VERSION]; 22 | if (rushPreviewVersion !== undefined) { 23 | console.log(`Using Rush version from environment variable ${RUSH_PREVIEW_VERSION}=${rushPreviewVersion}`); 24 | return rushPreviewVersion; 25 | } 26 | const rushJsonFolder = install_run_1.findRushJsonFolder(); 27 | const rushJsonPath = path.join(rushJsonFolder, install_run_1.RUSH_JSON_FILENAME); 28 | try { 29 | const rushJsonContents = fs.readFileSync(rushJsonPath, 'utf-8'); 30 | // Use a regular expression to parse out the rushVersion value because rush.json supports comments, 31 | // but JSON.parse does not and we don't want to pull in more dependencies than we need to in this script. 32 | const rushJsonMatches = rushJsonContents.match(/\"rushVersion\"\s*\:\s*\"([0-9a-zA-Z.+\-]+)\"/); 33 | return rushJsonMatches[1]; 34 | } 35 | catch (e) { 36 | throw new Error(`Unable to determine the required version of Rush from rush.json (${rushJsonFolder}). ` + 37 | 'The \'rushVersion\' field is either not assigned in rush.json or was specified ' + 38 | 'using an unexpected syntax.'); 39 | } 40 | } 41 | function _run() { 42 | const [nodePath, /* Ex: /bin/node */ scriptPath, /* /repo/common/scripts/install-run-rush.js */ ...packageBinArgs /* [build, --to, myproject] */] = process.argv; 43 | // Detect if this script was directly invoked, or if the install-run-rushx script was invokved to select the 44 | // appropriate binary inside the rush package to run 45 | const scriptName = path.basename(scriptPath); 46 | const bin = scriptName.toLowerCase() === 'install-run-rushx.js' ? 'rushx' : 'rush'; 47 | if (!nodePath || !scriptPath) { 48 | throw new Error('Unexpected exception: could not detect node path or script path'); 49 | } 50 | if (process.argv.length < 3) { 51 | console.log(`Usage: ${scriptName} [args...]`); 52 | if (scriptName === 'install-run-rush.js') { 53 | console.log(`Example: ${scriptName} build --to myproject`); 54 | } 55 | else { 56 | console.log(`Example: ${scriptName} custom-command`); 57 | } 58 | process.exit(1); 59 | } 60 | install_run_1.runWithErrorAndStatusCode(() => { 61 | const version = _getRushVersion(); 62 | console.log(`The rush.json configuration requests Rush version ${version}`); 63 | return install_run_1.installAndRun(PACKAGE_NAME, version, bin, packageBinArgs); 64 | }); 65 | } 66 | _run(); 67 | //# sourceMappingURL=install-run-rush.js.map -------------------------------------------------------------------------------- /common/scripts/install-run-rushx.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | // See the @microsoft/rush package's LICENSE file for license information. 4 | Object.defineProperty(exports, "__esModule", { value: true }); 5 | // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. 6 | // 7 | // This script is intended for usage in an automated build environment where the Rush command may not have 8 | // been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush 9 | // specified in the rush.json configuration file (if not already installed), and then pass a command-line to the 10 | // rushx command. 11 | // 12 | // An example usage would be: 13 | // 14 | // node common/scripts/install-run-rushx.js custom-command 15 | // 16 | // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ 17 | require("./install-run-rush"); 18 | //# sourceMappingURL=install-run-rushx.js.map -------------------------------------------------------------------------------- /common/scripts/install-run.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | // See the @microsoft/rush package's LICENSE file for license information. 4 | Object.defineProperty(exports, "__esModule", { value: true }); 5 | // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. 6 | // 7 | // This script is intended for usage in an automated build environment where a Node tool may not have 8 | // been preinstalled, or may have an unpredictable version. This script will automatically install the specified 9 | // version of the specified tool (if not already installed), and then pass a command-line to it. 10 | // An example usage would be: 11 | // 12 | // node common/scripts/install-run.js qrcode@1.2.2 qrcode https://rushjs.io 13 | // 14 | // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ 15 | const childProcess = require("child_process"); 16 | const fs = require("fs"); 17 | const os = require("os"); 18 | const path = require("path"); 19 | exports.RUSH_JSON_FILENAME = 'rush.json'; 20 | const RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME = 'RUSH_TEMP_FOLDER'; 21 | const INSTALLED_FLAG_FILENAME = 'installed.flag'; 22 | const NODE_MODULES_FOLDER_NAME = 'node_modules'; 23 | const PACKAGE_JSON_FILENAME = 'package.json'; 24 | /** 25 | * Parse a package specifier (in the form of name\@version) into name and version parts. 26 | */ 27 | function _parsePackageSpecifier(rawPackageSpecifier) { 28 | rawPackageSpecifier = (rawPackageSpecifier || '').trim(); 29 | const separatorIndex = rawPackageSpecifier.lastIndexOf('@'); 30 | let name; 31 | let version = undefined; 32 | if (separatorIndex === 0) { 33 | // The specifier starts with a scope and doesn't have a version specified 34 | name = rawPackageSpecifier; 35 | } 36 | else if (separatorIndex === -1) { 37 | // The specifier doesn't have a version 38 | name = rawPackageSpecifier; 39 | } 40 | else { 41 | name = rawPackageSpecifier.substring(0, separatorIndex); 42 | version = rawPackageSpecifier.substring(separatorIndex + 1); 43 | } 44 | if (!name) { 45 | throw new Error(`Invalid package specifier: ${rawPackageSpecifier}`); 46 | } 47 | return { name, version }; 48 | } 49 | /** 50 | * Resolve a package specifier to a static version 51 | */ 52 | function _resolvePackageVersion(rushCommonFolder, { name, version }) { 53 | if (!version) { 54 | version = '*'; // If no version is specified, use the latest version 55 | } 56 | if (version.match(/^[a-zA-Z0-9\-\+\.]+$/)) { 57 | // If the version contains only characters that we recognize to be used in static version specifiers, 58 | // pass the version through 59 | return version; 60 | } 61 | else { 62 | // version resolves to 63 | try { 64 | const rushTempFolder = _getRushTempFolder(rushCommonFolder); 65 | const sourceNpmrcFolder = path.join(rushCommonFolder, 'config', 'rush'); 66 | _syncNpmrc(sourceNpmrcFolder, rushTempFolder); 67 | const npmPath = getNpmPath(); 68 | // This returns something that looks like: 69 | // @microsoft/rush@3.0.0 '3.0.0' 70 | // @microsoft/rush@3.0.1 '3.0.1' 71 | // ... 72 | // @microsoft/rush@3.0.20 '3.0.20' 73 | // 74 | const npmVersionSpawnResult = childProcess.spawnSync(npmPath, ['view', `${name}@${version}`, 'version', '--no-update-notifier'], { 75 | cwd: rushTempFolder, 76 | stdio: [] 77 | }); 78 | if (npmVersionSpawnResult.status !== 0) { 79 | throw new Error(`"npm view" returned error code ${npmVersionSpawnResult.status}`); 80 | } 81 | const npmViewVersionOutput = npmVersionSpawnResult.stdout.toString(); 82 | const versionLines = npmViewVersionOutput.split('\n').filter((line) => !!line); 83 | const latestVersion = versionLines[versionLines.length - 1]; 84 | if (!latestVersion) { 85 | throw new Error('No versions found for the specified version range.'); 86 | } 87 | const versionMatches = latestVersion.match(/^.+\s\'(.+)\'$/); 88 | if (!versionMatches) { 89 | throw new Error(`Invalid npm output ${latestVersion}`); 90 | } 91 | return versionMatches[1]; 92 | } 93 | catch (e) { 94 | throw new Error(`Unable to resolve version ${version} of package ${name}: ${e}`); 95 | } 96 | } 97 | } 98 | let _npmPath = undefined; 99 | /** 100 | * Get the absolute path to the npm executable 101 | */ 102 | function getNpmPath() { 103 | if (!_npmPath) { 104 | try { 105 | if (os.platform() === 'win32') { 106 | // We're on Windows 107 | const whereOutput = childProcess.execSync('where npm', { stdio: [] }).toString(); 108 | const lines = whereOutput.split(os.EOL).filter((line) => !!line); 109 | // take the last result, we are looking for a .cmd command 110 | // see https://github.com/Microsoft/web-build-tools/issues/759 111 | _npmPath = lines[lines.length - 1]; 112 | } 113 | else { 114 | // We aren't on Windows - assume we're on *NIX or Darwin 115 | _npmPath = childProcess.execSync('which npm', { stdio: [] }).toString(); 116 | } 117 | } 118 | catch (e) { 119 | throw new Error(`Unable to determine the path to the NPM tool: ${e}`); 120 | } 121 | _npmPath = _npmPath.trim(); 122 | if (!fs.existsSync(_npmPath)) { 123 | throw new Error('The NPM executable does not exist'); 124 | } 125 | } 126 | return _npmPath; 127 | } 128 | exports.getNpmPath = getNpmPath; 129 | let _rushJsonFolder; 130 | /** 131 | * Find the absolute path to the folder containing rush.json 132 | */ 133 | function findRushJsonFolder() { 134 | if (!_rushJsonFolder) { 135 | let basePath = __dirname; 136 | let tempPath = __dirname; 137 | do { 138 | const testRushJsonPath = path.join(basePath, exports.RUSH_JSON_FILENAME); 139 | if (fs.existsSync(testRushJsonPath)) { 140 | _rushJsonFolder = basePath; 141 | break; 142 | } 143 | else { 144 | basePath = tempPath; 145 | } 146 | } while (basePath !== (tempPath = path.dirname(basePath))); // Exit the loop when we hit the disk root 147 | if (!_rushJsonFolder) { 148 | throw new Error('Unable to find rush.json.'); 149 | } 150 | } 151 | return _rushJsonFolder; 152 | } 153 | exports.findRushJsonFolder = findRushJsonFolder; 154 | /** 155 | * Create missing directories under the specified base directory, and return the resolved directory. 156 | * 157 | * Does not support "." or ".." path segments. 158 | * Assumes the baseFolder exists. 159 | */ 160 | function _ensureAndJoinPath(baseFolder, ...pathSegments) { 161 | let joinedPath = baseFolder; 162 | try { 163 | for (let pathSegment of pathSegments) { 164 | pathSegment = pathSegment.replace(/[\\\/]/g, '+'); 165 | joinedPath = path.join(joinedPath, pathSegment); 166 | if (!fs.existsSync(joinedPath)) { 167 | fs.mkdirSync(joinedPath); 168 | } 169 | } 170 | } 171 | catch (e) { 172 | throw new Error(`Error building local installation folder (${path.join(baseFolder, ...pathSegments)}): ${e}`); 173 | } 174 | return joinedPath; 175 | } 176 | /** 177 | * As a workaround, _syncNpmrc() copies the .npmrc file to the target folder, and also trims 178 | * unusable lines from the .npmrc file. If the source .npmrc file not exist, then _syncNpmrc() 179 | * will delete an .npmrc that is found in the target folder. 180 | * 181 | * Why are we trimming the .npmrc lines? NPM allows environment variables to be specified in 182 | * the .npmrc file to provide different authentication tokens for different registry. 183 | * However, if the environment variable is undefined, it expands to an empty string, which 184 | * produces a valid-looking mapping with an invalid URL that causes an error. Instead, 185 | * we'd prefer to skip that line and continue looking in other places such as the user's 186 | * home directory. 187 | * 188 | * IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities._syncNpmrc() 189 | */ 190 | function _syncNpmrc(sourceNpmrcFolder, targetNpmrcFolder) { 191 | const sourceNpmrcPath = path.join(sourceNpmrcFolder, '.npmrc'); 192 | const targetNpmrcPath = path.join(targetNpmrcFolder, '.npmrc'); 193 | try { 194 | if (fs.existsSync(sourceNpmrcPath)) { 195 | let npmrcFileLines = fs.readFileSync(sourceNpmrcPath).toString().split('\n'); 196 | npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim()); 197 | const resultLines = []; 198 | // Trim out lines that reference environment variables that aren't defined 199 | for (const line of npmrcFileLines) { 200 | // This finds environment variable tokens that look like "${VAR_NAME}" 201 | const regex = /\$\{([^\}]+)\}/g; 202 | const environmentVariables = line.match(regex); 203 | let lineShouldBeTrimmed = false; 204 | if (environmentVariables) { 205 | for (const token of environmentVariables) { 206 | // Remove the leading "${" and the trailing "}" from the token 207 | const environmentVariableName = token.substring(2, token.length - 1); 208 | if (!process.env[environmentVariableName]) { 209 | lineShouldBeTrimmed = true; 210 | break; 211 | } 212 | } 213 | } 214 | if (lineShouldBeTrimmed) { 215 | // Example output: 216 | // "; MISSING ENVIRONMENT VARIABLE: //my-registry.com/npm/:_authToken=${MY_AUTH_TOKEN}" 217 | resultLines.push('; MISSING ENVIRONMENT VARIABLE: ' + line); 218 | } 219 | else { 220 | resultLines.push(line); 221 | } 222 | } 223 | fs.writeFileSync(targetNpmrcPath, resultLines.join(os.EOL)); 224 | } 225 | else if (fs.existsSync(targetNpmrcPath)) { 226 | // If the source .npmrc doesn't exist and there is one in the target, delete the one in the target 227 | fs.unlinkSync(targetNpmrcPath); 228 | } 229 | } 230 | catch (e) { 231 | throw new Error(`Error syncing .npmrc file: ${e}`); 232 | } 233 | } 234 | /** 235 | * Detects if the package in the specified directory is installed 236 | */ 237 | function _isPackageAlreadyInstalled(packageInstallFolder) { 238 | try { 239 | const flagFilePath = path.join(packageInstallFolder, INSTALLED_FLAG_FILENAME); 240 | if (!fs.existsSync(flagFilePath)) { 241 | return false; 242 | } 243 | const fileContents = fs.readFileSync(flagFilePath).toString(); 244 | return fileContents.trim() === process.version; 245 | } 246 | catch (e) { 247 | return false; 248 | } 249 | } 250 | /** 251 | * Removes the following files and directories under the specified folder path: 252 | * - installed.flag 253 | * - 254 | * - node_modules 255 | */ 256 | function _cleanInstallFolder(rushTempFolder, packageInstallFolder) { 257 | try { 258 | const flagFile = path.resolve(packageInstallFolder, INSTALLED_FLAG_FILENAME); 259 | if (fs.existsSync(flagFile)) { 260 | fs.unlinkSync(flagFile); 261 | } 262 | const packageLockFile = path.resolve(packageInstallFolder, 'package-lock.json'); 263 | if (fs.existsSync(packageLockFile)) { 264 | fs.unlinkSync(packageLockFile); 265 | } 266 | const nodeModulesFolder = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME); 267 | if (fs.existsSync(nodeModulesFolder)) { 268 | const rushRecyclerFolder = _ensureAndJoinPath(rushTempFolder, 'rush-recycler', `install-run-${Date.now().toString()}`); 269 | fs.renameSync(nodeModulesFolder, rushRecyclerFolder); 270 | } 271 | } 272 | catch (e) { 273 | throw new Error(`Error cleaning the package install folder (${packageInstallFolder}): ${e}`); 274 | } 275 | } 276 | function _createPackageJson(packageInstallFolder, name, version) { 277 | try { 278 | const packageJsonContents = { 279 | 'name': 'ci-rush', 280 | 'version': '0.0.0', 281 | 'dependencies': { 282 | [name]: version 283 | }, 284 | 'description': 'DON\'T WARN', 285 | 'repository': 'DON\'T WARN', 286 | 'license': 'MIT' 287 | }; 288 | const packageJsonPath = path.join(packageInstallFolder, PACKAGE_JSON_FILENAME); 289 | fs.writeFileSync(packageJsonPath, JSON.stringify(packageJsonContents, undefined, 2)); 290 | } 291 | catch (e) { 292 | throw new Error(`Unable to create package.json: ${e}`); 293 | } 294 | } 295 | /** 296 | * Run "npm install" in the package install folder. 297 | */ 298 | function _installPackage(packageInstallFolder, name, version) { 299 | try { 300 | console.log(`Installing ${name}...`); 301 | const npmPath = getNpmPath(); 302 | const result = childProcess.spawnSync(npmPath, ['install'], { 303 | stdio: 'inherit', 304 | cwd: packageInstallFolder, 305 | env: process.env 306 | }); 307 | if (result.status !== 0) { 308 | throw new Error('"npm install" encountered an error'); 309 | } 310 | console.log(`Successfully installed ${name}@${version}`); 311 | } 312 | catch (e) { 313 | throw new Error(`Unable to install package: ${e}`); 314 | } 315 | } 316 | /** 317 | * Get the ".bin" path for the package. 318 | */ 319 | function _getBinPath(packageInstallFolder, binName) { 320 | const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin'); 321 | const resolvedBinName = (os.platform() === 'win32') ? `${binName}.cmd` : binName; 322 | return path.resolve(binFolderPath, resolvedBinName); 323 | } 324 | /** 325 | * Write a flag file to the package's install directory, signifying that the install was successful. 326 | */ 327 | function _writeFlagFile(packageInstallFolder) { 328 | try { 329 | const flagFilePath = path.join(packageInstallFolder, INSTALLED_FLAG_FILENAME); 330 | fs.writeFileSync(flagFilePath, process.version); 331 | } 332 | catch (e) { 333 | throw new Error(`Unable to create installed.flag file in ${packageInstallFolder}`); 334 | } 335 | } 336 | function _getRushTempFolder(rushCommonFolder) { 337 | const rushTempFolder = process.env[RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME]; 338 | if (rushTempFolder !== undefined) { 339 | _ensureFolder(rushTempFolder); 340 | return rushTempFolder; 341 | } 342 | else { 343 | return _ensureAndJoinPath(rushCommonFolder, 'temp'); 344 | } 345 | } 346 | function _ensureFolder(folderPath) { 347 | if (!fs.existsSync(folderPath)) { 348 | const parentDir = path.dirname(folderPath); 349 | _ensureFolder(parentDir); 350 | fs.mkdirSync(folderPath); 351 | } 352 | } 353 | function installAndRun(packageName, packageVersion, packageBinName, packageBinArgs) { 354 | const rushJsonFolder = findRushJsonFolder(); 355 | const rushCommonFolder = path.join(rushJsonFolder, 'common'); 356 | const rushTempFolder = _getRushTempFolder(rushCommonFolder); 357 | const packageInstallFolder = _ensureAndJoinPath(rushTempFolder, 'install-run', `${packageName}@${packageVersion}`); 358 | if (!_isPackageAlreadyInstalled(packageInstallFolder)) { 359 | // The package isn't already installed 360 | _cleanInstallFolder(rushTempFolder, packageInstallFolder); 361 | const sourceNpmrcFolder = path.join(rushCommonFolder, 'config', 'rush'); 362 | _syncNpmrc(sourceNpmrcFolder, packageInstallFolder); 363 | _createPackageJson(packageInstallFolder, packageName, packageVersion); 364 | _installPackage(packageInstallFolder, packageName, packageVersion); 365 | _writeFlagFile(packageInstallFolder); 366 | } 367 | const statusMessage = `Invoking "${packageBinName} ${packageBinArgs.join(' ')}"`; 368 | const statusMessageLine = new Array(statusMessage.length + 1).join('-'); 369 | console.log(os.EOL + statusMessage + os.EOL + statusMessageLine + os.EOL); 370 | const binPath = _getBinPath(packageInstallFolder, packageBinName); 371 | const result = childProcess.spawnSync(binPath, packageBinArgs, { 372 | stdio: 'inherit', 373 | cwd: process.cwd(), 374 | env: process.env 375 | }); 376 | return result.status; 377 | } 378 | exports.installAndRun = installAndRun; 379 | function runWithErrorAndStatusCode(fn) { 380 | process.exitCode = 1; 381 | try { 382 | const exitCode = fn(); 383 | process.exitCode = exitCode; 384 | } 385 | catch (e) { 386 | console.error(os.EOL + os.EOL + e.toString() + os.EOL + os.EOL); 387 | } 388 | } 389 | exports.runWithErrorAndStatusCode = runWithErrorAndStatusCode; 390 | function _run() { 391 | const [nodePath, /* Ex: /bin/node */ scriptPath, /* /repo/common/scripts/install-run-rush.js */ rawPackageSpecifier, /* qrcode@^1.2.0 */ packageBinName, /* qrcode */ ...packageBinArgs /* [-f, myproject/lib] */] = process.argv; 392 | if (!nodePath) { 393 | throw new Error('Unexpected exception: could not detect node path'); 394 | } 395 | if (path.basename(scriptPath).toLowerCase() !== 'install-run.js') { 396 | // If install-run.js wasn't directly invoked, don't execute the rest of this function. Return control 397 | // to the script that (presumably) imported this file 398 | return; 399 | } 400 | if (process.argv.length < 4) { 401 | console.log('Usage: install-run.js @ [args...]'); 402 | console.log('Example: install-run.js qrcode@1.2.2 qrcode https://rushjs.io'); 403 | process.exit(1); 404 | } 405 | runWithErrorAndStatusCode(() => { 406 | const rushJsonFolder = findRushJsonFolder(); 407 | const rushCommonFolder = _ensureAndJoinPath(rushJsonFolder, 'common'); 408 | const packageSpecifier = _parsePackageSpecifier(rawPackageSpecifier); 409 | const name = packageSpecifier.name; 410 | const version = _resolvePackageVersion(rushCommonFolder, packageSpecifier); 411 | if (packageSpecifier.version !== version) { 412 | console.log(`Resolved to ${name}@${version}`); 413 | } 414 | return installAndRun(name, version, packageBinName, packageBinArgs); 415 | }); 416 | } 417 | _run(); 418 | //# sourceMappingURL=install-run.js.map -------------------------------------------------------------------------------- /packages/specron-cli/CHANGELOG.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@specron/cli", 3 | "entries": [ 4 | { 5 | "version": "0.17.6", 6 | "tag": "@specron/cli_v0.17.6", 7 | "date": "Wed, 04 Aug 2021 13:37:50 GMT", 8 | "comments": {} 9 | }, 10 | { 11 | "version": "0.17.5", 12 | "tag": "@specron/cli_v0.17.5", 13 | "date": "Wed, 04 Aug 2021 13:37:40 GMT", 14 | "comments": {} 15 | }, 16 | { 17 | "version": "0.17.4", 18 | "tag": "@specron/cli_v0.17.4", 19 | "date": "Wed, 04 Aug 2021 13:34:22 GMT", 20 | "comments": {} 21 | }, 22 | { 23 | "version": "0.17.3", 24 | "tag": "@specron/cli_v0.17.3", 25 | "date": "Tue, 12 Jan 2021 14:59:18 GMT", 26 | "comments": {} 27 | }, 28 | { 29 | "version": "0.17.2", 30 | "tag": "@specron/cli_v0.17.2", 31 | "date": "Tue, 12 Jan 2021 12:34:19 GMT", 32 | "comments": {} 33 | }, 34 | { 35 | "version": "0.17.1", 36 | "tag": "@specron/cli_v0.17.1", 37 | "date": "Mon, 04 May 2020 11:19:54 GMT", 38 | "comments": {} 39 | }, 40 | { 41 | "version": "0.17.0", 42 | "tag": "@specron/cli_v0.17.0", 43 | "date": "Mon, 04 May 2020 10:16:53 GMT", 44 | "comments": {} 45 | }, 46 | { 47 | "version": "0.16.0", 48 | "tag": "@specron/cli_v0.16.0", 49 | "date": "Fri, 07 Feb 2020 11:38:38 GMT", 50 | "comments": {} 51 | }, 52 | { 53 | "version": "0.15.2", 54 | "tag": "@specron/cli_v0.15.2", 55 | "date": "Fri, 07 Feb 2020 11:38:14 GMT", 56 | "comments": {} 57 | }, 58 | { 59 | "version": "0.15.1", 60 | "tag": "@specron/cli_v0.15.1", 61 | "date": "Mon, 27 Jan 2020 10:44:17 GMT", 62 | "comments": {} 63 | }, 64 | { 65 | "version": "0.15.0", 66 | "tag": "@specron/cli_v0.15.0", 67 | "date": "Thu, 16 Jan 2020 09:44:14 GMT", 68 | "comments": {} 69 | }, 70 | { 71 | "version": "0.14.0", 72 | "tag": "@specron/cli_v0.14.0", 73 | "date": "Thu, 16 Jan 2020 08:27:04 GMT", 74 | "comments": {} 75 | }, 76 | { 77 | "version": "0.13.0", 78 | "tag": "@specron/cli_v0.13.0", 79 | "date": "Tue, 14 Jan 2020 12:07:56 GMT", 80 | "comments": {} 81 | }, 82 | { 83 | "version": "0.12.0", 84 | "tag": "@specron/cli_v0.12.0", 85 | "date": "Mon, 13 Jan 2020 09:39:01 GMT", 86 | "comments": {} 87 | }, 88 | { 89 | "version": "0.11.0", 90 | "tag": "@specron/cli_v0.11.0", 91 | "date": "Tue, 07 Jan 2020 09:53:08 GMT", 92 | "comments": {} 93 | }, 94 | { 95 | "version": "0.10.0", 96 | "tag": "@specron/cli_v0.10.0", 97 | "date": "Thu, 28 Nov 2019 11:45:10 GMT", 98 | "comments": {} 99 | }, 100 | { 101 | "version": "0.9.0", 102 | "tag": "@specron/cli_v0.9.0", 103 | "date": "Tue, 01 Oct 2019 18:29:23 GMT", 104 | "comments": {} 105 | }, 106 | { 107 | "version": "0.8.2", 108 | "tag": "@specron/cli_v0.8.2", 109 | "date": "Tue, 01 Oct 2019 18:27:47 GMT", 110 | "comments": {} 111 | }, 112 | { 113 | "version": "0.8.1", 114 | "tag": "@specron/cli_v0.8.1", 115 | "date": "Tue, 01 Oct 2019 18:14:09 GMT", 116 | "comments": {} 117 | }, 118 | { 119 | "version": "0.8.0", 120 | "tag": "@specron/cli_v0.8.0", 121 | "date": "Sun, 29 Sep 2019 22:26:46 GMT", 122 | "comments": {} 123 | } 124 | ] 125 | } 126 | -------------------------------------------------------------------------------- /packages/specron-cli/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - @specron/cli 2 | 3 | This log was last generated on Wed, 04 Aug 2021 13:37:50 GMT and should not be manually modified. 4 | 5 | ## 0.17.6 6 | Wed, 04 Aug 2021 13:37:50 GMT 7 | 8 | *Version update only* 9 | 10 | ## 0.17.5 11 | Wed, 04 Aug 2021 13:37:40 GMT 12 | 13 | *Version update only* 14 | 15 | ## 0.17.4 16 | Wed, 04 Aug 2021 13:34:22 GMT 17 | 18 | *Version update only* 19 | 20 | ## 0.17.3 21 | Tue, 12 Jan 2021 14:59:18 GMT 22 | 23 | *Version update only* 24 | 25 | ## 0.17.2 26 | Tue, 12 Jan 2021 12:34:19 GMT 27 | 28 | *Version update only* 29 | 30 | ## 0.17.1 31 | Mon, 04 May 2020 11:19:54 GMT 32 | 33 | *Version update only* 34 | 35 | ## 0.17.0 36 | Mon, 04 May 2020 10:16:53 GMT 37 | 38 | *Version update only* 39 | 40 | ## 0.16.0 41 | Fri, 07 Feb 2020 11:38:38 GMT 42 | 43 | *Version update only* 44 | 45 | ## 0.15.2 46 | Fri, 07 Feb 2020 11:38:14 GMT 47 | 48 | *Version update only* 49 | 50 | ## 0.15.1 51 | Mon, 27 Jan 2020 10:44:17 GMT 52 | 53 | *Version update only* 54 | 55 | ## 0.15.0 56 | Thu, 16 Jan 2020 09:44:14 GMT 57 | 58 | *Version update only* 59 | 60 | ## 0.14.0 61 | Thu, 16 Jan 2020 08:27:04 GMT 62 | 63 | *Version update only* 64 | 65 | ## 0.13.0 66 | Tue, 14 Jan 2020 12:07:56 GMT 67 | 68 | *Version update only* 69 | 70 | ## 0.12.0 71 | Mon, 13 Jan 2020 09:39:01 GMT 72 | 73 | *Version update only* 74 | 75 | ## 0.11.0 76 | Tue, 07 Jan 2020 09:53:08 GMT 77 | 78 | *Version update only* 79 | 80 | ## 0.10.0 81 | Thu, 28 Nov 2019 11:45:10 GMT 82 | 83 | *Version update only* 84 | 85 | ## 0.9.0 86 | Tue, 01 Oct 2019 18:29:23 GMT 87 | 88 | *Version update only* 89 | 90 | ## 0.8.2 91 | Tue, 01 Oct 2019 18:27:47 GMT 92 | 93 | *Version update only* 94 | 95 | ## 0.8.1 96 | Tue, 01 Oct 2019 18:14:09 GMT 97 | 98 | *Version update only* 99 | 100 | ## 0.8.0 101 | Sun, 29 Sep 2019 22:26:46 GMT 102 | 103 | *Initial release* 104 | 105 | -------------------------------------------------------------------------------- /packages/specron-cli/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/specron/framework/396d5e88cf1785b8d8157918645a98b3074eec8c/packages/specron-cli/README.md -------------------------------------------------------------------------------- /packages/specron-cli/bin/specron: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('../dist'); 4 | -------------------------------------------------------------------------------- /packages/specron-cli/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": ["dist/*"], 3 | "ext": "js,ts" 4 | } 5 | -------------------------------------------------------------------------------- /packages/specron-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@specron/cli", 3 | "version": "0.17.6", 4 | "description": "Command-line tool for Specron framework.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "bin": { 8 | "specron": "./bin/specron" 9 | }, 10 | "scripts": { 11 | "build": "npx tsc", 12 | "test": "npx nyc npx ava --verbose" 13 | }, 14 | "specron": { 15 | "compiler": { 16 | "build": "./build", 17 | "match": [ 18 | "./src/**/*.sol" 19 | ], 20 | "severities": [ 21 | "error", 22 | "warning" 23 | ] 24 | }, 25 | "flattener": { 26 | "build": "./build", 27 | "match": [ 28 | "./src/**/*.sol" 29 | ], 30 | "severities": [ 31 | "error", 32 | "warning" 33 | ] 34 | }, 35 | "sandbox": { 36 | "port": 8545 37 | }, 38 | "test": { 39 | "server": true, 40 | "port": 8545, 41 | "match": [ 42 | "./src/**/*.hay.*" 43 | ], 44 | "blockTime": null 45 | }, 46 | "require": [ 47 | "ts-node/register" 48 | ] 49 | }, 50 | "ava": { 51 | "concurrency": 1, 52 | "files": [ 53 | "dist/tests/*.test.js", 54 | "dist/tests/**/*.test.js" 55 | ], 56 | "timeout": "1m" 57 | }, 58 | "nyc": { 59 | "exclude": [ 60 | "src/tests" 61 | ] 62 | }, 63 | "license": "MIT", 64 | "devDependencies": { 65 | "@types/inquirer": "7.3.3", 66 | "@types/node": "16.4.11", 67 | "@types/yargs": "17.0.2", 68 | "ava": "3.15.0", 69 | "nyc": "15.1.0", 70 | "solc": "0.8.0", 71 | "ts-node": "10.1.0", 72 | "typescript": "4.3.5", 73 | "web3": "1.5.0" 74 | }, 75 | "dependencies": { 76 | "@hayspec/reporter": "0.10.2", 77 | "@specron/compiler": "0.17.6", 78 | "@specron/flattener": "0.17.6", 79 | "@specron/init": "0.17.6", 80 | "@specron/sandbox": "0.17.6", 81 | "@specron/spec": "0.17.6", 82 | "inquirer": "8.1.2", 83 | "yargs": "17.0.1" 84 | }, 85 | "peerDependencies": { 86 | "solc": "*", 87 | "web3": "*" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /packages/specron-cli/src/commands/compile.ts: -------------------------------------------------------------------------------- 1 | import { Compiler, DefaultReporter } from '@specron/compiler'; 2 | import { getConfig } from '../lib/env'; 3 | 4 | /** 5 | * Compiles Solidity contracts. 6 | */ 7 | export default async function (argv) { 8 | const config = getConfig(argv); 9 | const compiler = new Compiler({ 10 | settings: { 11 | optimizer: { 12 | enabled: config.settings.optimization > 0, 13 | runs: config.settings.optimization, 14 | }, 15 | evmVersion: config.compiler.evmVersion, 16 | }, 17 | reporter: new DefaultReporter(config.compiler.severities), 18 | }); 19 | await compiler.source(...config.compiler.match); 20 | 21 | try { 22 | compiler.compile(); 23 | if (config.compiler.clean) { 24 | compiler.clean(); 25 | } 26 | compiler.save(config.compiler.build); 27 | process.exit(0); 28 | } catch (e) { 29 | console.log(e); 30 | process.exit(2); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/specron-cli/src/commands/flatten.ts: -------------------------------------------------------------------------------- 1 | import { Flattener, DefaultReporter } from '@specron/flattener'; 2 | import { getConfig } from '../lib/env'; 3 | 4 | /** 5 | * Compiles Solidity contracts. 6 | */ 7 | export default async function (argv) { 8 | const config = getConfig(argv); 9 | 10 | const flattener = new Flattener({ 11 | reporter: new DefaultReporter(config.flattener.severities), 12 | }); 13 | flattener.source(...config.flattener.match); 14 | 15 | try { 16 | await flattener.flatten(); 17 | flattener.save(config.flattener.build); 18 | process.exit(0); 19 | } catch (e) { 20 | console.log(e); 21 | process.exit(2); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/specron-cli/src/commands/init.ts: -------------------------------------------------------------------------------- 1 | import * as inquirer from 'inquirer'; 2 | import { Generator } from '@specron/init'; 3 | import { Printer } from '@hayspec/reporter'; 4 | import { getConfig } from '../lib/env'; 5 | 6 | /** 7 | * Initializes project directory. 8 | */ 9 | export default async function (argv) { 10 | const config = getConfig(argv); 11 | const root = process.cwd(); 12 | const printer = new Printer(); 13 | 14 | let answers = {}; 15 | if (!(config.name && config.description)) { 16 | answers = await inquirer.prompt([ 17 | { 18 | type: 'input', 19 | name: 'name', 20 | message: "Project name:", 21 | default: config.name || 'myproject', 22 | }, 23 | { 24 | type: 'input', 25 | name: 'description', 26 | message: "Project description:", 27 | default: config.description || '.', 28 | }, 29 | ]); 30 | } else { 31 | answers = { 32 | name: config.name, 33 | description: config.description, 34 | }; 35 | } 36 | 37 | const generator = new Generator({ 38 | root, 39 | name: (answers['name'] || process.cwd().split(/\\|\//).reverse()[0]).toLowerCase(), 40 | description: answers['description'], 41 | }); 42 | try { 43 | await generator.build(); 44 | 45 | printer.end( 46 | printer.indent(1, ''), 47 | `Continue by running the commands below:` 48 | ); 49 | printer.end( 50 | printer.indent(2, ''), 51 | printer.colorize('gray', `$ npm install`) 52 | ); 53 | printer.end( 54 | printer.indent(2, ''), 55 | printer.colorize('gray', `$ npm test`) 56 | ); 57 | printer.end(); 58 | process.exit(0); 59 | 60 | } catch (e) { 61 | console.error(e); 62 | process.exit(2); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /packages/specron-cli/src/commands/sandbox.ts: -------------------------------------------------------------------------------- 1 | import { Sandbox } from '@specron/sandbox'; 2 | import { Printer } from '@hayspec/reporter'; 3 | import { getConfig } from '../lib/env'; 4 | 5 | /** 6 | * Starts Ethereum sandbox server. 7 | */ 8 | export default async function (argv) { 9 | const config = getConfig(argv); 10 | const printer = new Printer(); 11 | 12 | const sandbox = new Sandbox(config.sandbox); 13 | try { 14 | await sandbox.listen(); 15 | printer.end(); 16 | printer.end( 17 | printer.indent(1, ''), 18 | 'Sandbox blockchain' 19 | ); 20 | printer.end( 21 | printer.indent(2, ''), 22 | printer.colorize('gray', `Listening at localhost:${config.sandbox.port} ...`) 23 | ); 24 | printer.end(); 25 | } catch (e) { 26 | console.error(e); 27 | process.exit(2); 28 | } 29 | 30 | if (config.sandbox.ttl) { 31 | setTimeout(() => sandbox.close(), config.sandbox.ttl); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/specron-cli/src/commands/test.ts: -------------------------------------------------------------------------------- 1 | import { Runner, Spec, Stage, Reporter } from '@specron/spec'; 2 | import { Sandbox } from '@specron/sandbox'; 3 | import Web3 from 'web3'; 4 | import { getConfig } from '../lib/env'; 5 | 6 | /** 7 | * Runs tests. 8 | */ 9 | export default async function (argv) { 10 | const config = getConfig(argv); 11 | 12 | const sandbox = new Sandbox(config.test); 13 | const web3 = new Web3(sandbox.provider); 14 | const reporter = new Reporter(); 15 | const stage = new Stage(web3, reporter); 16 | const test = new Spec(stage); 17 | 18 | if (config.test.server) { 19 | await sandbox.listen(); 20 | } 21 | 22 | const runner = new Runner(); 23 | await runner.require(...config.test.match); 24 | runner.results.forEach((result) => { 25 | const message = result.file.substr(process.cwd().length + 1); 26 | test.spec(message, result.spec); 27 | }); 28 | 29 | try { 30 | await test.perform(); 31 | } catch (e) { 32 | console.log(e); 33 | process.exit(2); 34 | } 35 | 36 | if (config.test.server) { 37 | await sandbox.close(); 38 | } 39 | 40 | process.exit(reporter.failedCount ? 1 : 0); 41 | } 42 | -------------------------------------------------------------------------------- /packages/specron-cli/src/index.ts: -------------------------------------------------------------------------------- 1 | import * as yargs from 'yargs'; 2 | import initHandler from './commands/init'; 3 | import sandboxHandler from './commands/sandbox'; 4 | import compileHandler from './commands/compile'; 5 | import flattenHandler from './commands/flatten'; 6 | import testHandler from './commands/test'; 7 | import { getConfig } from './lib/env'; 8 | 9 | /** 10 | * Interface definition. 11 | */ 12 | const { argv } = yargs 13 | .usage('Usage: $0 --help') 14 | .command('compile', 'Compiles solidity contracts', (yargs) => yargs 15 | .usage('Usage: $0 --match *.sol --build ./build') 16 | .option('match', { 17 | array: true, 18 | description: 'Matching pattern', 19 | }) 20 | .option('evmVersion', { 21 | string: true, 22 | description: 'EVM version which will be used', 23 | }) 24 | .option('build', { 25 | string: true, 26 | description: 'Build folder path', 27 | }) 28 | .option('severities', { 29 | array: true, 30 | description: 'Toggle error and warnings visibility', 31 | }) 32 | .option('optimization', { 33 | number: true, 34 | description: 'Code optimization level', 35 | }) 36 | .option('clean', { 37 | boolean: true, 38 | description: 'Clean output', 39 | }), 40 | compileHandler) 41 | .command('flatten', 'Flattens solidity contracts', (yargs) => yargs 42 | .usage('Usage: $0 --match *.sol --build ./build') 43 | .option('match', { 44 | array: true, 45 | description: 'Matching pattern', 46 | }) 47 | .option('build', { 48 | string: true, 49 | description: 'Build folder path', 50 | }) 51 | .option('severities', { 52 | array: true, 53 | description: 'Toggle error and warnings visibility', 54 | }), 55 | flattenHandler) 56 | .command('init', 'Initializes project directory.', (yargs) => yargs 57 | .option('name', { 58 | string: true, 59 | description: 'Project name', 60 | }) 61 | .option('description', { 62 | string: true, 63 | description: 'Project description', 64 | }), 65 | initHandler) 66 | .command('sandbox', 'Starts Ethereum sandbox server.', (yargs) => yargs 67 | .option('port', { 68 | number: true, 69 | description: 'Server port number', 70 | }), 71 | sandboxHandler) 72 | .command('test', 'Runs tests', (yargs) => yargs 73 | .option('match', { 74 | array: true, 75 | description: 'Match pattern', 76 | }) 77 | .option('require', { 78 | array: true, 79 | description: 'Require dependencies', 80 | }) 81 | .option('server', { 82 | boolean: true, 83 | description: 'Start sandbox server', 84 | }) 85 | .option('port', { 86 | number: true, 87 | description: 'Server port number', 88 | }) 89 | .option('blockTime', { 90 | number: true, 91 | description: 'Seconds for automatic mining', 92 | }), 93 | testHandler) 94 | .epilog('Copyright © Xpepermint 2018.') 95 | .help() 96 | .version(); 97 | 98 | /** 99 | * Upgrading environment. 100 | */ 101 | getConfig(argv).require.forEach((v) => require(v)); 102 | -------------------------------------------------------------------------------- /packages/specron-cli/src/lib/env.ts: -------------------------------------------------------------------------------- 1 | import * as pt from 'path'; 2 | 3 | /** 4 | * Returns package.json data. 5 | */ 6 | export function getPackage() { 7 | try { 8 | return require(pt.join(process.cwd(), 'package.json')) || {}; 9 | } catch (e) { 10 | return {}; 11 | } 12 | } 13 | 14 | /** 15 | * Returns the first value of an arraye. 16 | */ 17 | export function getFirstValue(...values) { 18 | return values.filter((v) => typeof v !== 'undefined')[0]; 19 | } 20 | 21 | /** 22 | * Returns Specron options. 23 | */ 24 | export function getConfig(argv?: any) { 25 | const defaults = { 26 | compiler: {}, 27 | flattener: {}, 28 | settings: {}, 29 | sandbox: {}, 30 | test: {}, 31 | require: [], 32 | ...getPackage()['specron'], 33 | }; 34 | const custom = argv || {}; 35 | 36 | return { 37 | name: getFirstValue(custom['name'], defaults['name'], ''), 38 | description: getFirstValue(custom['description'], defaults['description'], ''), 39 | compiler: { 40 | build: getFirstValue(custom['build'], defaults['compiler']['build'], './build'), 41 | match: getFirstValue(custom['match'], defaults['compiler']['match'], []), 42 | severities: getFirstValue(custom['severities'], defaults['compiler']['severities'], ['error', 'warning']), 43 | evmVersion: getFirstValue(custom['evmVersion'], defaults['compiler']['evmVersion'], 'istanbul'), 44 | clean: getFirstValue(custom['clean'], defaults['compiler']['clean'], true), 45 | }, 46 | flattener: { 47 | build: getFirstValue(custom['build'], defaults['flattener']['build'], './build'), 48 | match: getFirstValue(custom['match'], defaults['flattener']['match'], []), 49 | severities: getFirstValue(custom['severities'], defaults['flattener']['severities'], ['error', 'warning']), 50 | }, 51 | settings: { 52 | optimization: getFirstValue(custom['optimization'], defaults['compiler']['optimization'], 200), 53 | }, 54 | sandbox: { 55 | port: getFirstValue(custom['port'], defaults['sandbox']['port'], 8545), 56 | ttl: getFirstValue(custom['ttl'], defaults['sandbox']['ttl'], 0), 57 | }, 58 | test: { 59 | server: custom['server'] !== false && defaults['test']['server'] !== false, 60 | port: getFirstValue(custom['port'], defaults['test']['port'], 8545), 61 | match: getFirstValue(custom['match'], defaults['test']['match'], []), 62 | blockTime: getFirstValue(custom['blockTime'], defaults['test']['blockTime'], null), 63 | }, 64 | require: getFirstValue(custom['require'], defaults['require'], []), 65 | }; 66 | } 67 | -------------------------------------------------------------------------------- /packages/specron-cli/src/tests/assets/invalid.hay.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@specron/spec'; 2 | 3 | const spec = new Spec(); 4 | 5 | spec.test('foo', async (context) => { 6 | context.true(true); 7 | }); 8 | 9 | spec.test('bar', async (context) => { 10 | context.true(false); 11 | }); 12 | 13 | export default spec; 14 | -------------------------------------------------------------------------------- /packages/specron-cli/src/tests/assets/token-a.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.0; 2 | 3 | import "./token-b.sol"; 4 | 5 | contract Token1 is Token2 {} 6 | -------------------------------------------------------------------------------- /packages/specron-cli/src/tests/assets/token-b.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.0; 2 | 3 | contract Token2 { 4 | 5 | /** 6 | * @dev Returns fake value. 7 | * @param _value Multiploer value. 8 | */ 9 | function test() 10 | public 11 | pure 12 | returns (uint256 _value) 13 | { 14 | _value = 123; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /packages/specron-cli/src/tests/assets/valid.hay.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '@specron/spec'; 2 | 3 | const spec = new Spec(); 4 | 5 | spec.test('foo', async (context) => { 6 | context.true(true); 7 | }); 8 | 9 | spec.test('bar', async (context) => { 10 | context.true(true); 11 | context.true(true); 12 | context.false(false); 13 | }); 14 | 15 | export default spec; 16 | -------------------------------------------------------------------------------- /packages/specron-cli/src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import * as util from 'util'; 3 | import * as cproc from 'child_process'; 4 | import * as pt from 'path'; 5 | 6 | const exec = util.promisify(cproc.exec); 7 | 8 | test('starts sandbox server', async (t) => { 9 | const command = `./bin/specron sandbox --port 8546 --ttl 1000`; 10 | const { stdout, stderr } = await exec(command); 11 | t.true(stdout.indexOf('localhost:8546') !== -1); 12 | t.true(stderr === ''); 13 | }); 14 | 15 | test('initializes current folder', async (t) => { 16 | const cwd = `./node_modules/.tmp/init-${Date.now()}`; 17 | const command = `mkdir -p ${cwd}; cd ${cwd}; ../../../bin/specron init --name foo --description bar; echo code: $?`; 18 | const { stdout, stderr } = await exec(command); 19 | t.true(stdout.indexOf('Continue by running the commands below:') !== -1); 20 | t.true(stdout.indexOf('code: 0') !== -1); 21 | t.true(stderr === ''); 22 | }); 23 | 24 | test('compiles smart contracts', async (t) => { 25 | const dist = `./node_modules/.tmp/compile-${Date.now()}`; 26 | const command = `./bin/specron compile --evmVersion byzantium --severities error warning --match ./src/tests/assets/*.sol --build ${dist}; echo code: $?`; 27 | const { stdout, stderr } = await exec(command); 28 | const tokena = require(pt.join(process.cwd(), dist, 'token-a.json')); 29 | t.is(tokena.Token1.metadata.settings.evmVersion, 'byzantium'); 30 | t.is(Object.keys(tokena).length, 1); 31 | t.true(stdout.indexOf('contracts') !== -1); 32 | t.true(stdout.indexOf('code: 0') !== -1); 33 | t.true(stderr === ''); 34 | }); 35 | 36 | test('flattens smart contracts', async (t) => { 37 | const dist = `./node_modules/.tmp/flatten-${Date.now()}`; 38 | const command = `./bin/specron flatten --severities error warning --match ./src/tests/assets/*.sol --build ${dist}; echo code: $?`; 39 | const { stdout, stderr } = await exec(command); 40 | t.true(stdout.indexOf('Contracts') !== -1); 41 | t.true(stdout.indexOf('code: 0') !== -1); 42 | t.true(stderr === ''); 43 | }); 44 | 45 | test.serial('runs valid tests', async (t) => { 46 | const command = `./bin/specron test --match ./src/tests/assets/valid.hay.ts --require ts-node/register; echo code: $?`; 47 | const { stdout, stderr } = await exec(command); 48 | t.true(stdout.indexOf('code: 0') !== -1); 49 | t.true(stderr === ''); 50 | }); 51 | 52 | test.serial('runs invalid tests', async (t) => { 53 | const command = `./bin/specron test --match ./src/tests/assets/invalid.hay.ts --require ts-node/register; echo code: $?`; 54 | const { stdout, stderr } = await exec(command); 55 | t.true(stdout.indexOf('src/tests/assets/invalid.hay.ts') !== -1); 56 | t.true(stdout.indexOf('code: 1') !== -1); 57 | t.true(stderr === ''); 58 | }); 59 | -------------------------------------------------------------------------------- /packages/specron-cli/src/tests/lib/env.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import { getConfig } from '../../lib/env'; 3 | 4 | test('method `getConfig` returns package.json specron configuration', async (t) => { 5 | t.deepEqual(getConfig(), { 6 | name: '', 7 | description: '', 8 | compiler: { 9 | build: './build', 10 | match: ['./src/**/*.sol'], 11 | severities: ['error', 'warning'], 12 | evmVersion: 'istanbul', 13 | clean: true, 14 | }, 15 | flattener: { 16 | build: './build', 17 | match: ['./src/**/*.sol'], 18 | severities: ['error', 'warning'], 19 | }, 20 | settings: { 21 | optimization: 200, 22 | }, 23 | sandbox: { 24 | port: 8545, 25 | ttl: 0, 26 | }, 27 | test: { 28 | server: true, 29 | port: 8545, 30 | match: ['./src/**/*.hay.*'], 31 | blockTime: null, 32 | }, 33 | require: ['ts-node/register'], 34 | }); 35 | }); 36 | 37 | test('method `getConfig` merges received configuration', async (t) => { 38 | t.deepEqual(getConfig({ 39 | match: ['foo'], 40 | port: 100, 41 | require: ['bar'], 42 | blockTime: 1, 43 | optimization: 0, 44 | }), { 45 | name: '', 46 | description: '', 47 | compiler: { 48 | build: './build', 49 | match: ['foo'], 50 | severities: ['error', 'warning'], 51 | evmVersion: 'istanbul', 52 | clean: true, 53 | }, 54 | flattener: { 55 | build: './build', 56 | match: ['foo'], 57 | severities: ['error', 'warning'], 58 | }, 59 | settings: { 60 | optimization: 0, 61 | }, 62 | sandbox: { 63 | port: 100, 64 | ttl: 0, 65 | }, 66 | test: { 67 | server: true, 68 | port: 100, 69 | match: ['foo'], 70 | blockTime: 1, 71 | }, 72 | require: ['bar'], 73 | }); 74 | }); 75 | -------------------------------------------------------------------------------- /packages/specron-cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "sourceMap": true, 8 | "outDir": "dist", 9 | "declaration": true, 10 | "esModuleInterop": true 11 | } 12 | } -------------------------------------------------------------------------------- /packages/specron-compiler/CHANGELOG.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@specron/compiler", 3 | "entries": [ 4 | { 5 | "version": "0.17.6", 6 | "tag": "@specron/compiler_v0.17.6", 7 | "date": "Wed, 04 Aug 2021 13:37:50 GMT", 8 | "comments": {} 9 | }, 10 | { 11 | "version": "0.17.5", 12 | "tag": "@specron/compiler_v0.17.5", 13 | "date": "Wed, 04 Aug 2021 13:37:40 GMT", 14 | "comments": {} 15 | }, 16 | { 17 | "version": "0.17.4", 18 | "tag": "@specron/compiler_v0.17.4", 19 | "date": "Wed, 04 Aug 2021 13:34:22 GMT", 20 | "comments": {} 21 | }, 22 | { 23 | "version": "0.17.3", 24 | "tag": "@specron/compiler_v0.17.3", 25 | "date": "Tue, 12 Jan 2021 14:59:18 GMT", 26 | "comments": {} 27 | }, 28 | { 29 | "version": "0.17.2", 30 | "tag": "@specron/compiler_v0.17.2", 31 | "date": "Tue, 12 Jan 2021 12:34:19 GMT", 32 | "comments": {} 33 | }, 34 | { 35 | "version": "0.17.1", 36 | "tag": "@specron/compiler_v0.17.1", 37 | "date": "Mon, 04 May 2020 11:19:54 GMT", 38 | "comments": {} 39 | }, 40 | { 41 | "version": "0.17.0", 42 | "tag": "@specron/compiler_v0.17.0", 43 | "date": "Mon, 04 May 2020 10:16:53 GMT", 44 | "comments": {} 45 | }, 46 | { 47 | "version": "0.16.0", 48 | "tag": "@specron/compiler_v0.16.0", 49 | "date": "Fri, 07 Feb 2020 11:38:38 GMT", 50 | "comments": {} 51 | }, 52 | { 53 | "version": "0.15.2", 54 | "tag": "@specron/compiler_v0.15.2", 55 | "date": "Fri, 07 Feb 2020 11:38:14 GMT", 56 | "comments": {} 57 | }, 58 | { 59 | "version": "0.15.1", 60 | "tag": "@specron/compiler_v0.15.1", 61 | "date": "Mon, 27 Jan 2020 10:44:17 GMT", 62 | "comments": {} 63 | }, 64 | { 65 | "version": "0.15.0", 66 | "tag": "@specron/compiler_v0.15.0", 67 | "date": "Thu, 16 Jan 2020 09:44:14 GMT", 68 | "comments": {} 69 | }, 70 | { 71 | "version": "0.14.0", 72 | "tag": "@specron/compiler_v0.14.0", 73 | "date": "Thu, 16 Jan 2020 08:27:04 GMT", 74 | "comments": {} 75 | }, 76 | { 77 | "version": "0.13.0", 78 | "tag": "@specron/compiler_v0.13.0", 79 | "date": "Tue, 14 Jan 2020 12:07:56 GMT", 80 | "comments": {} 81 | }, 82 | { 83 | "version": "0.12.0", 84 | "tag": "@specron/compiler_v0.12.0", 85 | "date": "Mon, 13 Jan 2020 09:39:01 GMT", 86 | "comments": {} 87 | }, 88 | { 89 | "version": "0.11.0", 90 | "tag": "@specron/compiler_v0.11.0", 91 | "date": "Tue, 07 Jan 2020 09:53:08 GMT", 92 | "comments": {} 93 | }, 94 | { 95 | "version": "0.10.0", 96 | "tag": "@specron/compiler_v0.10.0", 97 | "date": "Thu, 28 Nov 2019 11:45:10 GMT", 98 | "comments": {} 99 | }, 100 | { 101 | "version": "0.9.0", 102 | "tag": "@specron/compiler_v0.9.0", 103 | "date": "Tue, 01 Oct 2019 18:29:23 GMT", 104 | "comments": {} 105 | }, 106 | { 107 | "version": "0.8.2", 108 | "tag": "@specron/compiler_v0.8.2", 109 | "date": "Tue, 01 Oct 2019 18:27:47 GMT", 110 | "comments": {} 111 | }, 112 | { 113 | "version": "0.8.1", 114 | "tag": "@specron/compiler_v0.8.1", 115 | "date": "Tue, 01 Oct 2019 18:14:09 GMT", 116 | "comments": {} 117 | }, 118 | { 119 | "version": "0.8.0", 120 | "tag": "@specron/compiler_v0.8.0", 121 | "date": "Sun, 29 Sep 2019 22:26:46 GMT", 122 | "comments": {} 123 | }, 124 | { 125 | "version": "0.7.0", 126 | "tag": "@specron/compiler_v0.7.0", 127 | "date": "Tue, 30 Jul 2019 13:07:02 GMT", 128 | "comments": {} 129 | }, 130 | { 131 | "version": "0.5.6", 132 | "tag": "@specron/compiler_v0.5.6", 133 | "date": "Tue, 26 Feb 2019 12:05:55 GMT", 134 | "comments": {} 135 | }, 136 | { 137 | "version": "0.5.5", 138 | "tag": "@specron/compiler_v0.5.5", 139 | "date": "Tue, 26 Feb 2019 11:54:20 GMT", 140 | "comments": {} 141 | } 142 | ] 143 | } 144 | -------------------------------------------------------------------------------- /packages/specron-compiler/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - @specron/compiler 2 | 3 | This log was last generated on Wed, 04 Aug 2021 13:37:50 GMT and should not be manually modified. 4 | 5 | ## 0.17.6 6 | Wed, 04 Aug 2021 13:37:50 GMT 7 | 8 | *Version update only* 9 | 10 | ## 0.17.5 11 | Wed, 04 Aug 2021 13:37:40 GMT 12 | 13 | *Version update only* 14 | 15 | ## 0.17.4 16 | Wed, 04 Aug 2021 13:34:22 GMT 17 | 18 | *Version update only* 19 | 20 | ## 0.17.3 21 | Tue, 12 Jan 2021 14:59:18 GMT 22 | 23 | *Version update only* 24 | 25 | ## 0.17.2 26 | Tue, 12 Jan 2021 12:34:19 GMT 27 | 28 | *Version update only* 29 | 30 | ## 0.17.1 31 | Mon, 04 May 2020 11:19:54 GMT 32 | 33 | *Version update only* 34 | 35 | ## 0.17.0 36 | Mon, 04 May 2020 10:16:53 GMT 37 | 38 | *Version update only* 39 | 40 | ## 0.16.0 41 | Fri, 07 Feb 2020 11:38:38 GMT 42 | 43 | *Version update only* 44 | 45 | ## 0.15.2 46 | Fri, 07 Feb 2020 11:38:14 GMT 47 | 48 | *Version update only* 49 | 50 | ## 0.15.1 51 | Mon, 27 Jan 2020 10:44:17 GMT 52 | 53 | *Version update only* 54 | 55 | ## 0.15.0 56 | Thu, 16 Jan 2020 09:44:14 GMT 57 | 58 | *Version update only* 59 | 60 | ## 0.14.0 61 | Thu, 16 Jan 2020 08:27:04 GMT 62 | 63 | *Version update only* 64 | 65 | ## 0.13.0 66 | Tue, 14 Jan 2020 12:07:56 GMT 67 | 68 | *Version update only* 69 | 70 | ## 0.12.0 71 | Mon, 13 Jan 2020 09:39:01 GMT 72 | 73 | *Version update only* 74 | 75 | ## 0.11.0 76 | Tue, 07 Jan 2020 09:53:08 GMT 77 | 78 | *Version update only* 79 | 80 | ## 0.10.0 81 | Thu, 28 Nov 2019 11:45:10 GMT 82 | 83 | *Version update only* 84 | 85 | ## 0.9.0 86 | Tue, 01 Oct 2019 18:29:23 GMT 87 | 88 | *Version update only* 89 | 90 | ## 0.8.2 91 | Tue, 01 Oct 2019 18:27:47 GMT 92 | 93 | *Version update only* 94 | 95 | ## 0.8.1 96 | Tue, 01 Oct 2019 18:14:09 GMT 97 | 98 | *Version update only* 99 | 100 | ## 0.8.0 101 | Sun, 29 Sep 2019 22:26:46 GMT 102 | 103 | *Version update only* 104 | 105 | ## 0.7.0 106 | Tue, 30 Jul 2019 13:07:02 GMT 107 | 108 | *Version update only* 109 | 110 | ## 0.5.6 111 | Tue, 26 Feb 2019 12:05:55 GMT 112 | 113 | *Version update only* 114 | 115 | ## 0.5.5 116 | Tue, 26 Feb 2019 11:54:20 GMT 117 | 118 | *Initial release* 119 | 120 | -------------------------------------------------------------------------------- /packages/specron-compiler/README.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import { Compiler } from '.'; 3 | 4 | const compiler = new Compiler(); 5 | compiler.source('./src/tests/assets/*.sol'); 6 | compiler.source('./src/tests/assets/*.sol'); 7 | 8 | if (compiler.compile()) { 9 | compiler.save('./build/foo'); 10 | console.log('Done!'); 11 | } else { 12 | console.log('Errors:', JSON.stringify(compiler.output, null, 2)); 13 | } 14 | compiler.clear(); 15 | ``` 16 | -------------------------------------------------------------------------------- /packages/specron-compiler/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": ["dist/*"], 3 | "ext": "js,ts,sol" 4 | } 5 | -------------------------------------------------------------------------------- /packages/specron-compiler/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@specron/compiler", 3 | "version": "0.17.6", 4 | "description": "Solidity contract compiler for Specron framework.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "scripts": { 8 | "build": "npx tsc", 9 | "test": "npx nyc npx ava --verbose" 10 | }, 11 | "ava": { 12 | "concurrency": 1, 13 | "require": [ 14 | "ts-node/register" 15 | ], 16 | "extensions": [ 17 | "ts" 18 | ], 19 | "files": [ 20 | "src/tests/*.test.ts", 21 | "src/tests/**/*.test.ts" 22 | ], 23 | "timeout": "1m" 24 | }, 25 | "nyc": { 26 | "extension": [ 27 | ".ts" 28 | ], 29 | "require": [ 30 | "ts-node/register" 31 | ], 32 | "exclude": [ 33 | "src/tests" 34 | ] 35 | }, 36 | "license": "MIT", 37 | "devDependencies": { 38 | "@0xcert/ethereum-utils-contracts": "2.1.1", 39 | "@types/fs-extra": "9.0.12", 40 | "@types/node": "16.4.11", 41 | "ava": "3.15.0", 42 | "nyc": "15.1.0", 43 | "solc": "0.8.0", 44 | "ts-node": "10.1.0", 45 | "typescript": "4.3.5" 46 | }, 47 | "dependencies": { 48 | "@specron/flattener": "0.17.6", 49 | "@hayspec/reporter": "0.10.2", 50 | "fast-glob": "3.2.7", 51 | "fs-extra": "10.0.0" 52 | }, 53 | "peerDependencies": { 54 | "solc": "*" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/specron-compiler/src/core/compiler.ts: -------------------------------------------------------------------------------- 1 | import * as solc from 'solc'; 2 | import * as fs from 'fs'; 3 | import * as fsx from 'fs-extra'; 4 | import * as pth from 'path'; 5 | import { SolcInput, SolcOutput } from '../lib/solc'; 6 | import { DefaultReporter } from './reporter'; 7 | import { Flattener } from '@specron/flattener'; 8 | 9 | /** 10 | * Solidity compiler configuration object. 11 | */ 12 | export interface CompilerRecipe extends SolcInput { 13 | cwd?: string; 14 | reporter?: DefaultReporter; 15 | } 16 | 17 | /** 18 | * Solidity compiler. 19 | */ 20 | export class Compiler { 21 | protected reporter: DefaultReporter; 22 | public cwd: string; 23 | public input: SolcInput; 24 | public output: SolcOutput = {}; 25 | 26 | /** 27 | * Class constructor. 28 | * @param recipe Compiler configuration object. 29 | */ 30 | public constructor(recipe?: CompilerRecipe) { 31 | this.input = { 32 | sources: { 33 | ...(recipe ? recipe.sources : {}), 34 | }, 35 | language: recipe && recipe.language ? recipe.language : 'Solidity', 36 | settings: { 37 | evmVersion: 'istanbul', 38 | outputSelection: { 39 | '*': { 40 | '*': [ 41 | 'ast', 'abi', 'metadata', 'evm.bytecode.object', 'evm.methodIdentifiers', 42 | ], 43 | }, 44 | }, 45 | ...(recipe ? recipe.settings : {}), 46 | }, 47 | }; 48 | this.cwd = recipe && recipe.cwd ? recipe.cwd : process.cwd(); 49 | this.reporter = recipe && recipe.reporter ? recipe.reporter : null; 50 | } 51 | 52 | /** 53 | * Loads sources by pattern. 54 | * @param patterns File search patterns. 55 | */ 56 | public async source(...patterns: string[]) { 57 | const flattener = new Flattener(); 58 | flattener.source(...patterns); 59 | await flattener.flatten(); 60 | 61 | const keys = Object.keys(flattener.output.sources); 62 | keys.forEach(element => { 63 | this.input.sources[element] = { 64 | content: flattener.output.sources[element] 65 | } 66 | }); 67 | 68 | return keys.length; 69 | } 70 | 71 | /** 72 | * Finds and reads imports. 73 | * @param path Path to file. 74 | */ 75 | public findImports(path) { 76 | path = path.indexOf('./') !== 0 ? `./node_modules/${path}` : path; 77 | return { 78 | contents: fs.readFileSync(path).toString(), 79 | }; 80 | } 81 | 82 | /** 83 | * Compiles the solc input and memorizes the output. 84 | */ 85 | public compile() { 86 | if (this.reporter) { 87 | this.reporter.onCompileStart(this); 88 | } 89 | 90 | const input = JSON.stringify(this.input); 91 | 92 | this.output = JSON.parse( 93 | solc.compile(input, { import: this.findImports }) 94 | ); 95 | 96 | if (this.reporter) { 97 | this.reporter.onCompileEnd(this); 98 | } 99 | 100 | return !Array.isArray(this.output.errors); 101 | } 102 | 103 | /** 104 | * Cleans output of unnecessary contracts. 105 | */ 106 | public clean() { 107 | try { 108 | Object.keys(this.output.contracts || {}).forEach((file) => { 109 | const sourcePath = this.normalizePath(file); 110 | const isModule = sourcePath.indexOf('./node_modules') === 0; 111 | if (isModule) { 112 | return; 113 | } 114 | const matcher = new RegExp('(?<=^contract )(.*?)(?= |{|\n)','gm'); 115 | const contracts = fs.readFileSync(sourcePath).toString().match(matcher); 116 | const json = this.output.contracts[file]; 117 | Object.keys(json).forEach((contract) => { 118 | if (contracts && contracts.indexOf(contract) === -1) { 119 | delete this.output.contracts[file][contract]; 120 | } 121 | }); 122 | }); 123 | } catch {} 124 | } 125 | 126 | /** 127 | * Saves memorized compiler output to destination folder. 128 | * @param dist Destination folder. 129 | */ 130 | public save(dist: string) { 131 | if (this.reporter) { 132 | this.reporter.onSaveStart(this); 133 | } 134 | 135 | const target = pth.resolve(this.cwd, dist); 136 | fsx.ensureDirSync(target); 137 | 138 | let count = 0; 139 | Object.keys(this.output.contracts || {}).forEach((file) => { 140 | const sourcePath = this.normalizePath(file); 141 | 142 | const isModule = sourcePath.indexOf('./node_modules') === 0; 143 | if (isModule) { 144 | return; 145 | } 146 | 147 | const fileName = pth.basename(sourcePath); 148 | const contractName = fileName.split('.').slice(0, -1).join('.'); 149 | const destPath = pth.join(target, `${contractName}.json`); 150 | 151 | const json = this.output.contracts[file]; 152 | Object.keys(json).forEach((contract) => { 153 | if (json[contract].metadata) { 154 | json[contract].metadata = JSON.parse(json[contract].metadata); 155 | } 156 | }); 157 | 158 | const data = JSON.stringify(json, null, 2); 159 | fs.writeFileSync(destPath, data); 160 | 161 | count++; 162 | }); 163 | 164 | if (this.reporter) { 165 | this.reporter.onSaveEnd(this); 166 | } 167 | 168 | return count; 169 | } 170 | 171 | /** 172 | * Reinitializes the class. 173 | */ 174 | public clear() { 175 | this.output = {}; 176 | return this; 177 | } 178 | 179 | /** 180 | * Converts a file path not starting with a dot to match node_modules. 181 | * @param path File path. 182 | */ 183 | protected normalizePath(path: string) { 184 | return path.indexOf('./') !== 0 ? `./node_modules/${path}` : path; 185 | } 186 | 187 | } 188 | -------------------------------------------------------------------------------- /packages/specron-compiler/src/core/reporter.ts: -------------------------------------------------------------------------------- 1 | import { Printer } from '@hayspec/reporter'; 2 | import { Compiler } from './compiler'; 3 | 4 | /** 5 | * 6 | */ 7 | export type Severity = 'error' | 'warning'; 8 | 9 | /** 10 | * 11 | */ 12 | export class DefaultReporter { 13 | protected printer: Printer; 14 | protected severities: Severity[]; 15 | public constructor(severities?: Severity[]) { 16 | this.printer = new Printer(); 17 | this.severities = severities || ['error', 'warning']; 18 | } 19 | 20 | /** 21 | * 22 | */ 23 | public onCompileStart(compiler: Compiler) { 24 | this.printer.end(''); 25 | } 26 | 27 | /** 28 | * 29 | */ 30 | public onCompileEnd(compiler: Compiler) { 31 | if (compiler.output.errors) { 32 | this.onErrors(compiler); 33 | } 34 | } 35 | 36 | /** 37 | * 38 | */ 39 | public onSaveStart(compiler: Compiler) { 40 | if (!compiler.output.errors) { 41 | this.onContracts(compiler); 42 | } 43 | } 44 | 45 | /** 46 | * 47 | */ 48 | public onSaveEnd(compiler: Compiler) { 49 | this.onOverview(compiler); 50 | this.printer.end(''); 51 | } 52 | 53 | /** 54 | * 55 | */ 56 | protected onErrors(compiler: Compiler) { 57 | 58 | this.severities.forEach((severity) => { 59 | const failures = compiler.output.errors 60 | .filter((e) => e.severity === severity); 61 | 62 | if (failures.length) { 63 | this.printer.end( 64 | this.printer.indent(1, ''), 65 | severity === 'error' ? 'Errors' : 'Warnings' 66 | ); 67 | 68 | failures.filter((e) => e.formattedMessage).forEach((failure) => { 69 | const color = this.getErrorColor(failure); 70 | this.printer.end( 71 | this.printer.indent(2, ''), 72 | this.printer.colorize(color, failure.formattedMessage.trim()) 73 | ); 74 | }); 75 | } 76 | }); 77 | } 78 | 79 | /** 80 | * 81 | */ 82 | protected onContracts(compiler: Compiler) { 83 | const contracts = Object.keys(compiler.output.contracts || {}); 84 | 85 | if (contracts.length) { 86 | this.printer.end( 87 | this.printer.indent(1, ''), 88 | 'Contracts' 89 | ); 90 | contracts.forEach((contract) => { 91 | this.printer.end( 92 | this.printer.indent(2, ''), 93 | this.printer.colorize('gray', contract) 94 | ); 95 | }); 96 | } 97 | } 98 | 99 | /** 100 | * 101 | */ 102 | protected onOverview(compiler: Compiler) { 103 | this.printer.end(); 104 | 105 | const messages = []; 106 | 107 | const contracts = Object.keys(compiler.output.contracts || {}).length; 108 | if (contracts) { 109 | messages.push( 110 | this.printer.indent(1, ''), 111 | this.printer.colorize('greenBright', contracts), 112 | ' contracts', 113 | ); 114 | } 115 | 116 | if (this.severities.indexOf('error') !== -1) { 117 | const errors = (compiler.output.errors || []).filter((e) => e.severity === 'error').length; 118 | 119 | if (errors) { 120 | messages.push( 121 | this.printer.indent(1, ''), 122 | this.printer.colorize('redBright', errors), 123 | ' errors', 124 | ); 125 | } 126 | } 127 | 128 | if (this.severities.indexOf('warning') !== -1) { 129 | const warnings = (compiler.output.errors || []).filter((e) => e.severity === 'warning').length; 130 | 131 | if (warnings) { 132 | messages.push( 133 | this.printer.indent(1, ''), 134 | this.printer.colorize('yellowBright', warnings), 135 | ' warnings', 136 | ); 137 | } 138 | } 139 | if (messages.length) { 140 | this.printer.end(...messages); 141 | } 142 | } 143 | 144 | /** 145 | * 146 | */ 147 | protected getErrorColor(error: any) { 148 | if (error.severity === 'error') { 149 | return 'redBright'; 150 | } else { 151 | return 'yellowBright'; 152 | } 153 | } 154 | } 155 | 156 | 157 | -------------------------------------------------------------------------------- /packages/specron-compiler/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './core/compiler'; 2 | export * from './core/reporter'; 3 | export * from './lib/solc'; 4 | -------------------------------------------------------------------------------- /packages/specron-compiler/src/lib/solc.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Solc compiler configuration input. 3 | * @see http://solidity.readthedocs.io/en/v0.5.11/using-the-compiler.html 4 | */ 5 | export interface SolcInput { 6 | // Source code language. 7 | language?: 'Solidity' | 'Yul'; 8 | // Source. 9 | sources?: { 10 | [file: string]: { 11 | // Hash of the source file. 12 | keccak256?: string; 13 | // Source file URL. 14 | urls?: string[]; 15 | // Source code. 16 | content?: string; 17 | }; 18 | }; 19 | // Compiler options. 20 | settings?: { 21 | // Sorted list of remappings 22 | remappings?: string[]; 23 | // Optimizer settings (enabled defaults to false) 24 | optimizer?: { 25 | // Disabled by default 26 | enabled?: boolean; 27 | // Lower values will optimize more. 28 | runs?: number; 29 | // Switch optimizer components on or off in detail. 30 | details?: { 31 | // The peephole optimizer is always on if no details are given. 32 | peephole?: boolean; 33 | // The unused jumpdest remover is always on if no details. 34 | jumpdestRemover?: boolean; 35 | // Sometimes re-orders literals in commutative operations. 36 | orderLiterals?: boolean; 37 | // Removes duplicate code blocks. 38 | deduplicate?: boolean; 39 | // Common subexpression elimination. 40 | cse?: boolean; 41 | // Optimize representation of literal numbers and strings in code. 42 | constantOptimizer?: boolean; 43 | // The new Yul optimizer. 44 | yul?: boolean, 45 | // Tuning options for the Yul optimizer. 46 | yulDetails?: { 47 | // Improve allocation of stack slots for variables. 48 | stackAllocation?: boolean; 49 | }; 50 | }; 51 | }; 52 | // Version of the EVM to compile for. Affects type checking and code generation. 53 | evmVersion?: 'homestead' | 'tangerineWhistle' | 'spuriousDragon' | 'byzantium' | 'constantinople' | 'petersburg' | 'istanbul' | 'berlin'; 54 | // Metadata settings (optional) 55 | metadata?: { 56 | // Use only literal content and not URLs (false by default) 57 | useLiteralContent?: boolean; 58 | }; 59 | // Addresses of the libraries. If not all libraries are given here, it can result in unlinked objects whose output data is different. 60 | libraries?: { 61 | [file: string]: { 62 | [contract: string]: string; 63 | }; 64 | }; 65 | // The available output types. 66 | outputSelection?: { 67 | [file: string]: { 68 | [contract: string]: ( 69 | 'ast' | 'legacyAST' | 'abi' | 'devdoc' | 'userdoc' | 'metadata' 70 | | 'ir' | 'irOptimized' | 'evm.assembly' | 'evm.legacyAssembly' 71 | | 'evm.bytecode.object' | 'evm.bytecode.opcodes' 72 | | 'evm.bytecode.sourceMap' | 'evm.bytecode.linkReferences' 73 | | 'evm.deployedBytecode*' | 'evm.methodIdentifiers' 74 | | 'evm.gasEstimates' 75 | // | 'ewasm.wast' | 'ewasm.wasm' (not implemented) 76 | )[]; 77 | }; 78 | }; 79 | }; 80 | }; 81 | 82 | /** 83 | * Solc compiler output object. 84 | * @see http://solidity.readthedocs.io/en/v0.4.31/using-the-compiler.html 85 | */ 86 | export interface SolcOutput { 87 | // Optional: not present if no errors/warnings were encountered 88 | errors?: { 89 | // Optional: Location within the source file. 90 | sourceLocation?: { 91 | file: string; 92 | start: number; 93 | end: number; 94 | }; 95 | // Optional: Further locations (e.g. places of conflicting declarations) 96 | secondarySourceLocations?: { 97 | file: string; 98 | start: number; 99 | end: number; 100 | message: string; 101 | }[], 102 | // Error type. 103 | type: 'TypeError' | 'InternalCompilerError' | 'Exception'; 104 | // Component where the error originated. 105 | component: 'general' | 'ewasm'; 106 | // Severity level. 107 | severity: 'error' | 'warning'; 108 | // Error message. 109 | message: string; 110 | // Message formatted with source location. 111 | formattedMessage?: string; 112 | }[]; 113 | // This contains the file-level outputs. In can be limited/filtered by the outputSelection settings. 114 | sources?: { 115 | [file: string]: { 116 | // Identifier (used in source maps). 117 | id: number; 118 | // The AST object. 119 | ast: any; 120 | // The legacy AST object. 121 | legacyAST: any; 122 | }; 123 | }; 124 | // This contains the contract-level outputs. It can be limited/filtered by the outputSelection settings. 125 | contracts?: { 126 | [file: string]: { 127 | // If the language used has no contract names, this field should equal to an empty string. 128 | [contract: string]: { 129 | // The Ethereum Contract ABI. If empty, it is represented as an empty array. 130 | // See https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI 131 | abi: any[], 132 | // See the Metadata Output documentation (serialised JSON string). 133 | metadata: string; 134 | // User documentation (natspec). 135 | userdoc: any; 136 | // Developer documentation (natspec). 137 | devdoc: any; 138 | // Intermediate representation (string). 139 | ir: string; 140 | // EVM-related outputs. 141 | evm: { 142 | // Assembly (string). 143 | assembly: string; 144 | // Old-style assembly (object). 145 | legacyAssembly?: any; 146 | // Bytecode and related details. 147 | bytecode?: { 148 | // The bytecode as a hex string. 149 | object: string; 150 | // Opcodes list (string) 151 | opcodes: string; 152 | // The source mapping as a string. See the source mapping definition. 153 | sourceMap: string; 154 | // If given, this is an unlinked object. 155 | linkReferences: { 156 | [file: string]: { 157 | [lib: string]: { 158 | start: number; 159 | length: number; 160 | }[]; 161 | }; 162 | }; 163 | }; 164 | // The same layout as above. 165 | deployedBytecode?: { 166 | // The bytecode as a hex string. 167 | object: string; 168 | // Opcodes list (string) 169 | opcodes: string; 170 | // The source mapping as a string. See the source mapping definition. 171 | sourceMap: string; 172 | // If given, this is an unlinked object. 173 | linkReferences: { 174 | [file: string]: { 175 | [lib: string]: { 176 | start: number; 177 | length: number; 178 | }[]; 179 | }; 180 | }; 181 | }; 182 | // The list of function hashes 183 | methodIdentifiers?: { 184 | [fn: string]: string; 185 | }; 186 | // Function gas estimates. 187 | gasEstimates?: { 188 | creation?: { 189 | codeDepositCost: string; 190 | executionCost: string; 191 | totalCost: string; 192 | }; 193 | external?: { 194 | [fn: string]: string; 195 | }; 196 | internal?: { 197 | [fn: string]: string; 198 | }; 199 | }; 200 | }; 201 | // eWASM related outputs. 202 | ewasm?: { 203 | // S-expressions format. 204 | wast?: string; 205 | // Binary format (hex string). 206 | wasm?: string; 207 | }; 208 | }; 209 | }; 210 | }; 211 | } 212 | -------------------------------------------------------------------------------- /packages/specron-compiler/src/tests/assets/foo.js: -------------------------------------------------------------------------------- 1 | // fake file -------------------------------------------------------------------------------- /packages/specron-compiler/src/tests/assets/interface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.0; 2 | 3 | interface Token { 4 | function test() external; 5 | } -------------------------------------------------------------------------------- /packages/specron-compiler/src/tests/assets/token-a.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.0; 2 | 3 | import "./token-b.sol"; 4 | 5 | /** 6 | * Overriding contract. 7 | */ 8 | contract Token1 is Token2 {} // This contract overrides token b 9 | -------------------------------------------------------------------------------- /packages/specron-compiler/src/tests/assets/token-b.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.0; 2 | 3 | import "@0xcert/ethereum-utils-contracts/src/contracts/utils/address-utils.sol"; 4 | 5 | contract Token2 { 6 | 7 | /** 8 | * @dev Returns fake value. 9 | * @param _value Multiploer value. 10 | */ 11 | function test () 12 | public 13 | pure 14 | returns (uint256 _value) 15 | { 16 | uint256 a = 123456; 17 | uint256 b = a + 1; 18 | _value = b; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /packages/specron-compiler/src/tests/assets/token-c.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.0; 2 | 3 | contract Main { 4 | 5 | function test() 6 | public 7 | pure 8 | returns (uint256 _value) 9 | { 10 | _value = 100; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /packages/specron-compiler/src/tests/compiler.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import * as glob from 'fast-glob'; 3 | import { Compiler } from '..'; 4 | 5 | test('adds new source files', async (t) => { 6 | const compiler = new Compiler(); 7 | await compiler.source('./src/tests/assets/*.sol'); 8 | const files = Object.keys(compiler.input.sources); 9 | t.deepEqual(files, [ 10 | './src/tests/assets/interface.sol', 11 | './src/tests/assets/token-a.sol', 12 | './src/tests/assets/token-b.sol', 13 | './src/tests/assets/token-c.sol', 14 | ]); 15 | }); 16 | 17 | test('compiles source files', async (t) => { 18 | const compiler = new Compiler(); 19 | await compiler.source('./src/tests/assets/*.sol'); 20 | await compiler.compile(); 21 | const contracts = Object.keys(compiler.output.contracts); 22 | t.deepEqual(contracts, [ 23 | './src/tests/assets/interface.sol', 24 | './src/tests/assets/token-a.sol', 25 | './src/tests/assets/token-b.sol', 26 | './src/tests/assets/token-c.sol', 27 | ]); 28 | }); 29 | 30 | test('cleans compiled output', async (t) => { 31 | const compiler = new Compiler(); 32 | await compiler.source('./src/tests/assets/*.sol'); 33 | await compiler.compile(); 34 | compiler.clean(); 35 | Object.keys(compiler.output.contracts).forEach((element) => { 36 | t.is(Object.keys(compiler.output.contracts[element]).length, 1); 37 | }); 38 | }); 39 | 40 | test('saves compiled sources to destination', async (t) => { 41 | const compiler = new Compiler(); 42 | await compiler.source('./src/tests/assets/*.sol'); 43 | await compiler.compile(); 44 | compiler.save('./build/foo'); 45 | const files = glob.sync('./build/foo/*.json') as string[]; 46 | t.deepEqual(files, [ 47 | './build/foo/interface.json', 48 | './build/foo/token-a.json', 49 | './build/foo/token-b.json', 50 | './build/foo/token-c.json', 51 | ]); 52 | }); 53 | -------------------------------------------------------------------------------- /packages/specron-compiler/src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import * as compiler from '..'; 3 | 4 | test('exposes Compiler class', async (t) => { 5 | t.is(!!compiler.Compiler, true); 6 | }); 7 | -------------------------------------------------------------------------------- /packages/specron-compiler/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "sourceMap": true, 8 | "outDir": "dist", 9 | "declaration": true 10 | } 11 | } -------------------------------------------------------------------------------- /packages/specron-flattener/CHANGELOG.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@specron/flattener", 3 | "entries": [ 4 | { 5 | "version": "0.17.6", 6 | "tag": "@specron/flattener_v0.17.6", 7 | "date": "Wed, 04 Aug 2021 13:37:50 GMT", 8 | "comments": {} 9 | }, 10 | { 11 | "version": "0.17.5", 12 | "tag": "@specron/flattener_v0.17.5", 13 | "date": "Wed, 04 Aug 2021 13:37:40 GMT", 14 | "comments": {} 15 | }, 16 | { 17 | "version": "0.17.4", 18 | "tag": "@specron/flattener_v0.17.4", 19 | "date": "Wed, 04 Aug 2021 13:34:22 GMT", 20 | "comments": {} 21 | }, 22 | { 23 | "version": "0.17.3", 24 | "tag": "@specron/flattener_v0.17.3", 25 | "date": "Tue, 12 Jan 2021 14:59:18 GMT", 26 | "comments": {} 27 | }, 28 | { 29 | "version": "0.17.2", 30 | "tag": "@specron/flattener_v0.17.2", 31 | "date": "Tue, 12 Jan 2021 12:34:19 GMT", 32 | "comments": {} 33 | }, 34 | { 35 | "version": "0.17.1", 36 | "tag": "@specron/flattener_v0.17.1", 37 | "date": "Mon, 04 May 2020 11:19:54 GMT", 38 | "comments": {} 39 | }, 40 | { 41 | "version": "0.17.0", 42 | "tag": "@specron/flattener_v0.17.0", 43 | "date": "Mon, 04 May 2020 10:16:53 GMT", 44 | "comments": {} 45 | }, 46 | { 47 | "version": "0.16.0", 48 | "tag": "@specron/flattener_v0.16.0", 49 | "date": "Fri, 07 Feb 2020 11:38:38 GMT", 50 | "comments": {} 51 | }, 52 | { 53 | "version": "0.15.2", 54 | "tag": "@specron/flattener_v0.15.2", 55 | "date": "Fri, 07 Feb 2020 11:38:14 GMT", 56 | "comments": {} 57 | }, 58 | { 59 | "version": "0.15.1", 60 | "tag": "@specron/flattener_v0.15.1", 61 | "date": "Mon, 27 Jan 2020 10:44:17 GMT", 62 | "comments": {} 63 | }, 64 | { 65 | "version": "0.15.0", 66 | "tag": "@specron/flattener_v0.15.0", 67 | "date": "Thu, 16 Jan 2020 09:44:14 GMT", 68 | "comments": {} 69 | }, 70 | { 71 | "version": "0.14.0", 72 | "tag": "@specron/flattener_v0.14.0", 73 | "date": "Thu, 16 Jan 2020 08:27:04 GMT", 74 | "comments": {} 75 | }, 76 | { 77 | "version": "0.13.0", 78 | "tag": "@specron/flattener_v0.13.0", 79 | "date": "Tue, 14 Jan 2020 12:07:56 GMT", 80 | "comments": {} 81 | }, 82 | { 83 | "version": "0.12.0", 84 | "tag": "@specron/flattener_v0.12.0", 85 | "date": "Mon, 13 Jan 2020 09:39:01 GMT", 86 | "comments": {} 87 | }, 88 | { 89 | "version": "0.11.0", 90 | "tag": "@specron/flattener_v0.11.0", 91 | "date": "Tue, 07 Jan 2020 09:53:08 GMT", 92 | "comments": {} 93 | }, 94 | { 95 | "version": "0.10.0", 96 | "tag": "@specron/flattener_v0.10.0", 97 | "date": "Thu, 28 Nov 2019 11:45:10 GMT", 98 | "comments": {} 99 | }, 100 | { 101 | "version": "0.9.0", 102 | "tag": "@specron/flattener_v0.9.0", 103 | "date": "Tue, 01 Oct 2019 18:29:23 GMT", 104 | "comments": {} 105 | }, 106 | { 107 | "version": "0.8.2", 108 | "tag": "@specron/flattener_v0.8.2", 109 | "date": "Tue, 01 Oct 2019 18:27:47 GMT", 110 | "comments": {} 111 | }, 112 | { 113 | "version": "0.8.1", 114 | "tag": "@specron/flattener_v0.8.1", 115 | "date": "Tue, 01 Oct 2019 18:14:09 GMT", 116 | "comments": {} 117 | }, 118 | { 119 | "version": "0.8.0", 120 | "tag": "@specron/flattener_v0.8.0", 121 | "date": "Sun, 29 Sep 2019 22:26:46 GMT", 122 | "comments": {} 123 | }, 124 | { 125 | "version": "0.7.0", 126 | "tag": "@specron/flattener_v0.7.0", 127 | "date": "Tue, 30 Jul 2019 13:07:02 GMT", 128 | "comments": {} 129 | }, 130 | { 131 | "version": "0.5.6", 132 | "tag": "@specron/flattener_v0.5.6", 133 | "date": "Tue, 26 Feb 2019 12:05:55 GMT", 134 | "comments": {} 135 | }, 136 | { 137 | "version": "0.5.5", 138 | "tag": "@specron/flattener_v0.5.5", 139 | "date": "Tue, 26 Feb 2019 11:54:20 GMT", 140 | "comments": {} 141 | } 142 | ] 143 | } 144 | -------------------------------------------------------------------------------- /packages/specron-flattener/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - @specron/flattener 2 | 3 | This log was last generated on Wed, 04 Aug 2021 13:37:50 GMT and should not be manually modified. 4 | 5 | ## 0.17.6 6 | Wed, 04 Aug 2021 13:37:50 GMT 7 | 8 | *Version update only* 9 | 10 | ## 0.17.5 11 | Wed, 04 Aug 2021 13:37:40 GMT 12 | 13 | *Version update only* 14 | 15 | ## 0.17.4 16 | Wed, 04 Aug 2021 13:34:22 GMT 17 | 18 | *Version update only* 19 | 20 | ## 0.17.3 21 | Tue, 12 Jan 2021 14:59:18 GMT 22 | 23 | *Version update only* 24 | 25 | ## 0.17.2 26 | Tue, 12 Jan 2021 12:34:19 GMT 27 | 28 | *Version update only* 29 | 30 | ## 0.17.1 31 | Mon, 04 May 2020 11:19:54 GMT 32 | 33 | *Version update only* 34 | 35 | ## 0.17.0 36 | Mon, 04 May 2020 10:16:53 GMT 37 | 38 | *Version update only* 39 | 40 | ## 0.16.0 41 | Fri, 07 Feb 2020 11:38:38 GMT 42 | 43 | *Version update only* 44 | 45 | ## 0.15.2 46 | Fri, 07 Feb 2020 11:38:14 GMT 47 | 48 | *Version update only* 49 | 50 | ## 0.15.1 51 | Mon, 27 Jan 2020 10:44:17 GMT 52 | 53 | *Version update only* 54 | 55 | ## 0.15.0 56 | Thu, 16 Jan 2020 09:44:14 GMT 57 | 58 | *Version update only* 59 | 60 | ## 0.14.0 61 | Thu, 16 Jan 2020 08:27:04 GMT 62 | 63 | *Version update only* 64 | 65 | ## 0.13.0 66 | Tue, 14 Jan 2020 12:07:56 GMT 67 | 68 | *Version update only* 69 | 70 | ## 0.12.0 71 | Mon, 13 Jan 2020 09:39:01 GMT 72 | 73 | *Version update only* 74 | 75 | ## 0.11.0 76 | Tue, 07 Jan 2020 09:53:08 GMT 77 | 78 | *Version update only* 79 | 80 | ## 0.10.0 81 | Thu, 28 Nov 2019 11:45:10 GMT 82 | 83 | *Version update only* 84 | 85 | ## 0.9.0 86 | Tue, 01 Oct 2019 18:29:23 GMT 87 | 88 | *Version update only* 89 | 90 | ## 0.8.2 91 | Tue, 01 Oct 2019 18:27:47 GMT 92 | 93 | *Version update only* 94 | 95 | ## 0.8.1 96 | Tue, 01 Oct 2019 18:14:09 GMT 97 | 98 | *Version update only* 99 | 100 | ## 0.8.0 101 | Sun, 29 Sep 2019 22:26:46 GMT 102 | 103 | *Version update only* 104 | 105 | ## 0.7.0 106 | Tue, 30 Jul 2019 13:07:02 GMT 107 | 108 | *Version update only* 109 | 110 | ## 0.5.6 111 | Tue, 26 Feb 2019 12:05:55 GMT 112 | 113 | *Version update only* 114 | 115 | ## 0.5.5 116 | Tue, 26 Feb 2019 11:54:20 GMT 117 | 118 | *Initial release* 119 | 120 | -------------------------------------------------------------------------------- /packages/specron-flattener/README.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import { Flattener } from '.'; 3 | 4 | const flattener = new Flattener(); 5 | flattener.source('./src/tests/assets/*.sol'); 6 | flattener.source('./src/tests/assets/*.sol'); 7 | 8 | if (await flattener.flatten()) { 9 | flattener.save('./build/foo'); 10 | console.log('Done!'); 11 | } else { 12 | console.log('Errors:', JSON.stringify(compiler.output, null, 2)); 13 | } 14 | flattener.clear(); 15 | ``` 16 | -------------------------------------------------------------------------------- /packages/specron-flattener/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": ["dist/*"], 3 | "ext": "js,ts" 4 | } 5 | -------------------------------------------------------------------------------- /packages/specron-flattener/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@specron/flattener", 3 | "version": "0.17.6", 4 | "description": "Solidity files flattener for Specron framework.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "scripts": { 8 | "build": "npx tsc", 9 | "test": "npx nyc npx ava --verbose" 10 | }, 11 | "ava": { 12 | "concurrency": 1, 13 | "require": [ 14 | "ts-node/register" 15 | ], 16 | "extensions": [ 17 | "ts" 18 | ], 19 | "files": [ 20 | "src/tests/*.test.ts", 21 | "src/tests/**/*.test.ts" 22 | ], 23 | "timeout": "1m" 24 | }, 25 | "nyc": { 26 | "extension": [ 27 | ".ts" 28 | ], 29 | "require": [ 30 | "ts-node/register" 31 | ], 32 | "exclude": [ 33 | "src/tests" 34 | ] 35 | }, 36 | "license": "MIT", 37 | "devDependencies": { 38 | "@0xcert/ethereum-utils-contracts": "2.1.1", 39 | "@types/node": "16.4.11", 40 | "ava": "3.15.0", 41 | "nyc": "15.1.0", 42 | "ts-node": "10.1.0", 43 | "typescript": "4.3.5" 44 | }, 45 | "dependencies": { 46 | "@hayspec/reporter": "0.10.2", 47 | "fast-glob": "3.2.7", 48 | "sol-merger": "3.1.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/specron-flattener/src/core/flattener.ts: -------------------------------------------------------------------------------- 1 | import * as glob from 'fast-glob'; 2 | import { merge } from 'sol-merger'; 3 | import * as fs from 'fs'; 4 | import * as pth from 'path'; 5 | import * as fsx from 'fs-extra'; 6 | import { DefaultReporter } from './reporter'; 7 | 8 | /** 9 | * Initializer config recipe. 10 | */ 11 | export interface FlattenerRecipe { 12 | cwd?: string; 13 | reporter?: DefaultReporter; 14 | } 15 | 16 | /** 17 | * Initializer config recipe. 18 | */ 19 | export interface FlattenerOutput { 20 | sources: {[key: string]: string}; 21 | errors: any[]; 22 | } 23 | 24 | /** 25 | * Solidity files flattner. 26 | */ 27 | export class Flattener { 28 | protected reporter: DefaultReporter; 29 | public cwd: string; 30 | public sources: string[] = []; 31 | readonly output: FlattenerOutput; 32 | protected SPDX_COMMENT_REGEX = /SPDX-License-Identifier: .+/g; 33 | 34 | /** 35 | * Class constructor. 36 | * @param recipe Flattener configuration object. 37 | */ 38 | public constructor(recipe?: FlattenerRecipe) { 39 | this.cwd = recipe && recipe.cwd ? recipe.cwd : process.cwd(); 40 | this.reporter = recipe && recipe.reporter ? recipe.reporter : null; 41 | this.output = { sources: {}, errors: [] }; 42 | } 43 | 44 | /** 45 | * Loads sources by pattern. 46 | * @param patterns File search patterns. 47 | */ 48 | public source(...patterns: string[]) { 49 | const sources = glob.sync(patterns, { cwd: this.cwd }) 50 | .map((f) => f.toString()) 51 | .map((f) => this.normalizePath(f)); 52 | 53 | this.sources.push(...sources); 54 | 55 | return sources.length; 56 | } 57 | 58 | /** 59 | * Merges imports for all the sources and memorizes the output. 60 | */ 61 | public async flatten() { 62 | if (this.reporter) { 63 | this.reporter.onCompileStart(this); 64 | } 65 | 66 | this.output.errors = []; 67 | 68 | for (const source of this.sources) { 69 | let running = true; 70 | 71 | while(running) { 72 | await merge(source).then((c) => { 73 | const spdxs = c.match(this.SPDX_COMMENT_REGEX); 74 | if (spdxs && spdxs.length > 0) { 75 | c = c.replace(this.SPDX_COMMENT_REGEX, ''); 76 | c = `// ${spdxs[0]}\n${c}`; 77 | } 78 | this.output.sources[source] = c; 79 | running = false; 80 | }).catch((e) => { 81 | this.output.errors.push(e); 82 | running = false; 83 | }); 84 | } 85 | } 86 | 87 | if (this.reporter) { 88 | this.reporter.onCompileEnd(this); 89 | } 90 | 91 | return !!this.output.errors.length; 92 | } 93 | 94 | /** 95 | * Saves memorized outputs to destination folder. 96 | * @param dist Destination folder. 97 | */ 98 | public save(dist: string) { 99 | if (this.reporter) { 100 | this.reporter.onSaveStart(this); 101 | } 102 | 103 | const target = pth.resolve(this.cwd, dist); 104 | fsx.ensureDirSync(target); 105 | 106 | let count = 0; 107 | (this.sources || []).forEach((source) => { 108 | const fileName = pth.basename(source); 109 | const destPath = pth.join(target, fileName); 110 | const content = this.output.sources[source]; 111 | 112 | fs.writeFileSync(destPath, content); 113 | 114 | count++; 115 | }); 116 | 117 | if (this.reporter) { 118 | this.reporter.onSaveEnd(this); 119 | } 120 | 121 | return count; 122 | } 123 | 124 | /** 125 | * Reinitializes the class. 126 | */ 127 | public clear() { 128 | this.sources = []; 129 | return this; 130 | } 131 | 132 | /** 133 | * Converts a file path not starting with a dot to match node_modules. 134 | * @param path File path. 135 | */ 136 | protected normalizePath(path: string) { 137 | return path.indexOf('./') !== 0 ? `./node_modules/${path}` : path; 138 | } 139 | 140 | } -------------------------------------------------------------------------------- /packages/specron-flattener/src/core/reporter.ts: -------------------------------------------------------------------------------- 1 | import { Printer } from '@hayspec/reporter'; 2 | import { Flattener } from './flattener'; 3 | 4 | /** 5 | * 6 | */ 7 | export type Severity = 'error' | 'warning'; 8 | 9 | /** 10 | * 11 | */ 12 | export class DefaultReporter { 13 | protected printer: Printer; 14 | protected severities: Severity[]; 15 | public constructor(severities?: Severity[]) { 16 | this.printer = new Printer(); 17 | this.severities = severities || ['error', 'warning']; 18 | } 19 | 20 | /** 21 | * 22 | */ 23 | public onCompileStart(flattener: Flattener) { 24 | this.printer.end(''); 25 | } 26 | 27 | /** 28 | * 29 | */ 30 | public onCompileEnd(flattener: Flattener) { 31 | if (flattener.output.errors.length) { 32 | this.onErrors(flattener); 33 | } 34 | } 35 | 36 | /** 37 | * 38 | */ 39 | public onSaveStart(flattener: Flattener) { 40 | if (!flattener.output.errors.length) { 41 | this.onContracts(flattener); 42 | } 43 | } 44 | 45 | /** 46 | * 47 | */ 48 | public onSaveEnd(flattener: Flattener) { 49 | this.onOverview(flattener); 50 | this.printer.end(''); 51 | } 52 | 53 | /** 54 | * 55 | */ 56 | protected onErrors(flattener: Flattener) { 57 | 58 | const failures = flattener.output.errors; 59 | 60 | if (failures.length) { 61 | this.printer.end( 62 | this.printer.indent(1, ''), 63 | 'Errors', 64 | ); 65 | 66 | failures.filter((e) => !!e.message).forEach((failure) => { 67 | const color = this.getErrorColor(failure); 68 | this.printer.end( 69 | this.printer.indent(2, ''), 70 | this.printer.colorize(color, failure.message.trim()) 71 | ); 72 | }); 73 | } 74 | } 75 | 76 | /** 77 | * 78 | */ 79 | protected onContracts(flattener: Flattener) { 80 | const contracts = flattener.sources; 81 | 82 | if (contracts.length) { 83 | this.printer.end( 84 | this.printer.indent(1, ''), 85 | 'Contracts' 86 | ); 87 | contracts.forEach((contract) => { 88 | this.printer.end( 89 | this.printer.indent(2, ''), 90 | this.printer.colorize('gray', contract) 91 | ); 92 | }); 93 | } 94 | } 95 | 96 | /** 97 | * 98 | */ 99 | protected onOverview(flattener: Flattener) { 100 | this.printer.end(); 101 | 102 | const messages = []; 103 | 104 | const contracts = Object.keys(flattener.output.sources).length; 105 | if (contracts) { 106 | messages.push( 107 | this.printer.indent(1, ''), 108 | this.printer.colorize('gray', contracts), 109 | ' contracts', 110 | ); 111 | } 112 | 113 | if (this.severities.indexOf('error') !== -1) { 114 | const errors = (flattener.output.errors || []).length; 115 | 116 | if (errors) { 117 | messages.push( 118 | this.printer.indent(1, ''), 119 | this.printer.colorize('redBright', errors), 120 | ' errors', 121 | ); 122 | } 123 | } 124 | 125 | if (messages.length) { 126 | this.printer.end(...messages); 127 | } 128 | } 129 | 130 | /** 131 | * 132 | */ 133 | protected getErrorColor(error: any) { 134 | if (error.severity === 'error') { 135 | return 'redBright'; 136 | } else { 137 | return 'yellowBright'; 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /packages/specron-flattener/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './core/flattener'; 2 | export * from './core/reporter'; 3 | -------------------------------------------------------------------------------- /packages/specron-flattener/src/tests/assets/token-a.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | 3 | pragma solidity ^0.5.11; 4 | 5 | import "./token-b.sol"; 6 | 7 | contract Token1 is Token2 {} 8 | -------------------------------------------------------------------------------- /packages/specron-flattener/src/tests/assets/token-b.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.5.11; 3 | 4 | import "@0xcert/ethereum-utils-contracts/src/contracts/utils/address-utils.sol"; 5 | 6 | contract Token2 { 7 | 8 | /** 9 | * @dev Returns fake value. 10 | * @param _value Multiploer value. 11 | */ 12 | function test () 13 | public 14 | pure 15 | returns (uint256 _value) 16 | { 17 | uint256 a = 123456; 18 | uint256 b = a + 1; 19 | _value = b; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /packages/specron-flattener/src/tests/assets/token-c.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.11; 2 | 3 | contract Main { 4 | 5 | function test () 6 | public 7 | pure 8 | returns (uint256 _value) 9 | { 10 | _value = 100; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /packages/specron-flattener/src/tests/flattener.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import * as glob from 'fast-glob'; 3 | import { Flattener } from '..'; 4 | 5 | test('adds new source files', (t) => { 6 | const flattener = new Flattener(); 7 | flattener.source('./src/tests/assets/*.sol'); 8 | t.deepEqual(flattener.sources, [ 9 | './src/tests/assets/token-a.sol', 10 | './src/tests/assets/token-b.sol', 11 | './src/tests/assets/token-c.sol', 12 | ]); 13 | }); 14 | 15 | test('flattens source files', async (t) => { 16 | const flattener = new Flattener(); 17 | flattener.source('./src/tests/assets/*.sol'); 18 | await flattener.flatten(); 19 | const files = Object.keys(flattener.output.sources); 20 | t.deepEqual(files, [ 21 | './src/tests/assets/token-a.sol', 22 | './src/tests/assets/token-b.sol', 23 | './src/tests/assets/token-c.sol', 24 | ]); 25 | }); 26 | 27 | test('saves flattened sources to destination', async (t) => { 28 | const flattener = new Flattener(); 29 | flattener.source('./src/tests/assets/*.sol'); 30 | await flattener.flatten(); 31 | flattener.save('./build/bar'); 32 | const files = glob.sync('./build/bar/*.sol') as string[]; 33 | t.deepEqual(files, [ 34 | './build/bar/token-a.sol', 35 | './build/bar/token-b.sol', 36 | './build/bar/token-c.sol', 37 | ]); 38 | }); 39 | -------------------------------------------------------------------------------- /packages/specron-flattener/src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import * as init from '..'; 3 | 4 | test('exposes interface', async (t) => { 5 | t.true(!!init.Flattener); 6 | }); 7 | -------------------------------------------------------------------------------- /packages/specron-flattener/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "sourceMap": true, 8 | "outDir": "dist", 9 | "declaration": true 10 | } 11 | } -------------------------------------------------------------------------------- /packages/specron-init/CHANGELOG.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@specron/init", 3 | "entries": [ 4 | { 5 | "version": "0.17.6", 6 | "tag": "@specron/init_v0.17.6", 7 | "date": "Wed, 04 Aug 2021 13:37:50 GMT", 8 | "comments": {} 9 | }, 10 | { 11 | "version": "0.17.5", 12 | "tag": "@specron/init_v0.17.5", 13 | "date": "Wed, 04 Aug 2021 13:37:40 GMT", 14 | "comments": {} 15 | }, 16 | { 17 | "version": "0.17.4", 18 | "tag": "@specron/init_v0.17.4", 19 | "date": "Wed, 04 Aug 2021 13:34:22 GMT", 20 | "comments": {} 21 | }, 22 | { 23 | "version": "0.17.3", 24 | "tag": "@specron/init_v0.17.3", 25 | "date": "Tue, 12 Jan 2021 14:59:18 GMT", 26 | "comments": {} 27 | }, 28 | { 29 | "version": "0.17.2", 30 | "tag": "@specron/init_v0.17.2", 31 | "date": "Tue, 12 Jan 2021 12:34:19 GMT", 32 | "comments": {} 33 | }, 34 | { 35 | "version": "0.17.1", 36 | "tag": "@specron/init_v0.17.1", 37 | "date": "Mon, 04 May 2020 11:19:54 GMT", 38 | "comments": {} 39 | }, 40 | { 41 | "version": "0.17.0", 42 | "tag": "@specron/init_v0.17.0", 43 | "date": "Mon, 04 May 2020 10:16:53 GMT", 44 | "comments": {} 45 | }, 46 | { 47 | "version": "0.16.0", 48 | "tag": "@specron/init_v0.16.0", 49 | "date": "Fri, 07 Feb 2020 11:38:38 GMT", 50 | "comments": {} 51 | }, 52 | { 53 | "version": "0.15.2", 54 | "tag": "@specron/init_v0.15.2", 55 | "date": "Fri, 07 Feb 2020 11:38:14 GMT", 56 | "comments": {} 57 | }, 58 | { 59 | "version": "0.15.1", 60 | "tag": "@specron/init_v0.15.1", 61 | "date": "Mon, 27 Jan 2020 10:44:17 GMT", 62 | "comments": {} 63 | }, 64 | { 65 | "version": "0.15.0", 66 | "tag": "@specron/init_v0.15.0", 67 | "date": "Thu, 16 Jan 2020 09:44:14 GMT", 68 | "comments": {} 69 | }, 70 | { 71 | "version": "0.14.0", 72 | "tag": "@specron/init_v0.14.0", 73 | "date": "Thu, 16 Jan 2020 08:27:04 GMT", 74 | "comments": {} 75 | }, 76 | { 77 | "version": "0.13.0", 78 | "tag": "@specron/init_v0.13.0", 79 | "date": "Tue, 14 Jan 2020 12:07:56 GMT", 80 | "comments": {} 81 | }, 82 | { 83 | "version": "0.12.0", 84 | "tag": "@specron/init_v0.12.0", 85 | "date": "Mon, 13 Jan 2020 09:39:01 GMT", 86 | "comments": {} 87 | }, 88 | { 89 | "version": "0.11.0", 90 | "tag": "@specron/init_v0.11.0", 91 | "date": "Tue, 07 Jan 2020 09:53:08 GMT", 92 | "comments": {} 93 | }, 94 | { 95 | "version": "0.10.0", 96 | "tag": "@specron/init_v0.10.0", 97 | "date": "Thu, 28 Nov 2019 11:45:10 GMT", 98 | "comments": {} 99 | }, 100 | { 101 | "version": "0.9.0", 102 | "tag": "@specron/init_v0.9.0", 103 | "date": "Tue, 01 Oct 2019 18:29:23 GMT", 104 | "comments": {} 105 | }, 106 | { 107 | "version": "0.8.2", 108 | "tag": "@specron/init_v0.8.2", 109 | "date": "Tue, 01 Oct 2019 18:27:47 GMT", 110 | "comments": {} 111 | }, 112 | { 113 | "version": "0.8.1", 114 | "tag": "@specron/init_v0.8.1", 115 | "date": "Tue, 01 Oct 2019 18:14:09 GMT", 116 | "comments": {} 117 | }, 118 | { 119 | "version": "0.8.0", 120 | "tag": "@specron/init_v0.8.0", 121 | "date": "Sun, 29 Sep 2019 22:26:46 GMT", 122 | "comments": {} 123 | }, 124 | { 125 | "version": "0.7.0", 126 | "tag": "@specron/init_v0.7.0", 127 | "date": "Tue, 30 Jul 2019 13:07:02 GMT", 128 | "comments": {} 129 | }, 130 | { 131 | "version": "0.5.6", 132 | "tag": "@specron/init_v0.5.6", 133 | "date": "Tue, 26 Feb 2019 12:05:55 GMT", 134 | "comments": {} 135 | }, 136 | { 137 | "version": "0.5.5", 138 | "tag": "@specron/init_v0.5.5", 139 | "date": "Tue, 26 Feb 2019 11:54:20 GMT", 140 | "comments": {} 141 | } 142 | ] 143 | } 144 | -------------------------------------------------------------------------------- /packages/specron-init/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - @specron/init 2 | 3 | This log was last generated on Wed, 04 Aug 2021 13:37:50 GMT and should not be manually modified. 4 | 5 | ## 0.17.6 6 | Wed, 04 Aug 2021 13:37:50 GMT 7 | 8 | *Version update only* 9 | 10 | ## 0.17.5 11 | Wed, 04 Aug 2021 13:37:40 GMT 12 | 13 | *Version update only* 14 | 15 | ## 0.17.4 16 | Wed, 04 Aug 2021 13:34:22 GMT 17 | 18 | *Version update only* 19 | 20 | ## 0.17.3 21 | Tue, 12 Jan 2021 14:59:18 GMT 22 | 23 | *Version update only* 24 | 25 | ## 0.17.2 26 | Tue, 12 Jan 2021 12:34:19 GMT 27 | 28 | *Version update only* 29 | 30 | ## 0.17.1 31 | Mon, 04 May 2020 11:19:54 GMT 32 | 33 | *Version update only* 34 | 35 | ## 0.17.0 36 | Mon, 04 May 2020 10:16:53 GMT 37 | 38 | *Version update only* 39 | 40 | ## 0.16.0 41 | Fri, 07 Feb 2020 11:38:38 GMT 42 | 43 | *Version update only* 44 | 45 | ## 0.15.2 46 | Fri, 07 Feb 2020 11:38:14 GMT 47 | 48 | *Version update only* 49 | 50 | ## 0.15.1 51 | Mon, 27 Jan 2020 10:44:17 GMT 52 | 53 | *Version update only* 54 | 55 | ## 0.15.0 56 | Thu, 16 Jan 2020 09:44:14 GMT 57 | 58 | *Version update only* 59 | 60 | ## 0.14.0 61 | Thu, 16 Jan 2020 08:27:04 GMT 62 | 63 | *Version update only* 64 | 65 | ## 0.13.0 66 | Tue, 14 Jan 2020 12:07:56 GMT 67 | 68 | *Version update only* 69 | 70 | ## 0.12.0 71 | Mon, 13 Jan 2020 09:39:01 GMT 72 | 73 | *Version update only* 74 | 75 | ## 0.11.0 76 | Tue, 07 Jan 2020 09:53:08 GMT 77 | 78 | *Version update only* 79 | 80 | ## 0.10.0 81 | Thu, 28 Nov 2019 11:45:10 GMT 82 | 83 | *Version update only* 84 | 85 | ## 0.9.0 86 | Tue, 01 Oct 2019 18:29:23 GMT 87 | 88 | *Version update only* 89 | 90 | ## 0.8.2 91 | Tue, 01 Oct 2019 18:27:47 GMT 92 | 93 | *Version update only* 94 | 95 | ## 0.8.1 96 | Tue, 01 Oct 2019 18:14:09 GMT 97 | 98 | *Version update only* 99 | 100 | ## 0.8.0 101 | Sun, 29 Sep 2019 22:26:46 GMT 102 | 103 | *Version update only* 104 | 105 | ## 0.7.0 106 | Tue, 30 Jul 2019 13:07:02 GMT 107 | 108 | *Version update only* 109 | 110 | ## 0.5.6 111 | Tue, 26 Feb 2019 12:05:55 GMT 112 | 113 | *Version update only* 114 | 115 | ## 0.5.5 116 | Tue, 26 Feb 2019 11:54:20 GMT 117 | 118 | *Initial release* 119 | 120 | -------------------------------------------------------------------------------- /packages/specron-init/README.md: -------------------------------------------------------------------------------- 1 | ```js 2 | 3 | ``` 4 | -------------------------------------------------------------------------------- /packages/specron-init/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": ["dist/*"], 3 | "ext": "js,ts" 4 | } 5 | -------------------------------------------------------------------------------- /packages/specron-init/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@specron/init", 3 | "version": "0.17.6", 4 | "description": "Project generator for Specron framework.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "scripts": { 8 | "build": "npx tsc", 9 | "test": "npx nyc npx ava --verbose" 10 | }, 11 | "ava": { 12 | "concurrency": 1, 13 | "require": [ 14 | "ts-node/register" 15 | ], 16 | "extensions": [ 17 | "ts" 18 | ], 19 | "files": [ 20 | "src/tests/*.test.ts", 21 | "src/tests/**/*.test.ts" 22 | ], 23 | "timeout": "1m" 24 | }, 25 | "nyc": { 26 | "extension": [ 27 | ".ts" 28 | ], 29 | "require": [ 30 | "ts-node/register" 31 | ], 32 | "exclude": [ 33 | "src/tests" 34 | ] 35 | }, 36 | "license": "MIT", 37 | "devDependencies": { 38 | "@types/fs-extra": "9.0.12", 39 | "@types/node": "16.4.11", 40 | "ava": "3.15.0", 41 | "nyc": "15.1.0", 42 | "ts-node": "10.1.0", 43 | "typescript": "4.3.5" 44 | }, 45 | "dependencies": { 46 | "fs-extra": "10.0.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/specron-init/src/core/generator.ts: -------------------------------------------------------------------------------- 1 | import * as fsx from 'fs-extra'; 2 | import * as path from 'path'; 3 | import * as structure from './structure'; 4 | 5 | /** 6 | * Initializer config recipe. 7 | */ 8 | export interface GeneratorRecipe { 9 | root: string; 10 | name: string; 11 | description: string; 12 | } 13 | 14 | /** 15 | * Project structure initializer. 16 | */ 17 | export class Generator { 18 | protected recipe: GeneratorRecipe; 19 | 20 | /** 21 | * Class constructor. 22 | * @param recipe Initializer config recipe. 23 | */ 24 | public constructor (recipe: GeneratorRecipe) { 25 | this.recipe = recipe; 26 | } 27 | 28 | /** 29 | * Creates project files. 30 | */ 31 | public async build () { 32 | for (const file of structure.files) { 33 | const dest = path.resolve(this.recipe.root, ...file.path); 34 | 35 | const dir = path.dirname(dest); 36 | await fsx.ensureDir(dir); 37 | 38 | const src = file.content 39 | .join('\n') 40 | .replace('{{ name }}', this.recipe.name) 41 | .replace('{{ description }}', this.recipe.description); 42 | await fsx.writeFile(dest, src); 43 | } 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /packages/specron-init/src/core/structure.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * File recipe interface. 3 | */ 4 | export interface FileRecipe { 5 | path: string[]; 6 | content: string[]; 7 | } 8 | 9 | /** 10 | * Project files. 11 | */ 12 | export const files = [ 13 | { 14 | path: ['.gitignore'], 15 | content: [ 16 | `.DS_Store`, 17 | `.vscode`, 18 | `node_modules`, 19 | `dist`, 20 | `build`, 21 | ], 22 | }, 23 | { 24 | path: ['.npmignore'], 25 | content: [ 26 | `.DS_Store`, 27 | `.vscode`, 28 | `node_modules`, 29 | ], 30 | }, 31 | { 32 | path: ['package.json'], 33 | content: [ 34 | `{`, 35 | ` "name": "{{ name }}",`, 36 | ` "description": "{{ description }}",`, 37 | ` "version": "0.0.0",`, 38 | ` "scripts": {`, 39 | ` "compile": "specron compile",`, 40 | ` "sandbox": "specron sandbox",`, 41 | ` "prepare": "specron compile",`, 42 | ` "test": "specron compile && specron test"`, 43 | ` },`, 44 | ` "specron": {`, 45 | ` "compiler": {`, 46 | ` "build": "./build",`, 47 | ` "match": [`, 48 | ` "./src/**/*.sol"`, 49 | ` ]`, 50 | ` },`, 51 | ` "test": {`, 52 | ` "match": [`, 53 | ` "./src/**/*.test.*"`, 54 | ` ]`, 55 | ` },`, 56 | ` "require": [`, 57 | ` "ts-node/register"`, 58 | ` ]`, 59 | ` },`, 60 | ` "license": "MIT",`, 61 | ` "dependencies": {`, 62 | ` "@specron/cli": "latest",`, 63 | ` "@specron/spec": "latest",`, 64 | ` "solc": "0.6.1",`, 65 | ` "ts-node": "8.4.1",`, 66 | ` "typescript": "3.6.3",`, 67 | ` "web3": "1.2.0"`, 68 | ` }`, 69 | `}`, 70 | ], 71 | }, 72 | { 73 | path: ['src', 'contracts', 'main.sol'], 74 | content: [ 75 | `pragma solidity ^0.5.11;`, 76 | ``, 77 | `contract Main {`, 78 | ``, 79 | ` function works()`, 80 | ` public`, 81 | ` pure`, 82 | ` returns (uint256 _value)`, 83 | ` {`, 84 | ` _value = 100;`, 85 | ` }`, 86 | ``, 87 | `}`, 88 | ], 89 | }, 90 | { 91 | path: ['src', 'tests', 'main.test.ts'], 92 | content: [ 93 | `import { Spec } from '@specron/spec';`, 94 | ``, 95 | `const spec = new Spec();`, 96 | ``, 97 | `spec.test('returns boolean', async (ctx) => {`, 98 | ` const main = await ctx.deploy({`, 99 | ` src: './build/main.json',`, 100 | ` contract: 'Main',`, 101 | ` });`, 102 | ` const value = await main.instance.methods.works().call();`, 103 | ` ctx.is(value, '100');`, 104 | `});`, 105 | ``, 106 | `export default spec;`, 107 | ], 108 | }, 109 | { 110 | path: ['tsconfig.json'], 111 | content: [ 112 | `{`, 113 | ` "compilerOptions": {`, 114 | ` "module": "commonjs",`, 115 | ` "target": "es6"`, 116 | ` }`, 117 | `}`, 118 | ], 119 | }, 120 | ] as FileRecipe[]; 121 | -------------------------------------------------------------------------------- /packages/specron-init/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './core/generator'; 2 | -------------------------------------------------------------------------------- /packages/specron-init/src/tests/generator.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import * as fsx from 'fs-extra'; 3 | import * as path from 'path'; 4 | import { Generator } from '..'; 5 | 6 | test('builds project structure', async (t) => { 7 | const root = path.join('node_modules', `.test${Date.now()}`); 8 | const generator = new Generator({ 9 | root: root, 10 | name: '18sb3h301', 11 | description: '8f3nh19831', 12 | }); 13 | await generator.build(); 14 | const pkg = path.join(root, 'package.json'); 15 | const src = await fsx.readFile(pkg); 16 | t.is(src.indexOf('"18sb3h301"') !== 0, true); // replaced variable 17 | t.is(src.indexOf('"8f3nh19831"') !== 0, true); // replaced variable 18 | }); 19 | -------------------------------------------------------------------------------- /packages/specron-init/src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import * as init from '..'; 3 | 4 | test('exposes Generator class', async (t) => { 5 | t.true(!!init.Generator); 6 | }); 7 | -------------------------------------------------------------------------------- /packages/specron-init/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "sourceMap": true, 8 | "outDir": "dist", 9 | "declaration": true 10 | } 11 | } -------------------------------------------------------------------------------- /packages/specron-sandbox/CHANGELOG.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@specron/sandbox", 3 | "entries": [ 4 | { 5 | "version": "0.17.6", 6 | "tag": "@specron/sandbox_v0.17.6", 7 | "date": "Wed, 04 Aug 2021 13:37:50 GMT", 8 | "comments": {} 9 | }, 10 | { 11 | "version": "0.17.5", 12 | "tag": "@specron/sandbox_v0.17.5", 13 | "date": "Wed, 04 Aug 2021 13:37:40 GMT", 14 | "comments": {} 15 | }, 16 | { 17 | "version": "0.17.4", 18 | "tag": "@specron/sandbox_v0.17.4", 19 | "date": "Wed, 04 Aug 2021 13:34:22 GMT", 20 | "comments": {} 21 | }, 22 | { 23 | "version": "0.17.3", 24 | "tag": "@specron/sandbox_v0.17.3", 25 | "date": "Tue, 12 Jan 2021 14:59:18 GMT", 26 | "comments": {} 27 | }, 28 | { 29 | "version": "0.17.2", 30 | "tag": "@specron/sandbox_v0.17.2", 31 | "date": "Tue, 12 Jan 2021 12:34:19 GMT", 32 | "comments": {} 33 | }, 34 | { 35 | "version": "0.17.1", 36 | "tag": "@specron/sandbox_v0.17.1", 37 | "date": "Mon, 04 May 2020 11:19:54 GMT", 38 | "comments": {} 39 | }, 40 | { 41 | "version": "0.17.0", 42 | "tag": "@specron/sandbox_v0.17.0", 43 | "date": "Mon, 04 May 2020 10:16:53 GMT", 44 | "comments": {} 45 | }, 46 | { 47 | "version": "0.16.0", 48 | "tag": "@specron/sandbox_v0.16.0", 49 | "date": "Fri, 07 Feb 2020 11:38:38 GMT", 50 | "comments": {} 51 | }, 52 | { 53 | "version": "0.15.2", 54 | "tag": "@specron/sandbox_v0.15.2", 55 | "date": "Fri, 07 Feb 2020 11:38:14 GMT", 56 | "comments": {} 57 | }, 58 | { 59 | "version": "0.15.1", 60 | "tag": "@specron/sandbox_v0.15.1", 61 | "date": "Mon, 27 Jan 2020 10:44:17 GMT", 62 | "comments": {} 63 | }, 64 | { 65 | "version": "0.15.0", 66 | "tag": "@specron/sandbox_v0.15.0", 67 | "date": "Thu, 16 Jan 2020 09:44:14 GMT", 68 | "comments": {} 69 | }, 70 | { 71 | "version": "0.14.0", 72 | "tag": "@specron/sandbox_v0.14.0", 73 | "date": "Thu, 16 Jan 2020 08:27:04 GMT", 74 | "comments": {} 75 | }, 76 | { 77 | "version": "0.13.0", 78 | "tag": "@specron/sandbox_v0.13.0", 79 | "date": "Tue, 14 Jan 2020 12:07:57 GMT", 80 | "comments": {} 81 | }, 82 | { 83 | "version": "0.12.0", 84 | "tag": "@specron/sandbox_v0.12.0", 85 | "date": "Mon, 13 Jan 2020 09:39:01 GMT", 86 | "comments": {} 87 | }, 88 | { 89 | "version": "0.11.0", 90 | "tag": "@specron/sandbox_v0.11.0", 91 | "date": "Tue, 07 Jan 2020 09:53:08 GMT", 92 | "comments": {} 93 | }, 94 | { 95 | "version": "0.10.0", 96 | "tag": "@specron/sandbox_v0.10.0", 97 | "date": "Thu, 28 Nov 2019 11:45:10 GMT", 98 | "comments": {} 99 | }, 100 | { 101 | "version": "0.9.0", 102 | "tag": "@specron/sandbox_v0.9.0", 103 | "date": "Tue, 01 Oct 2019 18:29:23 GMT", 104 | "comments": {} 105 | }, 106 | { 107 | "version": "0.8.2", 108 | "tag": "@specron/sandbox_v0.8.2", 109 | "date": "Tue, 01 Oct 2019 18:27:47 GMT", 110 | "comments": {} 111 | }, 112 | { 113 | "version": "0.8.1", 114 | "tag": "@specron/sandbox_v0.8.1", 115 | "date": "Tue, 01 Oct 2019 18:14:09 GMT", 116 | "comments": {} 117 | }, 118 | { 119 | "version": "0.8.0", 120 | "tag": "@specron/sandbox_v0.8.0", 121 | "date": "Sun, 29 Sep 2019 22:26:46 GMT", 122 | "comments": {} 123 | }, 124 | { 125 | "version": "0.7.0", 126 | "tag": "@specron/sandbox_v0.7.0", 127 | "date": "Tue, 30 Jul 2019 13:07:02 GMT", 128 | "comments": {} 129 | }, 130 | { 131 | "version": "0.5.6", 132 | "tag": "@specron/sandbox_v0.5.6", 133 | "date": "Tue, 26 Feb 2019 12:05:55 GMT", 134 | "comments": {} 135 | }, 136 | { 137 | "version": "0.5.5", 138 | "tag": "@specron/sandbox_v0.5.5", 139 | "date": "Tue, 26 Feb 2019 11:54:20 GMT", 140 | "comments": {} 141 | } 142 | ] 143 | } 144 | -------------------------------------------------------------------------------- /packages/specron-sandbox/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - @specron/sandbox 2 | 3 | This log was last generated on Wed, 04 Aug 2021 13:37:50 GMT and should not be manually modified. 4 | 5 | ## 0.17.6 6 | Wed, 04 Aug 2021 13:37:50 GMT 7 | 8 | *Version update only* 9 | 10 | ## 0.17.5 11 | Wed, 04 Aug 2021 13:37:40 GMT 12 | 13 | *Version update only* 14 | 15 | ## 0.17.4 16 | Wed, 04 Aug 2021 13:34:22 GMT 17 | 18 | *Version update only* 19 | 20 | ## 0.17.3 21 | Tue, 12 Jan 2021 14:59:18 GMT 22 | 23 | *Version update only* 24 | 25 | ## 0.17.2 26 | Tue, 12 Jan 2021 12:34:19 GMT 27 | 28 | *Version update only* 29 | 30 | ## 0.17.1 31 | Mon, 04 May 2020 11:19:54 GMT 32 | 33 | *Version update only* 34 | 35 | ## 0.17.0 36 | Mon, 04 May 2020 10:16:53 GMT 37 | 38 | *Version update only* 39 | 40 | ## 0.16.0 41 | Fri, 07 Feb 2020 11:38:38 GMT 42 | 43 | *Version update only* 44 | 45 | ## 0.15.2 46 | Fri, 07 Feb 2020 11:38:14 GMT 47 | 48 | *Version update only* 49 | 50 | ## 0.15.1 51 | Mon, 27 Jan 2020 10:44:17 GMT 52 | 53 | *Version update only* 54 | 55 | ## 0.15.0 56 | Thu, 16 Jan 2020 09:44:14 GMT 57 | 58 | *Version update only* 59 | 60 | ## 0.14.0 61 | Thu, 16 Jan 2020 08:27:04 GMT 62 | 63 | *Version update only* 64 | 65 | ## 0.13.0 66 | Tue, 14 Jan 2020 12:07:57 GMT 67 | 68 | *Version update only* 69 | 70 | ## 0.12.0 71 | Mon, 13 Jan 2020 09:39:01 GMT 72 | 73 | *Version update only* 74 | 75 | ## 0.11.0 76 | Tue, 07 Jan 2020 09:53:08 GMT 77 | 78 | *Version update only* 79 | 80 | ## 0.10.0 81 | Thu, 28 Nov 2019 11:45:10 GMT 82 | 83 | *Version update only* 84 | 85 | ## 0.9.0 86 | Tue, 01 Oct 2019 18:29:23 GMT 87 | 88 | *Version update only* 89 | 90 | ## 0.8.2 91 | Tue, 01 Oct 2019 18:27:47 GMT 92 | 93 | *Version update only* 94 | 95 | ## 0.8.1 96 | Tue, 01 Oct 2019 18:14:09 GMT 97 | 98 | *Version update only* 99 | 100 | ## 0.8.0 101 | Sun, 29 Sep 2019 22:26:46 GMT 102 | 103 | *Version update only* 104 | 105 | ## 0.7.0 106 | Tue, 30 Jul 2019 13:07:02 GMT 107 | 108 | *Version update only* 109 | 110 | ## 0.5.6 111 | Tue, 26 Feb 2019 12:05:55 GMT 112 | 113 | *Version update only* 114 | 115 | ## 0.5.5 116 | Tue, 26 Feb 2019 11:54:20 GMT 117 | 118 | *Initial release* 119 | 120 | -------------------------------------------------------------------------------- /packages/specron-sandbox/README.md: -------------------------------------------------------------------------------- 1 | ```js 2 | import { Sandbox } from '../sandbox'; 3 | 4 | const sandbox = new Sandbox(); 5 | sandbox.listen(8911, 'localhost'); // => Promise 6 | ``` 7 | -------------------------------------------------------------------------------- /packages/specron-sandbox/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": ["dist/*"], 3 | "ext": "js,ts,sol" 4 | } 5 | -------------------------------------------------------------------------------- /packages/specron-sandbox/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@specron/sandbox", 3 | "version": "0.17.6", 4 | "description": "Ethereum sandbox server for Specron framework.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "scripts": { 8 | "build": "npx tsc", 9 | "test": "npx nyc npx ava --verbose" 10 | }, 11 | "ava": { 12 | "concurrency": 1, 13 | "require": [ 14 | "ts-node/register" 15 | ], 16 | "extensions": [ 17 | "ts" 18 | ], 19 | "files": [ 20 | "src/tests/*.test.ts", 21 | "src/tests/**/*.test.ts" 22 | ], 23 | "timeout": "1m" 24 | }, 25 | "nyc": { 26 | "extension": [ 27 | ".ts" 28 | ], 29 | "require": [ 30 | "ts-node/register" 31 | ], 32 | "exclude": [ 33 | "src/tests" 34 | ] 35 | }, 36 | "license": "MIT", 37 | "devDependencies": { 38 | "@types/node": "16.4.11", 39 | "@types/supertest": "2.0.11", 40 | "ava": "3.15.0", 41 | "nyc": "15.1.0", 42 | "supertest": "6.1.4", 43 | "ts-node": "10.1.0", 44 | "typescript": "4.3.5" 45 | }, 46 | "dependencies": { 47 | "ganache-cli": "6.12.2" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/specron-sandbox/src/core/sandbox.ts: -------------------------------------------------------------------------------- 1 | import * as ganache from 'ganache-cli'; 2 | 3 | /** 4 | * Sandbox configuration options. 5 | */ 6 | export interface SandboxOptions { 7 | port?: number; 8 | blockTime?: number; 9 | } 10 | 11 | /** 12 | * Sandbox server for testing Ethereum code. 13 | */ 14 | export class Sandbox { 15 | protected _server: any; 16 | protected options: SandboxOptions; 17 | 18 | /** 19 | * Returns and instance of a sandbox provider. 20 | * @param options Sandbox configuration options. 21 | */ 22 | public static createProvider(options?: SandboxOptions) { 23 | const provider = ganache.provider(options); 24 | provider.setMaxListeners(999999); // hide MaxListenersExceededWarning produced by ganache provider. 25 | return provider; 26 | } 27 | 28 | /** 29 | * Returns and instance of a sandbox server. 30 | * @param options Sandbox configuration options. 31 | */ 32 | public static createServer(options?: SandboxOptions) { 33 | const server = ganache.server(options); 34 | server.provider.setMaxListeners(999999); // hide MaxListenersExceededWarning produced by ganache provider. 35 | return server; 36 | } 37 | 38 | /** 39 | * 40 | * @param options Ganache configuration options. 41 | */ 42 | public constructor(options?: SandboxOptions) { 43 | this.options = { 44 | port: 8545, 45 | ...options, 46 | }; 47 | 48 | this._server = ganache.server(this.options); 49 | this._server.provider.setMaxListeners(999999); // hide MaxListenersExceededWarning produced by ganache provider. 50 | } 51 | 52 | /** 53 | * Returns Web3 provider instance. 54 | */ 55 | public get provider() { 56 | return this.server.provider; 57 | } 58 | 59 | /** 60 | * Returns Web3 provider instance. 61 | */ 62 | public get server() { 63 | return this._server; 64 | } 65 | 66 | /** 67 | * Starts the server. 68 | */ 69 | public async listen() { 70 | 71 | await new Promise((resolve, reject) => { 72 | this.server.listen(this.options.port, (e) => e ? reject(e) : resolve(null)); 73 | }); 74 | 75 | return this; 76 | } 77 | 78 | /** 79 | * Stops the server. 80 | */ 81 | public async close () { 82 | 83 | this._server.close(); 84 | 85 | return this; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /packages/specron-sandbox/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './core/sandbox'; 2 | -------------------------------------------------------------------------------- /packages/specron-sandbox/src/tests/core/sandbox.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import * as request from 'supertest'; 3 | import { Sandbox } from '../../core/sandbox'; 4 | 5 | const sandbox = new Sandbox({ port: 8911 }); 6 | 7 | test.before(async () => { 8 | await sandbox.listen(); 9 | }) 10 | test.after(async () => { 11 | sandbox.close(); 12 | }); 13 | 14 | test('server listens for requests', async (t) => { 15 | const res = await request('http://localhost:8911').get('/').catch((e) => e.response); 16 | t.is(res.status, 400); 17 | }); 18 | 19 | test('creates a sandbox Web3 provider', async (t) => { 20 | const res = Sandbox.createProvider(); 21 | t.true(!!res); 22 | }); 23 | -------------------------------------------------------------------------------- /packages/specron-sandbox/src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import * as sandbox from '..'; 3 | 4 | test('exposes Sandbox class', async (t) => { 5 | t.true(!!sandbox.Sandbox); 6 | }); 7 | -------------------------------------------------------------------------------- /packages/specron-sandbox/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "sourceMap": true, 8 | "outDir": "dist", 9 | "declaration": true 10 | } 11 | } -------------------------------------------------------------------------------- /packages/specron-spec/CHANGELOG.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@specron/spec", 3 | "entries": [ 4 | { 5 | "version": "0.17.6", 6 | "tag": "@specron/spec_v0.17.6", 7 | "date": "Wed, 04 Aug 2021 13:37:50 GMT", 8 | "comments": {} 9 | }, 10 | { 11 | "version": "0.17.5", 12 | "tag": "@specron/spec_v0.17.5", 13 | "date": "Wed, 04 Aug 2021 13:37:40 GMT", 14 | "comments": {} 15 | }, 16 | { 17 | "version": "0.17.4", 18 | "tag": "@specron/spec_v0.17.4", 19 | "date": "Wed, 04 Aug 2021 13:34:22 GMT", 20 | "comments": {} 21 | }, 22 | { 23 | "version": "0.17.3", 24 | "tag": "@specron/spec_v0.17.3", 25 | "date": "Tue, 12 Jan 2021 14:59:18 GMT", 26 | "comments": {} 27 | }, 28 | { 29 | "version": "0.17.2", 30 | "tag": "@specron/spec_v0.17.2", 31 | "date": "Tue, 12 Jan 2021 12:34:19 GMT", 32 | "comments": {} 33 | }, 34 | { 35 | "version": "0.17.1", 36 | "tag": "@specron/spec_v0.17.1", 37 | "date": "Mon, 04 May 2020 11:19:54 GMT", 38 | "comments": {} 39 | }, 40 | { 41 | "version": "0.17.0", 42 | "tag": "@specron/spec_v0.17.0", 43 | "date": "Mon, 04 May 2020 10:16:53 GMT", 44 | "comments": {} 45 | }, 46 | { 47 | "version": "0.16.0", 48 | "tag": "@specron/spec_v0.16.0", 49 | "date": "Fri, 07 Feb 2020 11:38:38 GMT", 50 | "comments": {} 51 | }, 52 | { 53 | "version": "0.15.2", 54 | "tag": "@specron/spec_v0.15.2", 55 | "date": "Fri, 07 Feb 2020 11:38:14 GMT", 56 | "comments": {} 57 | }, 58 | { 59 | "version": "0.15.1", 60 | "tag": "@specron/spec_v0.15.1", 61 | "date": "Mon, 27 Jan 2020 10:44:17 GMT", 62 | "comments": {} 63 | }, 64 | { 65 | "version": "0.15.0", 66 | "tag": "@specron/spec_v0.15.0", 67 | "date": "Thu, 16 Jan 2020 09:44:14 GMT", 68 | "comments": {} 69 | }, 70 | { 71 | "version": "0.14.0", 72 | "tag": "@specron/spec_v0.14.0", 73 | "date": "Thu, 16 Jan 2020 08:27:04 GMT", 74 | "comments": {} 75 | }, 76 | { 77 | "version": "0.13.0", 78 | "tag": "@specron/spec_v0.13.0", 79 | "date": "Tue, 14 Jan 2020 12:07:57 GMT", 80 | "comments": {} 81 | }, 82 | { 83 | "version": "0.12.0", 84 | "tag": "@specron/spec_v0.12.0", 85 | "date": "Mon, 13 Jan 2020 09:39:01 GMT", 86 | "comments": {} 87 | }, 88 | { 89 | "version": "0.11.0", 90 | "tag": "@specron/spec_v0.11.0", 91 | "date": "Tue, 07 Jan 2020 09:53:08 GMT", 92 | "comments": {} 93 | }, 94 | { 95 | "version": "0.10.0", 96 | "tag": "@specron/spec_v0.10.0", 97 | "date": "Thu, 28 Nov 2019 11:45:10 GMT", 98 | "comments": {} 99 | }, 100 | { 101 | "version": "0.9.0", 102 | "tag": "@specron/spec_v0.9.0", 103 | "date": "Tue, 01 Oct 2019 18:29:23 GMT", 104 | "comments": {} 105 | }, 106 | { 107 | "version": "0.8.2", 108 | "tag": "@specron/spec_v0.8.2", 109 | "date": "Tue, 01 Oct 2019 18:27:47 GMT", 110 | "comments": {} 111 | }, 112 | { 113 | "version": "0.8.1", 114 | "tag": "@specron/spec_v0.8.1", 115 | "date": "Tue, 01 Oct 2019 18:14:09 GMT", 116 | "comments": {} 117 | }, 118 | { 119 | "version": "0.8.0", 120 | "tag": "@specron/spec_v0.8.0", 121 | "date": "Sun, 29 Sep 2019 22:26:46 GMT", 122 | "comments": {} 123 | }, 124 | { 125 | "version": "0.7.0", 126 | "tag": "@specron/spec_v0.7.0", 127 | "date": "Tue, 30 Jul 2019 13:07:02 GMT", 128 | "comments": {} 129 | }, 130 | { 131 | "version": "0.5.6", 132 | "tag": "@specron/spec_v0.5.6", 133 | "date": "Tue, 26 Feb 2019 12:05:55 GMT", 134 | "comments": {} 135 | }, 136 | { 137 | "version": "0.5.5", 138 | "tag": "@specron/spec_v0.5.5", 139 | "date": "Tue, 26 Feb 2019 11:54:20 GMT", 140 | "comments": {} 141 | } 142 | ] 143 | } 144 | -------------------------------------------------------------------------------- /packages/specron-spec/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - @specron/spec 2 | 3 | This log was last generated on Wed, 04 Aug 2021 13:37:50 GMT and should not be manually modified. 4 | 5 | ## 0.17.6 6 | Wed, 04 Aug 2021 13:37:50 GMT 7 | 8 | *Version update only* 9 | 10 | ## 0.17.5 11 | Wed, 04 Aug 2021 13:37:40 GMT 12 | 13 | *Version update only* 14 | 15 | ## 0.17.4 16 | Wed, 04 Aug 2021 13:34:22 GMT 17 | 18 | *Version update only* 19 | 20 | ## 0.17.3 21 | Tue, 12 Jan 2021 14:59:18 GMT 22 | 23 | *Version update only* 24 | 25 | ## 0.17.2 26 | Tue, 12 Jan 2021 12:34:19 GMT 27 | 28 | *Version update only* 29 | 30 | ## 0.17.1 31 | Mon, 04 May 2020 11:19:54 GMT 32 | 33 | *Version update only* 34 | 35 | ## 0.17.0 36 | Mon, 04 May 2020 10:16:53 GMT 37 | 38 | *Version update only* 39 | 40 | ## 0.16.0 41 | Fri, 07 Feb 2020 11:38:38 GMT 42 | 43 | *Version update only* 44 | 45 | ## 0.15.2 46 | Fri, 07 Feb 2020 11:38:14 GMT 47 | 48 | *Version update only* 49 | 50 | ## 0.15.1 51 | Mon, 27 Jan 2020 10:44:17 GMT 52 | 53 | *Version update only* 54 | 55 | ## 0.15.0 56 | Thu, 16 Jan 2020 09:44:14 GMT 57 | 58 | *Version update only* 59 | 60 | ## 0.14.0 61 | Thu, 16 Jan 2020 08:27:04 GMT 62 | 63 | *Version update only* 64 | 65 | ## 0.13.0 66 | Tue, 14 Jan 2020 12:07:57 GMT 67 | 68 | *Version update only* 69 | 70 | ## 0.12.0 71 | Mon, 13 Jan 2020 09:39:01 GMT 72 | 73 | *Version update only* 74 | 75 | ## 0.11.0 76 | Tue, 07 Jan 2020 09:53:08 GMT 77 | 78 | *Version update only* 79 | 80 | ## 0.10.0 81 | Thu, 28 Nov 2019 11:45:10 GMT 82 | 83 | *Version update only* 84 | 85 | ## 0.9.0 86 | Tue, 01 Oct 2019 18:29:23 GMT 87 | 88 | *Version update only* 89 | 90 | ## 0.8.2 91 | Tue, 01 Oct 2019 18:27:47 GMT 92 | 93 | *Version update only* 94 | 95 | ## 0.8.1 96 | Tue, 01 Oct 2019 18:14:09 GMT 97 | 98 | *Version update only* 99 | 100 | ## 0.8.0 101 | Sun, 29 Sep 2019 22:26:46 GMT 102 | 103 | *Version update only* 104 | 105 | ## 0.7.0 106 | Tue, 30 Jul 2019 13:07:02 GMT 107 | 108 | *Version update only* 109 | 110 | ## 0.5.6 111 | Tue, 26 Feb 2019 12:05:55 GMT 112 | 113 | *Version update only* 114 | 115 | ## 0.5.5 116 | Tue, 26 Feb 2019 11:54:20 GMT 117 | 118 | *Initial release* 119 | 120 | -------------------------------------------------------------------------------- /packages/specron-spec/README.md: -------------------------------------------------------------------------------- 1 | ```ts 2 | import { Spec, Contract } from '@specron/core'; 3 | 4 | interface Data { 5 | id?: number; 6 | name?: string; 7 | User?: Contract; 8 | } 9 | 10 | const spec = new Spec(); 11 | 12 | spec.before(async (ctx) => { 13 | ctx.set('id', 100); 14 | ctx.set('web3', context.web3); 15 | ctx.set('User', await context.require({ src: './src/contracts/User' })); 16 | }); 17 | 18 | export default spec; 19 | ``` 20 | -------------------------------------------------------------------------------- /packages/specron-spec/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": ["dist/*"], 3 | "ext": "js,ts,sol" 4 | } 5 | -------------------------------------------------------------------------------- /packages/specron-spec/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@specron/spec", 3 | "version": "0.17.6", 4 | "description": "Test suits for Specron framework.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "scripts": { 8 | "build": "npx tsc", 9 | "test": "npx nyc npx ava --verbose" 10 | }, 11 | "ava": { 12 | "concurrency": 1, 13 | "require": [ 14 | "ts-node/register" 15 | ], 16 | "extensions": [ 17 | "ts" 18 | ], 19 | "files": [ 20 | "src/tests/*.test.ts", 21 | "src/tests/**/*.test.ts" 22 | ], 23 | "timeout": "1m" 24 | }, 25 | "nyc": { 26 | "extension": [ 27 | ".ts" 28 | ], 29 | "require": [ 30 | "ts-node/register" 31 | ], 32 | "exclude": [ 33 | "src/tests" 34 | ] 35 | }, 36 | "license": "MIT", 37 | "devDependencies": { 38 | "@0xcert/ethereum-utils-contracts": "2.1.1", 39 | "@types/node": "16.4.11", 40 | "ava": "3.15.0", 41 | "nyc": "15.1.0", 42 | "ts-node": "10.1.0", 43 | "typescript": "4.3.5", 44 | "web3": "1.5.0" 45 | }, 46 | "peerDependencies": { 47 | "web3": "*" 48 | }, 49 | "dependencies": { 50 | "@hayspec/reporter": "0.10.2", 51 | "@hayspec/runner": "0.10.2", 52 | "@hayspec/spec": "0.10.2", 53 | "@specron/sandbox": "0.17.6" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/specron-spec/src/asserts/reverts.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | function isRevertError(e, message?: string) { 5 | const isRevert = String(e).includes('revert') || (e.message !== undefined && e.message.includes('revert')); 6 | if (isRevert && message !== undefined) { 7 | return String(e).includes(message) || (e.message !== undefined && e.message.includes(message)); 8 | } 9 | return isRevert; 10 | } 11 | 12 | /** 13 | * 14 | */ 15 | export function reverts(fn: () => any, message?: string) { 16 | try { 17 | const res = fn(); 18 | if (res instanceof Promise) { 19 | return res.then(() => false).catch((e) => isRevertError(e, message)); 20 | } 21 | else { 22 | return false; 23 | } 24 | } 25 | catch (e) { 26 | return isRevertError(e, message); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/specron-spec/src/core/context.ts: -------------------------------------------------------------------------------- 1 | import { Context as ContextBase, AssertionNote } from '@hayspec/spec'; 2 | import { Stage } from './stage'; 3 | import { SignatureKind } from './types'; 4 | import { reverts } from '../asserts/reverts'; 5 | import { deploy } from '../methods/deploy'; 6 | import { tuple } from '../methods/tuple'; 7 | import { sign } from '../methods/sign'; 8 | 9 | /** 10 | * 11 | */ 12 | export class Context extends ContextBase { 13 | public stage: Stage; 14 | 15 | /** 16 | * 17 | */ 18 | public constructor(stage: Stage) { 19 | super(stage); 20 | } 21 | 22 | /** 23 | * 24 | */ 25 | public get web3() { 26 | return this.stage.web3; 27 | } 28 | 29 | /** 30 | * 31 | */ 32 | public reverts(fn: () => any, message?: any): AssertionNote | Promise { 33 | return this.assert({ 34 | assertion: 'reverts', 35 | handler: () => reverts(fn, message), 36 | message, 37 | }); 38 | } 39 | 40 | /** 41 | * 42 | */ 43 | public async deploy(options: { 44 | src: string; 45 | contract?: string; 46 | args?: any[]; 47 | from?: string; 48 | gas?: number; 49 | gasPrice?: number; 50 | }) { 51 | return deploy({ 52 | web3: this.stage.web3, 53 | args: [], 54 | from: await this.stage.web3.eth.getAccounts().then((a) => a[0]), 55 | gas: 6000000, 56 | gasPrice: 1, 57 | ...options, 58 | }); 59 | } 60 | 61 | /** 62 | * 63 | */ 64 | public tuple(obj) { 65 | return tuple(obj); 66 | } 67 | 68 | /** 69 | * 70 | */ 71 | public async sign(options: { 72 | data: string; 73 | kind?: SignatureKind; 74 | signer?: string; 75 | }) { 76 | return sign({ 77 | web3: this.stage.web3, 78 | signer: options.signer === undefined 79 | ? await this.stage.web3.eth.getAccounts().then((a) => a[0]) 80 | : options.signer, 81 | kind: options.kind === undefined 82 | ? SignatureKind.ETH_SIGN 83 | : options.kind, 84 | ...options, 85 | }); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /packages/specron-spec/src/core/reporter.ts: -------------------------------------------------------------------------------- 1 | import { DefaultReporter } from '@hayspec/reporter'; 2 | 3 | /** 4 | * 5 | */ 6 | export class Reporter extends DefaultReporter {} -------------------------------------------------------------------------------- /packages/specron-spec/src/core/runner.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from './spec'; 2 | import * as runner from '@hayspec/runner'; 3 | 4 | /** 5 | * 6 | */ 7 | export interface RunnerResult extends runner.RunnerResult { 8 | spec: Spec; 9 | } 10 | 11 | /** 12 | * 13 | */ 14 | export class Runner extends runner.Runner { 15 | public results: RunnerResult[] = []; 16 | 17 | /** 18 | * 19 | */ 20 | protected loadSpec(file: string) { 21 | const spec = require(file); 22 | 23 | if (spec instanceof Spec) { 24 | return { file, spec }; 25 | } 26 | else if (spec.default instanceof Spec) { 27 | return { file, spec: spec.default }; 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /packages/specron-spec/src/core/spec.ts: -------------------------------------------------------------------------------- 1 | import { Spec as SpecBase } from '@hayspec/spec'; 2 | import { DefaultReporter } from '@hayspec/reporter'; 3 | import { Sandbox } from '@specron/sandbox'; 4 | import { Stage } from './stage'; 5 | import { Context } from './context'; 6 | import Web3 from 'web3'; 7 | 8 | /** 9 | * 10 | */ 11 | type StageHandler = (stage: Stage) => (void | Promise); 12 | 13 | /** 14 | * 15 | */ 16 | type ContextHandler = (context: Context, stage: Stage) => (void | Promise); 17 | 18 | /** 19 | * 20 | */ 21 | export class Spec extends SpecBase { 22 | protected _stage: Stage; 23 | public parent: Spec; 24 | 25 | /** 26 | * 27 | */ 28 | public constructor(stage?: Stage, parent?: Spec) { 29 | super(stage, parent); 30 | } 31 | 32 | /** 33 | * 34 | */ 35 | public set stage(s: Stage) { 36 | if (this.parent) { 37 | this.parent.stage = s; 38 | } 39 | else { 40 | this._stage = s; 41 | } 42 | } 43 | 44 | /** 45 | * 46 | */ 47 | public get stage() { 48 | if (this.parent) { 49 | return this.parent.stage; 50 | } 51 | else { 52 | return this._stage; 53 | } 54 | } 55 | 56 | /** 57 | * 58 | */ 59 | public isRoot() { 60 | return !this.parent; 61 | } 62 | 63 | /** 64 | * 65 | */ 66 | public before(handler: StageHandler, append: boolean = true) { 67 | return super.before(handler, append); 68 | } 69 | 70 | /** 71 | * 72 | */ 73 | public beforeEach(handler: ContextHandler, append: boolean = true) { 74 | return super.beforeEach(handler, append); 75 | } 76 | 77 | /** 78 | * 79 | */ 80 | public after(handler: StageHandler, append: boolean = true) { 81 | return super.after(handler, append); 82 | } 83 | 84 | /** 85 | * 86 | */ 87 | public afterEach(handler: ContextHandler, append: boolean = true) { 88 | return super.afterEach(handler, append); 89 | } 90 | 91 | /** 92 | * 93 | */ 94 | public spec(message: string, spec: Spec) { 95 | return super.spec(message, spec); 96 | } 97 | 98 | /** 99 | * 100 | */ 101 | public test(message: string, handler: ContextHandler) { 102 | return super.test(message, handler); 103 | } 104 | 105 | /** 106 | * 107 | */ 108 | public skip(message: string, handler?: ContextHandler) { 109 | return super.skip(message, handler); 110 | } 111 | 112 | /** 113 | * 114 | */ 115 | public only(message: string, handler: ContextHandler) { 116 | return super.only(message, handler); 117 | } 118 | 119 | /** 120 | * 121 | */ 122 | protected createStage() { 123 | const web3 = new Web3(Sandbox.createProvider()); 124 | const reporter = new DefaultReporter(); 125 | return new Stage(web3, reporter); 126 | } 127 | 128 | /** 129 | * 130 | */ 131 | protected createContext() { 132 | return new Context(this.stage); 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /packages/specron-spec/src/core/stage.ts: -------------------------------------------------------------------------------- 1 | import { DefaultReporter } from "@hayspec/reporter"; 2 | import * as core from "@hayspec/spec"; 3 | import { SignatureKind } from "./types"; 4 | import { sign } from "../methods/sign"; 5 | import { tuple } from '../methods/tuple'; 6 | 7 | /** 8 | * 9 | */ 10 | export class Stage extends core.Stage { 11 | public web3: any; 12 | 13 | /** 14 | * 15 | */ 16 | public constructor (web3: any, reporter: DefaultReporter) { 17 | super(reporter); 18 | this.web3 = web3; 19 | } 20 | 21 | /** 22 | * 23 | */ 24 | public set(k: Key, v: Value) { 25 | (this.data as any)[k] = v; 26 | } 27 | 28 | /** 29 | * 30 | */ 31 | public get(k: Key) { 32 | return this.data[k]; 33 | } 34 | 35 | /** 36 | * 37 | */ 38 | public tuple(obj) { 39 | return tuple(obj); 40 | } 41 | 42 | /** 43 | * 44 | */ 45 | public async sign(options: { 46 | data: string; 47 | kind?: SignatureKind; 48 | signer?: string; 49 | }) { 50 | return sign({ 51 | web3: this.web3, 52 | signer: options.signer === undefined 53 | ? await this.web3.eth.getAccounts().then((a) => a[0]) 54 | : options.signer, 55 | kind: options.kind === undefined 56 | ? SignatureKind.ETH_SIGN 57 | : options.kind, 58 | ...options, 59 | }); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /packages/specron-spec/src/core/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | export enum SignatureKind { 5 | ETH_SIGN = 0, 6 | } -------------------------------------------------------------------------------- /packages/specron-spec/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './core/context'; 2 | export * from './core/reporter'; 3 | export * from './core/runner'; 4 | export * from './core/spec'; 5 | export * from './core/stage'; 6 | -------------------------------------------------------------------------------- /packages/specron-spec/src/methods/deploy.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | 3 | /** 4 | * 5 | */ 6 | export async function deploy(config: { 7 | src: string; 8 | contract?: string; 9 | web3: any; 10 | from: string; 11 | gas: number; 12 | gasPrice: number; 13 | args?: any[]; 14 | }) { 15 | const src = path.resolve(process.cwd(), (config.src[0] != '.' ? 'node_modules' : ''), config.src); 16 | const data = require(src); 17 | const abi = config.contract ? data[config.contract].abi : data.abi; 18 | const bytecode = config.contract ? data[config.contract].evm.bytecode.object : data.bytecode; 19 | const contract = new config.web3.eth.Contract(abi); 20 | let txHash = null; 21 | const receipt = await contract.deploy({ 22 | data: bytecode, 23 | arguments: config.args, 24 | }).send({ 25 | from: config.from, 26 | gas: config.gas, 27 | gasPrice: config.gasPrice, 28 | }).on('transactionHash', (transactionHash) => { 29 | txHash = transactionHash; 30 | }); 31 | const instance = new config.web3.eth.Contract( 32 | abi, 33 | receipt.options.address, 34 | { 35 | gas: config.gas, 36 | from: config.from, 37 | }, 38 | ); 39 | if(txHash) { 40 | const transactionReceipt = await config.web3.eth.getTransactionReceipt(txHash); 41 | Object.assign(receipt, transactionReceipt); 42 | } 43 | return { instance, receipt }; 44 | } 45 | -------------------------------------------------------------------------------- /packages/specron-spec/src/methods/sign.ts: -------------------------------------------------------------------------------- 1 | import { SignatureKind } from '../core/types'; 2 | 3 | /** 4 | * 5 | */ 6 | export async function sign(config: { 7 | web3: any; 8 | data: string; 9 | kind: SignatureKind; 10 | signer: string; 11 | }) { 12 | if (config.kind === SignatureKind.ETH_SIGN) { 13 | return signWithEthSign(config); 14 | } 15 | else { 16 | return null; 17 | } 18 | } 19 | 20 | /** 21 | * 22 | */ 23 | async function signWithEthSign(config) { 24 | try { 25 | const signature = await config.web3.eth.sign(config.data, config.signer); 26 | const signatureData = { 27 | signature, 28 | r: signature.substr(0, 66), 29 | s: `0x${signature.substr(66, 64)}`, 30 | v: parseInt(`0x${signature.substr(130, 2)}`), 31 | }; 32 | if (signatureData.v < 27) { 33 | signatureData.v = signatureData.v + 27; 34 | } 35 | return signatureData; 36 | } 37 | catch (err) { 38 | return null; 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /packages/specron-spec/src/methods/tuple.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Transforms an object into web3 tuple type. 3 | * @param obj Web3 structure as object. 4 | */ 5 | export function tuple(obj) { 6 | if (!(obj instanceof Object)) { 7 | return []; 8 | } 9 | var output = []; 10 | var i = 0; 11 | Object.keys(obj).forEach((k) => { 12 | if (obj[k] instanceof Object) { 13 | output[i] = tuple(obj[k]); 14 | } 15 | else if (obj[k] instanceof Array) { 16 | let j1 = 0; 17 | let temp1 = []; 18 | obj[k].forEach((ak) => { 19 | temp1[j1] = tuple(obj[k]); 20 | j1++; 21 | }); 22 | output[i] = temp1; 23 | } 24 | else { 25 | output[i] = obj[k]; 26 | } 27 | i++; 28 | }); 29 | return output; 30 | } 31 | -------------------------------------------------------------------------------- /packages/specron-spec/src/tests/asserts/reverts.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import { reverts } from '../../asserts/reverts'; 3 | 4 | test('succeeds for values that revert', async (t) => { 5 | t.true(reverts(() => { throw new Error('revert') })); 6 | t.true(await reverts(() => Promise.reject('revert'))); 7 | }); 8 | 9 | test('succeeds for values that revert with revert message check', async (t) => { 10 | t.true(reverts(() => { throw new Error('revert test message') }, 'test message')); 11 | t.true(await reverts(() => Promise.reject('revert test message'), 'test message')); 12 | 13 | t.false(reverts(() => { throw new Error('revert test message') }, 'testing')); 14 | t.false(await reverts(() => Promise.reject('revert test message'), 'testing')); 15 | }); 16 | 17 | test('succeeds for values that do not revert', async (t) => { 18 | t.false(reverts(() => { throw new Error() })); 19 | t.false(reverts(() => { return; })); 20 | t.false(await reverts(() => Promise.resolve())); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/specron-spec/src/tests/assets/Scaffold.hay.ts: -------------------------------------------------------------------------------- 1 | import { Spec } from '../..'; 2 | 3 | const subspec = new Spec(); 4 | 5 | subspec.test('provides asserts', (ctx) => { 6 | ctx.true(true); 7 | }); 8 | 9 | const spec = new Spec(); 10 | 11 | spec.test('provides asserts', (ctx) => { 12 | ctx.true(true); 13 | }); 14 | 15 | spec.test('provides web3', async (ctx) => { 16 | const accounts = await ctx.stage.web3.eth.getAccounts(); 17 | ctx.is(accounts[0].substr(0, 2), '0x'); 18 | }); 19 | 20 | spec.spec('can nest specs', subspec); 21 | 22 | export default spec; 23 | -------------------------------------------------------------------------------- /packages/specron-spec/src/tests/assets/scaffold-a.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi": [ 3 | { 4 | "constant": true, 5 | "inputs": [], 6 | "name": "test", 7 | "outputs": [ 8 | { 9 | "name": "_value", 10 | "type": "uint256" 11 | } 12 | ], 13 | "payable": false, 14 | "stateMutability": "pure", 15 | "type": "function" 16 | } 17 | ], 18 | "bytecode": "608060405234801561001057600080fd5b5060be8061001f6000396000f300608060405260043610603e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663f8a8fd6d81146043575b600080fd5b348015604e57600080fd5b5060556067565b60408051918252519081900360200190f35b60006201e24081607d82600163ffffffff608416565b9392505050565b600082820183811015607d57fe00a165627a7a72305820cdba2fefeccba6bd7410a146e7071d8629b1be78efb597100671ddf6e6444f0b0029", 19 | "contractName": "Scaffold" 20 | } -------------------------------------------------------------------------------- /packages/specron-spec/src/tests/assets/scaffold-b.json: -------------------------------------------------------------------------------- 1 | { 2 | "Main": { 3 | "abi": [ 4 | { 5 | "constant": true, 6 | "inputs": [], 7 | "name": "test", 8 | "outputs": [ 9 | { 10 | "name": "_value", 11 | "type": "uint256" 12 | } 13 | ], 14 | "payable": false, 15 | "stateMutability": "pure", 16 | "type": "function" 17 | } 18 | ], 19 | "devdoc": { 20 | "methods": {} 21 | }, 22 | "evm": { 23 | "assembly": " /* \"./src/tests/assets/token-c.sol\":26:140 contract Main {... */\n mstore(0x40, 0x80)\n callvalue\n /* \"--CODEGEN--\":8:17 */\n dup1\n /* \"--CODEGEN--\":5:7 */\n iszero\n tag_1\n jumpi\n /* \"--CODEGEN--\":30:31 */\n 0x0\n /* \"--CODEGEN--\":27:28 */\n dup1\n /* \"--CODEGEN--\":20:32 */\n revert\n /* \"--CODEGEN--\":5:7 */\ntag_1:\n /* \"./src/tests/assets/token-c.sol\":26:140 contract Main {... */\n pop\n dataSize(sub_0)\n dup1\n dataOffset(sub_0)\n 0x0\n codecopy\n 0x0\n return\nstop\n\nsub_0: assembly {\n /* \"./src/tests/assets/token-c.sol\":26:140 contract Main {... */\n mstore(0x40, 0x80)\n jumpi(tag_1, lt(calldatasize, 0x4))\n calldataload(0x0)\n 0x100000000000000000000000000000000000000000000000000000000\n swap1\n div\n 0xffffffff\n and\n dup1\n 0xf8a8fd6d\n eq\n tag_2\n jumpi\n tag_1:\n 0x0\n dup1\n revert\n /* \"./src/tests/assets/token-c.sol\":45:137 function test () ... */\n tag_2:\n callvalue\n /* \"--CODEGEN--\":8:17 */\n dup1\n /* \"--CODEGEN--\":5:7 */\n iszero\n tag_3\n jumpi\n /* \"--CODEGEN--\":30:31 */\n 0x0\n /* \"--CODEGEN--\":27:28 */\n dup1\n /* \"--CODEGEN--\":20:32 */\n revert\n /* \"--CODEGEN--\":5:7 */\n tag_3:\n /* \"./src/tests/assets/token-c.sol\":45:137 function test () ... */\n pop\n tag_4\n jump(tag_5)\n tag_4:\n mload(0x40)\n dup1\n dup3\n dup2\n mstore\n 0x20\n add\n swap2\n pop\n pop\n mload(0x40)\n dup1\n swap2\n sub\n swap1\n return\n tag_5:\n /* \"./src/tests/assets/token-c.sol\":96:110 uint256 _value */\n 0x0\n /* \"./src/tests/assets/token-c.sol\":129:132 100 */\n 0x64\n /* \"./src/tests/assets/token-c.sol\":120:132 _value = 100 */\n swap1\n pop\n /* \"./src/tests/assets/token-c.sol\":45:137 function test () ... */\n swap1\n jump\t// out\n\n auxdata: 0xa165627a7a72305820491e65f4c0b011f7a9235b2e70683b92a0af825141281b409689d2e3417736fb0029\n}\n", 24 | "bytecode": { 25 | "linkReferences": {}, 26 | "object": "6080604052348015600f57600080fd5b5060a18061001e6000396000f300608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063f8a8fd6d146044575b600080fd5b348015604f57600080fd5b506056606c565b6040518082815260200191505060405180910390f35b600060649050905600a165627a7a72305820491e65f4c0b011f7a9235b2e70683b92a0af825141281b409689d2e3417736fb0029", 27 | "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xA1 DUP1 PUSH2 0x1E PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x3F JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0xF8A8FD6D EQ PUSH1 0x44 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x4F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x56 PUSH1 0x6C JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 PUSH1 0x64 SWAP1 POP SWAP1 JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0x49 0x1e PUSH6 0xF4C0B011F7A9 0x23 JUMPDEST 0x2e PUSH17 0x683B92A0AF825141281B409689D2E34177 CALLDATASIZE CREATE2 STOP 0x29 ", 28 | "sourceMap": "26:114:2:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26:114:2;;;;;;;" 29 | }, 30 | "deployedBytecode": { 31 | "linkReferences": {}, 32 | "object": "608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063f8a8fd6d146044575b600080fd5b348015604f57600080fd5b506056606c565b6040518082815260200191505060405180910390f35b600060649050905600a165627a7a72305820491e65f4c0b011f7a9235b2e70683b92a0af825141281b409689d2e3417736fb0029", 33 | "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x3F JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0xF8A8FD6D EQ PUSH1 0x44 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x4F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x56 PUSH1 0x6C JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 PUSH1 0x64 SWAP1 POP SWAP1 JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0x49 0x1e PUSH6 0xF4C0B011F7A9 0x23 JUMPDEST 0x2e PUSH17 0x683B92A0AF825141281B409689D2E34177 CALLDATASIZE CREATE2 STOP 0x29 ", 34 | "sourceMap": "26:114:2:-;;;;;;;;;;;;;;;;;;;;;;;;45:92;;8:9:-1;5:2;;;30:1;27;20:12;5:2;45:92:2;;;;;;;;;;;;;;;;;;;;;;;;96:14;129:3;120:12;;45:92;:::o" 35 | }, 36 | "gasEstimates": { 37 | "creation": { 38 | "codeDepositCost": "32200", 39 | "executionCost": "87", 40 | "totalCost": "32287" 41 | }, 42 | "external": { 43 | "test()": "202" 44 | } 45 | }, 46 | "legacyAssembly": { 47 | ".code": [ 48 | { 49 | "begin": 26, 50 | "end": 140, 51 | "name": "PUSH", 52 | "value": "80" 53 | }, 54 | { 55 | "begin": 26, 56 | "end": 140, 57 | "name": "PUSH", 58 | "value": "40" 59 | }, 60 | { 61 | "begin": 26, 62 | "end": 140, 63 | "name": "MSTORE" 64 | }, 65 | { 66 | "begin": 26, 67 | "end": 140, 68 | "name": "CALLVALUE" 69 | }, 70 | { 71 | "begin": 8, 72 | "end": 17, 73 | "name": "DUP1" 74 | }, 75 | { 76 | "begin": 5, 77 | "end": 7, 78 | "name": "ISZERO" 79 | }, 80 | { 81 | "begin": 5, 82 | "end": 7, 83 | "name": "PUSH [tag]", 84 | "value": "1" 85 | }, 86 | { 87 | "begin": 5, 88 | "end": 7, 89 | "name": "JUMPI" 90 | }, 91 | { 92 | "begin": 30, 93 | "end": 31, 94 | "name": "PUSH", 95 | "value": "0" 96 | }, 97 | { 98 | "begin": 27, 99 | "end": 28, 100 | "name": "DUP1" 101 | }, 102 | { 103 | "begin": 20, 104 | "end": 32, 105 | "name": "REVERT" 106 | }, 107 | { 108 | "begin": 5, 109 | "end": 7, 110 | "name": "tag", 111 | "value": "1" 112 | }, 113 | { 114 | "begin": 5, 115 | "end": 7, 116 | "name": "JUMPDEST" 117 | }, 118 | { 119 | "begin": 26, 120 | "end": 140, 121 | "name": "POP" 122 | }, 123 | { 124 | "begin": 26, 125 | "end": 140, 126 | "name": "PUSH #[$]", 127 | "value": "0000000000000000000000000000000000000000000000000000000000000000" 128 | }, 129 | { 130 | "begin": 26, 131 | "end": 140, 132 | "name": "DUP1" 133 | }, 134 | { 135 | "begin": 26, 136 | "end": 140, 137 | "name": "PUSH [$]", 138 | "value": "0000000000000000000000000000000000000000000000000000000000000000" 139 | }, 140 | { 141 | "begin": 26, 142 | "end": 140, 143 | "name": "PUSH", 144 | "value": "0" 145 | }, 146 | { 147 | "begin": 26, 148 | "end": 140, 149 | "name": "CODECOPY" 150 | }, 151 | { 152 | "begin": 26, 153 | "end": 140, 154 | "name": "PUSH", 155 | "value": "0" 156 | }, 157 | { 158 | "begin": 26, 159 | "end": 140, 160 | "name": "RETURN" 161 | } 162 | ], 163 | ".data": { 164 | "0": { 165 | ".auxdata": "a165627a7a72305820491e65f4c0b011f7a9235b2e70683b92a0af825141281b409689d2e3417736fb0029", 166 | ".code": [ 167 | { 168 | "begin": 26, 169 | "end": 140, 170 | "name": "PUSH", 171 | "value": "80" 172 | }, 173 | { 174 | "begin": 26, 175 | "end": 140, 176 | "name": "PUSH", 177 | "value": "40" 178 | }, 179 | { 180 | "begin": 26, 181 | "end": 140, 182 | "name": "MSTORE" 183 | }, 184 | { 185 | "begin": 26, 186 | "end": 140, 187 | "name": "PUSH", 188 | "value": "4" 189 | }, 190 | { 191 | "begin": 26, 192 | "end": 140, 193 | "name": "CALLDATASIZE" 194 | }, 195 | { 196 | "begin": 26, 197 | "end": 140, 198 | "name": "LT" 199 | }, 200 | { 201 | "begin": 26, 202 | "end": 140, 203 | "name": "PUSH [tag]", 204 | "value": "1" 205 | }, 206 | { 207 | "begin": 26, 208 | "end": 140, 209 | "name": "JUMPI" 210 | }, 211 | { 212 | "begin": 26, 213 | "end": 140, 214 | "name": "PUSH", 215 | "value": "0" 216 | }, 217 | { 218 | "begin": 26, 219 | "end": 140, 220 | "name": "CALLDATALOAD" 221 | }, 222 | { 223 | "begin": 26, 224 | "end": 140, 225 | "name": "PUSH", 226 | "value": "100000000000000000000000000000000000000000000000000000000" 227 | }, 228 | { 229 | "begin": 26, 230 | "end": 140, 231 | "name": "SWAP1" 232 | }, 233 | { 234 | "begin": 26, 235 | "end": 140, 236 | "name": "DIV" 237 | }, 238 | { 239 | "begin": 26, 240 | "end": 140, 241 | "name": "PUSH", 242 | "value": "FFFFFFFF" 243 | }, 244 | { 245 | "begin": 26, 246 | "end": 140, 247 | "name": "AND" 248 | }, 249 | { 250 | "begin": 26, 251 | "end": 140, 252 | "name": "DUP1" 253 | }, 254 | { 255 | "begin": 26, 256 | "end": 140, 257 | "name": "PUSH", 258 | "value": "F8A8FD6D" 259 | }, 260 | { 261 | "begin": 26, 262 | "end": 140, 263 | "name": "EQ" 264 | }, 265 | { 266 | "begin": 26, 267 | "end": 140, 268 | "name": "PUSH [tag]", 269 | "value": "2" 270 | }, 271 | { 272 | "begin": 26, 273 | "end": 140, 274 | "name": "JUMPI" 275 | }, 276 | { 277 | "begin": 26, 278 | "end": 140, 279 | "name": "tag", 280 | "value": "1" 281 | }, 282 | { 283 | "begin": 26, 284 | "end": 140, 285 | "name": "JUMPDEST" 286 | }, 287 | { 288 | "begin": 26, 289 | "end": 140, 290 | "name": "PUSH", 291 | "value": "0" 292 | }, 293 | { 294 | "begin": 26, 295 | "end": 140, 296 | "name": "DUP1" 297 | }, 298 | { 299 | "begin": 26, 300 | "end": 140, 301 | "name": "REVERT" 302 | }, 303 | { 304 | "begin": 45, 305 | "end": 137, 306 | "name": "tag", 307 | "value": "2" 308 | }, 309 | { 310 | "begin": 45, 311 | "end": 137, 312 | "name": "JUMPDEST" 313 | }, 314 | { 315 | "begin": 45, 316 | "end": 137, 317 | "name": "CALLVALUE" 318 | }, 319 | { 320 | "begin": 8, 321 | "end": 17, 322 | "name": "DUP1" 323 | }, 324 | { 325 | "begin": 5, 326 | "end": 7, 327 | "name": "ISZERO" 328 | }, 329 | { 330 | "begin": 5, 331 | "end": 7, 332 | "name": "PUSH [tag]", 333 | "value": "3" 334 | }, 335 | { 336 | "begin": 5, 337 | "end": 7, 338 | "name": "JUMPI" 339 | }, 340 | { 341 | "begin": 30, 342 | "end": 31, 343 | "name": "PUSH", 344 | "value": "0" 345 | }, 346 | { 347 | "begin": 27, 348 | "end": 28, 349 | "name": "DUP1" 350 | }, 351 | { 352 | "begin": 20, 353 | "end": 32, 354 | "name": "REVERT" 355 | }, 356 | { 357 | "begin": 5, 358 | "end": 7, 359 | "name": "tag", 360 | "value": "3" 361 | }, 362 | { 363 | "begin": 5, 364 | "end": 7, 365 | "name": "JUMPDEST" 366 | }, 367 | { 368 | "begin": 45, 369 | "end": 137, 370 | "name": "POP" 371 | }, 372 | { 373 | "begin": 45, 374 | "end": 137, 375 | "name": "PUSH [tag]", 376 | "value": "4" 377 | }, 378 | { 379 | "begin": 45, 380 | "end": 137, 381 | "name": "PUSH [tag]", 382 | "value": "5" 383 | }, 384 | { 385 | "begin": 45, 386 | "end": 137, 387 | "name": "JUMP" 388 | }, 389 | { 390 | "begin": 45, 391 | "end": 137, 392 | "name": "tag", 393 | "value": "4" 394 | }, 395 | { 396 | "begin": 45, 397 | "end": 137, 398 | "name": "JUMPDEST" 399 | }, 400 | { 401 | "begin": 45, 402 | "end": 137, 403 | "name": "PUSH", 404 | "value": "40" 405 | }, 406 | { 407 | "begin": 45, 408 | "end": 137, 409 | "name": "MLOAD" 410 | }, 411 | { 412 | "begin": 45, 413 | "end": 137, 414 | "name": "DUP1" 415 | }, 416 | { 417 | "begin": 45, 418 | "end": 137, 419 | "name": "DUP3" 420 | }, 421 | { 422 | "begin": 45, 423 | "end": 137, 424 | "name": "DUP2" 425 | }, 426 | { 427 | "begin": 45, 428 | "end": 137, 429 | "name": "MSTORE" 430 | }, 431 | { 432 | "begin": 45, 433 | "end": 137, 434 | "name": "PUSH", 435 | "value": "20" 436 | }, 437 | { 438 | "begin": 45, 439 | "end": 137, 440 | "name": "ADD" 441 | }, 442 | { 443 | "begin": 45, 444 | "end": 137, 445 | "name": "SWAP2" 446 | }, 447 | { 448 | "begin": 45, 449 | "end": 137, 450 | "name": "POP" 451 | }, 452 | { 453 | "begin": 45, 454 | "end": 137, 455 | "name": "POP" 456 | }, 457 | { 458 | "begin": 45, 459 | "end": 137, 460 | "name": "PUSH", 461 | "value": "40" 462 | }, 463 | { 464 | "begin": 45, 465 | "end": 137, 466 | "name": "MLOAD" 467 | }, 468 | { 469 | "begin": 45, 470 | "end": 137, 471 | "name": "DUP1" 472 | }, 473 | { 474 | "begin": 45, 475 | "end": 137, 476 | "name": "SWAP2" 477 | }, 478 | { 479 | "begin": 45, 480 | "end": 137, 481 | "name": "SUB" 482 | }, 483 | { 484 | "begin": 45, 485 | "end": 137, 486 | "name": "SWAP1" 487 | }, 488 | { 489 | "begin": 45, 490 | "end": 137, 491 | "name": "RETURN" 492 | }, 493 | { 494 | "begin": 45, 495 | "end": 137, 496 | "name": "tag", 497 | "value": "5" 498 | }, 499 | { 500 | "begin": 45, 501 | "end": 137, 502 | "name": "JUMPDEST" 503 | }, 504 | { 505 | "begin": 96, 506 | "end": 110, 507 | "name": "PUSH", 508 | "value": "0" 509 | }, 510 | { 511 | "begin": 129, 512 | "end": 132, 513 | "name": "PUSH", 514 | "value": "64" 515 | }, 516 | { 517 | "begin": 120, 518 | "end": 132, 519 | "name": "SWAP1" 520 | }, 521 | { 522 | "begin": 120, 523 | "end": 132, 524 | "name": "POP" 525 | }, 526 | { 527 | "begin": 45, 528 | "end": 137, 529 | "name": "SWAP1" 530 | }, 531 | { 532 | "begin": 45, 533 | "end": 137, 534 | "name": "JUMP", 535 | "value": "[out]" 536 | } 537 | ] 538 | } 539 | } 540 | }, 541 | "methodIdentifiers": { 542 | "test()": "f8a8fd6d" 543 | } 544 | }, 545 | "metadata": { 546 | "compiler": { 547 | "version": "0.4.34+commit.e67f0147" 548 | }, 549 | "language": "Solidity", 550 | "output": { 551 | "abi": [ 552 | { 553 | "constant": true, 554 | "inputs": [], 555 | "name": "test", 556 | "outputs": [ 557 | { 558 | "name": "_value", 559 | "type": "uint256" 560 | } 561 | ], 562 | "payable": false, 563 | "stateMutability": "pure", 564 | "type": "function" 565 | } 566 | ], 567 | "devdoc": { 568 | "methods": {} 569 | }, 570 | "userdoc": { 571 | "methods": {} 572 | } 573 | }, 574 | "settings": { 575 | "compilationTarget": { 576 | "./src/tests/assets/token-c.sol": "Main" 577 | }, 578 | "evmVersion": "byzantium", 579 | "libraries": {}, 580 | "optimizer": { 581 | "enabled": false, 582 | "runs": 200 583 | }, 584 | "remappings": [] 585 | }, 586 | "sources": { 587 | "./src/tests/assets/token-c.sol": { 588 | "keccak256": "0xa1aa5460a58b4194d92493aab9d0563d473334b7b041deec52521021731e54ca", 589 | "urls": [ 590 | "bzzr://b0df5d16201c7a36603a09d31af445f8687731d34689d1ca13f4d168f8adde2c" 591 | ] 592 | } 593 | }, 594 | "version": 1 595 | }, 596 | "userdoc": { 597 | "methods": {} 598 | } 599 | } 600 | } -------------------------------------------------------------------------------- /packages/specron-spec/src/tests/assets/scaffold-ecrecover.json: -------------------------------------------------------------------------------- 1 | { 2 | "recoverContract": { 3 | "abi": [ 4 | { 5 | "constant": true, 6 | "inputs": [ 7 | { 8 | "name": "_data", 9 | "type": "bytes32" 10 | }, 11 | { 12 | "name": "_r", 13 | "type": "bytes32" 14 | }, 15 | { 16 | "name": "_s", 17 | "type": "bytes32" 18 | }, 19 | { 20 | "name": "_v", 21 | "type": "uint8" 22 | } 23 | ], 24 | "name": "recover", 25 | "outputs": [ 26 | { 27 | "name": "", 28 | "type": "address" 29 | } 30 | ], 31 | "payable": false, 32 | "stateMutability": "view", 33 | "type": "function" 34 | } 35 | ], 36 | "devdoc": { 37 | "methods": {} 38 | }, 39 | "evm": { 40 | "assembly": " /* \"./src/tests/assets/token-c.sol\":26:140 contract Main {... */\n mstore(0x40, 0x80)\n callvalue\n /* \"--CODEGEN--\":8:17 */\n dup1\n /* \"--CODEGEN--\":5:7 */\n iszero\n tag_1\n jumpi\n /* \"--CODEGEN--\":30:31 */\n 0x0\n /* \"--CODEGEN--\":27:28 */\n dup1\n /* \"--CODEGEN--\":20:32 */\n revert\n /* \"--CODEGEN--\":5:7 */\ntag_1:\n /* \"./src/tests/assets/token-c.sol\":26:140 contract Main {... */\n pop\n dataSize(sub_0)\n dup1\n dataOffset(sub_0)\n 0x0\n codecopy\n 0x0\n return\nstop\n\nsub_0: assembly {\n /* \"./src/tests/assets/token-c.sol\":26:140 contract Main {... */\n mstore(0x40, 0x80)\n jumpi(tag_1, lt(calldatasize, 0x4))\n calldataload(0x0)\n 0x100000000000000000000000000000000000000000000000000000000\n swap1\n div\n 0xffffffff\n and\n dup1\n 0xf8a8fd6d\n eq\n tag_2\n jumpi\n tag_1:\n 0x0\n dup1\n revert\n /* \"./src/tests/assets/token-c.sol\":45:137 function test () ... */\n tag_2:\n callvalue\n /* \"--CODEGEN--\":8:17 */\n dup1\n /* \"--CODEGEN--\":5:7 */\n iszero\n tag_3\n jumpi\n /* \"--CODEGEN--\":30:31 */\n 0x0\n /* \"--CODEGEN--\":27:28 */\n dup1\n /* \"--CODEGEN--\":20:32 */\n revert\n /* \"--CODEGEN--\":5:7 */\n tag_3:\n /* \"./src/tests/assets/token-c.sol\":45:137 function test () ... */\n pop\n tag_4\n jump(tag_5)\n tag_4:\n mload(0x40)\n dup1\n dup3\n dup2\n mstore\n 0x20\n add\n swap2\n pop\n pop\n mload(0x40)\n dup1\n swap2\n sub\n swap1\n return\n tag_5:\n /* \"./src/tests/assets/token-c.sol\":96:110 uint256 _value */\n 0x0\n /* \"./src/tests/assets/token-c.sol\":129:132 100 */\n 0x64\n /* \"./src/tests/assets/token-c.sol\":120:132 _value = 100 */\n swap1\n pop\n /* \"./src/tests/assets/token-c.sol\":45:137 function test () ... */\n swap1\n jump\t// out\n\n auxdata: 0xa165627a7a72305820491e65f4c0b011f7a9235b2e70683b92a0af825141281b409689d2e3417736fb0029\n}\n", 41 | "bytecode": { 42 | "linkReferences": {}, 43 | "object": "608060405234801561001057600080fd5b5061024f806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063388f2c3914610046575b600080fd5b34801561005257600080fd5b5061009e600480360381019080803560001916906020019092919080356000191690602001909291908035600019169060200190929190803560ff1690602001909291905050506100e0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000808560405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b6020831015156101685780518252602082019150602081019050602083039250610143565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209050600181848787604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af115801561020e573d6000803e3d6000fd5b505050602060405103519150509493505050505600a165627a7a72305820287388ff83090f55a037f595097a9dc345adc7346b9cb027e5cac3f973ef7aab0029", 44 | "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x24F DUP1 PUSH2 0x20 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x41 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0x388F2C39 EQ PUSH2 0x46 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH2 0x52 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x9E PUSH1 0x4 DUP1 CALLDATASIZE SUB DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH1 0x0 NOT AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH1 0x0 NOT AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH1 0x0 NOT AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH1 0xFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0xE0 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH1 0x40 MLOAD PUSH1 0x20 ADD DUP1 DUP1 PUSH32 0x19457468657265756D205369676E6564204D6573736167653A0A333200000000 DUP2 MSTORE POP PUSH1 0x1C ADD DUP3 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE PUSH1 0x40 MLOAD DUP1 DUP3 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 JUMPDEST PUSH1 0x20 DUP4 LT ISZERO ISZERO PUSH2 0x168 JUMPI DUP1 MLOAD DUP3 MSTORE PUSH1 0x20 DUP3 ADD SWAP2 POP PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH1 0x20 DUP4 SUB SWAP3 POP PUSH2 0x143 JUMP JUMPDEST PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB DUP1 NOT DUP3 MLOAD AND DUP2 DUP5 MLOAD AND DUP1 DUP3 OR DUP6 MSTORE POP POP POP POP POP POP SWAP1 POP ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 KECCAK256 SWAP1 POP PUSH1 0x1 DUP2 DUP5 DUP8 DUP8 PUSH1 0x40 MLOAD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MSTORE PUSH1 0x40 MLOAD DUP1 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD DUP5 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP4 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP5 POP POP POP POP POP PUSH1 0x20 PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 SUB SWAP1 DUP1 DUP5 SUB SWAP1 PUSH1 0x0 DUP7 GAS CALL ISZERO DUP1 ISZERO PUSH2 0x20E JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP PUSH1 0x20 PUSH1 0x40 MLOAD SUB MLOAD SWAP2 POP POP SWAP5 SWAP4 POP POP POP POP JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0x28 PUSH20 0x88FF83090F55A037F595097A9DC345ADC7346B9C 0xb0 0x27 0xe5 0xca 0xc3 0xf9 PUSH20 0xEF7AAB0029000000000000000000000000000000 ", 45 | "sourceMap": "26:413:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26:413:0;;;;;;;" 46 | }, 47 | "deployedBytecode": { 48 | "linkReferences": {}, 49 | "object": "608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063f8a8fd6d146044575b600080fd5b348015604f57600080fd5b506056606c565b6040518082815260200191505060405180910390f35b600060649050905600a165627a7a72305820491e65f4c0b011f7a9235b2e70683b92a0af825141281b409689d2e3417736fb0029", 50 | "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x3F JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0xF8A8FD6D EQ PUSH1 0x44 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x4F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x56 PUSH1 0x6C JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 PUSH1 0x64 SWAP1 POP SWAP1 JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0x49 0x1e PUSH6 0xF4C0B011F7A9 0x23 JUMPDEST 0x2e PUSH17 0x683B92A0AF825141281B409689D2E34177 CALLDATASIZE CREATE2 STOP 0x29 ", 51 | "sourceMap": "26:114:2:-;;;;;;;;;;;;;;;;;;;;;;;;45:92;;8:9:-1;5:2;;;30:1;27;20:12;5:2;45:92:2;;;;;;;;;;;;;;;;;;;;;;;;96:14;129:3;120:12;;45:92;:::o" 52 | }, 53 | "gasEstimates": { 54 | "Creation": { 55 | "codeDepositCost": "118200", 56 | "executionCost": "165", 57 | "totalCost": "118365" 58 | }, 59 | "External": { 60 | "recover(bytes32,bytes32,bytes32,uint8)": "infinite" 61 | } 62 | }, 63 | "methodIdentifiers": { 64 | "test()": "f8a8fd6d" 65 | } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /packages/specron-spec/src/tests/core/context.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import Web3 from 'web3'; 3 | import { Sandbox } from '@specron/sandbox'; 4 | import { Context, Stage, Reporter } from '../..'; 5 | 6 | const web3 = new Web3(Sandbox.createProvider()); 7 | const reporter = new Reporter({ mute: true }); 8 | const stage = new Stage(web3, reporter); 9 | 10 | test('variable `web3` exposes the web3 instance', async (t) => { 11 | const stage = new Stage(web3, reporter); 12 | const ctx = new Context(stage); 13 | t.is(ctx.web3, web3); 14 | }); 15 | 16 | test('method `deploy` deploys contract from JSON file', async (t) => { 17 | const stage = new Stage(web3, reporter); 18 | const ctx = new Context(stage); 19 | const contact = await ctx.deploy({ 20 | src: './src/tests/assets/scaffold-b.json', 21 | contract: 'Main', 22 | }); 23 | 24 | t.is(contact.instance.options.gas, 6000000); 25 | t.is(contact.instance.options.from, await stage.web3.eth.getAccounts().then((a) => a[0])); 26 | 27 | const res = await contact.instance.methods.test().call(); 28 | t.is(res, '100'); 29 | }); 30 | 31 | test('method `tuple` transforms an object to tuple type', async (t) => { 32 | const ctx = new Context(stage); 33 | const tuple = ctx.tuple({ 34 | foo: "FOO", 35 | }); 36 | t.deepEqual(tuple, [ 37 | "FOO", 38 | ]); 39 | }); 40 | 41 | test('method `sign` creates a signature and validates it', async (t) => { 42 | const ctx = new Context(stage); 43 | const data = web3.utils.randomHex(32); 44 | 45 | const signatureData = await ctx.sign({ data }); 46 | 47 | const recover = await ctx.deploy({ 48 | src: './src/tests/assets/scaffold-ecrecover.json', 49 | contract: 'recoverContract', 50 | }); 51 | const address = await recover.instance.methods.recover(data, signatureData.r, signatureData.s, signatureData.v).call(); 52 | t.is(address, await stage.web3.eth.getAccounts().then((a) => a[0])); 53 | }); 54 | 55 | test('method `reverts` asserts that function throws a revert error', async (t) => { 56 | const ctx = new Context(stage); 57 | const results = [ 58 | ctx.reverts(() => { throw new Error('revert'); }), 59 | await ctx.reverts(() => Promise.reject('revert'), 'foo'), 60 | await ctx.reverts(() => Promise.reject(new Error('revert foo')), 'foo'), 61 | ctx.reverts(() => { return; }, 'foo'), 62 | await ctx.reverts(() => Promise.resolve()), 63 | ]; 64 | t.deepEqual(results, [ 65 | { 66 | type: 'AssertionNote', 67 | message: null, 68 | assertion: 'reverts', 69 | success: true, 70 | }, 71 | { 72 | type: 'AssertionNote', 73 | message: 'foo', 74 | assertion: 'reverts', 75 | success: false, 76 | }, 77 | { 78 | type: 'AssertionNote', 79 | message: 'foo', 80 | assertion: 'reverts', 81 | success: true, 82 | }, 83 | { 84 | type: 'AssertionNote', 85 | message: 'foo', 86 | assertion: 'reverts', 87 | success: false, 88 | }, 89 | { 90 | type: 'AssertionNote', 91 | message: null, 92 | assertion: 'reverts', 93 | success: false, 94 | }, 95 | ]); 96 | }); 97 | -------------------------------------------------------------------------------- /packages/specron-spec/src/tests/core/runner.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import { Runner } from '../..'; 3 | 4 | test('method `require` loads spec files based on pattern', async (t) => { 5 | const runner = new Runner(); 6 | await runner.require('./src/tests/assets/*.hay.ts'); 7 | t.is(runner.results.length, 1); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/specron-spec/src/tests/core/stage.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import Web3 from 'web3'; 3 | import { Sandbox } from '@specron/sandbox'; 4 | import { Stage, Reporter } from '../..'; 5 | import { deploy } from '../../methods/deploy'; 6 | 7 | const web3 = new Web3(Sandbox.createProvider()); 8 | const reporter = new Reporter(); 9 | 10 | test('variable `web3` exposes the web3 instance', async (t) => { 11 | const stage = new Stage(web3, reporter); 12 | t.is(stage.web3, web3); 13 | }); 14 | 15 | test('method `tuple` transforms an object to tuple type', async (t) => { 16 | const stage = new Stage(web3, reporter); 17 | const tuple = stage.tuple({ 18 | foo: "FOO", 19 | }); 20 | t.deepEqual(tuple, [ 21 | "FOO", 22 | ]); 23 | }); 24 | 25 | test('method `sign` creates a signature and validates it', async (t) => { 26 | const stage = new Stage(web3, reporter); 27 | const data = web3.utils.randomHex(32); 28 | 29 | const signatureData = await stage.sign({ data }); 30 | 31 | const recover = await deploy({ 32 | web3, 33 | from: await web3.eth.getAccounts().then((a) => a[0]), 34 | gas: 6000000, 35 | gasPrice: 1, 36 | src: './src/tests/assets/scaffold-ecrecover.json', 37 | contract: 'recoverContract', 38 | }); 39 | const address = await recover.instance.methods.recover(data, signatureData.r, signatureData.s, signatureData.v).call(); 40 | 41 | t.is(address, await stage.web3.eth.getAccounts().then((a) => a[0])); 42 | }); 43 | -------------------------------------------------------------------------------- /packages/specron-spec/src/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import * as spec from '..'; 3 | 4 | test('exposes Context class', async (t) => { 5 | t.true(!!spec.Context); 6 | }); 7 | 8 | test('exposes Runner class', async (t) => { 9 | t.true(!!spec.Runner); 10 | }); 11 | 12 | test('exposes Spec class', async (t) => { 13 | t.true(!!spec.Spec); 14 | }); 15 | 16 | test('exposes Stage class', async (t) => { 17 | t.true(!!spec.Stage); 18 | }); 19 | 20 | -------------------------------------------------------------------------------- /packages/specron-spec/src/tests/methods/deploy.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import Web3 from 'web3'; 3 | import { Sandbox } from '@specron/sandbox'; 4 | import { deploy } from '../../methods/deploy'; 5 | 6 | const web3 = new Web3(Sandbox.createProvider({ port: 8545 })); 7 | 8 | test('deploys contract from specron file', async (t) => { 9 | const contact = await deploy({ 10 | web3, 11 | from: await web3.eth.getAccounts().then((a) => a[0]), 12 | gas: 6000000, 13 | gasPrice: 1, 14 | src: './src/tests/assets/scaffold-b.json', 15 | contract: 'Main', 16 | }); 17 | const res = await contact.instance.methods.test().call(); 18 | t.is(res, '100'); 19 | }); 20 | 21 | test('deploys contract from truffle file', async (t) => { 22 | const contact = await deploy({ 23 | web3, 24 | from: await web3.eth.getAccounts().then((a) => a[0]), 25 | gas: 6000000, 26 | gasPrice: 1, 27 | src: './src/tests/assets/scaffold-a.json', 28 | }); 29 | const res = await contact.instance.methods.test().call(); 30 | t.is(res, '123457'); 31 | }); 32 | 33 | test('deploys contract from node_modules', async (t) => { 34 | try { 35 | await deploy({ 36 | web3, 37 | from: await web3.eth.getAccounts().then((a) => a[0]), 38 | gas: 6000000, 39 | gasPrice: 1, 40 | src: '@0xcert/ethereum-utils-contracts/build/ownable.json', 41 | contract: 'Ownable', 42 | }); 43 | t.pass(); 44 | } catch (e) { 45 | t.fail(); 46 | } 47 | }); 48 | -------------------------------------------------------------------------------- /packages/specron-spec/src/tests/methods/sign.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import Web3 from 'web3'; 3 | import { Sandbox } from '@specron/sandbox'; 4 | import { SignatureKind } from '../../core/types'; 5 | import { sign } from '../../methods/sign'; 6 | import { deploy } from '../../methods/deploy'; 7 | 8 | const web3 = new Web3(Sandbox.createProvider({ port: 8545 })); 9 | 10 | test('performs eth sign', async (t) => { 11 | const signer = await web3.eth.getAccounts().then((a) => a[0]); 12 | const data = web3.utils.randomHex(32); 13 | 14 | const signatureData = await sign({ 15 | web3, 16 | kind: SignatureKind.ETH_SIGN, 17 | data, 18 | signer 19 | }); 20 | 21 | const recover = await deploy({ 22 | web3, 23 | from: await web3.eth.getAccounts().then((a) => a[0]), 24 | gas: 6000000, 25 | gasPrice: 1, 26 | src: './src/tests/assets/scaffold-ecrecover.json', 27 | contract: 'recoverContract', 28 | }); 29 | const address = await recover.instance.methods.recover(data, signatureData.r, signatureData.s, signatureData.v).call(); 30 | 31 | t.is(address, signer); 32 | }); 33 | 34 | test('performs eth sign with string data', async (t) => { 35 | const signer = await web3.eth.getAccounts().then((a) => a[0]); 36 | const data = 'test'; 37 | 38 | const signatureData = await sign({ 39 | web3, 40 | kind: SignatureKind.ETH_SIGN, 41 | data, 42 | signer 43 | }); 44 | 45 | t.not(signatureData, null); 46 | }); 47 | -------------------------------------------------------------------------------- /packages/specron-spec/src/tests/methods/tuple.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import { tuple } from '../../methods/tuple'; 3 | 4 | test('transforms an object to tuple', async (t) => { 5 | const res = tuple({ 6 | foo: "FOO", 7 | bar: ["BAR1", "BAR2"], 8 | baz: { 9 | bazfoo: [1, 2], 10 | bazbar: 'BAZBAR', 11 | }, 12 | zed: [ 13 | { 14 | zedfoo: [1, 2], 15 | zedbar: 'BAZBAR', 16 | } 17 | ] 18 | }); 19 | t.deepEqual(res, [ 20 | "FOO", 21 | ["BAR1", "BAR2"], 22 | [[1, 2], 'BAZBAR'], 23 | [[[1, 2], 'BAZBAR']], 24 | ]); 25 | }); 26 | -------------------------------------------------------------------------------- /packages/specron-spec/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "sourceMap": true, 8 | "outDir": "dist", 9 | "declaration": true, 10 | "esModuleInterop": true 11 | } 12 | } -------------------------------------------------------------------------------- /rush.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json", 3 | "rushVersion": "5.13.1", 4 | "npmVersion": "6.11.3", 5 | "nodeSupportedVersionRange": ">=11.0.0", 6 | "gitPolicy": {}, 7 | "repository": {}, 8 | "eventHooks": { 9 | "preRushInstall": [], 10 | "postRushInstall": [], 11 | "preRushBuild": [], 12 | "postRushBuild": [] 13 | }, 14 | "projects": [ 15 | { 16 | "packageName": "@specron/cli", 17 | "projectFolder": "packages/specron-cli", 18 | "versionPolicyName": "patchAll" 19 | }, 20 | { 21 | "packageName": "@specron/compiler", 22 | "projectFolder": "packages/specron-compiler", 23 | "versionPolicyName": "patchAll" 24 | }, 25 | { 26 | "packageName": "@specron/flattener", 27 | "projectFolder": "packages/specron-flattener", 28 | "versionPolicyName": "patchAll" 29 | }, 30 | { 31 | "packageName": "@specron/init", 32 | "projectFolder": "packages/specron-init", 33 | "versionPolicyName": "patchAll" 34 | }, 35 | { 36 | "packageName": "@specron/sandbox", 37 | "projectFolder": "packages/specron-sandbox", 38 | "versionPolicyName": "patchAll" 39 | }, 40 | { 41 | "packageName": "@specron/spec", 42 | "projectFolder": "packages/specron-spec", 43 | "versionPolicyName": "patchAll" 44 | } 45 | ] 46 | } 47 | --------------------------------------------------------------------------------