├── test ├── evm │ ├── tronbox-config.js │ ├── .gitignore │ ├── test │ │ ├── .git-folder-keeper │ │ ├── metacoin.js │ │ └── mycontract.js │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── contracts │ │ ├── ConvertLib.sol │ │ ├── Migrations.sol │ │ ├── MyContract1.sol │ │ ├── MyContract2.sol │ │ └── MetaCoin.sol │ ├── tronbox-evm-config.js │ └── tronbox.js ├── tre │ ├── .gitignore │ ├── tronbox-config.js │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── contracts │ │ ├── ConvertLib.sol │ │ ├── Migrations.sol │ │ └── MetaCoin.sol │ ├── test │ │ ├── helpers │ │ │ ├── wait.js │ │ │ └── shallowEqual.js │ │ └── metacoin.js │ └── tronbox.js ├── consolelogs │ ├── tronbox-config.js │ ├── .gitignore │ ├── test │ │ ├── .git-folder-keeper │ │ └── testLogs.js │ ├── runTest.sh │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── contracts │ │ └── Migrations.sol │ └── tronbox.js ├── abiv2 │ ├── .gitignore │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── contracts │ │ ├── Migrations.sol │ │ └── Tuple.sol │ ├── tronbox.js │ └── test │ │ └── tuple.js ├── fixtures │ ├── metacoin-box-0.4.0 │ │ ├── .gitignore │ │ ├── migrations │ │ │ ├── 1_initial_migration.js │ │ │ └── 2_deploy_contracts.js │ │ ├── contracts │ │ │ ├── ConvertLib.sol │ │ │ ├── Migrations.sol │ │ │ └── MetaCoin.sol │ │ ├── test │ │ │ ├── helpers │ │ │ │ └── wait.js │ │ │ └── metacoin.js │ │ ├── package.json │ │ └── tronbox.js │ ├── metacoin-box-0.5.0 │ │ ├── .gitignore │ │ ├── migrations │ │ │ ├── 1_initial_migration.js │ │ │ └── 2_deploy_contracts.js │ │ ├── contracts │ │ │ ├── ConvertLib.sol │ │ │ ├── Migrations.sol │ │ │ └── MetaCoin.sol │ │ ├── test │ │ │ ├── helpers │ │ │ │ └── wait.js │ │ │ └── metacoin.js │ │ ├── package.json │ │ └── tronbox.js │ └── metacoin-box-0.6.0 │ │ ├── .gitignore │ │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ │ ├── contracts │ │ ├── ConvertLib.sol │ │ ├── Migrations.sol │ │ └── MetaCoin.sol │ │ ├── test │ │ ├── helpers │ │ │ └── wait.js │ │ └── metacoin.js │ │ ├── package.json │ │ └── tronbox.js ├── runTest.sh └── runNile.sh ├── tronbox.dev ├── scripts ├── tronbox.js └── build.sh ├── .npmignore ├── assets └── TronBox-logo.png ├── sample-projects ├── javascript │ ├── sample-env │ ├── test │ │ └── .git-folder-keeper │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── contracts │ │ └── Migrations.sol │ ├── tronbox-evm-config.js │ ├── tronbox-config.js │ ├── README.md │ └── .gitignore └── javascript-metacoin │ ├── sample-env │ ├── migrations │ ├── 1_initial_migration.js │ └── 2_deploy_contracts.js │ ├── test │ └── helpers │ │ └── wait.js │ ├── contracts │ ├── Migrations.sol │ ├── ConvertLib.sol │ └── MetaCoin.sol │ ├── package.json │ ├── package-lock.json │ ├── tronbox-evm-config.js │ ├── tronbox-config.js │ ├── README.md │ └── .gitignore ├── src ├── lib │ ├── version.js │ ├── require-nocache.js │ ├── errors │ │ ├── taskerror.js │ │ ├── configurationerror.js │ │ ├── builderror.js │ │ └── deployerror.js │ ├── testing │ │ ├── SafeSend.sol │ │ ├── testresolver.js │ │ ├── deployed.js │ │ └── testsource.js │ ├── commands │ │ ├── deploy.js │ │ ├── index.js │ │ ├── build.js │ │ ├── serve.js │ │ ├── help.js │ │ ├── version.js │ │ ├── flatten.js │ │ ├── init.js │ │ ├── compile.js │ │ ├── console.js │ │ ├── watch.js │ │ ├── convert.js │ │ ├── migrate.js │ │ └── unbox.js │ ├── assertions.js │ ├── serve.js │ ├── copy.js │ ├── repl.js │ ├── environment.js │ ├── command.js │ └── build.js ├── components │ ├── Compile │ │ ├── messages.js │ │ └── compileerror.js │ ├── Deployer │ │ ├── src │ │ │ ├── actions │ │ │ │ ├── link.js │ │ │ │ ├── new.js │ │ │ │ ├── deploymany.js │ │ │ │ └── deploy.js │ │ │ ├── deferredchain.js │ │ │ └── linker.js │ │ └── index.js │ ├── TronWrap │ │ └── constants.js │ ├── Provisioner.js │ ├── Box │ │ ├── index.js │ │ └── lib │ │ │ ├── config.js │ │ │ └── utils │ │ │ └── index.js │ ├── Contract │ │ ├── index.js │ │ └── statuserror.js │ ├── Provider │ │ ├── error.js │ │ └── index.js │ ├── waitForTransactionReceipt.js │ ├── Migrate │ │ └── resolverintercept.js │ ├── ContractSchema │ │ └── spec │ │ │ ├── network-object.spec.json │ │ │ └── contract-object.spec.json │ ├── Resolver │ │ ├── npm.js │ │ ├── index.js │ │ └── fs.js │ ├── TronSolc.js │ ├── Artifactor.js │ └── Require.js ├── exec.js ├── index.js └── downloader.js ├── .babelrc ├── .prettierrc.json ├── LICENSE ├── CONTRIBUTING.md ├── eslint.config.js ├── .gitignore └── package.json /test/evm/tronbox-config.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /test/tre/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .env -------------------------------------------------------------------------------- /test/tre/tronbox-config.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /tronbox.dev: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('./src'); 3 | -------------------------------------------------------------------------------- /scripts/tronbox.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('.') 3 | -------------------------------------------------------------------------------- /test/consolelogs/tronbox-config.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.vscode 3 | /.idea 4 | /assets 5 | /scripts 6 | /src 7 | /test 8 | -------------------------------------------------------------------------------- /test/abiv2/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | src/js/metacoin-config.js 3 | node_modules 4 | build 5 | .env 6 | 7 | -------------------------------------------------------------------------------- /test/evm/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | src/js/metacoin-config.js 3 | node_modules 4 | build 5 | .env 6 | 7 | -------------------------------------------------------------------------------- /assets/TronBox-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tronprotocol/tronbox/HEAD/assets/TronBox-logo.png -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.4.0/.gitignore: -------------------------------------------------------------------------------- 1 | src/js/metacoin-config.js 2 | node_modules 3 | build 4 | .env -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.5.0/.gitignore: -------------------------------------------------------------------------------- 1 | src/js/metacoin-config.js 2 | node_modules 3 | build 4 | .env -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.6.0/.gitignore: -------------------------------------------------------------------------------- 1 | src/js/metacoin-config.js 2 | node_modules 3 | build 4 | .env -------------------------------------------------------------------------------- /test/consolelogs/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | src/js/metacoin-config.js 3 | node_modules 4 | build 5 | .env 6 | 7 | actual.log 8 | 9 | -------------------------------------------------------------------------------- /sample-projects/javascript/sample-env: -------------------------------------------------------------------------------- 1 | export PRIVATE_KEY_NILE=0000000000000000000000000000000000000000000000000000000000000001 2 | -------------------------------------------------------------------------------- /src/lib/version.js: -------------------------------------------------------------------------------- 1 | const bundle = require('../../package.json'); 2 | 3 | module.exports = { 4 | bundle: bundle.version 5 | }; 6 | -------------------------------------------------------------------------------- /test/evm/test/.git-folder-keeper: -------------------------------------------------------------------------------- 1 | This is a placeholder file to ensure the parent directory in the git repository. Feel free to remove. 2 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/sample-env: -------------------------------------------------------------------------------- 1 | export PRIVATE_KEY_SHASTA=0000000000000000000000000000000000000000000000000000000000000001 2 | -------------------------------------------------------------------------------- /test/consolelogs/test/.git-folder-keeper: -------------------------------------------------------------------------------- 1 | This is a placeholder file to ensure the parent directory in the git repository. Feel free to remove. 2 | -------------------------------------------------------------------------------- /sample-projects/javascript/test/.git-folder-keeper: -------------------------------------------------------------------------------- 1 | This is a placeholder file to ensure the parent directory in the git repository. Feel free to remove. 2 | -------------------------------------------------------------------------------- /src/components/Compile/messages.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preReleaseCompilerWarning: 'This is a pre-release compiler version, please do not use it in production.' 3 | }; 4 | -------------------------------------------------------------------------------- /test/abiv2/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('./Migrations.sol'); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /test/consolelogs/runTest.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | rm -rf build 4 | rm actual.log 5 | TRONBOX_SOLIDITY_CONSOLE_LOG=true ../../tronbox.dev migrate --quiet > actual.log 6 | ../../tronbox.dev test -------------------------------------------------------------------------------- /test/tre/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('./Migrations.sol'); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /src/lib/require-nocache.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = function (filePath) { 4 | delete require.cache[path.resolve(filePath)]; 5 | return require(filePath); 6 | }; 7 | -------------------------------------------------------------------------------- /test/evm/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('./Migrations.sol'); 2 | 3 | module.exports = async function (deployer) { 4 | await deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /sample-projects/javascript/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('./Migrations.sol'); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /sample-projects/javascript/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | // const MyContract = artifacts.require('./MyContract.sol'); 2 | 3 | module.exports = function (deployer) { 4 | // deployer.deploy(MyContract); 5 | }; 6 | -------------------------------------------------------------------------------- /test/abiv2/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const Tuple = artifacts.require('./Tuple.sol'); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Tuple, ['Tom', '30'], { overwrite: true }); 5 | }; 6 | -------------------------------------------------------------------------------- /test/consolelogs/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('./Migrations.sol'); 2 | 3 | module.exports = async function (deployer) { 4 | await deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.4.0/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('./Migrations.sol'); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.5.0/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('./Migrations.sol'); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.6.0/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('./Migrations.sol'); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env" 4 | ], 5 | "plugins": [ 6 | ["@babel/plugin-transform-runtime", 7 | { 8 | "regenerator": true 9 | } 10 | ] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/lib/errors/taskerror.js: -------------------------------------------------------------------------------- 1 | const TruffleError = require('@truffle/error'); 2 | class TaskError extends TruffleError { 3 | constructor(message) { 4 | super(message); 5 | } 6 | } 7 | 8 | module.exports = TaskError; 9 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('./Migrations.sol'); 2 | 3 | module.exports = async function (deployer) { 4 | await deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "semi": true, 4 | "printWidth": 120, 5 | "arrowParens": "avoid", 6 | "trailingComma": "none", 7 | "bracketSpacing": true, 8 | "singleQuote": true, 9 | "quoteProps": "as-needed" 10 | } 11 | -------------------------------------------------------------------------------- /src/components/Deployer/src/actions/link.js: -------------------------------------------------------------------------------- 1 | const Linker = require('../linker'); 2 | 3 | module.exports = function (library, destinations, deployer) { 4 | return function () { 5 | Linker.link(library, destinations, deployer.logger); 6 | }; 7 | }; 8 | -------------------------------------------------------------------------------- /src/lib/errors/configurationerror.js: -------------------------------------------------------------------------------- 1 | const TruffleError = require('@truffle/error'); 2 | 3 | class ConfigurationError extends TruffleError { 4 | constructor(message) { 5 | super(message); 6 | } 7 | } 8 | 9 | module.exports = ConfigurationError; 10 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | rm -rf build 4 | node_modules/.bin/babel --minified --no-comments src -d build 5 | cp -r src/components/ContractSchema/spec build/components/ContractSchema/spec 6 | cp scripts/tronbox.js build/. 7 | chmod +x build/tronbox.js 8 | -------------------------------------------------------------------------------- /test/evm/contracts/ConvertLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | library ConvertLib { 5 | function convert(uint amount, uint conversionRate) public pure returns (uint convertedAmount) { 6 | return amount * conversionRate; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/lib/testing/SafeSend.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.22; 2 | 3 | contract SafeSend { 4 | address public recipient; 5 | 6 | constructor(address _recipient) payable { 7 | recipient = _recipient; 8 | } 9 | 10 | function deliver() { 11 | selfdestruct(recipient); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.4.0/contracts/ConvertLib.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | library ConvertLib { 4 | function convert( 5 | uint amount, 6 | uint conversionRate 7 | ) public pure returns (uint convertedAmount) { 8 | return amount * conversionRate; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/lib/commands/deploy.js: -------------------------------------------------------------------------------- 1 | const migrate = require('./migrate'); 2 | 3 | const command = { 4 | command: 'deploy', 5 | description: '(alias for migrate)', 6 | builder: yargs => { 7 | migrate.builder(yargs, 'deploy'); 8 | }, 9 | run: migrate.run 10 | }; 11 | 12 | module.exports = command; 13 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.5.0/contracts/ConvertLib.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.4 <0.6.0; 2 | 3 | library ConvertLib { 4 | function convert( 5 | uint amount, 6 | uint conversionRate 7 | ) public pure returns (uint convertedAmount) { 8 | return amount * conversionRate; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/tre/contracts/ConvertLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | library ConvertLib { 5 | function convert( 6 | uint256 amount, 7 | uint256 conversionRate 8 | ) public pure returns (uint256 convertedAmount) { 9 | return amount * conversionRate; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/tre/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const ConvertLib = artifacts.require('./ConvertLib.sol'); 2 | const MetaCoin = artifacts.require('./MetaCoin.sol'); 3 | 4 | module.exports = function (deployer) { 5 | deployer.deploy(ConvertLib); 6 | deployer.link(ConvertLib, MetaCoin); 7 | deployer.deploy(MetaCoin, 10000); 8 | }; 9 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.6.0/contracts/ConvertLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.7.0; 3 | 4 | library ConvertLib { 5 | function convert( 6 | uint amount, 7 | uint conversionRate 8 | ) public pure returns (uint convertedAmount) { 9 | return amount * conversionRate; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.4.0/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const ConvertLib = artifacts.require('./ConvertLib.sol'); 2 | const MetaCoin = artifacts.require('./MetaCoin.sol'); 3 | 4 | module.exports = function (deployer) { 5 | deployer.deploy(ConvertLib); 6 | deployer.link(ConvertLib, MetaCoin); 7 | deployer.deploy(MetaCoin, 10000); 8 | }; 9 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.5.0/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const ConvertLib = artifacts.require('./ConvertLib.sol'); 2 | const MetaCoin = artifacts.require('./MetaCoin.sol'); 3 | 4 | module.exports = function (deployer) { 5 | deployer.deploy(ConvertLib); 6 | deployer.link(ConvertLib, MetaCoin); 7 | deployer.deploy(MetaCoin, 10000); 8 | }; 9 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.6.0/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const ConvertLib = artifacts.require('./ConvertLib.sol'); 2 | const MetaCoin = artifacts.require('./MetaCoin.sol'); 3 | 4 | module.exports = function (deployer) { 5 | deployer.deploy(ConvertLib); 6 | deployer.link(ConvertLib, MetaCoin); 7 | deployer.deploy(MetaCoin, 10000); 8 | }; 9 | -------------------------------------------------------------------------------- /src/lib/errors/builderror.js: -------------------------------------------------------------------------------- 1 | const colors = require('colors'); 2 | const TruffleError = require('@truffle/error'); 3 | 4 | class BuildError extends TruffleError { 5 | constructor(message) { 6 | message = 'Error building:\n\n' + message + '\n\n' + colors.red('Build failed. See above.'); 7 | super(message); 8 | } 9 | } 10 | 11 | module.exports = BuildError; 12 | -------------------------------------------------------------------------------- /test/consolelogs/test/testLogs.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | contract('TestLogs', function () { 4 | it('Should successfully output the log', async function () { 5 | const actualStr = fs.readFileSync('actual.log', 'utf-8'); 6 | const expectedStr = fs.readFileSync('expected.log', 'utf-8'); 7 | 8 | assert.equal(actualStr, expectedStr); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /src/components/Deployer/src/actions/new.js: -------------------------------------------------------------------------------- 1 | module.exports = function (contract, args, deployer) { 2 | return function () { 3 | deployer.logger.log('Creating new instance of ' + contract.contract_name); 4 | // Evaluate any arguments if they're promises 5 | return Promise.all(args).then(function () { 6 | return contract.new.apply(contract, args); 7 | }); 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /src/lib/errors/deployerror.js: -------------------------------------------------------------------------------- 1 | const colors = require('colors'); 2 | const TruffleError = require('@truffle/error'); 3 | class DeployError extends TruffleError { 4 | constructor(message) { 5 | message = 'Error deploying ' + contract_name + ':\n\n' + message + '\n\n' + colors.red('Deploy failed. See above.'); 6 | super(message); 7 | } 8 | } 9 | 10 | module.exports = DeployError; 11 | -------------------------------------------------------------------------------- /src/lib/commands/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | init: require('./init'), 3 | compile: require('./compile'), 4 | migrate: require('./migrate'), 5 | deploy: require('./deploy'), 6 | test: require('./test'), 7 | console: require('./console'), 8 | flatten: require('./flatten'), 9 | unbox: require('./unbox'), 10 | help: require('./help'), 11 | version: require('./version') 12 | }; 13 | -------------------------------------------------------------------------------- /test/tre/test/helpers/wait.js: -------------------------------------------------------------------------------- 1 | function sleep(millis) { 2 | return new Promise(resolve => setTimeout(resolve, millis)); 3 | } 4 | 5 | const chalk = require('chalk'); 6 | 7 | function log(x) { 8 | process.stdout.write(chalk.yellow(x)); 9 | } 10 | 11 | module.exports = async function (secs) { 12 | secs = secs || 1; 13 | log(`Sleeping for ${secs} second${secs === 1 ? '' : 's'}...`); 14 | await sleep(1000 * (secs || 1)); 15 | log(' Slept.\n'); 16 | }; 17 | -------------------------------------------------------------------------------- /src/lib/commands/build.js: -------------------------------------------------------------------------------- 1 | const command = { 2 | command: 'build', 3 | description: 'Execute build pipeline (if configuration present)', 4 | builder: {}, 5 | run: function (options, done) { 6 | process.env.CURRENT = 'build'; 7 | const Config = require('../../components/Config'); 8 | const Build = require('../build'); 9 | 10 | const config = Config.detect(options); 11 | Build.build(config, done); 12 | } 13 | }; 14 | 15 | module.exports = command; 16 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/test/helpers/wait.js: -------------------------------------------------------------------------------- 1 | const pc = require('picocolors'); 2 | 3 | function sleep(millis) { 4 | return new Promise(resolve => setTimeout(resolve, millis)); 5 | } 6 | 7 | function log(_) { 8 | process.stdout.write(pc.yellow(_)); 9 | } 10 | 11 | module.exports = async function (secs) { 12 | secs = secs || 1; 13 | log(`Sleeping for ${secs} second${secs === 1 ? '' : 's'}...`); 14 | await sleep(1000 * (secs || 1)); 15 | log(' Slept.\n'); 16 | }; 17 | -------------------------------------------------------------------------------- /test/evm/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | contract Migrations { 5 | address public owner = msg.sender; 6 | uint public last_completed_migration; 7 | 8 | modifier restricted() { 9 | require(msg.sender == owner, "This function is restricted to the contract's owner"); 10 | _; 11 | } 12 | 13 | function setCompleted(uint completed) public restricted { 14 | last_completed_migration = completed; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sample-projects/javascript/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | contract Migrations { 5 | address public owner = msg.sender; 6 | uint public last_completed_migration; 7 | 8 | modifier restricted() { 9 | require(msg.sender == owner, "This function is restricted to the contract's owner"); 10 | _; 11 | } 12 | 13 | function setCompleted(uint completed) public restricted { 14 | last_completed_migration = completed; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | contract Migrations { 5 | address public owner = msg.sender; 6 | uint public last_completed_migration; 7 | 8 | modifier restricted() { 9 | require(msg.sender == owner, "This function is restricted to the contract's owner"); 10 | _; 11 | } 12 | 13 | function setCompleted(uint completed) public restricted { 14 | last_completed_migration = completed; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/consolelogs/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | contract Migrations { 5 | address public owner = msg.sender; 6 | uint public last_completed_migration; 7 | 8 | modifier restricted() { 9 | require( 10 | msg.sender == owner, 11 | "This function is restricted to the contract's owner" 12 | ); 13 | _; 14 | } 15 | 16 | function setCompleted(uint completed) public restricted { 17 | last_completed_migration = completed; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.4.0/test/helpers/wait.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable n/no-unpublished-require */ 2 | function sleep(millis) { 3 | return new Promise(resolve => setTimeout(resolve, millis)); 4 | } 5 | 6 | const chalk = require('chalk'); 7 | 8 | function log(x) { 9 | process.stdout.write(chalk.yellow(x)); 10 | } 11 | 12 | module.exports = async function (secs) { 13 | secs = secs || 1; 14 | log(`Sleeping for ${secs} second${secs === 1 ? '' : 's'}...`); 15 | await sleep(1000 * (secs || 1)); 16 | log(' Slept.\n'); 17 | }; 18 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.5.0/test/helpers/wait.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable n/no-unpublished-require */ 2 | function sleep(millis) { 3 | return new Promise(resolve => setTimeout(resolve, millis)); 4 | } 5 | 6 | const chalk = require('chalk'); 7 | 8 | function log(x) { 9 | process.stdout.write(chalk.yellow(x)); 10 | } 11 | 12 | module.exports = async function (secs) { 13 | secs = secs || 1; 14 | log(`Sleeping for ${secs} second${secs === 1 ? '' : 's'}...`); 15 | await sleep(1000 * (secs || 1)); 16 | log(' Slept.\n'); 17 | }; 18 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.6.0/test/helpers/wait.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable n/no-unpublished-require */ 2 | function sleep(millis) { 3 | return new Promise(resolve => setTimeout(resolve, millis)); 4 | } 5 | 6 | const chalk = require('chalk'); 7 | 8 | function log(x) { 9 | process.stdout.write(chalk.yellow(x)); 10 | } 11 | 12 | module.exports = async function (secs) { 13 | secs = secs || 1; 14 | log(`Sleeping for ${secs} second${secs === 1 ? '' : 's'}...`); 15 | await sleep(1000 * (secs || 1)); 16 | log(' Slept.\n'); 17 | }; 18 | -------------------------------------------------------------------------------- /src/components/Deployer/src/actions/deploymany.js: -------------------------------------------------------------------------------- 1 | const deploy = require('./deploy'); 2 | 3 | module.exports = function (arr, deployer) { 4 | return function () { 5 | const deployments = arr.map(function (args) { 6 | let contract; 7 | 8 | if (Array.isArray(args)) { 9 | contract = args.shift(); 10 | } else { 11 | contract = args; 12 | args = []; 13 | } 14 | 15 | return deploy(contract, args, deployer)(); 16 | }); 17 | 18 | return Promise.all(deployments); 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /src/components/TronWrap/constants.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | deployParameters: { 3 | feeLimit: 1e9, 4 | userFeePercentage: 100, 5 | originEnergyLimit: 1e7, 6 | callValue: 0, 7 | tokenValue: undefined, 8 | tokenId: undefined, 9 | from: undefined, 10 | 11 | // evm 12 | gasPrice: undefined, 13 | gas: undefined, 14 | gasLimit: undefined, 15 | maxPriorityFeePerGas: undefined, 16 | maxFeePerGas: undefined, 17 | nonce: undefined, 18 | type: undefined, 19 | value: 0 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /test/evm/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const MyContract1 = artifacts.require('./MyContract1.sol'); 2 | const MyContract2 = artifacts.require('./MyContract2.sol'); 3 | const ConvertLib = artifacts.require('./ConvertLib.sol'); 4 | const MetaCoin = artifacts.require('./MetaCoin.sol'); 5 | 6 | module.exports = async function (deployer) { 7 | await deployer.deploy(MyContract1, 1); 8 | await deployer.deploy(MyContract2, 2, { value: 1 }); 9 | 10 | await deployer.deploy(ConvertLib); 11 | deployer.link(ConvertLib, MetaCoin); 12 | await deployer.deploy(MetaCoin, 10000); 13 | }; 14 | -------------------------------------------------------------------------------- /src/components/Provisioner.js: -------------------------------------------------------------------------------- 1 | const provision = function (abstraction, options) { 2 | if (options.provider) { 3 | abstraction.setProvider(options.provider); 4 | } 5 | 6 | if (options.network_id) { 7 | abstraction.setNetwork(options.network_id); 8 | } 9 | 10 | ['from', 'fee_limit', 'consume_user_resource_percent', 'privateKey', 'call_value'].forEach(function (key) { 11 | if (options[key]) { 12 | const obj = {}; 13 | obj[key] = options[key]; 14 | abstraction.defaults(obj); 15 | } 16 | }); 17 | 18 | return abstraction; 19 | }; 20 | 21 | module.exports = provision; 22 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "metacoin", 3 | "version": "3.0.0", 4 | "description": "MetaCoin smart contract example for Tronbox", 5 | "scripts": { 6 | "test": "tronbox test" 7 | }, 8 | "keywords": [ 9 | "tron", 10 | "tronbox", 11 | "contracts", 12 | "solidity" 13 | ], 14 | "originalAuthors": "truffle-box", 15 | "author": { 16 | "name": "Francesco Sullo", 17 | "email": "francesco@sullo.co" 18 | }, 19 | "license": "MIT", 20 | "dependencies": { 21 | "@openzeppelin/contracts": "5.4.0", 22 | "picocolors": "1.1.1" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/exec.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const spawn = require('child_process').spawn; 3 | 4 | const cli_path = path.resolve(path.join(__dirname, './index.js')); 5 | 6 | const args = [cli_path, 'exec']; 7 | 8 | Array.prototype.push.apply(args, process.argv.slice(2)); 9 | 10 | const cmd = spawn('node', args); 11 | 12 | cmd.stdout.on('data', data => { 13 | console.info(data.toString()); 14 | }); 15 | 16 | cmd.stderr.on('data', data => { 17 | console.error(data.toString()); 18 | }); 19 | 20 | cmd.on('close', code => { 21 | process.exit(code); 22 | }); 23 | 24 | cmd.on('error', function (err) { 25 | throw err; 26 | }); 27 | -------------------------------------------------------------------------------- /src/components/Box/index.js: -------------------------------------------------------------------------------- 1 | const utils = require('./lib/utils'); 2 | 3 | class Box { 4 | static async unbox(url, destination, options) { 5 | options = options || {}; 6 | options.logger = options.logger || { 7 | log: function () {} 8 | }; 9 | 10 | options.logger.log('Downloading...'); 11 | await utils.downloadBox(url, destination); 12 | 13 | options.logger.log('Unpacking...'); 14 | const boxConfig = await utils.unpackBox(destination); 15 | 16 | options.logger.log('Setting up...'); 17 | await utils.setupBox(boxConfig, destination); 18 | return boxConfig; 19 | } 20 | } 21 | 22 | module.exports = Box; 23 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.4.0/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | constructor() public { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) public restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.5.0/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >0.4.18 <0.6.0; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | constructor() public { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) public restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/lib/commands/serve.js: -------------------------------------------------------------------------------- 1 | const command = { 2 | command: 'serve', 3 | description: 'Serve the build directory on localhost and watch for changes', 4 | builder: { 5 | port: { 6 | alias: 'p', 7 | default: '8080' 8 | } 9 | }, 10 | run: function (options, done) { 11 | process.env.CURRENT = 'serve'; 12 | const Serve = require('../serve'); 13 | const Config = require('../../components/Config'); 14 | const watch = require('./watch'); 15 | 16 | const config = Config.detect(options); 17 | Serve.start(config, function () { 18 | watch.run(options, done); 19 | }); 20 | } 21 | }; 22 | 23 | module.exports = command; 24 | -------------------------------------------------------------------------------- /src/components/Contract/index.js: -------------------------------------------------------------------------------- 1 | const Schema = require('../ContractSchema'); 2 | const Contract = require('./contract.js'); 3 | 4 | const contract = function (options) { 5 | const binary = Schema.normalize(options || {}); 6 | 7 | // We retrieve the tronweb instance. 8 | // TronWeb should be already initiated at this point. 9 | Contract.initTronWeb(); 10 | 11 | // Note we don't use `new` here at all. This will cause the class to 12 | // "mutate" instead of instantiate an instance. 13 | return Contract.clone(binary); 14 | }; 15 | 16 | module.exports = contract; 17 | 18 | if (typeof window !== 'undefined') { 19 | window.TruffleContract = contract; 20 | } 21 | -------------------------------------------------------------------------------- /test/abiv2/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | contract Migrations { 5 | address public owner; 6 | uint public last_completed_migration; 7 | 8 | modifier restricted() { 9 | if (msg.sender == owner) _; 10 | } 11 | 12 | constructor() { 13 | owner = msg.sender; 14 | } 15 | 16 | function setCompleted(uint completed) public restricted { 17 | last_completed_migration = completed; 18 | } 19 | 20 | function upgrade(address new_address) public restricted { 21 | Migrations upgraded = Migrations(new_address); 22 | upgraded.setCompleted(last_completed_migration); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/tre/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | contract Migrations { 5 | address public owner; 6 | uint public last_completed_migration; 7 | 8 | modifier restricted() { 9 | if (msg.sender == owner) _; 10 | } 11 | 12 | constructor() { 13 | owner = msg.sender; 14 | } 15 | 16 | function setCompleted(uint completed) public restricted { 17 | last_completed_migration = completed; 18 | } 19 | 20 | function upgrade(address new_address) public restricted { 21 | Migrations upgraded = Migrations(new_address); 22 | upgraded.setCompleted(last_completed_migration); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.4.0/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "metacoin-box", 3 | "version": "2.0.6", 4 | "description": "", 5 | "directories": { 6 | "test": "test" 7 | }, 8 | "scripts": { 9 | "dev": "lite-server -c ./bs-config.js", 10 | "test": "echo \\\"Error: no test specified\\\" && exit 1", 11 | "setup-dapp": "bash scripts/migrate-and-setup.sh" 12 | }, 13 | "originalAuthors": "truffle-box", 14 | "author": { 15 | "name": "Francesco Sullo", 16 | "email": "francesco@sullo.co" 17 | }, 18 | "license": "MIT", 19 | "devDependencies": { 20 | "chalk": "^2.4.1", 21 | "lite-server": "^2.4.0" 22 | }, 23 | "dependencies": {} 24 | } 25 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.5.0/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "metacoin-box", 3 | "version": "2.0.6", 4 | "description": "", 5 | "directories": { 6 | "test": "test" 7 | }, 8 | "scripts": { 9 | "dev": "lite-server -c ./bs-config.js", 10 | "test": "echo \\\"Error: no test specified\\\" && exit 1", 11 | "setup-dapp": "bash scripts/migrate-and-setup.sh" 12 | }, 13 | "originalAuthors": "truffle-box", 14 | "author": { 15 | "name": "Francesco Sullo", 16 | "email": "francesco@sullo.co" 17 | }, 18 | "license": "MIT", 19 | "devDependencies": { 20 | "chalk": "^2.4.1", 21 | "lite-server": "^2.4.0" 22 | }, 23 | "dependencies": {} 24 | } 25 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.6.0/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "metacoin-box", 3 | "version": "2.0.6", 4 | "description": "", 5 | "directories": { 6 | "test": "test" 7 | }, 8 | "scripts": { 9 | "dev": "lite-server -c ./bs-config.js", 10 | "test": "echo \\\"Error: no test specified\\\" && exit 1", 11 | "setup-dapp": "bash scripts/migrate-and-setup.sh" 12 | }, 13 | "originalAuthors": "truffle-box", 14 | "author": { 15 | "name": "Francesco Sullo", 16 | "email": "francesco@sullo.co" 17 | }, 18 | "license": "MIT", 19 | "devDependencies": { 20 | "chalk": "^2.4.1", 21 | "lite-server": "^2.4.0" 22 | }, 23 | "dependencies": {} 24 | } 25 | -------------------------------------------------------------------------------- /test/evm/contracts/MyContract1.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | contract MyContract1 { 5 | uint256 public myNumber; 6 | 7 | constructor(uint256 _myNumber) { 8 | myNumber = _myNumber; 9 | } 10 | 11 | function setMyNumber(uint256 _myNumber) public { 12 | myNumber = _myNumber; 13 | } 14 | 15 | function getBalance(address _addr) public view returns (uint256 balance) { 16 | balance = _addr.balance; 17 | } 18 | 19 | function myAddress() public view returns (address addr) { 20 | addr = address(this); 21 | } 22 | 23 | function getSender() public view returns (address addr) { 24 | addr = msg.sender; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/evm/contracts/MyContract2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | contract MyContract2 { 5 | uint256 public myNumber; 6 | 7 | constructor(uint256 _myNumber) payable { 8 | myNumber = _myNumber; 9 | } 10 | 11 | function setMyNumber(uint256 _myNumber) public payable { 12 | myNumber = _myNumber; 13 | } 14 | 15 | function getBalance(address _addr) public view returns (uint256 balance) { 16 | balance = _addr.balance; 17 | } 18 | 19 | function myAddress() public view returns (address addr) { 20 | addr = address(this); 21 | } 22 | 23 | function getSender() public view returns (address addr) { 24 | addr = msg.sender; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.6.0/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.7.0; 3 | 4 | contract Migrations { 5 | address public owner; 6 | uint public last_completed_migration; 7 | 8 | modifier restricted() { 9 | if (msg.sender == owner) _; 10 | } 11 | 12 | constructor() public { 13 | owner = msg.sender; 14 | } 15 | 16 | function setCompleted(uint completed) public restricted { 17 | last_completed_migration = completed; 18 | } 19 | 20 | function upgrade(address new_address) public restricted { 21 | Migrations upgraded = Migrations(new_address); 22 | upgraded.setCompleted(last_completed_migration); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/lib/assertions.js: -------------------------------------------------------------------------------- 1 | const BigNumber = require('bignumber.js'); 2 | module.exports = function (chai) { 3 | const assert = chai.assert; 4 | chai.Assertion.addProperty('address', function () { 5 | this.assert( 6 | this._obj.length === 42, 7 | 'expected #{this} to be a 42 character address (0x...)', 8 | 'expected #{this} to not be a 42 character address (0x...)' 9 | ); 10 | 11 | const number = BigNumber(this._obj); 12 | this.assert(number.equals(0) === false, 'expected address #{this} to not be zero', "you shouldn't ever see this."); 13 | }); 14 | assert.isAddress = function (val, exp, msg) { 15 | return new chai.Assertion(val, msg).to.be.address; 16 | }; 17 | }; 18 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/contracts/ConvertLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | /** 5 | * @title ConvertLib - Conversion Library 6 | * @dev Provides a simple conversion function to multiply a value by a conversion rate. 7 | */ 8 | library ConvertLib { 9 | /** 10 | * @dev Multiplies the input value by the specified conversion rate. 11 | * @param _amount The value to convert. 12 | * @param _conversionRate The conversion rate. 13 | * @return convertedAmount The converted value. 14 | */ 15 | function convert(uint _amount, uint _conversionRate) public pure returns (uint convertedAmount) { 16 | return _amount * _conversionRate; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/components/Box/lib/config.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | 3 | function setDefaults(config) { 4 | config = config || {}; 5 | 6 | const hooks = config.hooks || {}; 7 | 8 | return { 9 | ignore: config.ignore || [], 10 | commands: config.commands || { 11 | compile: 'tronbox compile', 12 | migrate: 'tronbox migrate', 13 | test: 'tronbox test' 14 | }, 15 | hooks: { 16 | 'post-unpack': hooks['post-unpack'] || '' 17 | } 18 | }; 19 | } 20 | 21 | function read(path) { 22 | return fs 23 | .readFile(path) 24 | .catch(function () { 25 | return '{}'; 26 | }) 27 | .then(JSON.parse) 28 | .then(setDefaults); 29 | } 30 | 31 | module.exports = { 32 | read: read, 33 | setDefaults: setDefaults 34 | }; 35 | -------------------------------------------------------------------------------- /src/components/Provider/error.js: -------------------------------------------------------------------------------- 1 | const TruffleError = require('@truffle/error'); 2 | 3 | // HACK: string comparison seems to be only way to identify being unable to 4 | // connect to RPC node. 5 | const NOT_CONNECTED_MESSAGE = 'Invalid JSON RPC response: ""'; 6 | 7 | class ProviderError extends TruffleError { 8 | constructor(message) { 9 | if (message === NOT_CONNECTED_MESSAGE) { 10 | message = 11 | 'Could not connect to your node.\n' + 12 | 'Please check that the node:\n' + 13 | ' - is running\n' + 14 | ' - is reachable over the network\n' + 15 | ' - is configured correctly in your project configuration.\n'; 16 | } 17 | super(message); 18 | this.message = message; 19 | } 20 | } 21 | 22 | module.exports = ProviderError; 23 | -------------------------------------------------------------------------------- /src/lib/commands/help.js: -------------------------------------------------------------------------------- 1 | const yargs = require('yargs/yargs'); 2 | const version = require('../version'); 3 | 4 | const command = { 5 | command: 'help', 6 | describe: 'Show general help and list all available commands', 7 | builder: {}, 8 | run: function (options, done) { 9 | const args = yargs().detectLocale(false).exitProcess(false).version(false).help(false); 10 | 11 | Object.keys(options.commands).forEach(function (command) { 12 | args.command(options.commands[command]); 13 | }); 14 | 15 | args 16 | .usage( 17 | `TronBox v${version.bundle} - a development framework for Tron 18 | 19 | Usage: tronbox [options]` 20 | ) 21 | .epilog('See more at https://tronbox.io/docs/') 22 | .showHelp(); 23 | 24 | done(); 25 | } 26 | }; 27 | 28 | module.exports = command; 29 | -------------------------------------------------------------------------------- /src/lib/serve.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const finalhandler = require('finalhandler'); 3 | const serveStatic = require('serve-static'); 4 | const path = require('path'); 5 | 6 | const Serve = { 7 | start: function (options, done) { 8 | const serve = serveStatic(options.build_directory); 9 | 10 | const server = http.createServer(function (req, res) { 11 | const done = finalhandler(req, res); 12 | serve(req, res, done); 13 | }); 14 | 15 | const port = options.port || options.p || 8080; 16 | 17 | server.listen(port); 18 | 19 | const display_directory = '.' + path.sep + path.relative(options.working_directory, options.build_directory); 20 | 21 | options.logger.log('Serving static assets in ' + display_directory + ' on port ' + port + '...'); 22 | done(); 23 | } 24 | }; 25 | 26 | module.exports = Serve; 27 | -------------------------------------------------------------------------------- /test/tre/test/helpers/shallowEqual.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | function shallowEqual(actual, expected, message) { 4 | const actualKeys = Object.keys(actual); 5 | const expectedKeys = Object.keys(expected); 6 | 7 | assert.deepStrictEqual(actualKeys, expectedKeys, `${message}: Keys do not match`); 8 | 9 | for (const key of actualKeys) { 10 | const actualValue = actual[key]; 11 | const expectedValue = expected[key]; 12 | 13 | if (key === 'memory' || key === 'stack' || key === 'storage') { 14 | continue; 15 | } 16 | 17 | if (typeof actualValue === 'object' && typeof expectedValue === 'object') { 18 | shallowEqual(actualValue, expectedValue, message); 19 | continue; 20 | } 21 | 22 | assert.strictEqual(actualValue, expectedValue, `${message}: Values for key '${key}' do not match`); 23 | } 24 | } 25 | 26 | module.exports = shallowEqual; 27 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const ConvertLib = artifacts.require('./ConvertLib.sol'); 2 | const MetaCoin = artifacts.require('./MetaCoin.sol'); 3 | 4 | module.exports = async function (deployer, network) { 5 | await deployer.deploy(ConvertLib); 6 | await deployer.link(ConvertLib, MetaCoin); 7 | await deployer.deploy(MetaCoin, 10000); 8 | 9 | if (network === 'development' && typeof web3 === 'undefined') { 10 | // This code block is executed only when the network is 'development' as defined in tronbox-config.js 11 | const metaCoinInstance = await MetaCoin.deployed(); 12 | 13 | const { 14 | block_header: { 15 | raw_data: { timestamp } 16 | } 17 | } = await tronWeb.trx.getCurrentBlock(); 18 | const unlockTime = Math.round(timestamp / 1000) + 6; 19 | await metaCoinInstance.lock(unlockTime, { callValue: 1, feeLimit: 5000000 }); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /src/components/Compile/compileerror.js: -------------------------------------------------------------------------------- 1 | const colors = require('colors'); 2 | const TruffleError = require('@truffle/error'); 3 | 4 | class CompileError extends TruffleError { 5 | constructor(message) { 6 | // Note we trim() because solc likes to add extra whitespace. 7 | let fancy_message = message.trim() + '\n' + colors.red('Compilation failed. See above.'); 8 | let normal_message = message.trim(); 9 | 10 | if ( 11 | /0\.5\.4/.test(normal_message) && 12 | !!~normal_message.indexOf('Source file requires different compiler version') 13 | ) { 14 | normal_message = 15 | normal_message.split('ParserError:')[0] + 16 | '\nParserError: Source file requires different compiler version (current compiler is 0.5.4+commit.7b0de266.mod.Emscripten.clang)'; 17 | fancy_message = normal_message + '\n' + colors.red('Compilation failed. See above.'); 18 | } 19 | super(fancy_message); 20 | } 21 | } 22 | 23 | module.exports = CompileError; 24 | -------------------------------------------------------------------------------- /src/lib/commands/version.js: -------------------------------------------------------------------------------- 1 | const { maxVersion } = require('../../components/TronSolc'); 2 | const version = require('../version'); 3 | const describe = 'Show version information'; 4 | 5 | const command = { 6 | command: 'version', 7 | describe, 8 | builder: yargs => { 9 | yargs 10 | .usage( 11 | `TronBox v${version.bundle}\n\n${describe}\n 12 | Usage: $0 version` 13 | ) 14 | .version(false) 15 | .group(['help'], 'Options:'); 16 | }, 17 | run: function (options, done) { 18 | process.env.CURRENT = 'version'; 19 | const version = require('../version'); 20 | 21 | let bundle_version; 22 | 23 | if (version.bundle) { 24 | bundle_version = 'v' + version.bundle; 25 | } else { 26 | bundle_version = '(unbundled)'; 27 | } 28 | 29 | options.logger.log('TronBox ' + bundle_version); 30 | options.logger.log('Solidity v' + maxVersion + ' (tron-solc)'); 31 | 32 | done(); 33 | } 34 | }; 35 | 36 | module.exports = command; 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Consensys LLC, TRON, and authors. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /test/evm/tronbox-evm-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | bttc: { 4 | // Don't put your private key here: 5 | privateKey: process.env.PRIVATE_KEY_BTTC, 6 | /* 7 | Create a .env file (it must be gitignored) containing something like 8 | 9 | export PRIVATE_KEY_BTTC=4E7FEC...656243 10 | 11 | Then, run the migration with: 12 | 13 | source .env && tronbox migrate --network bttc --evm 14 | */ 15 | fullHost: 'https://rpc.bt.io', 16 | gas: 8500000, // Gas sent with each transaction 17 | gasPrice: '500000000000000', // 500,000 gwei (in wei) 18 | network_id: '1' 19 | }, 20 | development: { 21 | privateKey: process.env.PRIVATE_KEY_DEV, 22 | fullHost: 'http://127.0.0.1:8545', 23 | network_id: '9' 24 | } 25 | }, 26 | compilers: { 27 | solc: { 28 | version: '0.8.6', 29 | settings: { 30 | // optimizer: { 31 | // enabled: true, 32 | // runs: 200 33 | // }, 34 | // evmVersion: 'istanbul' 35 | } 36 | } 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "metacoin", 3 | "version": "3.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "metacoin", 9 | "version": "3.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@openzeppelin/contracts": "5.4.0", 13 | "picocolors": "1.1.1" 14 | } 15 | }, 16 | "node_modules/@openzeppelin/contracts": { 17 | "version": "5.4.0", 18 | "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.4.0.tgz", 19 | "integrity": "sha512-eCYgWnLg6WO+X52I16TZt8uEjbtdkgLC0SUX/xnAksjjrQI4Xfn4iBRoI5j55dmlOhDv1Y7BoR3cU7e3WWhC6A==", 20 | "license": "MIT" 21 | }, 22 | "node_modules/picocolors": { 23 | "version": "1.1.1", 24 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 25 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 26 | "license": "ISC" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/components/waitForTransactionReceipt.js: -------------------------------------------------------------------------------- 1 | // thanks Xavier Leprêtre 2 | // https://gist.github.com/xavierlepretre/88682e871f4ad07be4534ae560692ee6 3 | 4 | const waitForTransactionReceipt = 5 | tronWeb => 6 | (txHash = false, interval = 500) => { 7 | const transactionReceiptAsync = (resolve, reject) => { 8 | tronWeb.trx 9 | .getTransactionInfo(txHash) 10 | .then(receipt => { 11 | if (!receipt || JSON.stringify(receipt) === '{}') { 12 | setTimeout(() => transactionReceiptAsync(resolve, reject), interval); 13 | } else { 14 | resolve(receipt); 15 | } 16 | }) 17 | .catch(error => { 18 | reject(error); 19 | }); 20 | }; 21 | if (Array.isArray(txHash)) { 22 | return Promise.all(txHash.map(oneTxHash => waitForTransactionReceipt(oneTxHash, interval))); 23 | } else if (typeof txHash === 'string') { 24 | return new Promise(transactionReceiptAsync); 25 | } else { 26 | throw new Error('Invalid Type: ' + txHash); 27 | } 28 | }; 29 | 30 | module.exports = waitForTransactionReceipt; 31 | -------------------------------------------------------------------------------- /src/lib/testing/testresolver.js: -------------------------------------------------------------------------------- 1 | function TestResolver(resolver, source, search_path) { 2 | this.resolver = resolver; 3 | this.source = source; 4 | this.options = resolver.options; 5 | this.search_path = search_path; 6 | 7 | this.seen = []; 8 | this.require_cache = {}; 9 | this.cache_on = true; 10 | } 11 | 12 | TestResolver.prototype.require = function (import_path) { 13 | if (this.cache_on && this.require_cache[import_path]) { 14 | return this.require_cache[import_path]; 15 | } 16 | 17 | // Remember: This throws if not found. 18 | const result = this.resolver.require(import_path, this.search_path); 19 | 20 | this.require_cache[import_path] = result; 21 | 22 | return result; 23 | }; 24 | 25 | TestResolver.prototype.resolve = function (import_path, imported_from, callback) { 26 | const self = this; 27 | this.source.resolve(import_path, function (err, result, resolved_path) { 28 | if (err) return callback(err); 29 | if (result) return callback(null, result, resolved_path); 30 | 31 | self.resolver.resolve(import_path, imported_from, callback); 32 | }); 33 | }; 34 | 35 | module.exports = TestResolver; 36 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | We appreciate your interest in contributing! Please follow these steps to get started: 4 | 5 | 1. **Fork this repository.** 6 | 7 | 2. **Clone your forked repository.** 8 | 9 | Use the following command to clone it: 10 | 11 | ```bash 12 | git clone git@github.com:your-username/tronbox.git 13 | ``` 14 | 15 | Replace `your-username` with your GitHub username. 16 | 17 | 3. **Install Node.js using nvm.** 18 | 19 | Make sure to use a version higher than 18. You can install the recommended version like this: 20 | 21 | ```bash 22 | nvm install v18.20.8 23 | nvm use v18.20.8 24 | ``` 25 | 26 | 4. **Install the project's dependencies.** 27 | 28 | Run the following command in the root of the project: 29 | 30 | ```bash 31 | npm install 32 | ``` 33 | 34 | 5. **Run the unbuilt version of TronBox for better debugging during development.** 35 | 36 | You can do this with the following command: 37 | 38 | ```bash 39 | ./tronbox.dev migrate --reset 40 | ``` 41 | 42 | If you like this project, please consider giving it a star! 43 | 44 | Thank you for your contributions! 45 | -------------------------------------------------------------------------------- /src/components/Deployer/src/deferredchain.js: -------------------------------------------------------------------------------- 1 | function DeferredChain() { 2 | const self = this; 3 | this.chain = new Promise(function (accept, reject) { 4 | self._accept = accept; 5 | self._reject = reject; 6 | }); 7 | 8 | this.await = new Promise(function () { 9 | self._done = arguments[0]; 10 | self._error = arguments[1]; 11 | }); 12 | this.started = false; 13 | } 14 | 15 | DeferredChain.prototype.then = function (fn) { 16 | const self = this; 17 | this.chain = this.chain.then(function () { 18 | const args = Array.prototype.slice.call(arguments); 19 | 20 | return fn.apply(null, args); 21 | }); 22 | this.chain = this.chain.catch(function (e) { 23 | self._error(e); 24 | }); 25 | 26 | return this; 27 | }; 28 | 29 | DeferredChain.prototype.catch = function (fn) { 30 | this.chain = this.chain.catch(function () { 31 | const args = Array.prototype.slice.call(arguments); 32 | 33 | return fn.apply(null, args); 34 | }); 35 | 36 | return this; 37 | }; 38 | 39 | DeferredChain.prototype.start = function () { 40 | this.started = true; 41 | this.chain = this.chain.then(this._done); 42 | this._accept(); 43 | return this.await; 44 | }; 45 | 46 | module.exports = DeferredChain; 47 | -------------------------------------------------------------------------------- /src/lib/commands/flatten.js: -------------------------------------------------------------------------------- 1 | const version = require('../version'); 2 | const describe = 'Flattens and prints contracts and their dependencies'; 3 | 4 | const command = { 5 | command: 'flatten', 6 | describe, 7 | builder: yargs => { 8 | yargs 9 | .usage( 10 | `TronBox v${version.bundle}\n\n${describe}\n 11 | Usage: $0 flatten ` 12 | ) 13 | .version(false) 14 | .positional('files', { 15 | describe: 'One or more contract source file paths to flatten', 16 | type: 'string', 17 | array: true, 18 | demandOption: true 19 | }) 20 | .group(['help'], 'Options:') 21 | .example('$0 flatten contracts/Foo.sol', '') 22 | .example('$0 flatten contracts/Foo.sol contracts/Bar.sol', '') 23 | .example('$0 flatten contracts/Foo.sol > Flattened.sol', ''); 24 | }, 25 | run: function (options, done) { 26 | process.env.CURRENT = 'flatten'; 27 | const Flatten = require('../../components/Flatten'); 28 | 29 | const filePaths = options._; 30 | 31 | if (!filePaths.length) { 32 | console.error('Usage: tronbox flatten \n'); 33 | done(); 34 | return; 35 | } 36 | 37 | Flatten.run(filePaths, done); 38 | } 39 | }; 40 | 41 | module.exports = command; 42 | -------------------------------------------------------------------------------- /test/evm/contracts/MetaCoin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | import './ConvertLib.sol'; 5 | 6 | // This is just a simple example of a coin-like contract. 7 | // It is not standards compatible and cannot be expected to talk to other 8 | // coin/token contracts. 9 | 10 | contract MetaCoin { 11 | mapping(address => uint) balances; 12 | 13 | event Transfer(address _from, address _to, uint256 _value); 14 | 15 | address owner; 16 | 17 | constructor(uint initialBalance) { 18 | owner = msg.sender; 19 | balances[msg.sender] = initialBalance; 20 | } 21 | 22 | function sendCoin(address receiver, uint amount) public returns (bool sufficient) { 23 | if (balances[msg.sender] < amount) return false; 24 | balances[msg.sender] -= amount; 25 | balances[receiver] += amount; 26 | emit Transfer(msg.sender, receiver, amount); 27 | return true; 28 | } 29 | 30 | function getConvertedBalance(address addr) public view returns (uint) { 31 | return ConvertLib.convert(getBalance(addr), 2); 32 | } 33 | 34 | function getBalance(address addr) public view returns (uint) { 35 | return balances[addr]; 36 | } 37 | 38 | function getOwner() public view returns (address) { 39 | return owner; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.5.0/tronbox.js: -------------------------------------------------------------------------------- 1 | const port = process.env.HOST_PORT || 9090; 2 | 3 | module.exports = { 4 | networks: { 5 | mainnet: { 6 | // Don't put your private key here: 7 | privateKey: process.env.PRIVATE_KEY_MAINNET, 8 | /* 9 | Create a .env file (it must be gitignored) containing something like 10 | 11 | export PRIVATE_KEY_MAINNET=4E7FEC...656243 12 | 13 | Then, run the migration with: 14 | 15 | source .env && tronbox migrate --network mainnet 16 | 17 | */ 18 | userFeePercentage: 100, 19 | feeLimit: 1e8, 20 | fullHost: 'https://api.trongrid.io', 21 | network_id: '1' 22 | }, 23 | shasta: { 24 | privateKey: process.env.PRIVATE_KEY_SHASTA, 25 | userFeePercentage: 50, 26 | feeLimit: 1e8, 27 | fullHost: 'https://api.shasta.trongrid.io', 28 | network_id: '2' 29 | }, 30 | development: { 31 | // For tronbox/tre docker image 32 | privateKey: '0000000000000000000000000000000000000000000000000000000000000001', 33 | userFeePercentage: 0, 34 | feeLimit: 1e8, 35 | fullHost: 'http://127.0.0.1:' + port, 36 | network_id: '9' 37 | }, 38 | compilers: { 39 | solc: { 40 | version: '0.5.4' 41 | } 42 | } 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.6.0/tronbox.js: -------------------------------------------------------------------------------- 1 | const port = process.env.HOST_PORT || 9090; 2 | 3 | module.exports = { 4 | networks: { 5 | mainnet: { 6 | // Don't put your private key here: 7 | privateKey: process.env.PRIVATE_KEY_MAINNET, 8 | /* 9 | Create a .env file (it must be gitignored) containing something like 10 | 11 | export PRIVATE_KEY_MAINNET=4E7FEC...656243 12 | 13 | Then, run the migration with: 14 | 15 | source .env && tronbox migrate --network mainnet 16 | 17 | */ 18 | userFeePercentage: 100, 19 | feeLimit: 1e8, 20 | fullHost: 'https://api.trongrid.io', 21 | network_id: '1' 22 | }, 23 | shasta: { 24 | privateKey: process.env.PRIVATE_KEY_SHASTA, 25 | userFeePercentage: 50, 26 | feeLimit: 1e8, 27 | fullHost: 'https://api.shasta.trongrid.io', 28 | network_id: '2' 29 | }, 30 | development: { 31 | // For tronbox/tre docker image 32 | privateKey: '0000000000000000000000000000000000000000000000000000000000000001', 33 | userFeePercentage: 0, 34 | feeLimit: 1e8, 35 | fullHost: 'http://127.0.0.1:' + port, 36 | network_id: '9' 37 | }, 38 | compilers: { 39 | solc: { 40 | version: '0.6.0' 41 | } 42 | } 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.4.0/contracts/MetaCoin.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import './ConvertLib.sol'; 4 | 5 | // This is just a simple example of a coin-like contract. 6 | // It is not standards compatible and cannot be expected to talk to other 7 | // coin/token contracts. 8 | 9 | contract MetaCoin { 10 | mapping(address => uint) balances; 11 | 12 | event Transfer(address _from, address _to, uint256 _value); 13 | 14 | address owner; 15 | 16 | constructor(uint initialBalance) public { 17 | owner = msg.sender; 18 | balances[msg.sender] = initialBalance; 19 | } 20 | 21 | function sendCoin( 22 | address receiver, 23 | uint amount 24 | ) public returns (bool sufficient) { 25 | if (balances[msg.sender] < amount) return false; 26 | balances[msg.sender] -= amount; 27 | balances[receiver] += amount; 28 | emit Transfer(msg.sender, receiver, amount); 29 | return true; 30 | } 31 | 32 | function getBalanceInEth(address addr) public view returns (uint) { 33 | return ConvertLib.convert(getBalance(addr), 2); 34 | } 35 | 36 | function getBalance(address addr) public view returns (uint) { 37 | return balances[addr]; 38 | } 39 | 40 | function getOwner() public view returns (address) { 41 | return owner; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.5.0/contracts/MetaCoin.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.4; 2 | 3 | import './ConvertLib.sol'; 4 | 5 | // This is just a simple example of a coin-like contract. 6 | // It is not standards compatible and cannot be expected to talk to other 7 | // coin/token contracts. 8 | 9 | contract MetaCoin { 10 | mapping(address => uint) balances; 11 | 12 | event Transfer(address _from, address _to, uint256 _value); 13 | 14 | address owner; 15 | 16 | constructor(uint initialBalance) public { 17 | owner = msg.sender; 18 | balances[msg.sender] = initialBalance; 19 | } 20 | 21 | function sendCoin( 22 | address receiver, 23 | uint amount 24 | ) public returns (bool sufficient) { 25 | if (balances[msg.sender] < amount) return false; 26 | balances[msg.sender] -= amount; 27 | balances[receiver] += amount; 28 | emit Transfer(msg.sender, receiver, amount); 29 | return true; 30 | } 31 | 32 | function getBalanceInEth(address addr) public view returns (uint) { 33 | return ConvertLib.convert(getBalance(addr), 2); 34 | } 35 | 36 | function getBalance(address addr) public view returns (uint) { 37 | return balances[addr]; 38 | } 39 | 40 | function getOwner() public view returns (address) { 41 | return owner; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/components/Contract/statuserror.js: -------------------------------------------------------------------------------- 1 | const TruffleError = require('@truffle/error'); 2 | 3 | const defaultGas = 90000; 4 | 5 | class StatusError extends TruffleError { 6 | constructor(args, tx, receipt) { 7 | let message; 8 | const gasLimit = parseInt(args.gas) || defaultGas; 9 | 10 | if (receipt.gasUsed === gasLimit) { 11 | message = 12 | 'Transaction: ' + 13 | tx + 14 | ' exited with an error (status 0) after consuming all gas.\n' + 15 | 'Please check that the transaction:\n' + 16 | ' - satisfies all conditions set by Solidity `assert` statements.\n' + 17 | ' - has enough gas to execute the full transaction.\n' + 18 | ' - does not trigger an invalid opcode by other means (ex: accessing an array out of bounds).'; 19 | } else { 20 | message = 21 | 'Transaction: ' + 22 | tx + 23 | ' exited with an error (status 0).\n' + 24 | 'Please check that the transaction:\n' + 25 | ' - satisfies all conditions set by Solidity `require` statements.\n' + 26 | ' - does not trigger a Solidity `revert` statement.\n'; 27 | } 28 | 29 | super(message); 30 | this.tx = tx; 31 | this.receipt = receipt; 32 | } 33 | } 34 | 35 | module.exports = StatusError; 36 | -------------------------------------------------------------------------------- /src/components/Deployer/src/linker.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | link: function (library, destinations, logger) { 3 | logger = logger || console; 4 | 5 | if (!Array.isArray(destinations)) { 6 | destinations = [destinations]; 7 | } 8 | 9 | if (!library.contract_name) { 10 | throw new Error('Cannot link a library with no name.'); 11 | } 12 | 13 | let hasAddress = false; 14 | 15 | // Abstractions; don't want to use .address directly because it will throw. 16 | if (typeof library.isDeployed) { 17 | hasAddress = library.isDeployed(); 18 | } else { 19 | hasAddress = library.address; 20 | } 21 | 22 | if (!hasAddress) { 23 | throw new Error('Cannot link library: ' + library.contract_name + ' has no address. Has it been deployed?'); 24 | } 25 | 26 | destinations.forEach(function (destination) { 27 | // Don't link if result will have no effect. 28 | if (destination.links[library.contract_name] === library.address) return; // already linked to same address 29 | if (destination.unlinked_binary.indexOf(library.contract_name) < 0) return; // no linkage available 30 | 31 | logger.log('Linking ' + library.contract_name + ' to ' + destination.contract_name); 32 | destination.link(library); 33 | }); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.4.0/tronbox.js: -------------------------------------------------------------------------------- 1 | const port = process.env.HOST_PORT || 9090; 2 | 3 | module.exports = { 4 | networks: { 5 | mainnet: { 6 | // Don't put your private key here: 7 | privateKey: process.env.PRIVATE_KEY_MAINNET, 8 | /* 9 | Create a .env file (it must be gitignored) containing something like 10 | 11 | export PRIVATE_KEY_MAINNET=4E7FEC...656243 12 | 13 | Then, run the migration with: 14 | 15 | source .env && tronbox migrate --network mainnet 16 | 17 | */ 18 | userFeePercentage: 100, 19 | feeLimit: 1e8, 20 | fullHost: 'https://api.trongrid.io', 21 | network_id: '1' 22 | }, 23 | shasta: { 24 | privateKey: process.env.PRIVATE_KEY_SHASTA, 25 | userFeePercentage: 50, 26 | feeLimit: 1e8, 27 | fullHost: 'https://api.shasta.trongrid.io', 28 | network_id: '2' 29 | }, 30 | development: { 31 | // For tronbox/tre docker image 32 | privateKey: '0000000000000000000000000000000000000000000000000000000000000001', 33 | userFeePercentage: 0, 34 | feeLimit: 1e8, 35 | fullHost: 'http://127.0.0.1:' + port, 36 | network_id: '9' 37 | }, 38 | compilers: { 39 | solc: { 40 | version: '0.4.25' 41 | } 42 | } 43 | }, 44 | useZeroFourCompiler: true 45 | }; 46 | -------------------------------------------------------------------------------- /test/abiv2/contracts/Tuple.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | contract Tuple { 6 | struct Person { 7 | string name; 8 | uint256 age; 9 | } 10 | 11 | Person[] persons; 12 | 13 | constructor(Person memory person) { 14 | persons.push(person); 15 | persons.push(Person('Lily', 20)); 16 | persons.push(Person('Oscar', 30)); 17 | } 18 | 19 | function insert(Person memory person) public { 20 | persons.push(person); 21 | } 22 | 23 | function insertBatch(Person[] memory person) public { 24 | for (uint256 i = 0; i < person.length; i++) { 25 | persons.push(person[i]); 26 | } 27 | } 28 | 29 | function getPerson() public view returns (Person[] memory) { 30 | return persons; 31 | } 32 | 33 | function echoPerson(Person memory person) public pure returns (Person memory) { 34 | return person; 35 | } 36 | 37 | function getPersonById(uint256 id) public view returns (Person memory) { 38 | return persons[id]; 39 | } 40 | 41 | function func(uint256) public pure returns (bytes4) { 42 | return bytes4(keccak256('func(uint256)')); // 7f98a45e 43 | } 44 | 45 | function func(address) public pure returns (bytes4) { 46 | return bytes4(keccak256('func(address)')); // b8550dc7 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.6.0/contracts/MetaCoin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.7.0; 3 | 4 | import './ConvertLib.sol'; 5 | 6 | // This is just a simple example of a coin-like contract. 7 | // It is not standards compatible and cannot be expected to talk to other 8 | // coin/token contracts. 9 | 10 | contract MetaCoin { 11 | mapping(address => uint) balances; 12 | 13 | event Transfer(address _from, address _to, uint256 _value); 14 | 15 | address owner; 16 | 17 | constructor(uint initialBalance) public { 18 | owner = msg.sender; 19 | balances[msg.sender] = initialBalance; 20 | } 21 | 22 | function sendCoin( 23 | address receiver, 24 | uint amount 25 | ) public returns (bool sufficient) { 26 | if (balances[msg.sender] < amount) return false; 27 | balances[msg.sender] -= amount; 28 | balances[receiver] += amount; 29 | emit Transfer(msg.sender, receiver, amount); 30 | return true; 31 | } 32 | 33 | function getBalanceInEth(address addr) public view returns (uint) { 34 | return ConvertLib.convert(getBalance(addr), 2); 35 | } 36 | 37 | function getBalance(address addr) public view returns (uint) { 38 | return balances[addr]; 39 | } 40 | 41 | function getOwner() public view returns (address) { 42 | return owner; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/components/Migrate/resolverintercept.js: -------------------------------------------------------------------------------- 1 | function ResolverIntercept(resolver) { 2 | this.resolver = resolver; 3 | this.cache = {}; 4 | } 5 | 6 | ResolverIntercept.prototype.require = function (import_path) { 7 | // Modify import_path so the cache key is consistently the same irrespective 8 | // of whether a user explicated .sol extension 9 | import_path = import_path.replace(/\.sol$/i, ''); 10 | 11 | // TODO: Using the import path for relative files may result in multiple 12 | // paths for the same file. This could return different objects since it won't be a cache hit. 13 | if (this.cache[import_path]) { 14 | return this.cache[import_path]; 15 | } 16 | 17 | // Note, will error if nothing is found. 18 | const resolved = this.resolver.require(import_path); 19 | 20 | this.cache[import_path] = resolved; 21 | 22 | // During migrations, we could be on a network that takes a long time to accept 23 | // transactions (i.e., contract deployment close to block size). Because successful 24 | // migration is more important than wait time in those cases, we'll synchronize "forever". 25 | resolved.synchronization_timeout = 0; 26 | 27 | return resolved; 28 | }; 29 | 30 | ResolverIntercept.prototype.contracts = function () { 31 | const self = this; 32 | return Object.keys(this.cache).map(function (key) { 33 | return self.cache[key]; 34 | }); 35 | }; 36 | 37 | module.exports = ResolverIntercept; 38 | -------------------------------------------------------------------------------- /src/components/Provider/index.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const { providers } = require('tronweb'); 3 | const wrapper = require('./wrapper'); 4 | 5 | module.exports = { 6 | wrap: function (provider, options) { 7 | return wrapper.wrap(provider, options); 8 | }, 9 | 10 | create: function (options) { 11 | let provider; 12 | const fullHost = options.fullHost || options.fullNode; 13 | 14 | if (options.provider && typeof options.provider === 'function') { 15 | provider = options.provider(); 16 | } else if (options.provider) { 17 | provider = options.provider; 18 | } else { 19 | const HttpProvider = providers.HttpProvider; 20 | 21 | HttpProvider.prototype.send = async function (payload) { 22 | const { data } = await axios.post(`${fullHost}/jsonrpc`, payload); 23 | return data; 24 | }; 25 | 26 | HttpProvider.prototype.sendAsync = function (payload, callback) { 27 | return axios 28 | .post(`${fullHost}/jsonrpc`, payload) 29 | .then(({ data }) => { 30 | callback(null, data); 31 | }) 32 | .catch(error => { 33 | callback(error); 34 | }); 35 | }; 36 | 37 | provider = new HttpProvider(fullHost); 38 | } 39 | return this.wrap(provider, options); 40 | }, 41 | 42 | test_connection: function (provider, callback) { 43 | callback(null, true); 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | require('source-map-support/register'); 2 | 3 | const Command = require('./lib/command'); 4 | const downloader = require('./downloader'); 5 | 6 | const command = new Command(require('./lib/commands')); 7 | 8 | const options = { 9 | logger: console 10 | }; 11 | 12 | const commands = process.argv.slice(2); 13 | 14 | if (commands[0] === '--download-compiler' && commands[1]) { 15 | downloader(commands[1], commands[2]); 16 | } else { 17 | command.run(commands, options, function (err) { 18 | if (err) { 19 | if (typeof err === 'number') { 20 | // If a number is returned, exit with that number. 21 | process.exit(err); 22 | } else if (err instanceof Error) { 23 | console.error(err.stack || err.message); 24 | } else { 25 | // Handle other types (string, object, etc.) 26 | console.error(err.message || err.toString() || String(err)); 27 | } 28 | process.exit(1); 29 | } 30 | 31 | // Don't exit if no error; if something is keeping the process open, 32 | // like `tronbox console`, then let it. 33 | 34 | // Clear any polling or open sockets - `provider-engine` in HDWallet 35 | // and `web3 1.0 confirmations` both leave interval timers etc wide open. 36 | const handles = process._getActiveHandles(); 37 | handles.forEach(handle => { 38 | if (typeof handle.close === 'function') { 39 | handle.close(); 40 | } 41 | }); 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /src/lib/testing/deployed.js: -------------------------------------------------------------------------------- 1 | // Using web3 for its sha function... 2 | const TronWrap = require('../../components/TronWrap'); 3 | 4 | const Deployed = { 5 | makeSolidityDeployedAddressesLibrary: function (mapping) { 6 | const self = this; 7 | 8 | let source = ''; 9 | source += 'pragma solidity ^0.4.17; \n\n library DeployedAddresses {' + '\n'; 10 | 11 | Object.keys(mapping).forEach(function (name) { 12 | let address = mapping[name]; 13 | 14 | let body = 'revert();'; 15 | 16 | if (address) { 17 | address = self.toChecksumAddress(address.replace(/^(0x|41)/, '0x')); 18 | body = 'return ' + address + ';'; 19 | } 20 | 21 | source += ' function ' + name + '() public pure returns (address) { ' + body + ' }'; 22 | source += '\n'; 23 | }); 24 | 25 | source += '}'; 26 | 27 | return source; 28 | }, 29 | 30 | // Pulled from ethereumjs-util, but I don't want all its dependencies at the moment. 31 | toChecksumAddress: function (address) { 32 | address = address.toLowerCase().replace('0x', ''); 33 | const hash = TronWrap().sha3(address).replace('0x', ''); 34 | let ret = '0x'; 35 | 36 | for (let i = 0; i < address.length; i++) { 37 | if (parseInt(hash[i], 16) >= 8) { 38 | ret += address[i].toUpperCase(); 39 | } else { 40 | ret += address[i]; 41 | } 42 | } 43 | 44 | return ret; 45 | } 46 | }; 47 | 48 | module.exports = Deployed; 49 | -------------------------------------------------------------------------------- /test/abiv2/tronbox.js: -------------------------------------------------------------------------------- 1 | const port = process.env.HOST_PORT || 9090; 2 | 3 | module.exports = { 4 | networks: { 5 | mainnet: { 6 | // Don't put your private key here: 7 | privateKey: process.env.PRIVATE_KEY_MAINNET, 8 | /* 9 | Create a .env file (it must be gitignored) containing something like 10 | 11 | export PRIVATE_KEY_MAINNET=4E7FEC...656243 12 | 13 | Then, run the migration with: 14 | 15 | source .env && tronbox migrate --network mainnet 16 | 17 | */ 18 | userFeePercentage: 100, 19 | feeLimit: 1e8, 20 | fullHost: 'https://api.trongrid.io', 21 | network_id: '1' 22 | }, 23 | nile: { 24 | mnemonic: process.env.MNEMONIC_NILE, 25 | userFeePercentage: 100, 26 | feeLimit: 1e10, 27 | fullHost: 'https://api.nileex.io', 28 | network_id: '2' 29 | }, 30 | shasta: { 31 | privateKey: process.env.PRIVATE_KEY_SHASTA, 32 | userFeePercentage: 50, 33 | feeLimit: 1e8, 34 | fullHost: 'https://api.shasta.trongrid.io', 35 | network_id: '2' 36 | }, 37 | development: { 38 | // For tronbox/tre docker image 39 | privateKey: '0000000000000000000000000000000000000000000000000000000000000001', 40 | userFeePercentage: 0, 41 | feeLimit: 1e9, 42 | fullHost: 'http://127.0.0.1:' + port, 43 | network_id: '9' 44 | }, 45 | compilers: { 46 | solc: { 47 | version: '0.8.20' 48 | } 49 | } 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /test/runTest.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo 'Test abiv2' 4 | cd abiv2 5 | rm -rf build 6 | ../../tronbox.dev test 7 | cd .. 8 | 9 | echo 'Test tre' 10 | cd tre 11 | rm -rf build 12 | ../../tronbox.dev test 13 | cd .. 14 | 15 | echo 'Test init' 16 | rm -rf build 17 | mkdir build 18 | cd build 19 | TRONBOX_CREATE_JAVASCRIPT_PROJECT_WITH_DEFAULTS=true ../../tronbox.dev init 20 | ../../tronbox.dev migrate 21 | cd .. 22 | 23 | echo 'Test init metacoin' 24 | rm -rf build 25 | mkdir build 26 | cd build 27 | TRONBOX_CREATE_JAVASCRIPT_METACOIN_PROJECT_WITH_DEFAULTS=true ../../tronbox.dev init 28 | ../../tronbox.dev test 29 | cd .. 30 | 31 | echo 'Test unbox metacoin' 32 | rm -rf build 33 | mkdir build 34 | cd build 35 | ../../tronbox.dev unbox metacoin-box 36 | ../../tronbox.dev test 37 | cd .. 38 | 39 | echo 'Test unbox beacon' 40 | rm -rf build 41 | mkdir build 42 | cd build 43 | ../../tronbox.dev unbox beacon 44 | ../../tronbox.dev test 45 | cd .. 46 | 47 | echo 'Test unbox transparent' 48 | rm -rf build 49 | mkdir build 50 | cd build 51 | ../../tronbox.dev unbox transparent 52 | ../../tronbox.dev test 53 | cd .. 54 | 55 | echo 'Test unbox uups' 56 | rm -rf build 57 | mkdir build 58 | cd build 59 | ../../tronbox.dev unbox uups 60 | ../../tronbox.dev test 61 | cd .. 62 | 63 | rm -rf build 64 | 65 | echo 'Test Console.log' 66 | cd consolelogs 67 | sh runTest.sh 68 | cd .. 69 | 70 | echo 'Test evm' 71 | cd evm 72 | rm -rf build 73 | ../../tronbox.dev test --evm 74 | cd .. 75 | -------------------------------------------------------------------------------- /test/runNile.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo 'Nile: Test abiv2' 4 | cd abiv2 5 | rm -rf build 6 | ../../tronbox.dev migrate --network nile 7 | cd .. 8 | 9 | echo 'Nile: Test init' 10 | rm -rf build 11 | mkdir build 12 | cd build 13 | TRONBOX_CREATE_JAVASCRIPT_PROJECT_WITH_DEFAULTS=true ../../tronbox.dev init 14 | ../../tronbox.dev migrate --network nile 15 | cd .. 16 | 17 | echo 'Nile: Test init metacoin' 18 | rm -rf build 19 | mkdir build 20 | cd build 21 | TRONBOX_CREATE_JAVASCRIPT_METACOIN_PROJECT_WITH_DEFAULTS=true ../../tronbox.dev init 22 | ../../tronbox.dev migrate --network nile 23 | cd .. 24 | 25 | echo 'Nile: Test unbox metacoin' 26 | rm -rf build 27 | mkdir build 28 | cd build 29 | ../../tronbox.dev unbox metacoin-box 30 | ../../tronbox.dev migrate --network nile 31 | cd .. 32 | 33 | echo 'Nile: Test unbox beacon' 34 | rm -rf build 35 | mkdir build 36 | cd build 37 | ../../tronbox.dev unbox beacon 38 | ../../tronbox.dev migrate --network nile 39 | cd .. 40 | 41 | echo 'Nile: Test unbox transparent' 42 | rm -rf build 43 | mkdir build 44 | cd build 45 | ../../tronbox.dev unbox transparent 46 | ../../tronbox.dev migrate --network nile 47 | cd .. 48 | 49 | echo 'Nile: Test unbox uups' 50 | rm -rf build 51 | mkdir build 52 | cd build 53 | ../../tronbox.dev unbox uups 54 | ../../tronbox.dev migrate --network nile 55 | cd .. 56 | 57 | rm -rf build 58 | 59 | echo 'BTTC: Test evm' 60 | cd evm 61 | rm -rf build 62 | ../../tronbox.dev migrate --network bttc --evm 63 | cd .. 64 | -------------------------------------------------------------------------------- /test/tre/tronbox.js: -------------------------------------------------------------------------------- 1 | const port = process.env.HOST_PORT || 9090; 2 | 3 | module.exports = { 4 | networks: { 5 | mainnet: { 6 | // Don't put your private key here: 7 | privateKey: process.env.PRIVATE_KEY_MAINNET, 8 | /* 9 | Create a .env file (it must be gitignored) containing something like 10 | 11 | export PRIVATE_KEY_MAINNET=4E7FEC...656243 12 | 13 | Then, run the migration with: 14 | 15 | source .env && tronbox migrate --network mainnet 16 | 17 | */ 18 | userFeePercentage: 100, 19 | feeLimit: 1e8, 20 | fullHost: 'https://api.trongrid.io', 21 | network_id: '1' 22 | }, 23 | shasta: { 24 | privateKey: process.env.PRIVATE_KEY_SHASTA, 25 | userFeePercentage: 50, 26 | feeLimit: 1e8, 27 | fullHost: 'https://api.shasta.trongrid.io', 28 | network_id: '2' 29 | }, 30 | nile: { 31 | privateKey: process.env.PRIVATE_KEY_NILE, 32 | userFeePercentage: 100, 33 | feeLimit: 1000 * 1e6, 34 | fullHost: 'https://api.nileex.io', 35 | network_id: '3' 36 | }, 37 | development: { 38 | // For tronbox/tre docker image 39 | privateKey: '0000000000000000000000000000000000000000000000000000000000000001', 40 | userFeePercentage: 0, 41 | feeLimit: 1e8, 42 | fullHost: 'http://127.0.0.1:' + port, 43 | network_id: '9' 44 | }, 45 | compilers: { 46 | solc: { 47 | version: '0.8.20' 48 | } 49 | } 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /sample-projects/javascript/tronbox-evm-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | bttc: { 4 | // Don't put your private key here: 5 | privateKey: process.env.PRIVATE_KEY_BTTC, 6 | /** 7 | * Create a .env file (it must be gitignored) containing something like 8 | * 9 | * export PRIVATE_KEY_BTTC=4E7FEC...656243 10 | * 11 | * Then, run the migration with: 12 | * 13 | * source .env && tronbox migrate --network bttc --evm 14 | */ 15 | fullHost: 'https://rpc.bt.io', 16 | // gas: 8500000, // Gas sent with each transaction 17 | // gasPrice: '500000000000000', // 500,000 gwei (in wei) 18 | network_id: '1' 19 | }, 20 | donau: { 21 | privateKey: process.env.PRIVATE_KEY_DONAU, 22 | fullHost: 'https://pre-rpc.bt.io', 23 | network_id: '2' 24 | }, 25 | development: { 26 | privateKey: process.env.PRIVATE_KEY_DEV, 27 | fullHost: 'http://127.0.0.1:8545', 28 | network_id: '9' 29 | } 30 | }, 31 | compilers: { 32 | solc: { 33 | version: '0.8.7', 34 | // An object with the same schema as the settings entry in the Input JSON. 35 | // See https://docs.soliditylang.org/en/latest/using-the-compiler.html#input-description 36 | settings: { 37 | // optimizer: { 38 | // enabled: true, 39 | // runs: 200 40 | // }, 41 | // evmVersion: 'istanbul', 42 | // viaIR: true, 43 | } 44 | } 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/tronbox-evm-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | bttc: { 4 | // Don't put your private key here: 5 | privateKey: process.env.PRIVATE_KEY_BTTC, 6 | /** 7 | * Create a .env file (it must be gitignored) containing something like 8 | * 9 | * export PRIVATE_KEY_BTTC=4E7FEC...656243 10 | * 11 | * Then, run the migration with: 12 | * 13 | * source .env && tronbox migrate --network bttc --evm 14 | */ 15 | fullHost: 'https://rpc.bt.io', 16 | // gas: 8500000, // Gas sent with each transaction 17 | // gasPrice: '500000000000000', // 500,000 gwei (in wei) 18 | network_id: '1' 19 | }, 20 | donau: { 21 | privateKey: process.env.PRIVATE_KEY_DONAU, 22 | fullHost: 'https://pre-rpc.bt.io', 23 | network_id: '2' 24 | }, 25 | development: { 26 | privateKey: process.env.PRIVATE_KEY_DEV, 27 | fullHost: 'http://127.0.0.1:8545', 28 | network_id: '9' 29 | } 30 | }, 31 | compilers: { 32 | solc: { 33 | version: '0.8.23', 34 | // An object with the same schema as the settings entry in the Input JSON. 35 | // See https://docs.soliditylang.org/en/latest/using-the-compiler.html#input-description 36 | settings: { 37 | // optimizer: { 38 | // enabled: true, 39 | // runs: 200 40 | // }, 41 | // evmVersion: 'istanbul', 42 | // viaIR: true, 43 | } 44 | } 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /src/lib/commands/init.js: -------------------------------------------------------------------------------- 1 | const version = require('../version'); 2 | const describe = 'Initialize new TronBox project'; 3 | 4 | const command = { 5 | command: 'init', 6 | describe, 7 | builder: yargs => { 8 | yargs 9 | .usage( 10 | `TronBox v${version.bundle}\n\n${describe}\n 11 | Usage: $0 init` 12 | ) 13 | .version(false) 14 | .group(['help'], 'Options:'); 15 | }, 16 | run: function (options, done) { 17 | const fs = require('fs'); 18 | const path = require('path'); 19 | if (fs.existsSync(path.resolve(process.cwd(), './truffle-config.js'))) { 20 | const ConvertCommand = require('./convert'); 21 | return ConvertCommand.run(options, done); 22 | } 23 | 24 | process.env.CURRENT = 'init'; 25 | const Config = require('../../components/Config'); 26 | const OS = require('os'); 27 | const InitCommand = require('../../components/Init'); 28 | 29 | const config = Config.default().with({ 30 | logger: console 31 | }); 32 | 33 | if (options._ && options._.length > 0) { 34 | config.logger.log('Error: `tronbox init` no longer accepts a project template name as an argument.'); 35 | config.logger.log(); 36 | config.logger.log( 37 | ' - For an empty project, use `tronbox init` with no arguments' + 38 | OS.EOL + 39 | ' - Or, browse the TronBox Boxes at !' 40 | ); 41 | process.exit(1); 42 | } 43 | 44 | InitCommand.run(options, done); 45 | } 46 | }; 47 | 48 | module.exports = command; 49 | -------------------------------------------------------------------------------- /src/lib/commands/compile.js: -------------------------------------------------------------------------------- 1 | const version = require('../version'); 2 | const describe = 'Compile contract source files'; 3 | 4 | const command = { 5 | command: 'compile', 6 | describe, 7 | builder: yargs => { 8 | yargs 9 | .usage( 10 | `TronBox v${version.bundle}\n\n${describe}\n 11 | Usage: $0 compile [--all] [--evm] [--quiet] ` 12 | ) 13 | .version(false) 14 | .options({ 15 | all: { 16 | describe: 'Compile all contracts, not just changed ones', 17 | type: 'boolean' 18 | }, 19 | evm: { 20 | describe: 'Use EVM configuration', 21 | type: 'boolean' 22 | }, 23 | quiet: { 24 | describe: 'Suppress all output except errors', 25 | type: 'boolean' 26 | } 27 | }) 28 | .example('$0 compile', 'Compile all contracts in the project') 29 | .example('$0 compile --all', 'Compile all contracts, even if not changed') 30 | .example('$0 compile --evm', 'Compile using EVM configuration') 31 | .group(['all', 'evm', 'quiet', 'help'], 'Options:'); 32 | }, 33 | run: function (options, done) { 34 | process.env.CURRENT = 'compile'; 35 | const Config = require('../../components/Config'); 36 | const Contracts = require('../../components/WorkflowCompile'); 37 | 38 | if (options.quiet || options.silent) { 39 | options.logger = { 40 | log: function () {} 41 | }; 42 | } 43 | 44 | const config = Config.detect(options); 45 | Contracts.compile(config, done); 46 | } 47 | }; 48 | 49 | module.exports = command; 50 | -------------------------------------------------------------------------------- /test/consolelogs/tronbox.js: -------------------------------------------------------------------------------- 1 | const port = process.env.HOST_PORT || 9090; 2 | 3 | module.exports = { 4 | networks: { 5 | mainnet: { 6 | // Don't put your private key here: 7 | privateKey: process.env.PRIVATE_KEY_MAINNET, 8 | /* 9 | Create a .env file (it must be gitignored) containing something like 10 | 11 | export PRIVATE_KEY_MAINNET=4E7FEC...656243 12 | 13 | Then, run the migration with: 14 | 15 | source .env && tronbox migrate --network mainnet 16 | 17 | */ 18 | userFeePercentage: 100, 19 | feeLimit: 1000 * 1e6, 20 | fullHost: 'https://api.trongrid.io', 21 | network_id: '1' 22 | }, 23 | shasta: { 24 | privateKey: process.env.PRIVATE_KEY_SHASTA, 25 | userFeePercentage: 50, 26 | feeLimit: 1000 * 1e6, 27 | fullHost: 'https://api.shasta.trongrid.io', 28 | network_id: '2' 29 | }, 30 | nile: { 31 | privateKey: process.env.PRIVATE_KEY_NILE, 32 | userFeePercentage: 100, 33 | feeLimit: 1000 * 1e6, 34 | fullHost: 'https://nile.trongrid.io', 35 | network_id: '3' 36 | }, 37 | development: { 38 | // For tronbox/tre docker image 39 | privateKey: '0000000000000000000000000000000000000000000000000000000000000001', 40 | userFeePercentage: 0, 41 | feeLimit: 1000 * 1e6, 42 | fullHost: 'http://127.0.0.1:' + port, 43 | network_id: '9' 44 | }, 45 | compilers: { 46 | solc: { 47 | version: '0.8.6' 48 | } 49 | } 50 | }, 51 | // solc compiler optimize 52 | solc: { 53 | optimizer: { 54 | enabled: true, 55 | runs: 200 56 | } 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /src/components/ContractSchema/spec/network-object.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "network-object.spec.json", 3 | "$schema": "http://json-schema.org/schema#", 4 | "title": "Network Object", 5 | "type": "object", 6 | "properties": { 7 | "address": { 8 | "$ref": "#/definitions/Address" 9 | }, 10 | "transactionHash": { 11 | "$ref": "#/definitions/TransactionHash" 12 | }, 13 | "events": { 14 | "type": "object", 15 | "patternProperties": { 16 | "^0x[a-fA-F0-9]{64}$": { 17 | "$ref": "abi.spec.json#/definitions/Event" 18 | } 19 | }, 20 | "additionalProperties": false 21 | }, 22 | "links": { 23 | "type": "object", 24 | "patternProperties": { 25 | "^[a-zA-Z_][a-zA-Z0-9_]*$": { 26 | "$ref": "#/definitions/Link" 27 | } 28 | }, 29 | "additionalProperties": false 30 | } 31 | }, 32 | "additionalProperties": false, 33 | "definitions": { 34 | "Address": { 35 | "type": "string", 36 | "pattern": "^0x[a-fA-F0-9]{40}$" 37 | }, 38 | "TransactionHash": { 39 | "type": "string", 40 | "pattern": "^0x[a-fA-F0-9]{64}$" 41 | }, 42 | "Link": { 43 | "type": "object", 44 | "properties": { 45 | "address": { 46 | "$ref": "#/definitions/Address" 47 | }, 48 | "events": { 49 | "type": "object", 50 | "patternProperties": { 51 | "^0x[a-fA-F0-9]{64}$": { 52 | "$ref": "abi.spec.json#/definitions/Event" 53 | } 54 | }, 55 | "additionalProperties": false 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/components/Box/lib/utils/index.js: -------------------------------------------------------------------------------- 1 | const unbox = require('./unbox'); 2 | 3 | module.exports = { 4 | downloadBox: function (url, destination) { 5 | let tmpDir; 6 | let tmpCleanup; 7 | 8 | return Promise.resolve() 9 | .then(function () { 10 | return unbox.checkDestination(destination); 11 | }) 12 | .then(function () { 13 | return unbox.verifyURL(url); 14 | }) 15 | .then(function () { 16 | return unbox.setupTempDirectory(); 17 | }) 18 | .then(function (dir, func) { 19 | // save tmpDir result 20 | tmpDir = dir; 21 | tmpCleanup = func; 22 | }) 23 | .then(function () { 24 | return unbox.fetchRepository(url, tmpDir); 25 | }) 26 | .then(function () { 27 | return unbox.copyTempIntoDestination(tmpDir, destination); 28 | }) 29 | .then(tmpCleanup); 30 | }, 31 | 32 | unpackBox: function (destination) { 33 | let boxConfig; 34 | 35 | return Promise.resolve() 36 | .then(function () { 37 | return unbox.readBoxConfig(destination); 38 | }) 39 | .then(function (cfg) { 40 | boxConfig = cfg; 41 | }) 42 | .then(function () { 43 | return unbox.cleanupUnpack(boxConfig, destination); 44 | }) 45 | .then(function () { 46 | return boxConfig; 47 | }); 48 | }, 49 | 50 | setupBox: function (boxConfig, destination) { 51 | return Promise.resolve() 52 | .then(function () { 53 | return unbox.installBoxDependencies(boxConfig, destination); 54 | }) 55 | .then(function () { 56 | return boxConfig; 57 | }); 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /test/evm/tronbox.js: -------------------------------------------------------------------------------- 1 | const port = process.env.HOST_PORT || 9090; 2 | 3 | module.exports = { 4 | networks: { 5 | mainnet: { 6 | // Don't put your private key here: 7 | privateKey: process.env.PRIVATE_KEY_MAINNET, 8 | /* 9 | Create a .env file (it must be gitignored) containing something like 10 | 11 | export PRIVATE_KEY_MAINNET=4E7FEC...656243 12 | 13 | Then, run the migration with: 14 | 15 | source .env && tronbox migrate --network mainnet 16 | 17 | */ 18 | userFeePercentage: 100, 19 | feeLimit: 1000 * 1e6, 20 | fullHost: 'https://api.trongrid.io', 21 | network_id: '1' 22 | }, 23 | shasta: { 24 | privateKey: process.env.PRIVATE_KEY, 25 | userFeePercentage: 50, 26 | feeLimit: 1000 * 1e6, 27 | fullHost: 'https://api.shasta.trongrid.io', 28 | network_id: '2' 29 | }, 30 | nile: { 31 | privateKey: process.env.PRIVATE_KEY, 32 | userFeePercentage: 100, 33 | feeLimit: 1000 * 1e6, 34 | fullHost: 'https://nile.trongrid.io', 35 | network_id: '3' 36 | }, 37 | development: { 38 | // For tronbox/tre docker image 39 | privateKey: '0000000000000000000000000000000000000000000000000000000000000001', 40 | userFeePercentage: 0, 41 | feeLimit: 1000 * 1e6, 42 | fullHost: 'http://127.0.0.1:' + port, 43 | network_id: '9' 44 | }, 45 | compilers: { 46 | solc: { 47 | version: '0.8.6' 48 | } 49 | } 50 | }, 51 | // solc compiler optimize 52 | solc: { 53 | // optimizer: { 54 | // enabled: true, 55 | // runs: 200 56 | // }, 57 | // evmVersion: 'istanbul' 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /src/lib/copy.js: -------------------------------------------------------------------------------- 1 | const cpr = require('cpr'); 2 | const fs = require('fs'); 3 | const _ = require('lodash'); 4 | 5 | const cpr_options = { 6 | deleteFirst: false, 7 | overwrite: false, 8 | confirm: true 9 | }; 10 | 11 | // This module will copy a file or directory, and by default 12 | // won't override individual files. If a file exists, it will 13 | // simply move onto the next file. 14 | 15 | const copy = function (from, to, extra_options, callback) { 16 | if (typeof extra_options === 'function') { 17 | callback = extra_options; 18 | extra_options = {}; 19 | } 20 | 21 | const options = _.merge(_.clone(cpr_options), extra_options); 22 | 23 | cpr(from, to, options, function (err, files) { 24 | const new_files = []; 25 | 26 | // Remove placeholders. Placeholders allow us to copy "empty" directories, 27 | // but lets NPM and git not ignore them. 28 | files = files || []; 29 | for (const file of files) { 30 | if (file.match(/.*PLACEHOLDER.*/) != null) { 31 | fs.unlinkSync(file); 32 | continue; 33 | } 34 | new_files.push(file); 35 | } 36 | 37 | callback(err, new_files); 38 | }); 39 | }; 40 | 41 | copy.file = function (from, to, callback) { 42 | const readStream = fs.createReadStream(from, 'utf8'); 43 | const writeStream = fs.createWriteStream(to, 'utf8'); 44 | 45 | readStream.on('error', function (err) { 46 | callback(err); 47 | callback = function () {}; 48 | }); 49 | 50 | writeStream.on('error', function (err) { 51 | callback(err); 52 | callback = function () {}; 53 | }); 54 | 55 | writeStream.on('finish', function () { 56 | callback(); 57 | }); 58 | 59 | readStream.pipe(writeStream); 60 | }; 61 | 62 | module.exports = copy; 63 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | const nodePlugin = require('eslint-plugin-n'); 2 | const globals = require('globals'); 3 | 4 | module.exports = [ 5 | nodePlugin.configs['flat/recommended-script'], 6 | { 7 | rules: { 8 | eqeqeq: ['error', 'smart'], 9 | 'no-console': [ 10 | 'error', 11 | { 12 | allow: ['debug', 'info', 'warn', 'error'] 13 | } 14 | ], 15 | 'no-var': ['error'], 16 | 'prefer-const': [ 17 | 'error', 18 | { 19 | destructuring: 'all' 20 | } 21 | ], 22 | 'n/exports-style': ['error', 'module.exports'], 23 | 'n/prefer-global/buffer': ['error', 'always'], 24 | 'n/prefer-global/console': ['error', 'always'], 25 | 'n/prefer-global/process': ['error', 'always'], 26 | 'n/prefer-global/text-decoder': ['error', 'always'], 27 | 'n/prefer-global/text-encoder': ['error', 'always'], 28 | 'n/prefer-global/url': ['error', 'always'], 29 | 'n/prefer-global/url-search-params': ['error', 'always'], 30 | 'n/no-process-exit': ['off'], 31 | 'n/no-unpublished-require': [ 32 | 'error', 33 | { 34 | allowModules: ['eslint-plugin-n', 'globals'] 35 | } 36 | ], 37 | 'no-unused-vars': [ 38 | 'error', 39 | { 40 | args: 'after-used', 41 | ignoreRestSiblings: true, 42 | argsIgnorePattern: '^_', 43 | caughtErrors: 'none' 44 | } 45 | ] 46 | } 47 | }, 48 | { 49 | files: ['./test/**/*.js'], 50 | languageOptions: { 51 | globals: { 52 | ...globals.mocha, 53 | tronWeb: 'readonly', 54 | tronWrap: 'readonly', 55 | web3: 'readonly', 56 | assert: 'readonly', 57 | expect: 'readonly', 58 | artifacts: 'readonly', 59 | contract: 'readonly' 60 | } 61 | } 62 | } 63 | ]; 64 | -------------------------------------------------------------------------------- /test/evm/test/metacoin.js: -------------------------------------------------------------------------------- 1 | const MetaCoin = artifacts.require('./MetaCoin.sol'); 2 | 3 | contract('MetaCoin', function (accounts) { 4 | let meta; 5 | 6 | before(async function () { 7 | meta = await MetaCoin.deployed(); 8 | }); 9 | 10 | it('should verify that the contract has been deployed by accounts[0]', async function () { 11 | assert.equal(await meta.getOwner(), web3.eth.accounts.wallet[0].address); 12 | }); 13 | 14 | it('should put 10000 MetaCoin in the first account', async function () { 15 | const balance = await meta.getBalance(accounts[0], { from: accounts[0] }); 16 | assert.equal(balance, 10000, "10000 wasn't in the first account"); 17 | }); 18 | 19 | it('should call a function that depends on a linked library', async function () { 20 | this.timeout(10000); 21 | const metaCoinBalance = await meta.getBalance.call(accounts[0]); 22 | const metaCoinConvertedBalance = await meta.getConvertedBalance.call(accounts[0]); 23 | assert.equal( 24 | metaCoinConvertedBalance, 25 | 2n * metaCoinBalance, 26 | 'Library function returned unexpected function, linkage may be broken' 27 | ); 28 | }); 29 | 30 | it('should send coins from account 0 to 1', async function () { 31 | const account1 = meta.address; 32 | const account_one_starting_balance = await meta.getBalance.call(accounts[0]); 33 | const account_two_starting_balance = await meta.getBalance.call(account1); 34 | await meta.sendCoin(account1, 10, { 35 | from: accounts[0] 36 | }); 37 | assert.equal( 38 | await meta.getBalance.call(accounts[0]), 39 | account_one_starting_balance - 10n, 40 | "Amount wasn't correctly taken from the sender" 41 | ); 42 | assert.equal( 43 | await meta.getBalance.call(account1), 44 | account_two_starting_balance + 10n, 45 | "Amount wasn't correctly sent to the receiver" 46 | ); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /sample-projects/javascript/tronbox-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | mainnet: { 4 | // Don't put your private key here: 5 | privateKey: process.env.PRIVATE_KEY_MAINNET, 6 | /** 7 | * Create a .env file (it must be gitignored) containing something like 8 | * 9 | * export PRIVATE_KEY_MAINNET=4E7FEC...656243 10 | * 11 | * Then, run the migration with: 12 | * 13 | * source .env && tronbox migrate --network mainnet 14 | */ 15 | userFeePercentage: 100, 16 | feeLimit: 1000 * 1e6, 17 | fullHost: 'https://api.trongrid.io', 18 | network_id: '1' 19 | }, 20 | shasta: { 21 | // Obtain test coin at https://shasta.tronex.io/ 22 | privateKey: process.env.PRIVATE_KEY_SHASTA, 23 | userFeePercentage: 50, 24 | feeLimit: 1000 * 1e6, 25 | fullHost: 'https://api.shasta.trongrid.io', 26 | network_id: '2' 27 | }, 28 | nile: { 29 | // Obtain test coin at https://nileex.io/join/getJoinPage 30 | privateKey: process.env.PRIVATE_KEY_NILE, 31 | userFeePercentage: 100, 32 | feeLimit: 1000 * 1e6, 33 | fullHost: 'https://nile.trongrid.io', 34 | network_id: '3' 35 | }, 36 | development: { 37 | // For tronbox/tre docker image 38 | // See https://hub.docker.com/r/tronbox/tre 39 | privateKey: '0000000000000000000000000000000000000000000000000000000000000001', 40 | userFeePercentage: 0, 41 | feeLimit: 1000 * 1e6, 42 | fullHost: 'http://127.0.0.1:9090', 43 | network_id: '9' 44 | } 45 | }, 46 | compilers: { 47 | solc: { 48 | version: '0.8.6', 49 | // An object with the same schema as the settings entry in the Input JSON. 50 | // See https://docs.soliditylang.org/en/latest/using-the-compiler.html#input-description 51 | settings: { 52 | // optimizer: { 53 | // enabled: true, 54 | // runs: 200 55 | // }, 56 | // evmVersion: 'istanbul', 57 | // viaIR: true, 58 | } 59 | } 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/tronbox-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | mainnet: { 4 | // Don't put your private key here: 5 | privateKey: process.env.PRIVATE_KEY_MAINNET, 6 | /** 7 | * Create a .env file (it must be gitignored) containing something like 8 | * 9 | * export PRIVATE_KEY_MAINNET=4E7FEC...656243 10 | * 11 | * Then, run the migration with: 12 | * 13 | * source .env && tronbox migrate --network mainnet 14 | */ 15 | userFeePercentage: 100, 16 | feeLimit: 1000 * 1e6, 17 | fullHost: 'https://api.trongrid.io', 18 | network_id: '1' 19 | }, 20 | shasta: { 21 | // Obtain test coin at https://shasta.tronex.io/ 22 | privateKey: process.env.PRIVATE_KEY_SHASTA, 23 | userFeePercentage: 50, 24 | feeLimit: 1000 * 1e6, 25 | fullHost: 'https://api.shasta.trongrid.io', 26 | network_id: '2' 27 | }, 28 | nile: { 29 | // Obtain test coin at https://nileex.io/join/getJoinPage 30 | privateKey: process.env.PRIVATE_KEY_NILE, 31 | userFeePercentage: 100, 32 | feeLimit: 1000 * 1e6, 33 | fullHost: 'https://nile.trongrid.io', 34 | network_id: '3' 35 | }, 36 | development: { 37 | // For tronbox/tre docker image 38 | // See https://hub.docker.com/r/tronbox/tre 39 | privateKey: '0000000000000000000000000000000000000000000000000000000000000001', 40 | userFeePercentage: 0, 41 | feeLimit: 1000 * 1e6, 42 | fullHost: 'http://127.0.0.1:9090', 43 | network_id: '9' 44 | } 45 | }, 46 | compilers: { 47 | solc: { 48 | version: '0.8.23', 49 | // An object with the same schema as the settings entry in the Input JSON. 50 | // See https://docs.soliditylang.org/en/latest/using-the-compiler.html#input-description 51 | settings: { 52 | // optimizer: { 53 | // enabled: true, 54 | // runs: 200 55 | // }, 56 | // evmVersion: 'istanbul', 57 | // viaIR: true, 58 | } 59 | } 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /sample-projects/javascript/README.md: -------------------------------------------------------------------------------- 1 | # Sample TronBox Project 2 | 3 | This is a bare-minimum TronBox project. 4 | 5 | ## Configuration 6 | 7 | Your configuration file is called `tronbox-config.js` and is located at the root of your project directory. 8 | 9 | ## Compiling 10 | 11 | To compile your contracts, use the following command: 12 | 13 | ```shell 14 | tronbox compile 15 | ``` 16 | 17 | ## Migration 18 | 19 | The project comes pre-configured with four separate networks: 20 | 21 | - Mainnet (https://api.trongrid.io) 22 | - Shasta Testnet (https://api.shasta.trongrid.io) 23 | - Nile Testnet (https://nile.trongrid.io). 24 | - Localnet (http://127.0.0.1:9090) 25 | 26 | ### Mainnet 27 | 28 | To deploy your contracts to Mainnet, you can run the following: 29 | 30 | ```shell 31 | tronbox migrate --network mainnet 32 | ``` 33 | 34 | ### Shasta Testnet 35 | 36 | Obtain test coin at https://shasta.tronex.io/ 37 | 38 | To deploy your contracts to Shasta Testnet, you can run the following: 39 | 40 | ```shell 41 | tronbox migrate --network shasta 42 | ``` 43 | 44 | ### Nile Testnet 45 | 46 | Obtain test coin at https://nileex.io/join/getJoinPage 47 | 48 | To deploy your contracts to Nile Testnet, you can run the following: 49 | 50 | ```shell 51 | tronbox migrate --network nile 52 | ``` 53 | 54 | ### Localnet 55 | 56 | The TronBox Runtime Environment provides a complete development framework for Tron, including a private network for testing. 57 | 58 | Get tronbox/tre docker image at https://hub.docker.com/r/tronbox/tre 59 | 60 | To deploy your contracts to Localnet, you can run the following: 61 | 62 | ```shell 63 | tronbox migrate 64 | ``` 65 | 66 | ## Testing 67 | 68 | To test your contracts, you can run the following: 69 | 70 | ```shell 71 | tronbox test --network 72 | ``` 73 | 74 | ## Work with EVM 75 | 76 | TronBox supports deploying contracts on EVM-compatible blockchains. 77 | 78 | For more information, please refer to: https://tronbox.io/docs/guides/work-with-evm 79 | 80 | ## Additional Resources 81 | 82 | For further learning, visit the official TronBox site at https://tronbox.io 83 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/README.md: -------------------------------------------------------------------------------- 1 | # MetaCoin TronBox Project 2 | 3 | This is a MetaCoin TronBox project. 4 | 5 | ## Configuration 6 | 7 | Your configuration file is called `tronbox-config.js` and is located at the root of your project directory. 8 | 9 | ## Compiling 10 | 11 | To compile your contracts, use the following command: 12 | 13 | ```shell 14 | tronbox compile 15 | ``` 16 | 17 | ## Migration 18 | 19 | The project comes pre-configured with four separate networks: 20 | 21 | - Mainnet (https://api.trongrid.io) 22 | - Shasta Testnet (https://api.shasta.trongrid.io) 23 | - Nile Testnet (https://nile.trongrid.io). 24 | - Localnet (http://127.0.0.1:9090) 25 | 26 | ### Mainnet 27 | 28 | To deploy your contracts to Mainnet, you can run the following: 29 | 30 | ```shell 31 | tronbox migrate --network mainnet 32 | ``` 33 | 34 | ### Shasta Testnet 35 | 36 | Obtain test coin at https://shasta.tronex.io/ 37 | 38 | To deploy your contracts to Shasta Testnet, you can run the following: 39 | 40 | ```shell 41 | tronbox migrate --network shasta 42 | ``` 43 | 44 | ### Nile Testnet 45 | 46 | Obtain test coin at https://nileex.io/join/getJoinPage 47 | 48 | To deploy your contracts to Nile Testnet, you can run the following: 49 | 50 | ```shell 51 | tronbox migrate --network nile 52 | ``` 53 | 54 | ### Localnet 55 | 56 | The TronBox Runtime Environment provides a complete development framework for Tron, including a private network for testing. 57 | 58 | Get tronbox/tre docker image at https://hub.docker.com/r/tronbox/tre 59 | 60 | To deploy your contracts to Localnet, you can run the following: 61 | 62 | ```shell 63 | tronbox migrate 64 | ``` 65 | 66 | ## Testing 67 | 68 | To test your contracts, you can run the following: 69 | 70 | ```shell 71 | tronbox test --network 72 | ``` 73 | 74 | ## Work with EVM 75 | 76 | TronBox supports deploying contracts on EVM-compatible blockchains. 77 | 78 | For more information, please refer to: https://tronbox.io/docs/guides/work-with-evm 79 | 80 | ## Additional Resources 81 | 82 | For further learning, visit the official TronBox site at https://tronbox.io 83 | -------------------------------------------------------------------------------- /test/tre/test/metacoin.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | const MetaCoin = artifacts.require('./MetaCoin.sol'); 3 | 4 | // The following tests require TronBox >= 2.1.x 5 | // and TronBox Runtime Environment (https://hub.docker.com/r/tronbox/tre) 6 | 7 | contract('MetaCoin', function (accounts) { 8 | let meta; 9 | 10 | before(async function () { 11 | meta = await MetaCoin.deployed(); 12 | if (accounts.length < 3) { 13 | // Set your own accounts if you are not using TronBox Runtime Environment 14 | } 15 | }); 16 | 17 | it('should verify that there are at least three available accounts', async function () { 18 | if (accounts.length < 3) { 19 | console.info( 20 | chalk.blue( 21 | '\nYOUR ATTENTION, PLEASE.]\nTo test MetaCoin you should use TronBox Runtime Environment (https://hub.docker.com/r/tronbox/tre) as your private network.\nAlternatively, you must set your own accounts in the "before" statement in "test/metacoin.js".\n' 22 | ) 23 | ); 24 | } 25 | assert.isTrue(accounts.length >= 3); 26 | }); 27 | 28 | it('should verify that the contract has been deployed by accounts[0]', async function () { 29 | assert.equal(await meta.getOwner(), tronWeb.address.toHex(accounts[0])); 30 | }); 31 | 32 | it('should put 10000 MetaCoin in the first account', async function () { 33 | const balance = await meta.getBalance(accounts[0], { from: accounts[0] }); 34 | assert.equal(balance, 10000n, "10000 wasn't in the first account"); 35 | }); 36 | 37 | it('should send coins from account 0 to 1', async function () { 38 | assert.isTrue(accounts[1] ? true : false, 'accounts[1] does not exist. Use TronBox Runtime Environment!'); 39 | 40 | this.timeout(10000); 41 | const meta = await MetaCoin.deployed(); 42 | const account_one_starting_balance = await meta.getBalance.call(accounts[0]); 43 | const account_two_starting_balance = await meta.getBalance.call(accounts[1]); 44 | await meta.sendCoin(accounts[1], 10, { 45 | from: accounts[0] 46 | }); 47 | assert.equal( 48 | await meta.getBalance.call(accounts[0]), 49 | account_one_starting_balance - 10n, 50 | "Amount wasn't correctly taken from the sender" 51 | ); 52 | assert.equal( 53 | await meta.getBalance.call(accounts[1]), 54 | account_two_starting_balance + 10n, 55 | "Amount wasn't correctly sent to the receiver" 56 | ); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /src/components/Resolver/npm.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | 4 | function NPM(working_directory) { 5 | this.working_directory = working_directory; 6 | } 7 | 8 | NPM.prototype.require = function (import_path, search_path) { 9 | if (import_path.indexOf('.') === 0 || import_path.indexOf('/') === 0) { 10 | return null; 11 | } 12 | const contract_name = path.basename(import_path, '.sol'); 13 | const regex = new RegExp(`(.*)/${contract_name}`); 14 | let package_name = ''; 15 | const matched = regex.exec(import_path); 16 | if (matched) { 17 | package_name = matched[1]; 18 | } 19 | const expected_path = path.join( 20 | search_path || this.working_directory, 21 | 'node_modules', 22 | package_name, 23 | 'build', 24 | 'contracts', 25 | contract_name + '.json' 26 | ); 27 | try { 28 | const result = fs.readFileSync(expected_path, 'utf8'); 29 | return JSON.parse(result); 30 | } catch (e) { 31 | return null; 32 | } 33 | }; 34 | 35 | NPM.prototype.resolve = function (import_path, imported_from, callback) { 36 | // If nothing's found, body returns `undefined` 37 | let body; 38 | let modulesDir = this.working_directory; 39 | 40 | while (true) { 41 | const expected_path = path.join(modulesDir, 'node_modules', import_path); 42 | 43 | try { 44 | body = fs.readFileSync(expected_path, { encoding: 'utf8' }); 45 | break; 46 | } catch (err) {} 47 | 48 | // Recurse outwards until impossible 49 | const oldModulesDir = modulesDir; 50 | modulesDir = path.join(modulesDir, '..'); 51 | if (modulesDir === oldModulesDir) { 52 | break; 53 | } 54 | } 55 | return callback(null, body, import_path); 56 | }; 57 | 58 | // We're resolving package paths to other package paths, not absolute paths. 59 | // This will ensure the source fetcher conintues to use the correct sources for packages. 60 | // i.e., if some_module/contracts/MyContract.sol imported "./AnotherContract.sol", 61 | // we're going to resolve it to some_module/contracts/AnotherContract.sol, ensuring 62 | // that when this path is evaluated this source is used again. 63 | NPM.prototype.resolve_dependency_path = function (import_path, dependency_path) { 64 | const dirname = path.dirname(import_path); 65 | return path.join(dirname, dependency_path); 66 | }; 67 | 68 | NPM.prototype.provision_contracts = function (callback) { 69 | // TODO: Fill this out! 70 | callback(null, {}); 71 | }; 72 | 73 | module.exports = NPM; 74 | -------------------------------------------------------------------------------- /test/tre/contracts/MetaCoin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | import './ConvertLib.sol'; 5 | 6 | // This is just a simple example of a coin-like contract. 7 | // It is not standards compatible and cannot be expected to talk to other 8 | // coin/token contracts. 9 | 10 | contract MetaCoin { 11 | uint256 public totalSupply = 0; 12 | mapping(address => uint) balances; 13 | 14 | event Transfer(address _from, address _to, uint256 _value); 15 | 16 | address owner; 17 | 18 | constructor(uint initialBalance) { 19 | owner = msg.sender; 20 | balances[msg.sender] = initialBalance; 21 | } 22 | 23 | function sendCoin( 24 | address receiver, 25 | uint amount 26 | ) public returns (bool sufficient) { 27 | if (balances[msg.sender] < amount) return false; 28 | balances[msg.sender] -= amount; 29 | balances[receiver] += amount; 30 | emit Transfer(msg.sender, receiver, amount); 31 | return true; 32 | } 33 | 34 | function getBalance(address addr) public view returns (uint) { 35 | return balances[addr]; 36 | } 37 | 38 | function getConvertedBalance(address addr) public view returns (uint) { 39 | return ConvertLib.convert(getBalance(addr), 2); 40 | } 41 | 42 | function getOwner() public view returns (address) { 43 | return owner; 44 | } 45 | 46 | // Helper functions 47 | function getMsgSender() public view returns (address sender) { 48 | sender = msg.sender; 49 | } 50 | 51 | function getTrxBalance(address addr) public view returns (uint256 balance) { 52 | balance = addr.balance; 53 | } 54 | 55 | function getBlockNumber() public view returns (uint256 blockNumber) { 56 | blockNumber = block.number; 57 | } 58 | 59 | function getBlockHash( 60 | uint256 blockNumber 61 | ) public view returns (bytes32 blockHash) { 62 | blockHash = blockhash(blockNumber); 63 | } 64 | 65 | function getLastBlockHash() public view returns (bytes32 blockHash) { 66 | blockHash = blockhash(block.number - 1); 67 | } 68 | 69 | function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { 70 | timestamp = block.timestamp; 71 | } 72 | 73 | function getCurrentBlockDifficulty() 74 | public 75 | view 76 | returns (uint256 difficulty) 77 | { 78 | difficulty = block.difficulty; 79 | } 80 | 81 | function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) { 82 | gaslimit = block.gaslimit; 83 | } 84 | 85 | function getCurrentBlockCoinbase() public view returns (address coinbase) { 86 | coinbase = block.coinbase; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/lib/commands/console.js: -------------------------------------------------------------------------------- 1 | const version = require('../version'); 2 | const describe = 'Run a console with contract abstractions and commands available'; 3 | 4 | const command = { 5 | command: 'console', 6 | describe, 7 | builder: yargs => { 8 | yargs 9 | .usage( 10 | `TronBox v${version.bundle}\n\n${describe}\n 11 | Usage: $0 console [--network ] [--evm]` 12 | ) 13 | .version(false) 14 | .options({ 15 | network: { 16 | describe: 'Network name in configuration', 17 | type: 'string' 18 | }, 19 | evm: { 20 | describe: 'Use EVM configuration', 21 | type: 'boolean' 22 | } 23 | }) 24 | .example('$0 console', 'Start the console with the development network') 25 | .example('$0 console --network nile', 'Start the console with the nile network') 26 | .example('$0 console --evm', 'Start the console with EVM configuration') 27 | .group(['network', 'evm', 'help'], 'Options:'); 28 | }, 29 | run: function (options, done) { 30 | process.env.CURRENT = 'console'; 31 | const Config = require('../../components/Config'); 32 | const Console = require('../console'); 33 | const Environment = require('../environment'); 34 | 35 | const TronWrap = require('../../components/TronWrap'); 36 | const logErrorAndExit = require('../../components/TronWrap').logErrorAndExit; 37 | 38 | const config = Config.detect(options); 39 | 40 | if (!config.network && config.networks.development) { 41 | config.network = 'development'; 42 | } 43 | // init TronWeb 44 | try { 45 | TronWrap(config.networks[config.network], { 46 | evm: options.evm, 47 | verify: true, 48 | logger: options.logger 49 | }); 50 | } catch (err) { 51 | logErrorAndExit(console, err.message); 52 | } 53 | 54 | // This require a smell? 55 | const commands = require('./index'); 56 | const excluded = ['console', 'init', 'flatten', 'unbox']; 57 | 58 | const available_commands = Object.keys(commands).filter(function (name) { 59 | return excluded.indexOf(name) === -1; 60 | }); 61 | 62 | const console_commands = {}; 63 | available_commands.forEach(function (name) { 64 | console_commands[name] = commands[name]; 65 | }); 66 | 67 | Environment.detect(config, function (err) { 68 | if (err) return done(err); 69 | 70 | const c = new Console( 71 | console_commands, 72 | config.with({ 73 | noAliases: true 74 | }) 75 | ); 76 | c.start(done); 77 | }); 78 | } 79 | }; 80 | 81 | module.exports = command; 82 | -------------------------------------------------------------------------------- /test/evm/test/mycontract.js: -------------------------------------------------------------------------------- 1 | const MyContract1 = artifacts.require('./MyContract1.sol'); 2 | const MyContract2 = artifacts.require('./MyContract2.sol'); 3 | 4 | contract('MyContract', function (accounts) { 5 | let c1; 6 | let c2; 7 | 8 | before(async function () { 9 | c1 = await MyContract1.deployed(); 10 | c2 = await MyContract2.deployed(); 11 | }); 12 | 13 | it('should check the initial value of the contract', async function () { 14 | assert.equal(await c1.myNumber(), 1, 'The value in MyContract1 should be 1'); 15 | assert.equal(await c2.myNumber(), 2, 'The value in MyContract2 should be 2'); 16 | }); 17 | 18 | it('should check the initial balance of the contract', async function () { 19 | assert.equal(await c1.getBalance(c1.address), 0, 'The balance of MyContract1 should be 0'); 20 | assert.equal(await c1.getBalance(c2.address), 1, 'The balance of MyContract2 should be 1'); 21 | }); 22 | 23 | it('should set the value in the contract', async function () { 24 | await c1.setMyNumber(100); 25 | assert.equal(await c1.myNumber(), 100, 'The value in MyContract1 should be set to 100'); 26 | 27 | try { 28 | await c1.setMyNumber(200, { value: 1 }); 29 | } catch {} 30 | assert.equal(await c1.myNumber(), 100, 'The value in MyContract1 should remain 100'); 31 | assert.equal(await c1.getBalance(c1.address), 0, 'The balance of MyContract1 should be 0'); 32 | 33 | await c2.setMyNumber(200); 34 | assert.equal(await c2.myNumber(), 200, 'The value in MyContract2 should be set to 200'); 35 | await c2.setMyNumber(300, { value: 1 }); 36 | assert.equal(await c2.myNumber(), 300, 'The value in MyContract2 should be set to 300'); 37 | assert.equal(await c1.getBalance(c2.address), 2, 'The balance of MyContract2 should be 2'); 38 | }); 39 | 40 | it('should set the from', async function () { 41 | const sender1 = await c1.getSender(); 42 | assert.equal(sender1, accounts[0], 'The sender should be accounts[0]'); 43 | 44 | const from = '0x1234567890123456789012345678901234567890'; 45 | const sender2 = await c1.getSender({ from }); 46 | assert.equal(sender2, from, 'The sender should be 0x1234567890123456789012345678901234567890'); 47 | }); 48 | 49 | it('should return the contract address', async function () { 50 | const c1Address = await c1.myAddress(); 51 | assert.equal(c1Address.toLowerCase(), c1.address, 'The address should be the address of MyContract1'); 52 | 53 | const c2Ins = await c1.at(c2.address); 54 | const c2Address = await c2Ins.myAddress(); 55 | assert.equal(c2Address.toLowerCase(), c2.address, 'The address should be the address of MyContract2'); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /src/components/Deployer/index.js: -------------------------------------------------------------------------------- 1 | const expect = require('@truffle/expect'); 2 | const DeferredChain = require('./src/deferredchain'); 3 | const deploy = require('./src/actions/deploy'); 4 | const deployMany = require('./src/actions/deploymany'); 5 | const link = require('./src/actions/link'); 6 | const create = require('./src/actions/new'); 7 | const { dlog } = require('../TronWrap'); 8 | 9 | function Deployer(options) { 10 | const self = this; 11 | options = options || {}; 12 | 13 | expect.options(options, ['provider', 'network', 'network_id']); 14 | 15 | this.chain = new DeferredChain(); 16 | this.logger = options.logger || { 17 | log: function () {} 18 | }; 19 | this.known_contracts = {}; 20 | (options.contracts || []).forEach(function (contract) { 21 | self.known_contracts[contract.contract_name] = contract; 22 | }); 23 | this.network = options.network; 24 | this.network_id = options.network_id; 25 | this.provider = options.provider; 26 | this.basePath = options.basePath || process.cwd(); 27 | this.options = options; 28 | } 29 | 30 | // Note: In all code below we overwrite this.chain every time .then() is used 31 | // in order to ensure proper error processing. 32 | 33 | Deployer.prototype.start = function () { 34 | return this.chain.start(); 35 | }; 36 | 37 | Deployer.prototype.link = function (library, destinations) { 38 | return this.queueOrExec(link(library, destinations, this)); 39 | }; 40 | 41 | Deployer.prototype.deploy = function () { 42 | const args = Array.prototype.slice.call(arguments); 43 | const contract = args.shift(); 44 | 45 | if (Array.isArray(contract)) { 46 | dlog('Deploy many'); 47 | return this.queueOrExec(deployMany(contract, this)); 48 | } else { 49 | dlog('Deploy one'); 50 | return this.queueOrExec(deploy(contract, args, this)); 51 | } 52 | }; 53 | 54 | Deployer.prototype.new = function () { 55 | const args = Array.prototype.slice.call(arguments); 56 | const contract = args.shift(); 57 | 58 | return this.queueOrExec(create(contract, args, this)); 59 | }; 60 | 61 | Deployer.prototype.exec = function () { 62 | throw new Error('deployer.exec() has been deprecated; please seen the tronbox-require package for integration.'); 63 | }; 64 | 65 | Deployer.prototype.then = function (fn) { 66 | const self = this; 67 | 68 | return this.queueOrExec(function () { 69 | self.logger.log('Running step...'); 70 | return fn(this); 71 | }); 72 | }; 73 | 74 | Deployer.prototype.queueOrExec = function (fn) { 75 | if (this.chain.started) { 76 | return new Promise(function (accept) { 77 | accept(); 78 | }).then(fn); 79 | } else { 80 | return this.chain.then(fn); 81 | } 82 | }; 83 | 84 | module.exports = Deployer; 85 | -------------------------------------------------------------------------------- /src/components/Resolver/index.js: -------------------------------------------------------------------------------- 1 | const EPMSource = require('./epm'); 2 | const NPMSource = require('./npm'); 3 | const FSSource = require('./fs'); 4 | const path = require('path'); 5 | const whilst = require('async/whilst'); 6 | const contract = require('../Contract'); 7 | const expect = require('@truffle/expect'); 8 | const provision = require('../Provisioner'); 9 | 10 | function Resolver(options) { 11 | expect.options(options, ['working_directory', 'contracts_build_directory']); 12 | 13 | this.options = options; 14 | 15 | this.sources = [ 16 | new EPMSource(options.working_directory, options.contracts_build_directory), 17 | new NPMSource(options.working_directory), 18 | new NPMSource(__dirname), 19 | new FSSource(options.working_directory, options.contracts_build_directory) 20 | ]; 21 | } 22 | 23 | // This function might be doing too much. If so, too bad (for now). 24 | Resolver.prototype.require = function (import_path, search_path) { 25 | const self = this; 26 | 27 | for (let i = 0; i < this.sources.length; i++) { 28 | const source = this.sources[i]; 29 | const result = source.require(import_path, search_path); 30 | if (result) { 31 | const abstraction = contract(result); 32 | provision(abstraction, self.options); 33 | return abstraction; 34 | } 35 | } 36 | throw new Error('Could not find artifacts for ' + import_path + ' from any sources'); 37 | }; 38 | 39 | Resolver.prototype.resolve = function (import_path, imported_from, callback) { 40 | const self = this; 41 | 42 | if (typeof imported_from === 'function') { 43 | callback = imported_from; 44 | imported_from = null; 45 | } 46 | 47 | let resolved_body = null; 48 | let resolved_path = null; 49 | let current_index = -1; 50 | let current_source; 51 | 52 | whilst( 53 | function () { 54 | return !resolved_body && current_index < self.sources.length - 1; 55 | }, 56 | function (next) { 57 | current_index += 1; 58 | current_source = self.sources[current_index]; 59 | 60 | current_source.resolve(import_path, imported_from, function (err, body, file_path) { 61 | if (!err && body) { 62 | resolved_body = body; 63 | resolved_path = file_path; 64 | } 65 | next(err); 66 | }); 67 | }, 68 | function (err) { 69 | if (err) return callback(err); 70 | 71 | if (!resolved_body) { 72 | let message = 73 | 'Could not find ' + path.relative(self.options.working_directory, import_path) + ' from any sources'; 74 | 75 | if (imported_from) { 76 | message += '; imported from ' + path.relative(self.options.working_directory, imported_from); 77 | } 78 | 79 | return callback(new Error(message)); 80 | } 81 | 82 | callback(null, resolved_body, resolved_path, current_source); 83 | } 84 | ); 85 | }; 86 | 87 | module.exports = Resolver; 88 | -------------------------------------------------------------------------------- /src/components/Deployer/src/actions/deploy.js: -------------------------------------------------------------------------------- 1 | const TronWrap = require('../../../TronWrap'); 2 | const { dlog } = require('../../../TronWrap'); 3 | const Contract = require('../../../Contract'); 4 | const provision = require('../../../Provisioner'); 5 | 6 | module.exports = function (contract, args, deployer) { 7 | return function () { 8 | let should_deploy = true; 9 | const trufflePlugin = deployer.trufflePlugin || false; 10 | 11 | if (!contract.initTronWeb) { 12 | const abstraction = Contract(contract._json); 13 | // abstraction.defaults(this.class_defaults) 14 | provision(abstraction, deployer.options); 15 | contract = abstraction; 16 | } 17 | 18 | // Evaluate any arguments if they're promises (we need to do this in all cases to maintain consistency) 19 | return Promise.all(args) 20 | .then(function (new_args) { 21 | // Check the last argument. If it's an object that tells us not to overwrite, then lets not. 22 | if (new_args.length > 0) { 23 | const last_arg = new_args[new_args.length - 1]; 24 | if (typeof last_arg === 'object' && last_arg.overwrite === false && contract.isDeployed()) { 25 | should_deploy = false; 26 | } 27 | delete last_arg.overwrite; 28 | } 29 | 30 | if (should_deploy === true) { 31 | let prefix = 'Deploying '; 32 | if (contract.isDeployed()) { 33 | prefix = 'Replacing '; 34 | } 35 | deployer.logger.log(prefix + contract.contract_name + '...'); 36 | dlog(new_args); 37 | return contract.new.apply(contract, new_args); 38 | } else { 39 | return contract.deployed(); 40 | } 41 | }) 42 | .then(function (instance) { 43 | const tronWrap = TronWrap(); 44 | if (should_deploy === true) { 45 | if (tronWrap._web3) { 46 | deployer.logger.log(contract.contract_name + ':\n (hex) ' + instance.address); 47 | } else { 48 | deployer.logger.log( 49 | contract.contract_name + 50 | ':\n (base58) ' + 51 | tronWrap.address.fromHex(instance.address) + 52 | '\n (hex) ' + 53 | instance.address 54 | ); 55 | } 56 | } else { 57 | deployer.logger.log("Didn't deploy " + contract.contract_name + '; using ' + instance.address); 58 | } 59 | 60 | instance.address = trufflePlugin ? instance.address.replace(/^41/, '0x') : instance.address; 61 | 62 | // Ensure the address and tx-hash are set on the contract. 63 | contract.address = instance.address; 64 | contract.transactionHash = instance.transactionHash; 65 | 66 | dlog('Instance name:', instance && instance.constructor ? instance.constructor.contractName : null); 67 | return instance; 68 | }); 69 | }; 70 | }; 71 | -------------------------------------------------------------------------------- /test/abiv2/test/tuple.js: -------------------------------------------------------------------------------- 1 | const { assert } = require('chai'); 2 | const Tuple = artifacts.require('./Tuple.sol'); 3 | 4 | // The following tests require TronBox >= 2.1.x 5 | 6 | contract('Tuple', function () { 7 | let tuple; 8 | 9 | function turnBN2N(values) { 10 | if (values instanceof Array) { 11 | return values.map(turnBN2N); 12 | } 13 | if (values._isBigNumber) return values.toNumber(); 14 | if (typeof values === 'bigint') return Number(values); 15 | return values; 16 | } 17 | 18 | before(async function () { 19 | tuple = await Tuple.deployed(); 20 | }); 21 | 22 | it('should have 3 `person`s with `Tom` which is the first to verify that the argument passed to constructor works', async function () { 23 | assert.deepEqual(turnBN2N(await tuple.getPerson()), [ 24 | ['Tom', 30], 25 | ['Lily', 20], 26 | ['Oscar', 30] 27 | ]); 28 | }); 29 | 30 | it('should get `Tom 30` to verify getPersonById is working', async function () { 31 | const person = await tuple.getPersonById(0); 32 | assert.deepEqual(turnBN2N(person), ['Tom', 30]); 33 | }); 34 | 35 | it('should return the same person', async function () { 36 | const person1 = ['return', 101]; 37 | const person2 = turnBN2N(await tuple.echoPerson(person1)); 38 | assert.deepEqual(person1, person2); 39 | }); 40 | 41 | it('should insert person', async function () { 42 | const lastPersons = turnBN2N(await tuple.getPerson()); 43 | const person1 = ['insert', 100]; 44 | await tuple.insert(person1); 45 | const person2 = [['insert', 101]]; 46 | await tuple.insert(person2); 47 | const persons = turnBN2N(await tuple.getPerson()); 48 | assert.deepEqual(lastPersons.concat([person1, ...person2]), persons); 49 | }); 50 | 51 | it('should insert persons', async function () { 52 | const lastPersons = turnBN2N(await tuple.getPerson()); 53 | const persons1 = [ 54 | ['insert2', 99], 55 | ['insert3', 98] 56 | ]; 57 | await tuple.insertBatch(persons1); 58 | const persons2 = turnBN2N(await tuple.getPerson()); 59 | assert.deepEqual(lastPersons.concat(persons1), persons2); 60 | }); 61 | 62 | it('should correctly call overloaded functions', async function () { 63 | const uint256Result = await tuple['func(uint256)'](1); 64 | const addressResult = await tuple['func(address)'](tuple.address); 65 | assert.equal(uint256Result, '0x7f98a45e', 'func(uint256) returned an unexpected value'); 66 | assert.equal(addressResult, '0xb8550dc7', 'func(address) returned an unexpected value'); 67 | 68 | const uint256CallResult = await tuple['func(uint256)'].call(1); 69 | const addressCallResult = await tuple['func(address)'].call(tuple.address); 70 | assert.equal(uint256CallResult, '0x7f98a45e', 'func(uint256) using .call returned an unexpected value'); 71 | assert.equal(addressCallResult, '0xb8550dc7', 'func(address) using .call returned an unexpected value'); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # vitepress build output 108 | **/.vitepress/dist 109 | 110 | # vitepress cache directory 111 | **/.vitepress/cache 112 | 113 | # Docusaurus cache and generated files 114 | .docusaurus 115 | 116 | # Serverless directories 117 | .serverless/ 118 | 119 | # FuseBox cache 120 | .fusebox/ 121 | 122 | # DynamoDB Local files 123 | .dynamodb/ 124 | 125 | # TernJS port file 126 | .tern-port 127 | 128 | # Stores VSCode versions used for testing VSCode extensions 129 | .vscode-test 130 | 131 | # yarn v2 132 | .yarn/cache 133 | .yarn/unplugged 134 | .yarn/build-state.yml 135 | .yarn/install-state.gz 136 | .pnp.* 137 | 138 | # OSX 139 | .DS_Store 140 | 141 | # TronBox build directory 142 | build 143 | 144 | -------------------------------------------------------------------------------- /sample-projects/javascript/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # vitepress build output 108 | **/.vitepress/dist 109 | 110 | # vitepress cache directory 111 | **/.vitepress/cache 112 | 113 | # Docusaurus cache and generated files 114 | .docusaurus 115 | 116 | # Serverless directories 117 | .serverless/ 118 | 119 | # FuseBox cache 120 | .fusebox/ 121 | 122 | # DynamoDB Local files 123 | .dynamodb/ 124 | 125 | # TernJS port file 126 | .tern-port 127 | 128 | # Stores VSCode versions used for testing VSCode extensions 129 | .vscode-test 130 | 131 | # yarn v2 132 | .yarn/cache 133 | .yarn/unplugged 134 | .yarn/build-state.yml 135 | .yarn/install-state.gz 136 | .pnp.* 137 | 138 | # OSX 139 | .DS_Store 140 | 141 | # TronBox build directory 142 | build 143 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # vitepress build output 108 | **/.vitepress/dist 109 | 110 | # vitepress cache directory 111 | **/.vitepress/cache 112 | 113 | # Docusaurus cache and generated files 114 | .docusaurus 115 | 116 | # Serverless directories 117 | .serverless/ 118 | 119 | # FuseBox cache 120 | .fusebox/ 121 | 122 | # DynamoDB Local files 123 | .dynamodb/ 124 | 125 | # TernJS port file 126 | .tern-port 127 | 128 | # Stores VSCode versions used for testing VSCode extensions 129 | .vscode-test 130 | 131 | # yarn v2 132 | .yarn/cache 133 | .yarn/unplugged 134 | .yarn/build-state.yml 135 | .yarn/install-state.gz 136 | .pnp.* 137 | 138 | # OSX 139 | .DS_Store 140 | 141 | # TronBox build directory 142 | build 143 | -------------------------------------------------------------------------------- /src/components/TronSolc.js: -------------------------------------------------------------------------------- 1 | const { execSync } = require('child_process'); 2 | const path = require('path'); 3 | const chalk = require('chalk'); 4 | const fs = require('fs-extra'); 5 | const homedir = require('homedir'); 6 | const wrapper = require('solc/wrapper'); 7 | let { name, version } = require('../../package'); 8 | 9 | const maxVersion = '0.8.25'; 10 | 11 | function compareVersions(version1, version2) { 12 | const v1Parts = version1.split('.').map(Number); 13 | const v2Parts = version2.split('.').map(Number); 14 | const maxLength = Math.max(v1Parts.length, v2Parts.length); 15 | for (let i = 0; i < maxLength; i++) { 16 | const v1 = v1Parts[i] || 0; // Treat missing parts as 0 17 | const v2 = v2Parts[i] || 0; 18 | if (v1 > v2) { 19 | return 1; // version1 is greater 20 | } else if (v1 < v2) { 21 | return -1; // version2 is greater 22 | } 23 | // If equal, continue to the next part 24 | } 25 | return 0; // Versions are equal 26 | } 27 | 28 | function getWrapper(options = {}) { 29 | let compilerVersion = maxVersion; 30 | const solcDir = path.join(homedir(), '.tronbox', options.evm ? 'evm-solc' : 'solc'); 31 | 32 | if (options.networks) { 33 | if (options.networks.useZeroFourCompiler) { 34 | compilerVersion = '0.4.25'; 35 | } else if (options.networks.useZeroFiveCompiler) { 36 | compilerVersion = '0.5.4'; 37 | } 38 | try { 39 | if (options.networks.compilers) { 40 | compilerVersion = options.networks.compilers.solc.version; 41 | } 42 | if (options.compilers) { 43 | compilerVersion = options.compilers.solc.version; 44 | } 45 | 46 | if (compareVersions(compilerVersion, maxVersion) > 0 && !options.evm) { 47 | console.error(`${chalk.red( 48 | chalk.bold('Error:') 49 | )} TronBox v${version} currently supports Tron Solidity compiler versions up to ${chalk.green(maxVersion)}. 50 | You are using version ${chalk.yellow(compilerVersion)}, which is not supported.`); 51 | process.exit(); 52 | } 53 | } catch (e) {} 54 | } 55 | 56 | const soljsonPath = path.join(solcDir, `soljson_v${compilerVersion}.js`); 57 | 58 | if (!fs.existsSync(soljsonPath)) { 59 | if (process.argv[1]) { 60 | name = process.argv[1]; 61 | } 62 | if (process.env.TRONBOX_NAME) { 63 | name = process.env.TRONBOX_NAME; 64 | } 65 | 66 | options.logger.log(`Fetching ${options.evm ? 'Ethereum' : 'Tron'} Solidity compiler version ${compilerVersion}...`); 67 | try { 68 | const result = execSync(`${name} --download-compiler ${compilerVersion} ${options.evm ? '--evm' : ''}`, { 69 | env: { ...process.env, FORCE_COLOR: '1' }, 70 | encoding: 'utf8', 71 | stdio: ['ignore', 'pipe', 'pipe'] 72 | }); 73 | 74 | options.logger.log(result); 75 | } catch (error) { 76 | const errorOutput = error.stderr || error.stdout || error.message; 77 | console.error(errorOutput.trimEnd()); 78 | process.exit(1); 79 | } 80 | } 81 | const soljson = eval('require')(soljsonPath); 82 | return wrapper(soljson); 83 | } 84 | 85 | module.exports.getWrapper = getWrapper; 86 | module.exports.maxVersion = maxVersion; 87 | -------------------------------------------------------------------------------- /src/downloader.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | const path = require('path'); 3 | const fs = require('fs-extra'); 4 | const homedir = require('homedir'); 5 | const req = require('axios'); 6 | 7 | async function downloader(compilerVersion, evm) { 8 | const dir = path.join(homedir(), '.tronbox', evm ? 'evm-solc' : 'solc'); 9 | const soljsonPath = path.join(dir, `soljson_v${compilerVersion}.js`); 10 | 11 | await fs.ensureDir(path.join(dir)); 12 | 13 | let soljsonUrl = ''; 14 | if (evm) { 15 | try { 16 | const solidityUrl = 'https://binaries.soliditylang.org/bin'; 17 | const list = await req.get(`${solidityUrl}/list.json`); 18 | if (list && list.data) { 19 | if (list.data.releases && list.data.releases[compilerVersion]) { 20 | soljsonUrl = `${solidityUrl}/${list.data.releases[compilerVersion]}`; 21 | } else { 22 | process.stderr.write( 23 | chalk.red( 24 | chalk.bold('Error:'), 25 | `Unable to locate Solidity compiler version ${chalk.yellow(compilerVersion)}.` 26 | ) + '\n' 27 | ); 28 | 29 | process.exit(1); 30 | } 31 | } 32 | } catch (error) { 33 | process.stderr.write(chalk.red(chalk.bold('Error:'), 'Failed to fetch Solidity compiler list.') + '\n'); 34 | process.exit(1); 35 | } 36 | } else { 37 | try { 38 | const solidityUrl = 'https://tronprotocol.github.io/solc-bin/wasm'; 39 | const list = await req.get(`${solidityUrl}/list.json`); 40 | if (list && list.data && list.data.builds) { 41 | list.data.builds.forEach(_ => { 42 | const { version, path } = _; 43 | if (version === compilerVersion) { 44 | soljsonUrl = `${solidityUrl}/${path}`; 45 | } 46 | }); 47 | if (!soljsonUrl) { 48 | process.stderr.write( 49 | chalk.red( 50 | chalk.bold('Error:'), 51 | `Unable to locate Solidity compiler version ${chalk.yellow(compilerVersion)}.` 52 | ) + '\n' 53 | ); 54 | process.exit(1); 55 | } 56 | } 57 | } catch (error) { 58 | process.stderr.write(chalk.red(chalk.bold('Error:'), 'Failed to fetch Solidity compiler list.') + '\n'); 59 | process.exit(1); 60 | } 61 | } 62 | 63 | try { 64 | const res = await req.get(soljsonUrl, { 65 | responseType: 'arraybuffer' 66 | }); 67 | 68 | if (res && res.data) { 69 | await fs.writeFile(soljsonPath, res.data); 70 | // double check 71 | if (!fs.existsSync(soljsonPath)) { 72 | process.stderr.write(chalk.red(chalk.bold('Error:'), 'Permission required.') + '\n'); 73 | process.stderr.write(` 74 | Most likely, you installed Node.js as root. 75 | Please, download the compiler manually, running: 76 | 77 | tronbox --download-compiler ${compilerVersion} ${evm ? '--evm' : ''} 78 | `); 79 | } else { 80 | process.stdout.write('Compiler downloaded.\n'); 81 | } 82 | } 83 | } catch (error) { 84 | process.stderr.write(chalk.red(chalk.bold('Error:'), 'Wrong Solidity compiler version.') + '\n'); 85 | process.exit(1); 86 | } 87 | } 88 | 89 | module.exports = downloader; 90 | -------------------------------------------------------------------------------- /sample-projects/javascript-metacoin/contracts/MetaCoin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.20; 3 | 4 | import { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol'; 5 | import './ConvertLib.sol'; 6 | 7 | // To use console.log, you need TronBox Runtime Environment 8 | // (https://hub.docker.com/r/tronbox/tre) as your private network. 9 | // Uncomment this line to use console.log 10 | // import "tronbox/console.sol"; 11 | 12 | /** 13 | * @title MetaCoin - Example Token Contract 14 | * @dev Implements a MetaCoin token contract with example methods. 15 | */ 16 | contract MetaCoin is ERC20 { 17 | // Address of the contract deployer 18 | address public owner; 19 | 20 | // Unlock time for TRX locking feature 21 | uint256 public unlockTime; 22 | 23 | /** 24 | * @param _initialSupply The initial supply. 25 | */ 26 | constructor(uint256 _initialSupply) ERC20('MetaCoin', 'MC') { 27 | owner = msg.sender; 28 | _mint(msg.sender, _initialSupply); 29 | } 30 | 31 | /** 32 | * @dev Transfers tokens to a specified address. 33 | * @param _receiver The address to receive the tokens. 34 | * @param _amount The amount of tokens to send. 35 | * @return success Whether the transfer was successful. Returns false if the balance is insufficient. 36 | */ 37 | function sendCoin(address _receiver, uint256 _amount) public returns (bool success) { 38 | _transfer(msg.sender, _receiver, _amount); 39 | 40 | // Uncomment the following line and the import of "tronbox/console.sol" to print logs in the terminal. 41 | // console.log("Transferring from %s to %s %s tokens", msg.sender, _receiver, _amount); 42 | 43 | return true; 44 | } 45 | 46 | /** 47 | * @dev Locks a certain amount of TRX until a specified unlock time. 48 | * @param _unlockTime The future unlock time. 49 | */ 50 | function lock(uint256 _unlockTime) public payable { 51 | require(block.timestamp < _unlockTime, 'Unlock time should be in the future'); 52 | require(msg.sender == owner, "You aren't the owner"); 53 | 54 | unlockTime = _unlockTime; 55 | } 56 | 57 | /** 58 | * @dev Withdraws locked TRX to a specified address after the unlock time has passed. 59 | * @param _to The address to send the TRX to. 60 | */ 61 | function withdraw(address _to) public { 62 | require(block.timestamp >= unlockTime, "You can't withdraw yet"); 63 | require(msg.sender == owner, "You aren't the owner"); 64 | require(_to != address(0), 'Invalid address'); 65 | 66 | payable(_to).transfer(address(this).balance); 67 | } 68 | 69 | /** 70 | * @dev Gets the token balance of the specified address and converts it to another unit. 71 | * @param _account The address to query the balance for. 72 | * @return convertedBalance The converted balance. 73 | */ 74 | function getConvertedBalance(address _account) public view returns (uint256 convertedBalance) { 75 | return ConvertLib.convert(balanceOf(_account), 2); 76 | } 77 | 78 | /** 79 | * @dev Gets the address of the contract owner. 80 | * @return ownerAddress The address of the contract owner. 81 | */ 82 | function getOwner() public view returns (address ownerAddress) { 83 | return owner; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tronbox", 3 | "namespace": "tronprotocol", 4 | "version": "4.4.0", 5 | "description": "TronBox - Simple development framework for Tron", 6 | "keywords": [ 7 | "TronBox", 8 | "TRON", 9 | "Solidity", 10 | "Truffle", 11 | "Contract" 12 | ], 13 | "scripts": { 14 | "build": "scripts/build.sh", 15 | "test": "npm run build && cd test && sh runTest.sh", 16 | "prepare": "npm run build", 17 | "lint": "eslint \"src/**/*.js\" \"test/**/*.js\"", 18 | "format": "prettier --write \"src/**/*.js\" \"test/**/*.js\"" 19 | }, 20 | "dependencies": { 21 | "@solidity-parser/parser": "^0.16.0", 22 | "@truffle/contract-sources": "^0.1.12", 23 | "@truffle/error": "0.2.2", 24 | "@truffle/expect": "0.1.7", 25 | "ajv": "^6.10.2", 26 | "async": "2.6.4", 27 | "axios": "1.12.0", 28 | "bignumber.js": "^7.2.1", 29 | "chai": "4.1.2", 30 | "chalk": "^2.4.1", 31 | "chokidar": "^3.5.3", 32 | "colors": "^1.1.2", 33 | "cpr": "^0.4.3", 34 | "debug": "^3.1.0", 35 | "del": "^2.2.0", 36 | "enquirer": "^2.4.1", 37 | "finalhandler": "^1.1.2", 38 | "find-up": "^4.1.0", 39 | "fs-extra": "^8.1.0", 40 | "graphlib": "^2.1.7", 41 | "homedir": "^0.6.0", 42 | "lodash": "^4.17.15", 43 | "mkdirp": "^0.5.1", 44 | "mocha": "10.2.0", 45 | "node-dir": "0.1.17", 46 | "original-require": "1.0.1", 47 | "serve-static": "^1.10.0", 48 | "solc": "^0.8.21", 49 | "source-map-support": "^0.5.3", 50 | "spawn-args": "^0.1.0", 51 | "temp": "^0.8.3", 52 | "tmp": "0.0.33", 53 | "tronweb": "^6.0.0", 54 | "truffle-blockchain-utils": "^0.0.5", 55 | "tsort": "^0.0.1", 56 | "vcsurl": "^0.1.1", 57 | "web3": "^4.16.0", 58 | "yargs": "^15.4.1", 59 | "yauzl": "^3.2.0" 60 | }, 61 | "devDependencies": { 62 | "@babel/cli": "^7.23.4", 63 | "@babel/core": "^7.23.3", 64 | "@babel/plugin-transform-runtime": "^7.23.4", 65 | "@babel/preset-env": "^7.6.3", 66 | "eslint": "^9.31.0", 67 | "eslint-plugin-n": "^17.15.1", 68 | "globals": "^16.1.0", 69 | "prettier": "^2.8.5", 70 | "tslib": "^2.8.1" 71 | }, 72 | "bin": { 73 | "tronbox": "build/tronbox.js" 74 | }, 75 | "engines": { 76 | "node": ">=18.0.0" 77 | }, 78 | "repository": { 79 | "type": "git", 80 | "url": "https://github.com/tronprotocol/tronbox.git" 81 | }, 82 | "homepage": "https://tronbox.io", 83 | "bugs": { 84 | "url": "https://github.com/tronprotocol/tronbox/issues" 85 | }, 86 | "originalAuthor": "consensys.net", 87 | "author": "tron.network", 88 | "authors": [ 89 | { 90 | "name": "Tim Coulter", 91 | "email": "tim@timothyjcoulter.com", 92 | "url": "https://github.com/tcoulter" 93 | }, 94 | { 95 | "name": "alinger", 96 | "email": "alinger@forke.cn" 97 | }, 98 | { 99 | "name": "Francesco Sullo", 100 | "email": "francesco@sullo.co", 101 | "url": "https://github.com/sullof" 102 | }, 103 | { 104 | "name": "Kang JianCheng", 105 | "email": "1063303665@qq.com", 106 | "url": "https://github.com/kjc233" 107 | } 108 | ], 109 | "publishConfig": { 110 | "access": "public" 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/lib/commands/watch.js: -------------------------------------------------------------------------------- 1 | const command = { 2 | command: 'watch', 3 | description: 'Watch filesystem for changes and rebuild the project automatically', 4 | builder: {}, 5 | run: function (options) { 6 | process.env.CURRENT = 'watch'; 7 | const Build = require('../build'); 8 | const Config = require('../../components/Config'); 9 | const chokidar = require('chokidar'); 10 | const path = require('path'); 11 | const colors = require('colors'); 12 | const Contracts = require('../../components/WorkflowCompile'); 13 | const TruffleError = require('@truffle/error'); 14 | 15 | const config = Config.detect(options); 16 | 17 | const printSuccess = function () { 18 | config.logger.log(colors.green('Completed without errors on ' + new Date().toString())); 19 | }; 20 | 21 | const printFailure = function (err) { 22 | if (err instanceof TruffleError) { 23 | console.error(err.message); 24 | } else { 25 | // Bubble up all other unexpected errors. 26 | console.error(err.stack || err.toString()); 27 | } 28 | }; 29 | 30 | let working = false; 31 | let needs_rebuild = true; 32 | let needs_recompile = true; 33 | 34 | const watchPaths = [ 35 | path.join(config.working_directory, 'app/**/*'), 36 | path.join(config.contracts_build_directory, '/**/*'), 37 | path.join(config.contracts_directory, '/**/*'), 38 | path.join(config.working_directory, 'tronbox-config.js'), 39 | path.join(config.working_directory, 'tronbox.js') 40 | ]; 41 | 42 | chokidar 43 | .watch(watchPaths, { 44 | ignored: /[/\\]\./, // Ignore files prefixed with "." 45 | cwd: config.working_directory, 46 | ignoreInitial: true 47 | }) 48 | .on('all', function (event, filePath) { 49 | // On changed/added/deleted 50 | const display_path = path.join('./', filePath.replace(config.working_directory, '')); 51 | config.logger.log(colors.cyan('>> File ' + display_path + ' changed.')); 52 | 53 | needs_rebuild = true; 54 | 55 | if (path.join(config.working_directory, filePath).indexOf(config.contracts_directory) >= 0) { 56 | needs_recompile = true; 57 | } 58 | }); 59 | 60 | const check_rebuild = function () { 61 | if (working) { 62 | setTimeout(check_rebuild, 200); 63 | return; 64 | } 65 | 66 | if (needs_rebuild) { 67 | needs_rebuild = false; 68 | 69 | if (config.build != null) { 70 | config.logger.log('Rebuilding...'); 71 | working = true; 72 | 73 | Build.build(config, function (err) { 74 | if (err) { 75 | printFailure(err); 76 | } else { 77 | printSuccess(); 78 | } 79 | working = false; 80 | }); 81 | } 82 | } else if (needs_recompile) { 83 | needs_recompile = false; 84 | working = true; 85 | 86 | Contracts.compile(config, function (err) { 87 | if (err) { 88 | printFailure(err); 89 | } 90 | working = false; 91 | }); 92 | } 93 | 94 | setTimeout(check_rebuild, 200); 95 | }; 96 | 97 | check_rebuild(); 98 | } 99 | }; 100 | 101 | module.exports = command; 102 | -------------------------------------------------------------------------------- /src/components/Artifactor.js: -------------------------------------------------------------------------------- 1 | const Schema = require('./ContractSchema'); 2 | const fs = require('fs-extra'); 3 | const path = require('path'); 4 | const _ = require('lodash'); 5 | 6 | function Artifactor(destination) { 7 | this.destination = destination; 8 | } 9 | 10 | Artifactor.prototype.save = function (object, options) { 11 | const self = this; 12 | 13 | return new Promise(function (accept, reject) { 14 | object = Schema.normalize(object); 15 | 16 | Object.values(object.networks).forEach(_ => (_.address = _.address.toLowerCase().replace(/^0x/, '41'))); 17 | 18 | if (options.evm) { 19 | Object.values(object.networks).forEach(_ => (_.address = _.address.toLowerCase().replace(/^41/, '0x'))); 20 | } 21 | 22 | if (!object.contractName) { 23 | return reject(new Error('You must specify a contract name.')); 24 | } 25 | 26 | let output_path = object.contractName; 27 | 28 | // Create new path off of destination. 29 | output_path = path.join(self.destination, output_path); 30 | output_path = path.resolve(output_path); 31 | 32 | // Add json extension. 33 | output_path = output_path + '.json'; 34 | 35 | fs.readFile(output_path, { encoding: 'utf8' }, function (err, json) { 36 | // No need to handle the error. If the file doesn't exist then we'll start afresh 37 | // with a new object. 38 | 39 | let finalObject = object; 40 | 41 | if (!err) { 42 | let existingObjDirty; 43 | try { 44 | existingObjDirty = JSON.parse(json); 45 | } catch (e) { 46 | reject(e); 47 | } 48 | 49 | // normalize existing and merge into final 50 | finalObject = Schema.normalize(existingObjDirty); 51 | 52 | // merge networks 53 | const finalNetworks = {}; 54 | _.merge(finalNetworks, finalObject.networks, object.networks); 55 | 56 | // update existing with new 57 | _.assign(finalObject, object); 58 | finalObject.networks = finalNetworks; 59 | } 60 | 61 | // update timestamp 62 | finalObject.updatedAt = new Date().toISOString(); 63 | 64 | // output object 65 | fs.outputFile(output_path, JSON.stringify(finalObject, null, 2), 'utf8', function (err) { 66 | if (err) return reject(err); 67 | accept(); 68 | }); 69 | }); 70 | }); 71 | }; 72 | 73 | Artifactor.prototype.saveAll = function (objects, options) { 74 | const self = this; 75 | 76 | if (Array.isArray(objects)) { 77 | const array = objects; 78 | objects = {}; 79 | 80 | array.forEach(function (item) { 81 | objects[item.contract_name] = item; 82 | }); 83 | } 84 | 85 | return new Promise(function (accept, reject) { 86 | fs.stat(self.destination, function (err) { 87 | if (err) { 88 | return reject(new Error('Destination ' + self.destination + " doesn't exist!")); 89 | } 90 | accept(); 91 | }); 92 | }).then(function () { 93 | const promises = []; 94 | 95 | Object.keys(objects).forEach(function (contractName) { 96 | const object = objects[contractName]; 97 | object.contractName = contractName; 98 | promises.push(self.save(object, options)); 99 | }); 100 | 101 | return Promise.all(promises); 102 | }); 103 | }; 104 | 105 | module.exports = Artifactor; 106 | -------------------------------------------------------------------------------- /src/lib/repl.js: -------------------------------------------------------------------------------- 1 | const repl = require('repl'); 2 | const expect = require('@truffle/expect'); 3 | const async = require('async'); 4 | const EventEmitter = require('events'); 5 | const inherits = require('util').inherits; 6 | 7 | inherits(ReplManager, EventEmitter); 8 | 9 | function ReplManager(options) { 10 | EventEmitter.call(this); 11 | 12 | expect.options(options, [ 13 | 'working_directory', 14 | 'contracts_directory', 15 | 'contracts_build_directory', 16 | 'migrations_directory', 17 | 'network', 18 | 'network_id', 19 | 'provider', 20 | 'resolver', 21 | 'build_directory' 22 | ]); 23 | 24 | this.options = options; 25 | this.repl = options.repl; 26 | 27 | this.contexts = []; 28 | } 29 | 30 | ReplManager.prototype.start = function (options) { 31 | const self = this; 32 | 33 | this.contexts.push({ 34 | prompt: options.prompt, 35 | interpreter: options.interpreter, 36 | done: options.done 37 | }); 38 | 39 | const currentContext = this.contexts[this.contexts.length - 1]; 40 | 41 | if (!this.repl) { 42 | this.repl = repl.start({ 43 | prompt: currentContext.prompt, 44 | eval: this.interpret.bind(this) 45 | }); 46 | 47 | this.repl.on('exit', function () { 48 | // If we exit for some reason, call done functions for good measure 49 | // then ensure the process is completely killed. Once the repl exits, 50 | // the process is in a bad state and can't be recovered (e.g., stdin is closed). 51 | const doneFunctions = self.contexts.map(function (context) { 52 | return context.done 53 | ? function () { 54 | context.done(); 55 | } 56 | : function () {}; 57 | }); 58 | async.series(doneFunctions, function () { 59 | process.exit(); 60 | }); 61 | }); 62 | } 63 | 64 | // Bubble the internal repl's exit event 65 | this.repl.on('exit', function () { 66 | self.emit('exit'); 67 | }); 68 | 69 | this.repl.setPrompt(options.prompt); 70 | this.setContextVars(options.context || {}); 71 | }; 72 | 73 | ReplManager.prototype.setContextVars = function (obj) { 74 | const self = this; 75 | if (this.repl) { 76 | Object.keys(obj).forEach(function (key) { 77 | self.repl.context[key] = obj[key]; 78 | }); 79 | } 80 | }; 81 | 82 | ReplManager.prototype.stop = function (callback) { 83 | const oldContext = this.contexts.pop(); 84 | 85 | if (oldContext.done) { 86 | oldContext.done(); 87 | } 88 | 89 | const currentContext = this.contexts[this.contexts.length - 1]; 90 | 91 | if (currentContext) { 92 | this.repl.setPrompt(currentContext.prompt); 93 | } else { 94 | // If there's no new context, stop the process altogether. 95 | // Though this might seem like an out of place process.exit(), 96 | // once the Node repl closes, the state of the process is not 97 | // recoverable; e.g., stdin is closed and can't be reopened. 98 | // Since we can't recover to a state before the repl was opened, 99 | // we should just exit. He're, we'll exit after we've popped 100 | // off the stack of all repl contexts. 101 | process.exit(); 102 | } 103 | 104 | if (callback) { 105 | callback(); 106 | } 107 | }; 108 | 109 | ReplManager.prototype.interpret = function (cmd, context, filename, callback) { 110 | const currentContext = this.contexts[this.contexts.length - 1]; 111 | currentContext.interpreter(cmd, context, filename, callback); 112 | }; 113 | 114 | module.exports = ReplManager; 115 | -------------------------------------------------------------------------------- /src/lib/testing/testsource.js: -------------------------------------------------------------------------------- 1 | const Deployed = require('./deployed'); 2 | const path = require('path'); 3 | const fs = require('fs'); 4 | const contract = require('../../components/Contract'); 5 | const find_contracts = require('@truffle/contract-sources'); 6 | 7 | function TestSource(config) { 8 | this.config = config; 9 | } 10 | 11 | TestSource.prototype.require = function () { 12 | return null; // FSSource will get it. 13 | }; 14 | 15 | TestSource.prototype.resolve = function (import_path, callback) { 16 | const self = this; 17 | 18 | if (import_path === 'truffle/DeployedAddresses.sol') { 19 | return find_contracts(this.config.contracts_directory, function (err, source_files) { 20 | // Ignore this error. Continue on. 21 | 22 | fs.readdir(self.config.contracts_build_directory, function (err, abstraction_files) { 23 | if (err) return callback(err); 24 | 25 | const mapping = {}; 26 | 27 | const blacklist = ['Assert', 'DeployedAddresses']; 28 | 29 | // Ensure we have a mapping for source files and abstraction files 30 | // to prevent any compile errors in tests. 31 | source_files.forEach(function (file) { 32 | const name = path.basename(file, '.sol'); 33 | if (blacklist.indexOf(name) >= 0) return; 34 | mapping[name] = false; 35 | }); 36 | 37 | abstraction_files.forEach(function (file) { 38 | const name = path.basename(file, '.json'); 39 | if (blacklist.indexOf(name) >= 0) return; 40 | mapping[name] = false; 41 | }); 42 | 43 | const promises = abstraction_files.map(function (file) { 44 | return new Promise(function (accept, reject) { 45 | fs.readFile(path.join(self.config.contracts_build_directory, file), 'utf8', function (err, body) { 46 | if (err) return reject(err); 47 | accept(body); 48 | }); 49 | }); 50 | }); 51 | Promise.all(promises) 52 | .then(function (files_data) { 53 | const addresses = files_data 54 | .map(function (data) { 55 | return JSON.parse(data); 56 | }) 57 | .map(function (json) { 58 | return contract(json); 59 | }) 60 | .map(function (c) { 61 | c.setNetwork(self.config.network_id); 62 | if (c.isDeployed()) { 63 | return c.address; 64 | } 65 | return null; 66 | }); 67 | 68 | addresses.forEach(function (address, i) { 69 | const name = path.basename(abstraction_files[i], '.json'); 70 | 71 | if (blacklist.indexOf(name) >= 0) return; 72 | 73 | mapping[name] = address; 74 | }); 75 | 76 | return Deployed.makeSolidityDeployedAddressesLibrary(mapping); 77 | }) 78 | .then(function (addressSource) { 79 | callback(null, addressSource, import_path); 80 | }) 81 | .catch(callback); 82 | }); 83 | }); 84 | } 85 | 86 | if (import_path === 'truffle/Assert.sol') { 87 | return fs.readFile(path.resolve(path.join(__dirname, 'Assert.sol')), { encoding: 'utf8' }, function (err, body) { 88 | callback(err, body, import_path); 89 | }); 90 | } 91 | 92 | return callback(); 93 | }; 94 | 95 | TestSource.prototype.resolve_dependency_path = function (import_path, dependency_path) { 96 | return dependency_path; 97 | }; 98 | 99 | module.exports = TestSource; 100 | -------------------------------------------------------------------------------- /src/components/Require.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const Module = require('module'); 4 | const vm = require('vm'); 5 | const originalrequire = require('original-require'); 6 | const expect = require('@truffle/expect'); 7 | const Config = require('./Config'); 8 | 9 | // options.file: path to file to execute. Must be a module that exports a function. 10 | // options.args: arguments passed to the exported function within file. If a callback 11 | // is not included in args, exported function is treated as synchronous. 12 | // options.context: Object containing any global variables you'd like set when this 13 | // function is run. 14 | const Require = { 15 | file: (options, config) => { 16 | const file = options.file; 17 | 18 | expect.options(options, ['file']); 19 | 20 | options = Config.default().with(options); 21 | 22 | const source = fs.readFileSync(options.file, { encoding: 'utf8' }); 23 | 24 | // Modified from here: https://gist.github.com/anatoliychakkaev/1599423 25 | const m = new Module(file); 26 | 27 | global.config = config; 28 | 29 | // Provide all the globals listed here: https://nodejs.org/api/globals.html 30 | const context = { 31 | Buffer: Buffer, 32 | __dirname: path.dirname(file), 33 | __filename: file, 34 | clearImmediate: clearImmediate, 35 | clearInterval: clearInterval, 36 | clearTimeout: clearTimeout, 37 | console: console, 38 | // eslint-disable-next-line n/exports-style 39 | exports: exports, 40 | global: global, 41 | module: m, 42 | process: process, 43 | require: pkgPath => { 44 | // Ugh. Simulate a full require function for the file. 45 | pkgPath = pkgPath.trim(); 46 | 47 | // If absolute, just require. 48 | if (path.isAbsolute(pkgPath)) return originalrequire(pkgPath); 49 | 50 | // If relative, it's relative to the file. 51 | if (pkgPath[0] === '.') { 52 | return originalrequire(path.join(path.dirname(file), pkgPath)); 53 | } else { 54 | // Not absolute, not relative, must be a globally or locally installed module. 55 | // Try local first. 56 | // Here we have to require from the node_modules directory directly. 57 | 58 | let moduleDir = path.dirname(file); 59 | while (true) { 60 | try { 61 | return originalrequire(path.join(moduleDir, 'node_modules', pkgPath)); 62 | } catch (e) {} 63 | const oldModuleDir = moduleDir; 64 | moduleDir = path.join(moduleDir, '..'); 65 | if (moduleDir === oldModuleDir) break; 66 | } 67 | 68 | // Try global, and let the error throw. 69 | return originalrequire(pkgPath); 70 | } 71 | }, 72 | artifacts: options.resolver, 73 | setImmediate: setImmediate, 74 | setInterval: setInterval, 75 | setTimeout: setTimeout 76 | }; 77 | 78 | // Now add contract names. 79 | Object.keys(options.context || {}).forEach(key => { 80 | context[key] = options.context[key]; 81 | }); 82 | 83 | const old_cwd = process.cwd(); 84 | 85 | process.chdir(path.dirname(file)); 86 | 87 | const script = vm.createScript(source, file); 88 | try { 89 | script.runInNewContext(context); 90 | } catch (error) { 91 | console.error(error); 92 | process.exit(1); 93 | } 94 | 95 | process.chdir(old_cwd); 96 | 97 | return m.exports; 98 | } 99 | }; 100 | 101 | module.exports = Require; 102 | -------------------------------------------------------------------------------- /src/lib/environment.js: -------------------------------------------------------------------------------- 1 | const TruffleError = require('@truffle/error'); 2 | const expect = require('@truffle/expect'); 3 | const Resolver = require('../components/Resolver'); 4 | const Artifactor = require('../components/Artifactor'); 5 | const TronWrap = require('../components/TronWrap'); 6 | 7 | const Environment = { 8 | // It's important config is a Config object and not a vanilla object 9 | detect: function (config, callback) { 10 | expect.options(config, ['networks']); 11 | 12 | if (!config.resolver) { 13 | config.resolver = new Resolver(config); 14 | } 15 | 16 | if (!config.artifactor) { 17 | config.artifactor = new Artifactor(config.contracts_build_directory); 18 | } 19 | 20 | if (!config.network && config.networks['development']) { 21 | config.network = 'development'; 22 | } 23 | 24 | if (!config.network) { 25 | return callback(new Error('No network specified. Cannot determine current network.')); 26 | } 27 | const network_config = config.networks[config.network]; 28 | 29 | if (!network_config) { 30 | return callback( 31 | new TruffleError( 32 | 'Unknown network "' + config.network + '". See your tronbox configuration file for available networks.' 33 | ) 34 | ); 35 | } 36 | 37 | let network_id = config.networks[config.network].network_id; 38 | 39 | if (!network_id) { 40 | return callback( 41 | new Error( 42 | "You must specify a network_id in your '" + config.network + "' configuration in order to use this network." 43 | ) 44 | ); 45 | } 46 | 47 | const tronWrap = TronWrap(); 48 | 49 | function detectNetworkId(done) { 50 | if (network_id !== '*') { 51 | return done(null, network_id); 52 | } 53 | network_id = '*'; 54 | config.networks[config.network].network_id = network_id; 55 | done(null, network_id); 56 | } 57 | 58 | function detectFromAddress(done) { 59 | if (config.from) { 60 | return done(); 61 | } 62 | 63 | tronWrap._getAccounts(function (err, accounts) { 64 | if (err) return done(err); 65 | config.networks[config.network].from = accounts[0]; 66 | config.networks[config.network].privateKey = tronWrap._privateKeyByAccount[accounts[0]]; 67 | done(); 68 | }); 69 | } 70 | 71 | detectNetworkId(function (err) { 72 | if (err) return callback(err); 73 | detectFromAddress(callback); 74 | }); 75 | }, 76 | 77 | // Ensure you call Environment.detect() first. 78 | fork: function (config, callback) { 79 | expect.options(config, ['from']); 80 | 81 | const forkedNetwork = config.network + '-fork'; 82 | 83 | config.networks[forkedNetwork] = { 84 | network_id: config.network_id, 85 | provider: undefined, 86 | // TestRPC.provider({ 87 | // fork: config.provider, 88 | // unlocked_accounts: [config.networks[config.network].from] 89 | // }), 90 | from: config.from 91 | }; 92 | config.network = forkedNetwork; 93 | 94 | callback(); 95 | }, 96 | 97 | develop: function (config, testrpcOptions, callback) { 98 | expect.options(config, ['networks']); 99 | 100 | const network = config.network || 'develop'; 101 | 102 | config.networks[network] = { 103 | network_id: testrpcOptions.network_id, 104 | provider: '' 105 | }; 106 | 107 | config.network = network; 108 | 109 | Environment.detect(config, callback); 110 | } 111 | }; 112 | 113 | module.exports = Environment; 114 | -------------------------------------------------------------------------------- /src/lib/commands/convert.js: -------------------------------------------------------------------------------- 1 | const command = { 2 | command: 'convert', 3 | description: 'Convert a truffle project to tronbox project', 4 | builder: {}, 5 | run: function (options, done) { 6 | const fs = require('fs'); 7 | const path = require('path'); 8 | const Config = require('../../components/Config'); 9 | const config = Config.default().with({ 10 | logger: console 11 | }); 12 | if (!fs.existsSync(path.join(process.cwd(), './truffle-config.js'))) { 13 | config.logger.log("It's not a truffle project. Will start `tronbox init`"); 14 | const InitCommand = require('./init'); 15 | return InitCommand.run(options, done); 16 | } 17 | 18 | if (fs.existsSync(path.resolve(process.cwd(), './tronbox-config.js'))) { 19 | config.logger.log("It's already a tronbox project."); 20 | return; 21 | } 22 | 23 | function downloadConfig() { 24 | function downloadFile(url, target) { 25 | return new Promise(async (resolve, reject) => { 26 | try { 27 | const axios = require('axios'); 28 | const response = await axios.get(url, { responseType: 'stream' }); 29 | response.data.pipe(fs.createWriteStream(target)).on('close', resolve).on('error', reject); 30 | } catch (error) { 31 | reject(error); 32 | } 33 | }); 34 | } 35 | const configFilePromise = downloadFile( 36 | 'https://raw.githubusercontent.com/tronsuper/bare-box/master/tronbox.js', 37 | path.join(process.cwd(), './tronbox-config.js') 38 | ); 39 | const migrationFilePromise = downloadFile( 40 | 'https://raw.githubusercontent.com/Tronbox-boxes/metacoin-box/master/contracts/Migrations.sol', 41 | path.join(process.cwd(), './contracts/Migrations.sol') 42 | ); 43 | const migrationDeployFilePromise = downloadFile( 44 | 'https://raw.githubusercontent.com/Tronbox-boxes/metacoin-box/master/migrations/1_initial_migration.js', 45 | path.join(process.cwd(), './migrations/1_initial_migration.js') 46 | ); 47 | return Promise.all([configFilePromise, migrationFilePromise, migrationDeployFilePromise]); 48 | } 49 | 50 | function convertTests() { 51 | const testDirPath = path.join(process.cwd(), './test'); 52 | if (!fs.existsSync(testDirPath)) return; 53 | const stats = fs.statSync(testDirPath); 54 | if (!stats.isDirectory()) return; 55 | 56 | function translateTestFile(file) { 57 | const content = fs.readFileSync(file).toString(); 58 | const translatedContent = ` 59 | const ganache = require('ganache'); 60 | const Web3 = require('web3'); 61 | const [web3, provider] = require('tronbox-web3')(new Web3(Web3.givenProvider), ganache.provider()); 62 | ${content} 63 | `; 64 | fs.writeFileSync(file, translatedContent); 65 | config.logger.log(`convert file ${file} successful`); 66 | } 67 | 68 | function walkTestDir(dir) { 69 | const files = fs.readdirSync(dir); 70 | files.forEach(file => { 71 | const currentFile = path.join(dir, file); 72 | const stats = fs.statSync(currentFile); 73 | if (stats.isDirectory()) return walkTestDir(currentFile); 74 | if (!stats.isFile()) return; 75 | if (path.extname(currentFile) !== '.js') return; 76 | translateTestFile(currentFile); 77 | }); 78 | } 79 | 80 | walkTestDir(testDirPath); 81 | } 82 | 83 | downloadConfig().then(() => { 84 | config.logger.log('OK. Conversion is done. Enjoy tronbox!'); 85 | config.logger.log(); 86 | done(); 87 | }); 88 | convertTests(); 89 | } 90 | }; 91 | 92 | module.exports = command; 93 | -------------------------------------------------------------------------------- /src/lib/command.js: -------------------------------------------------------------------------------- 1 | const TaskError = require('./errors/taskerror'); 2 | const yargs = require('yargs/yargs'); 3 | const _ = require('lodash'); 4 | const version = require('./version'); 5 | 6 | function Command(commands) { 7 | this.commands = commands; 8 | 9 | const args = yargs().detectLocale(false).exitProcess(false); 10 | 11 | Object.keys(this.commands).forEach(command => { 12 | args.command(this.commands[command]); 13 | }); 14 | 15 | this.args = args; 16 | } 17 | 18 | Command.prototype.getCommand = function (cmds, noAliases) { 19 | const args = yargs().detectLocale(false).exitProcess(false).version(false).help(false); 20 | 21 | Object.keys(this.commands).forEach(command => { 22 | args.command(this.commands[command]); 23 | }); 24 | 25 | const argv = args.parse(cmds); 26 | 27 | if (argv._.length === 0) { 28 | argv._.push('help'); 29 | } 30 | 31 | const input = argv._[0]; 32 | let chosenCommand = null; 33 | 34 | // If the command wasn't specified directly, go through a process 35 | // for inferring the command. 36 | if (this.commands[input]) { 37 | chosenCommand = input; 38 | } else if (noAliases !== true) { 39 | let currentLength = 1; 40 | const availableCommandNames = Object.keys(this.commands); 41 | 42 | // Loop through each letter of the input until we find a command 43 | // that uniquely matches. 44 | while (currentLength <= input.length) { 45 | // Gather all possible commands that match with the current length 46 | const possibleCommands = availableCommandNames.filter(function (possibleCommand) { 47 | return possibleCommand.substring(0, currentLength) === input.substring(0, currentLength); 48 | }); 49 | 50 | // Did we find only one command that matches? If so, use that one. 51 | if (possibleCommands.length === 1) { 52 | chosenCommand = possibleCommands[0]; 53 | break; 54 | } 55 | 56 | currentLength += 1; 57 | } 58 | } 59 | 60 | if (!chosenCommand) { 61 | return null; 62 | } 63 | 64 | const command = this.commands[chosenCommand]; 65 | 66 | return { 67 | name: chosenCommand, 68 | argv: argv, 69 | command: command 70 | }; 71 | }; 72 | 73 | Command.prototype.run = function (command, options, callback) { 74 | if (typeof options === 'function') { 75 | callback = options; 76 | options = {}; 77 | } 78 | 79 | const result = this.getCommand(command, typeof options.noAliases === 'boolean' ? options.noAliases : true); 80 | 81 | if (!result) { 82 | return callback( 83 | new TaskError( 84 | `\`tronbox ${command[0]}\` is an invalid command. 85 | 86 | Please use \`tronbox help\` to see a list of available commands. 87 | 88 | TronBox v${version.bundle}` 89 | ) 90 | ); 91 | } 92 | 93 | const argv = result.argv; 94 | 95 | // Remove the task name itself. 96 | if (argv._) { 97 | argv._.shift(); 98 | } 99 | 100 | // We don't need this. 101 | delete argv['$0']; 102 | 103 | // Some options might throw if options is a Config object. If so, let's ignore those options. 104 | const clone = {}; 105 | Object.keys(options).forEach(function (key) { 106 | try { 107 | clone[key] = options[key]; 108 | } catch (e) { 109 | // Do nothing with values that throw. 110 | } 111 | }); 112 | 113 | options = _.extend(clone, argv); 114 | options.commands = this.commands; 115 | 116 | if (result.name !== 'help' && argv.help) { 117 | this.args.parse(command); 118 | return callback(); 119 | } 120 | 121 | try { 122 | result.command.run(options, callback); 123 | } catch (err) { 124 | callback(err); 125 | } 126 | }; 127 | 128 | module.exports = Command; 129 | -------------------------------------------------------------------------------- /src/components/Resolver/fs.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const eachSeries = require('async/eachSeries'); 4 | 5 | function FS(working_directory, contracts_build_directory) { 6 | this.working_directory = working_directory; 7 | this.contracts_build_directory = contracts_build_directory; 8 | } 9 | 10 | FS.prototype.requireJson = function (import_path) { 11 | const workingDirectory = this.working_directory; 12 | 13 | if (!import_path.startsWith('./')) { 14 | import_path = `./node_modules/${import_path}`; 15 | } 16 | 17 | try { 18 | const result = fs.readFileSync(path.join(workingDirectory, import_path), 'utf8'); 19 | return JSON.parse(result); 20 | } catch (e) { 21 | return null; 22 | } 23 | }; 24 | 25 | FS.prototype.require = function (import_path, search_path) { 26 | search_path = search_path || this.contracts_build_directory; 27 | 28 | // For Windows: Allow import paths to be either path separator ('\' or '/') 29 | // by converting all '/' to the default (path.sep); 30 | import_path = import_path.replace(/\//g, path.sep); 31 | 32 | if (path.extname(import_path) === '.json') { 33 | return this.requireJson(import_path); 34 | } 35 | 36 | const contract_name = this.getContractName(import_path, search_path); 37 | 38 | // If we have an absolute path, only check the file if it's a child of the working_directory. 39 | if (path.isAbsolute(import_path)) { 40 | if (import_path.indexOf(this.working_directory) !== 0) { 41 | return null; 42 | } 43 | import_path = './' + import_path.replace(this.working_directory); 44 | } 45 | 46 | try { 47 | const result = fs.readFileSync(path.join(search_path, contract_name + '.json'), 'utf8'); 48 | return JSON.parse(result); 49 | } catch (e) { 50 | return null; 51 | } 52 | }; 53 | 54 | FS.prototype.getContractName = function (sourcePath, searchPath) { 55 | searchPath = searchPath || this.contracts_build_directory; 56 | 57 | const filenames = fs.readdirSync(searchPath); 58 | for (let i = 0; i < filenames.length; i++) { 59 | const filename = filenames[i]; 60 | 61 | const artifact = JSON.parse(fs.readFileSync(path.resolve(searchPath, filename))); 62 | 63 | if (artifact.sourcePath === sourcePath) { 64 | return artifact.contractName; 65 | } 66 | } 67 | 68 | // fallback 69 | return path.basename(sourcePath, '.sol'); 70 | }; 71 | 72 | FS.prototype.resolve = function (import_path, imported_from, callback) { 73 | imported_from = imported_from || ''; 74 | 75 | const possible_paths = [import_path, path.join(path.dirname(imported_from), import_path)]; 76 | 77 | let resolved_body = null; 78 | let resolved_path = null; 79 | 80 | eachSeries( 81 | possible_paths, 82 | function (possible_path, finished) { 83 | if (resolved_body != null) { 84 | return finished(); 85 | } 86 | 87 | // Check the expected path. 88 | fs.readFile(possible_path, { encoding: 'utf8' }, function (err, body) { 89 | // If there's an error, that means we can't read the source even if 90 | // it exists. Treat it as if it doesn't by ignoring any errors. 91 | // body will be undefined if error. 92 | if (body) { 93 | resolved_body = body; 94 | resolved_path = possible_path; 95 | } 96 | 97 | return finished(); 98 | }); 99 | }, 100 | function (err) { 101 | if (err) return callback(err); 102 | callback(null, resolved_body, resolved_path); 103 | } 104 | ); 105 | }; 106 | 107 | // Here we're resolving from local files to local files, all absolute. 108 | FS.prototype.resolve_dependency_path = function (import_path, dependency_path) { 109 | const dirname = path.dirname(import_path); 110 | return path.resolve(path.join(dirname, dependency_path)); 111 | }; 112 | 113 | module.exports = FS; 114 | -------------------------------------------------------------------------------- /src/lib/build.js: -------------------------------------------------------------------------------- 1 | const mkdirp = require('mkdirp'); 2 | const del = require('del'); 3 | const Contracts = require('../components/WorkflowCompile'); 4 | const BuildError = require('./errors/builderror'); 5 | const child_process = require('child_process'); 6 | const spawnargs = require('spawn-args'); 7 | const _ = require('lodash'); 8 | const expect = require('@truffle/expect'); 9 | 10 | function CommandBuilder(command) { 11 | this.command = command; 12 | } 13 | 14 | CommandBuilder.prototype.build = function (options, callback) { 15 | console.debug('Running `' + this.command + '`...'); 16 | 17 | const args = spawnargs(this.command); 18 | const ps = args.shift(); 19 | 20 | const cmd = child_process.spawn(ps, args, { 21 | detached: false, 22 | cwd: options.working_directory, 23 | env: _.merge(process.env, { 24 | WORKING_DIRECTORY: options.working_directory, 25 | BUILD_DESTINATION_DIRECTORY: options.destination_directory, 26 | BUILD_CONTRACTS_DIRECTORY: options.contracts_build_directory 27 | }) 28 | }); 29 | 30 | cmd.stdout.on('data', function (data) { 31 | console.debug(data.toString()); 32 | }); 33 | 34 | cmd.stderr.on('data', function (data) { 35 | console.debug('build error: ' + data); 36 | }); 37 | 38 | cmd.on('close', function (code) { 39 | let error = null; 40 | if (code !== 0) { 41 | error = 'Command exited with code ' + code; 42 | } 43 | callback(error); 44 | }); 45 | }; 46 | 47 | const Build = { 48 | clean: function (options, callback) { 49 | const destination = options.build_directory; 50 | const contracts_build_directory = options.contracts_build_directory; 51 | 52 | // Clean first. 53 | del([destination + '/*', '!' + contracts_build_directory]).then(function () { 54 | mkdirp(destination, callback); 55 | }); 56 | }, 57 | 58 | // Note: key is a legacy parameter that will eventually be removed. 59 | // It's specific to the default builder and we should phase it out. 60 | build: function (options, callback) { 61 | expect.options(options, ['build_directory', 'working_directory', 'contracts_build_directory', 'networks']); 62 | 63 | let builder = options.build; 64 | 65 | // Duplicate build directory for legacy purposes 66 | options.destination_directory = options.build_directory; 67 | 68 | // No builder specified. Ignore the build then. 69 | if (typeof builder === 'undefined') { 70 | if (!options.quiet) { 71 | return callback(new BuildError("No build configuration specified. Can't build.")); 72 | } 73 | return callback(); 74 | } 75 | 76 | if (typeof builder === 'string') { 77 | builder = new CommandBuilder(builder); 78 | } else if (typeof builder !== 'function') { 79 | if (!builder.build) { 80 | return callback( 81 | new BuildError( 82 | 'Build configuration can no longer be specified as an object. Please see our documentation for an updated list of supported build configurations.' 83 | ) 84 | ); 85 | } 86 | } else { 87 | // If they've only provided a build function, use that. 88 | builder = { 89 | build: builder 90 | }; 91 | } 92 | 93 | // Use our own clean method unless the builder supplies one. 94 | let clean = this.clean; 95 | if (builder.hasOwnProperty('clean')) { 96 | clean = builder.clean; 97 | } 98 | 99 | clean(options, function (err) { 100 | if (err) return callback(err); 101 | 102 | // If necessary. This prevents errors due to the .sol.js files not existing. 103 | Contracts.compile(options, function (err) { 104 | if (err) return callback(err); 105 | 106 | builder.build(options, function (err) { 107 | if (!err) return callback(); 108 | 109 | if (typeof err === 'string') { 110 | err = new BuildError(err); 111 | } 112 | 113 | callback(err); 114 | }); 115 | }); 116 | }); 117 | } 118 | }; 119 | 120 | module.exports = Build; 121 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.4.0/test/metacoin.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable n/no-unpublished-require */ 2 | const wait = require('./helpers/wait'); 3 | const chalk = require('chalk'); 4 | const MetaCoin = artifacts.require('./MetaCoin.sol'); 5 | 6 | // The following tests require TronBox >= 2.1.x 7 | // and Tron Quickstart (https://github.com/tronprotocol/docker-tron-quickstart) 8 | 9 | contract('MetaCoin', function (accounts) { 10 | let meta; 11 | 12 | before(async function () { 13 | meta = await MetaCoin.deployed(); 14 | if (accounts.length < 3) { 15 | // Set your own accounts if you are not using Tron Quickstart 16 | } 17 | }); 18 | 19 | it('should verify that there are at least three available accounts', async function () { 20 | if (accounts.length < 3) { 21 | console.info( 22 | chalk.blue( 23 | '\nYOUR ATTENTION, PLEASE.]\nTo test MetaCoin you should use Tron Quickstart (https://github.com/tronprotocol/docker-tron-quickstart) as your private network.\nAlternatively, you must set your own accounts in the "before" statement in "test/metacoin.js".\n' 24 | ) 25 | ); 26 | } 27 | assert.isTrue(accounts.length >= 3); 28 | }); 29 | 30 | it('should verify that the contract has been deployed by accounts[0]', async function () { 31 | assert.equal(await meta.getOwner(), tronWeb.address.toHex(accounts[0])); 32 | }); 33 | 34 | it('should put 10000 MetaCoin in the first account', async function () { 35 | const balance = await meta.getBalance(accounts[0], { from: accounts[0] }); 36 | assert.equal(balance, 10000, "10000 wasn't in the first account"); 37 | }); 38 | 39 | it('should call a function that depends on a linked library', async function () { 40 | this.timeout(10000); 41 | const meta = await MetaCoin.deployed(); 42 | wait(1); 43 | const metaCoinBalance = (await meta.getBalance.call(accounts[0])).toNumber(); 44 | const metaCoinEthBalance = (await meta.getBalanceInEth.call(accounts[0])).toNumber(); 45 | assert.equal( 46 | metaCoinEthBalance, 47 | 2 * metaCoinBalance, 48 | 'Library function returned unexpected function, linkage may be broken' 49 | ); 50 | }); 51 | 52 | it('should send coins from account 0 to 3 and verify that a Transfer event has been emitted', function (done) { 53 | assert.isTrue(accounts[3] ? true : false, 'accounts[1] does not exist. Use Tron Quickstart!'); 54 | 55 | this.timeout(20000); 56 | MetaCoin.deployed().then(meta => { 57 | return tronWeb 58 | .contract() 59 | .at(meta.address) 60 | .then(meta2 => { 61 | meta2.Transfer().watch((err, res) => { 62 | if (res) { 63 | assert.equal(res.result._from, tronWeb.address.toHex(accounts[0])); 64 | assert.equal(res.result._to, tronWeb.address.toHex(accounts[3])); 65 | assert.equal(res.result._value, 1); 66 | done(); 67 | } 68 | }); 69 | 70 | meta.sendCoin(accounts[3], 1, { 71 | from: accounts[0] 72 | }); 73 | }); 74 | }); 75 | }); 76 | 77 | it('should send coins from account 0 to 1', async function () { 78 | assert.isTrue(accounts[1] ? true : false, 'accounts[1] does not exist. Use Tron Quickstart!'); 79 | 80 | this.timeout(10000); 81 | const meta = await MetaCoin.deployed(); 82 | wait(3); 83 | const account_one_starting_balance = (await meta.getBalance.call(accounts[0])).toNumber(); 84 | const account_two_starting_balance = (await meta.getBalance.call(accounts[1])).toNumber(); 85 | await meta.sendCoin(accounts[1], 10, { 86 | from: accounts[0] 87 | }); 88 | assert.equal( 89 | await meta.getBalance.call(accounts[0]), 90 | account_one_starting_balance - 10, 91 | "Amount wasn't correctly taken from the sender" 92 | ); 93 | assert.equal( 94 | await meta.getBalance.call(accounts[1]), 95 | account_two_starting_balance + 10, 96 | "Amount wasn't correctly sent to the receiver" 97 | ); 98 | }); 99 | }); 100 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.5.0/test/metacoin.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable n/no-unpublished-require */ 2 | const wait = require('./helpers/wait'); 3 | const chalk = require('chalk'); 4 | const MetaCoin = artifacts.require('./MetaCoin.sol'); 5 | 6 | // The following tests require TronBox >= 2.1.x 7 | // and Tron Quickstart (https://github.com/tronprotocol/docker-tron-quickstart) 8 | 9 | contract('MetaCoin', function (accounts) { 10 | let meta; 11 | 12 | before(async function () { 13 | meta = await MetaCoin.deployed(); 14 | if (accounts.length < 3) { 15 | // Set your own accounts if you are not using Tron Quickstart 16 | } 17 | }); 18 | 19 | it('should verify that there are at least three available accounts', async function () { 20 | if (accounts.length < 3) { 21 | console.info( 22 | chalk.blue( 23 | '\nYOUR ATTENTION, PLEASE.]\nTo test MetaCoin you should use Tron Quickstart (https://github.com/tronprotocol/docker-tron-quickstart) as your private network.\nAlternatively, you must set your own accounts in the "before" statement in "test/metacoin.js".\n' 24 | ) 25 | ); 26 | } 27 | assert.isTrue(accounts.length >= 3); 28 | }); 29 | 30 | it('should verify that the contract has been deployed by accounts[0]', async function () { 31 | assert.equal(await meta.getOwner(), tronWeb.address.toHex(accounts[0])); 32 | }); 33 | 34 | it('should put 10000 MetaCoin in the first account', async function () { 35 | const balance = await meta.getBalance(accounts[0], { from: accounts[0] }); 36 | assert.equal(balance, 10000, "10000 wasn't in the first account"); 37 | }); 38 | 39 | it('should call a function that depends on a linked library', async function () { 40 | this.timeout(10000); 41 | const meta = await MetaCoin.deployed(); 42 | wait(1); 43 | const metaCoinBalance = (await meta.getBalance.call(accounts[0])).toNumber(); 44 | const metaCoinEthBalance = (await meta.getBalanceInEth.call(accounts[0])).toNumber(); 45 | assert.equal( 46 | metaCoinEthBalance, 47 | 2 * metaCoinBalance, 48 | 'Library function returned unexpected function, linkage may be broken' 49 | ); 50 | }); 51 | 52 | it('should send coins from account 0 to 3 and verify that a Transfer event has been emitted', function (done) { 53 | assert.isTrue(accounts[3] ? true : false, 'accounts[1] does not exist. Use Tron Quickstart!'); 54 | 55 | this.timeout(20000); 56 | MetaCoin.deployed().then(meta => { 57 | return tronWeb 58 | .contract() 59 | .at(meta.address) 60 | .then(meta2 => { 61 | meta2.Transfer().watch((err, res) => { 62 | if (res) { 63 | assert.equal(res.result._from, tronWeb.address.toHex(accounts[0])); 64 | assert.equal(res.result._to, tronWeb.address.toHex(accounts[3])); 65 | assert.equal(res.result._value, 1); 66 | done(); 67 | } 68 | }); 69 | 70 | meta.sendCoin(accounts[3], 1, { 71 | from: accounts[0] 72 | }); 73 | }); 74 | }); 75 | }); 76 | 77 | it('should send coins from account 0 to 1', async function () { 78 | assert.isTrue(accounts[1] ? true : false, 'accounts[1] does not exist. Use Tron Quickstart!'); 79 | 80 | this.timeout(10000); 81 | const meta = await MetaCoin.deployed(); 82 | wait(3); 83 | const account_one_starting_balance = (await meta.getBalance.call(accounts[0])).toNumber(); 84 | const account_two_starting_balance = (await meta.getBalance.call(accounts[1])).toNumber(); 85 | await meta.sendCoin(accounts[1], 10, { 86 | from: accounts[0] 87 | }); 88 | assert.equal( 89 | await meta.getBalance.call(accounts[0]), 90 | account_one_starting_balance - 10, 91 | "Amount wasn't correctly taken from the sender" 92 | ); 93 | assert.equal( 94 | await meta.getBalance.call(accounts[1]), 95 | account_two_starting_balance + 10, 96 | "Amount wasn't correctly sent to the receiver" 97 | ); 98 | }); 99 | }); 100 | -------------------------------------------------------------------------------- /test/fixtures/metacoin-box-0.6.0/test/metacoin.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable n/no-unpublished-require */ 2 | const wait = require('./helpers/wait'); 3 | const chalk = require('chalk'); 4 | const MetaCoin = artifacts.require('./MetaCoin.sol'); 5 | 6 | // The following tests require TronBox >= 2.1.x 7 | // and Tron Quickstart (https://github.com/tronprotocol/docker-tron-quickstart) 8 | 9 | contract('MetaCoin', function (accounts) { 10 | let meta; 11 | 12 | before(async function () { 13 | meta = await MetaCoin.deployed(); 14 | if (accounts.length < 3) { 15 | // Set your own accounts if you are not using Tron Quickstart 16 | } 17 | }); 18 | 19 | it('should verify that there are at least three available accounts', async function () { 20 | if (accounts.length < 3) { 21 | console.info( 22 | chalk.blue( 23 | '\nYOUR ATTENTION, PLEASE.]\nTo test MetaCoin you should use Tron Quickstart (https://github.com/tronprotocol/docker-tron-quickstart) as your private network.\nAlternatively, you must set your own accounts in the "before" statement in "test/metacoin.js".\n' 24 | ) 25 | ); 26 | } 27 | assert.isTrue(accounts.length >= 3); 28 | }); 29 | 30 | it('should verify that the contract has been deployed by accounts[0]', async function () { 31 | assert.equal(await meta.getOwner(), tronWeb.address.toHex(accounts[0])); 32 | }); 33 | 34 | it('should put 10000 MetaCoin in the first account', async function () { 35 | const balance = await meta.getBalance(accounts[0], { from: accounts[0] }); 36 | assert.equal(balance, 10000, "10000 wasn't in the first account"); 37 | }); 38 | 39 | it('should call a function that depends on a linked library', async function () { 40 | this.timeout(10000); 41 | const meta = await MetaCoin.deployed(); 42 | wait(1); 43 | const metaCoinBalance = (await meta.getBalance.call(accounts[0])).toNumber(); 44 | const metaCoinEthBalance = (await meta.getBalanceInEth.call(accounts[0])).toNumber(); 45 | assert.equal( 46 | metaCoinEthBalance, 47 | 2 * metaCoinBalance, 48 | 'Library function returned unexpected function, linkage may be broken' 49 | ); 50 | }); 51 | 52 | it('should send coins from account 0 to 3 and verify that a Transfer event has been emitted', function (done) { 53 | assert.isTrue(accounts[3] ? true : false, 'accounts[1] does not exist. Use Tron Quickstart!'); 54 | 55 | this.timeout(20000); 56 | MetaCoin.deployed().then(meta => { 57 | return tronWeb 58 | .contract() 59 | .at(meta.address) 60 | .then(meta2 => { 61 | meta2.Transfer().watch((err, res) => { 62 | if (res) { 63 | assert.equal(res.result._from, tronWeb.address.toHex(accounts[0])); 64 | assert.equal(res.result._to, tronWeb.address.toHex(accounts[3])); 65 | assert.equal(res.result._value, 1); 66 | done(); 67 | } 68 | }); 69 | 70 | meta.sendCoin(accounts[3], 1, { 71 | from: accounts[0] 72 | }); 73 | }); 74 | }); 75 | }); 76 | 77 | it('should send coins from account 0 to 1', async function () { 78 | assert.isTrue(accounts[1] ? true : false, 'accounts[1] does not exist. Use Tron Quickstart!'); 79 | 80 | this.timeout(10000); 81 | const meta = await MetaCoin.deployed(); 82 | wait(3); 83 | const account_one_starting_balance = (await meta.getBalance.call(accounts[0])).toNumber(); 84 | const account_two_starting_balance = (await meta.getBalance.call(accounts[1])).toNumber(); 85 | await meta.sendCoin(accounts[1], 10, { 86 | from: accounts[0] 87 | }); 88 | assert.equal( 89 | await meta.getBalance.call(accounts[0]), 90 | account_one_starting_balance - 10, 91 | "Amount wasn't correctly taken from the sender" 92 | ); 93 | assert.equal( 94 | await meta.getBalance.call(accounts[1]), 95 | account_two_starting_balance + 10, 96 | "Amount wasn't correctly sent to the receiver" 97 | ); 98 | }); 99 | }); 100 | -------------------------------------------------------------------------------- /src/lib/commands/migrate.js: -------------------------------------------------------------------------------- 1 | const version = require('../version'); 2 | const describe = 'Run migrations to deploy contracts'; 3 | 4 | const command = { 5 | command: 'migrate', 6 | describe, 7 | builder: (yargs, cmd = 'migrate') => { 8 | yargs 9 | .usage( 10 | `TronBox v${version.bundle}\n\n${describe}\n 11 | Usage: $0 ${cmd} [--network ] 12 | ${' '.repeat(cmd.length)} [--reset] [--from ] [--to ] 13 | ${' '.repeat(cmd.length)} [--compile-all] [--evm] [--quiet]` 14 | ) 15 | .version(false) 16 | .options({ 17 | network: { 18 | describe: 'Network name in configuration', 19 | type: 'string' 20 | }, 21 | reset: { 22 | describe: 'Re-run all migrations', 23 | type: 'boolean' 24 | }, 25 | from: { 26 | alias: 'f', 27 | describe: 'Specify a migration number to run from', 28 | type: 'number' 29 | }, 30 | to: { 31 | describe: 'Specify a migration number to run to', 32 | type: 'number' 33 | }, 34 | 'compile-all': { 35 | describe: 'Recompile all contracts', 36 | type: 'boolean' 37 | }, 38 | evm: { 39 | describe: 'Use EVM configuration', 40 | type: 'boolean' 41 | }, 42 | quiet: { 43 | describe: 'Suppress all output except errors', 44 | type: 'boolean' 45 | } 46 | }) 47 | .example(`$0 ${cmd}`, 'Run all migrations on the development network') 48 | .example(`$0 ${cmd} --network nile`, 'Run migrations on the nile network') 49 | .example(`$0 ${cmd} --reset`, 'Re-run all migrations') 50 | .group(['network', 'reset', 'from', 'to', 'compile-all', 'evm', 'quiet', 'help'], 'Options:'); 51 | }, 52 | run: function (options, done) { 53 | process.env.CURRENT = 'migrate'; 54 | const OS = require('os'); 55 | const Config = require('../../components/Config'); 56 | const Contracts = require('../../components/WorkflowCompile'); 57 | const Migrate = require('../../components/Migrate'); 58 | const Environment = require('../environment'); 59 | const TronWrap = require('../../components/TronWrap'); 60 | const { dlog } = require('../../components/TronWrap'); 61 | const logErrorAndExit = require('../../components/TronWrap').logErrorAndExit; 62 | 63 | if (options.quiet || options.silent) { 64 | options.logger = { 65 | log: function () {} 66 | }; 67 | } 68 | 69 | const config = Config.detect(options); 70 | 71 | // if "development" exists, default to using that 72 | if (!config.network && config.networks.development) { 73 | config.network = 'development'; 74 | } 75 | // init TronWeb 76 | try { 77 | TronWrap(config.networks[config.network], { 78 | evm: options.evm, 79 | verify: true, 80 | logger: options.logger 81 | }); 82 | } catch (err) { 83 | logErrorAndExit(console, err.message); 84 | } 85 | 86 | function runMigrations(callback) { 87 | if (options.f) { 88 | Migrate.runFrom(options.f, config, done); 89 | } else { 90 | Migrate.needsMigrating(config, function (err, needsMigrating) { 91 | if (err) return callback(err); 92 | 93 | if (needsMigrating) { 94 | dlog('Starting migration'); 95 | Migrate.run(config, done); 96 | } else { 97 | config.logger.log('Network up to date.'); 98 | callback(); 99 | } 100 | }); 101 | } 102 | } 103 | 104 | config.logger.log("Using network '" + config.network + "'." + OS.EOL); 105 | 106 | Contracts.compile(config, function (err) { 107 | if (err) return done(err); 108 | Environment.detect(config, function (err) { 109 | if (err) return done(err); 110 | 111 | config.logger.log(); 112 | runMigrations(done); 113 | }); 114 | }); 115 | } 116 | }; 117 | 118 | module.exports = command; 119 | -------------------------------------------------------------------------------- /src/lib/commands/unbox.js: -------------------------------------------------------------------------------- 1 | /* 2 | * returns a VCS url string given: 3 | * - a VCS url string 4 | * - a github `org/repo` string 5 | * - a string containing a repo under the `tronsuper` org 6 | */ 7 | function normalizeURL(url) { 8 | url = url || 'https://github.com/tronsuper/bare-box'; 9 | 10 | // full URL already 11 | if (url.indexOf('://') !== -1 || url.indexOf('git@') !== -1) { 12 | return url; 13 | } 14 | 15 | if (url.split('/').length === 2) { 16 | // `org/repo` 17 | return 'https://github.com/' + url; 18 | } 19 | 20 | if (url.indexOf('/') === -1) { 21 | // repo name only 22 | if (url.indexOf('-box') === -1) { 23 | url = url + '-box'; 24 | } 25 | return 'https://github.com/tronsuper/' + url; 26 | } 27 | 28 | throw new Error('Box specified in invalid format'); 29 | } 30 | 31 | /* 32 | * returns a list of messages, one for each command, formatted 33 | * so that: 34 | * 35 | * command key: command string 36 | * 37 | * are aligned 38 | */ 39 | function formatCommands(commands) { 40 | const names = Object.keys(commands); 41 | 42 | const maxLength = Math.max.apply( 43 | null, 44 | names.map(function (name) { 45 | return name.length; 46 | }) 47 | ); 48 | 49 | return names.map(function (name) { 50 | const spacing = Array(maxLength - name.length + 1).join(' '); 51 | return ' ' + name + ': ' + spacing + commands[name]; 52 | }); 53 | } 54 | 55 | const version = require('../version'); 56 | const describe = 'Download a pre-built TronBox Box template'; 57 | 58 | const command = { 59 | command: 'unbox', 60 | describe, 61 | builder: yargs => { 62 | yargs 63 | .usage( 64 | `TronBox v${version.bundle}\n\n${describe}\n 65 | Usage: $0 unbox [] [--quiet]` 66 | ) 67 | .version(false) 68 | .options({ 69 | quiet: { 70 | describe: 'Suppress all output except errors', 71 | type: 'boolean' 72 | } 73 | }) 74 | .positional('name', { 75 | describe: 'Box name, GitHub username/repo, or a full git repo URL. If omitted, downloads the default box.', 76 | type: 'string' 77 | }) 78 | .example('$0 unbox', 'Download the default TronBox Box') 79 | .example('$0 unbox metacoin', 'Download the "metacoin" TronBox Box') 80 | .example('$0 unbox tronsuper/bare-box', 'Download a TronBox Box from a GitHub username/repository') 81 | .example('$0 unbox https://gitlab.com/user/my-box', 'Download a TronBox Box using its full Git repository URL') 82 | .group(['quiet', 'help'], 'Options:'); 83 | }, 84 | run: function (options, done) { 85 | const Config = require('../../components/Config'); 86 | const Box = require('../../components/Box'); 87 | const OS = require('os'); 88 | const chalk = require('chalk'); 89 | 90 | const config = Config.default().with({ 91 | logger: console 92 | }); 93 | 94 | if (options.quiet || options.silent) { 95 | config.logger = { 96 | log: function () {} 97 | }; 98 | } 99 | 100 | const url = normalizeURL(options._[0]); 101 | Box.unbox(url, options.working_directory || config.working_directory, { 102 | logger: config.logger 103 | }) 104 | .then(function (boxConfig) { 105 | config.logger.log('Unbox successful. Sweet!' + OS.EOL); 106 | 107 | const commandMessages = formatCommands(boxConfig.commands); 108 | if (commandMessages.length > 0) { 109 | config.logger.log('Commands:' + OS.EOL); 110 | } 111 | commandMessages.forEach(function (message) { 112 | config.logger.log(message); 113 | }); 114 | 115 | if (boxConfig.epilogue) { 116 | config.logger.log(boxConfig.epilogue.replace('\n', OS.EOL)); 117 | } 118 | 119 | done(); 120 | }) 121 | .catch(err => { 122 | if (err) { 123 | console.error(chalk.red(chalk.bold('ERROR:'), err.message ? err.message : err)); 124 | process.exit(1); 125 | } 126 | done(); 127 | }); 128 | } 129 | }; 130 | 131 | module.exports = command; 132 | -------------------------------------------------------------------------------- /test/consolelogs/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const AddressAddressLogs = artifacts.require('./AddressAddressLogs.sol'); 2 | const AddressBoolLogs = artifacts.require('./AddressBoolLogs.sol'); 3 | const AddressStringLogs = artifacts.require('./AddressStringLogs.sol'); 4 | const AddressUintLogs = artifacts.require('./AddressUintLogs.sol'); 5 | const BoolAddressLogs = artifacts.require('./BoolAddressLogs.sol'); 6 | const BoolBoolLogs = artifacts.require('./BoolBoolLogs.sol'); 7 | const BoolStringLogs = artifacts.require('./BoolStringLogs.sol'); 8 | const BoolUintLogs = artifacts.require('./BoolUintLogs.sol'); 9 | const StringAddressLogs = artifacts.require('./StringAddressLogs.sol'); 10 | const StringBoolLogs = artifacts.require('./StringBoolLogs.sol'); 11 | const StringStringLogs = artifacts.require('./StringStringLogs.sol'); 12 | const StringUintLogs = artifacts.require('./StringUintLogs.sol'); 13 | const UintAddressLogs = artifacts.require('./UintAddressLogs.sol'); 14 | const UintBoolLogs = artifacts.require('./UintBoolLogs.sol'); 15 | const UintStringLogs = artifacts.require('./UintStringLogs.sol'); 16 | const UintUintLogs = artifacts.require('./UintUintLogs.sol'); 17 | const SingleLogs = artifacts.require('./SingleLogs.sol'); 18 | const MostSignificantBitSetLogs = artifacts.require('./MostSignificantBitSetLogs.sol'); 19 | const CreationLogs = artifacts.require('./CreationLogs.sol'); 20 | const CreationRevertingLogs = artifacts.require('./CreationRevertingLogs.sol'); 21 | const CreationMultipleLogs = artifacts.require('./CreationMultipleLogs.sol'); 22 | const TriggerLogs = artifacts.require('./TriggerLogs.sol'); 23 | 24 | module.exports = async function (deployer) { 25 | // Skip deployment while testing 26 | if (global.config.test_files) { 27 | return; 28 | } 29 | const sleep = (millis = 3000) => { 30 | return new Promise(resolve => setTimeout(resolve, millis)); 31 | }; 32 | const setBalance = async () => { 33 | await tronWrap.send('tre_setAccountBalance', [tronWrap.defaultAddress.base58, 100000 * 1e6]); 34 | }; 35 | const testCallLogs = async (contract, prefix = 'callLogs') => { 36 | await sleep(); 37 | await deployer.deploy(contract); 38 | const logs = await contract.deployed(); 39 | console.info(`=== ${prefix} start ===`); 40 | await logs.callLogs(); 41 | console.info(`=== ${prefix} end ===`); 42 | }; 43 | const testDeployLogs = async (contract, prefix = 'deployLogs') => { 44 | await sleep(); 45 | console.info(`=== ${prefix} start ===`); 46 | try { 47 | await deployer.deploy(contract); 48 | } catch (e) {} 49 | console.info(`=== ${prefix} end ===`); 50 | }; 51 | const testSendLogs = async (contract, func = 'sendLogs') => { 52 | await sleep(); 53 | await deployer.deploy(contract); 54 | const logs = await contract.deployed(); 55 | console.info(`=== ${func} start ===`); 56 | await logs[func](); 57 | console.info(`=== ${func} end ===`); 58 | }; 59 | 60 | await setBalance(); 61 | await testCallLogs(AddressAddressLogs, 'AddressAddress'); 62 | await testCallLogs(AddressBoolLogs, 'AddressBool'); 63 | await testCallLogs(AddressStringLogs, 'AddressString'); 64 | await testCallLogs(AddressUintLogs, 'AddressUint'); 65 | await testCallLogs(BoolAddressLogs, 'BoolAddress'); 66 | await testCallLogs(BoolBoolLogs, 'BoolBool'); 67 | await testCallLogs(BoolStringLogs, 'BoolString'); 68 | await testCallLogs(BoolUintLogs, 'BoolUint'); 69 | await testCallLogs(StringAddressLogs, 'StringAddress'); 70 | await testCallLogs(StringBoolLogs, 'StringBool'); 71 | await testCallLogs(StringStringLogs, 'StringString'); 72 | await testCallLogs(StringUintLogs, 'StringUint'); 73 | await testCallLogs(UintAddressLogs, 'UintAddress'); 74 | await testCallLogs(UintBoolLogs, 'UintBool'); 75 | await testCallLogs(UintStringLogs, 'UintString'); 76 | await testCallLogs(UintUintLogs, 'UintUint'); 77 | await testCallLogs(SingleLogs, 'Single'); 78 | await testCallLogs(MostSignificantBitSetLogs, 'MostSignificantBitSet'); 79 | 80 | await setBalance(); 81 | await testDeployLogs(CreationLogs, 'Creation'); 82 | await testDeployLogs(CreationRevertingLogs, 'CreationReverting'); 83 | await testDeployLogs(CreationMultipleLogs, 'CreationMultiple'); 84 | 85 | await testSendLogs(TriggerLogs, 'f1'); 86 | await testSendLogs(TriggerLogs, 'f2'); 87 | }; 88 | -------------------------------------------------------------------------------- /src/components/ContractSchema/spec/contract-object.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "contract-object.spec.json", 3 | "$schema": "http://json-schema.org/schema#", 4 | "title": "Contract Object", 5 | "description": "Describes a contract consumable by Truffle, possibly including deployed instances on networks", 6 | "type": "object", 7 | "properties": { 8 | "contractName": { 9 | "allOf": [ 10 | { 11 | "$ref": "#/definitions/ContractName" 12 | }, 13 | { 14 | "description": "Name used to identify the contract", 15 | "default": "Contract" 16 | } 17 | ] 18 | }, 19 | "abi": { 20 | "allOf": [ 21 | { 22 | "$ref": "abi.spec.json#" 23 | }, 24 | { 25 | "description": "Interface description returned by compiler for source" 26 | } 27 | ] 28 | }, 29 | "bytecode": { 30 | "allOf": [ 31 | { 32 | "$ref": "#/definitions/Bytecode" 33 | }, 34 | { 35 | "description": "Bytecode sent as contract-creation transaction data, with unresolved link references" 36 | } 37 | ] 38 | }, 39 | "deployedBytecode": { 40 | "allOf": [ 41 | { 42 | "$ref": "#/definitions/Bytecode" 43 | }, 44 | { 45 | "description": "On-chain deployed contract bytecode, with unresolved link references" 46 | } 47 | ] 48 | }, 49 | "sourceMap": { 50 | "allOf": [ 51 | { 52 | "$ref": "#/definitions/SourceMap" 53 | }, 54 | { 55 | "description": "Source mapping for contract-creation transaction data bytecode" 56 | } 57 | ] 58 | }, 59 | "deployedSourceMap": { 60 | "allOf": [ 61 | { 62 | "$ref": "#/definitions/SourceMap" 63 | }, 64 | { 65 | "description": "Source mapping for contract bytecode" 66 | } 67 | ] 68 | }, 69 | "source": { 70 | "$ref": "#/definitions/Source" 71 | }, 72 | "sourcePath": { 73 | "$ref": "#/definitions/SourcePath" 74 | }, 75 | "ast": { 76 | "$ref": "#/definitions/AST" 77 | }, 78 | "legacyAST": { 79 | "$ref": "#/definitions/LegacyAST" 80 | }, 81 | "compiler": { 82 | "type": "object", 83 | "properties": { 84 | "name": { 85 | "type": "string" 86 | }, 87 | "version": { 88 | "type": "string" 89 | } 90 | } 91 | }, 92 | "networks": { 93 | "patternProperties": { 94 | "^[a-zA-Z0-9]+$": { 95 | "$ref": "network-object.spec.json#" 96 | } 97 | }, 98 | "additionalProperties": false 99 | }, 100 | "schemaVersion": { 101 | "$ref": "#/definitions/SchemaVersion" 102 | }, 103 | "updatedAt": { 104 | "type": "string", 105 | "format": "date-time" 106 | } 107 | }, 108 | "required": [ 109 | "abi" 110 | ], 111 | "patternProperties": { 112 | "^x-": { 113 | "anyOf": [ 114 | { 115 | "type": "string" 116 | }, 117 | { 118 | "type": "number" 119 | }, 120 | { 121 | "type": "object" 122 | }, 123 | { 124 | "type": "array" 125 | } 126 | ] 127 | } 128 | }, 129 | "additionalProperties": false, 130 | "definitions": { 131 | "ContractName": { 132 | "type": "string", 133 | "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" 134 | }, 135 | "Bytecode": { 136 | "type": "string", 137 | "pattern": "^0x0$|^0x([a-fA-F0-9]{2}|__.{38})+$" 138 | }, 139 | "Source": { 140 | "type": "string" 141 | }, 142 | "SourceMap": { 143 | "type": "string", 144 | "examples": [ 145 | "315:637:1:-;;;452:55;;;;;;;-1:-1:-1;;;;;485:9:1;476:19;:8;:19;;;;;;;;;;498:5;476:27;;452:55;315:637;;;;;;;" 146 | ] 147 | }, 148 | "SourcePath": { 149 | "type": "string" 150 | }, 151 | "AST": { 152 | "type": "object" 153 | }, 154 | "LegacyAST": { 155 | "type": "object" 156 | }, 157 | "SchemaVersion": { 158 | "type": "string", 159 | "pattern": "[0-9]+\\.[0-9]+\\.[0-9]+" 160 | } 161 | } 162 | } 163 | --------------------------------------------------------------------------------