├── .github ├── contributing.md └── workflows │ ├── tx-coverage.yml │ ├── tx-lint.yml │ └── tx-test.yml ├── .gitignore ├── .npmignore ├── .nycrc ├── .prettierignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── docs ├── README.md ├── classes │ ├── faketransaction.md │ └── transaction.md └── interfaces │ ├── faketxdata.md │ ├── transactionoptions.md │ ├── transformabletobuffer.md │ └── txdata.md ├── examples ├── custom-chain-tx.ts ├── ropsten-tx.ts └── transactions.ts ├── karma.conf.js ├── package.json ├── prettier.config.js ├── src ├── fake.ts ├── index.ts ├── transaction.ts └── types.ts ├── test ├── api.ts ├── fake.ts ├── index.ts ├── transactionRunner.ts ├── ttTransactionTestEip155VitaliksTests.json ├── txs.json └── types.ts ├── tsconfig.json ├── tsconfig.prod.json └── tslint.json /.github/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Great that you want to contribute to the `EthereumJS` [ecosystem](https://ethereumjs.readthedocs.io/en/latest/introduction.html). `EthereumJS` is managed by the Ethereum Foundation and largely driven by the wider community. Everyone is welcome to join the effort and help to improve on the libraries (see our [Code of Conduct](https://ethereumjs.readthedocs.io/en/latest/code_of_conduct.html) 🌷). 4 | 5 | We have written up some [Contribution Guidelines](https://ethereumjs.readthedocs.io/en/latest/contributing.html#how-to-start) to help you getting started. 6 | 7 | These include information on how we work with **Git** and how our **general workflow** and **technical setup** looks like (stuff like language, tooling, code quality and style). 8 | 9 | Happy Coding! 👾 😀 💻 10 | -------------------------------------------------------------------------------- /.github/workflows/tx-coverage.yml: -------------------------------------------------------------------------------- 1 | name: tx-coverage 2 | on: [push, pull_request] 3 | jobs: 4 | coverage: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/setup-node@v1 8 | with: 9 | node-version: 12.x 10 | 11 | - uses: actions/checkout@v1 12 | - run: npm install 13 | - run: npm run coverage 14 | - run: npm run coveralls 15 | 16 | - name: Post coverage data to coveralls.io for analysis 17 | uses: coverallsapp/github-action@master 18 | with: 19 | github-token: ${{ secrets.GITHUB_TOKEN }} 20 | -------------------------------------------------------------------------------- /.github/workflows/tx-lint.yml: -------------------------------------------------------------------------------- 1 | name: tx-lint 2 | on: [push, pull_request] 3 | jobs: 4 | lint: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/setup-node@v1 8 | with: 9 | node-version: 12.x 10 | 11 | - uses: actions/checkout@v1 12 | - run: npm install 13 | - run: npm run lint 14 | env: 15 | CI: true 16 | -------------------------------------------------------------------------------- /.github/workflows/tx-test.yml: -------------------------------------------------------------------------------- 1 | name: tx-test 2 | on: [push, pull_request] 3 | jobs: 4 | test: 5 | runs-on: ubuntu-latest 6 | strategy: 7 | matrix: 8 | node-version: [8.x, 10.x, 12.x, 13.x] 9 | 10 | steps: 11 | - name: Use Node.js ${{ matrix.node-version }} 12 | uses: actions/setup-node@v1 13 | with: 14 | node-version: ${{ matrix.node-version }} 15 | 16 | - uses: actions/checkout@v1 17 | - run: npm install 18 | 19 | - run: npm run test:node 20 | env: 21 | CI: true 22 | 23 | - run: npm run test:browser 24 | env: 25 | CI: true 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | .idea/ 3 | test-build/ 4 | package-lock.json 5 | 6 | # Created by https://www.gitignore.io/api/osx,node 7 | 8 | es5 9 | 10 | ### OSX ### 11 | *.DS_Store 12 | .AppleDouble 13 | .LSOverride 14 | 15 | # Icon must end with two \r 16 | Icon 17 | # Thumbnails 18 | ._* 19 | # Files that might appear in the root of a volume 20 | .DocumentRevisions-V100 21 | .fseventsd 22 | .Spotlight-V100 23 | .TemporaryItems 24 | .Trashes 25 | .VolumeIcon.icns 26 | .com.apple.timemachine.donotpresent 27 | # Directories potentially created on remote AFP share 28 | .AppleDB 29 | .AppleDesktop 30 | Network Trash Folder 31 | Temporary Items 32 | .apdisk 33 | .idea 34 | 35 | 36 | ### Node ### 37 | # Logs 38 | logs 39 | *.log 40 | npm-debug.log* 41 | 42 | # Runtime data 43 | pids 44 | *.pid 45 | *.seed 46 | *.pid.lock 47 | 48 | # Directory for instrumented libs generated by jscoverage/JSCover 49 | lib-cov 50 | 51 | # Coverage directory used by tools like istanbul 52 | coverage 53 | 54 | # nyc test coverage 55 | .nyc_output 56 | 57 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 58 | .grunt 59 | 60 | # node-waf configuration 61 | .lock-wscript 62 | 63 | # Compiled binary addons (http://nodejs.org/api/addons.html) 64 | build/Release 65 | 66 | # Dependency directories 67 | node_modules 68 | jspm_packages 69 | 70 | # Optional npm cache directory 71 | .npm 72 | 73 | # Optional eslint cache 74 | .eslintcache 75 | 76 | # Optional REPL history 77 | .node_repl_history 78 | 79 | # Output of 'npm pack' 80 | *.tgz 81 | 82 | # Yarn Integrity file 83 | .yarn-integrity 84 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .git/ 3 | test/ 4 | es5/.gitkeep 5 | .gitignore 6 | .travis.yml 7 | .babelrc 8 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@ethereumjs/config-nyc" 3 | } -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | package.json 4 | dist 5 | .nyc_output -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8" 4 | - "10" 5 | - "11" 6 | env: 7 | - CXX=g++-4.8 8 | services: 9 | - xvfb 10 | addons: 11 | apt: 12 | sources: 13 | - ubuntu-toolchain-r-test 14 | packages: 15 | - g++-4.8 16 | env: 17 | global: 18 | - DISPLAY=:99.0 19 | matrix: 20 | - CXX=g++-4.8 TEST_SUITE=test:node 21 | matrix: 22 | fast_finish: true 23 | include: 24 | - os: linux 25 | node_js: "8" 26 | env: CXX=g++-4.8 TEST_SUITE=coveralls 27 | - os: linux 28 | node_js: "8" 29 | env: CXX=g++-4.8 TEST_SUITE=lint 30 | - os: linux 31 | node_js: "10" 32 | env: CXX=g++-4.8 TEST_SUITE=coveralls 33 | - os: linux 34 | node_js: "10" 35 | env: CXX=g++-4.8 TEST_SUITE=lint 36 | - os: linux 37 | node_js: "11" 38 | env: CXX=g++-4.8 TEST_SUITE=coveralls 39 | - os: linux 40 | node_js: "11" 41 | env: CXX=g++-4.8 TEST_SUITE=lint 42 | # - os: linux 43 | # node_js: "4" 44 | # env: CXX=g++-4.8 TEST_SUITE=test:browser 45 | script: npm run $TEST_SUITE 46 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 6 | (modification: no type change headlines) and this project adheres to 7 | [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 8 | 9 | ## [2.1.2] - 2019-12-19 10 | 11 | - Added support for the `MuirGlacier` HF by updating the `ethereumjs-common` dependency 12 | to [v1.5.0](https://github.com/ethereumjs/ethereumjs-common/releases/tag/v1.5.0) 13 | 14 | [2.1.2]: https://github.com/ethereumjs/ethereumjs-tx/compare/v2.1.1...v2.1.2 15 | 16 | ## [2.1.1] - 2019-08-30 17 | 18 | - Added support for `Istanbul` reduced non-zero call data gas prices 19 | ([EIP-2028](https://eips.ethereum.org/EIPS/eip-2028)), 20 | PR [#171](https://github.com/ethereumjs/ethereumjs-tx/pull/171) 21 | 22 | [2.1.1]: https://github.com/ethereumjs/ethereumjs-tx/compare/v2.1.0...v2.1.1 23 | 24 | ## [2.1.0] - 2019-06-28 25 | 26 | **Using testnets and custom/private networks is now easier** 27 | 28 | This release is focused on making this library easier to use in chains other than `mainnet`. 29 | 30 | Using standard testnets can be as easy as passing their names to the `Transaction` constructor. For 31 | example, `new Transaction(rawTx, {chain: 'ropsten', hardfork: 'byzantium'})` is enough to use this 32 | library with Ropsten on Byzantium. 33 | 34 | If you are using a custom network, you can take advantage of [ethereumjs-common](https://github.com/ethereumjs/ethereumjs-common), 35 | which contains all the network parameters. In this version of `ethereumjs-tx` you can use its new 36 | `Common.forCustomNetwork` to create a `Common` instance based on a standard network with some 37 | parameters changed. You can see an example of how to do this [here](https://github.com/ethereumjs/ethereumjs-common/blob/9e624f86107cea904d8171524130d92c99bf9302/src/index.ts). 38 | 39 | List of changes: 40 | 41 | - Upgraded [ethereumjs-common](https://github.com/ethereumjs/ethereumjs-common) to `^1.3.0` 42 | - Added more documentation and examples on how to create transactions for public testnets and 43 | custom networks. 44 | 45 | [2.1.0]: https://github.com/ethereumjs/ethereumjs-tx/compare/v2.0.0...v2.1.0 46 | 47 | ## [2.0.0] - 2019-06-03 48 | 49 | **TypeScript / Module Import / Node Support** 50 | 51 | First `TypeScript` based release of the library, see 52 | PR [#145](https://github.com/ethereumjs/ethereumjs-tx/pull/145) for details. 53 | 54 | This comes along with some changes on the API, Node import of the exposed 55 | classes now goes like this: 56 | 57 | ```javascript 58 | const EthereumTx = require('ethereumjs-transaction').Transaction 59 | const FakeEthereumTx = require('ethereumjs-transaction').FakeTransaction 60 | ``` 61 | 62 | The library now also comes with a **type declaration file** distributed along 63 | with the package published. 64 | 65 | Along with this release we drop official support for `Node` versions `4`,`5` 66 | and `6`. Officially tested versions are now `Node` `8`, `10` and `11` 67 | (see PRs [#138](https://github.com/ethereumjs/ethereumjs-tx/pull/138) and 68 | [#146](https://github.com/ethereumjs/ethereumjs-tx/pull/146)). 69 | 70 | **Hardfork Support / Official Test Updates** 71 | 72 | Along with a long overdue update of the official Ethereum Transaction tests 73 | (see PRs [#131](https://github.com/ethereumjs/ethereumjs-tx/pull/131) and 74 | [#138](https://github.com/ethereumjs/ethereumjs-tx/pull/138) for 75 | `FakeTransaction`) and 76 | an introduction of setting chain and hardfork by using our shared 77 | [ethereumjs-common](https://github.com/ethereumjs/ethereumjs-common) class 78 | (see PR [#131](https://github.com/ethereumjs/ethereumjs-tx/pull/130)) the 79 | transaction library now supports all HFs up to the `Petersburg` hardfork, 80 | see [constructor option docs](https://github.com/ethereumjs/ethereumjs-tx/blob/master/docs/interfaces/transactionoptions.md) for information on instantiation and default values (current hardfork default: `petersburg`). 81 | 82 | API Changes: 83 | 84 | - Removal of the `data.chainId` parameter, use the `opts.chain` parameter or a custom `Common` instance 85 | 86 | **Default EIP-155 Support** 87 | 88 | Along with defaulting to a post-`Spurious Dragon` HF replay protection from 89 | [EIP-155](https://eips.ethereum.org/EIPS/eip-155) is now activated by default. Transactions are subsequently also by default signed with `EIP-155` replay protection, 90 | see PRs [#153](https://github.com/ethereumjs/ethereumjs-tx/pull/153), 91 | [#147](https://github.com/ethereumjs/ethereumjs-tx/pull/147) and 92 | [#143](https://github.com/ethereumjs/ethereumjs-tx/pull/143). 93 | 94 | This comes with some changes in how different `v` values passed on instantation 95 | or changed on runtime are handled: 96 | 97 | - The constructor throws if the `v` value is present, indicates that `EIP-155` 98 | was enabled, and the chain id it indicates doesn't match the one of the 99 | internal `common` object 100 | - No default `v` is set. If a transaction isn't signed, it would be an empty 101 | buffer 102 | - If `v` is changed after construction its value is validated in its setter 103 | 104 | For activating non-`EIP-155` behavior instantiate the transaction with a 105 | pre-`Spurious Dragon` hardfork option. 106 | 107 | [2.0.0]: https://github.com/ethereumjs/ethereumjs-tx/compare/v1.3.7...v2.0.0 108 | 109 | ## [1.3.7] - 2018-07-25 110 | 111 | - Fix bug causing `FakeTransaction.from` to not retrieve sender address from tx signature, see PR [#118](https://github.com/ethereumjs/ethereumjs-tx/pull/118) 112 | 113 | [1.3.7]: https://github.com/ethereumjs/ethereumjs-tx/compare/v1.3.6...v1.3.7 114 | 115 | ## [1.3.6] - 2018-07-02 116 | 117 | - Fixes issue [#108](https://github.com/ethereumjs/ethereumjs-tx/issues/108) with the `FakeTransaction.hash()` function by reverting the introduced signature handling changes in Fake transaction hash creation from PR [#94](https://github.com/ethereumjs/ethereumjs-tx/pull/94) introduced in `v1.3.5`. The signature is now again only created and added to the hash when `from` address is set and `from` is not defaulting to the zero adress any more, see PR [#110](https://github.com/ethereumjs/ethereumjs-tx/pull/110) 118 | - Added additional tests to cover issue described above 119 | 120 | [1.3.6]: https://github.com/ethereumjs/ethereumjs-tx/compare/v1.3.5...v1.3.6 121 | 122 | ## [1.3.5] - 2018-06-22 123 | 124 | - Include signature by default in `FakeTransaction.hash`, PR [#97](https://github.com/ethereumjs/ethereumjs-tx/pull/97) 125 | - Fix `FakeTransaction` signature failure bug, PR [#94](https://github.com/ethereumjs/ethereumjs-tx/pull/94) 126 | 127 | [1.3.5]: https://github.com/ethereumjs/ethereumjs-tx/compare/v1.3.4...v1.3.5 128 | 129 | ## [1.3.4] - 2018-03-06 130 | 131 | - Fix a bug producing hash collisions on `FakeTransaction` for different senders, PR [#81](https://github.com/ethereumjs/ethereumjs-tx/pull/81) 132 | - Switched from deprecated `es2015` to `env` babel preset, PR [#86](https://github.com/ethereumjs/ethereumjs-tx/pull/86) 133 | - Dropped Node 4 support 134 | 135 | [1.3.4]: https://github.com/ethereumjs/ethereumjs-tx/compare/v1.3.3...v1.3.4 136 | 137 | ## [1.3.3] - 2017-07-12 138 | 139 | - Allow zeros in `v`,`r`,`s` signature values 140 | - Dropped `browserify` transform from `package.json` 141 | - (combined v1.3.3 and v1.3.2 release notes) 142 | 143 | [1.3.3]: https://github.com/ethereumjs/ethereumjs-tx/compare/v1.3.1...v1.3.3 144 | 145 | ## [1.3.1] - 2017-05-13 146 | 147 | - Added `ES5` build 148 | 149 | [1.3.1]: https://github.com/ethereumjs/ethereumjs-tx/compare/v1.3.0...v1.3.1 150 | 151 | ## [1.3.0] - 2017-04-24 152 | 153 | - `EIP155`: allow `v` value to be greater than one byte (replay attack protection) 154 | - Added `browserify` `ES2015` transform to `package.json` 155 | - Improved documentation 156 | - (combined v1.3.0, v1.2.5 and v1.2.4 release notes) 157 | 158 | [1.3.0]: https://github.com/ethereumjs/ethereumjs-tx/compare/v1.2.3...v1.3.0 159 | 160 | ## [1.2.3] - 2017-01-30 161 | 162 | - `EIP155` hash implementation 163 | - README example and doc fixes 164 | 165 | [1.2.3]: https://github.com/ethereumjs/ethereumjs-tx/compare/v1.2.2...v1.2.3 166 | 167 | ## [1.2.2] - 2016-12-15 168 | 169 | - Moved `chainId` param to `txParams`, parse `sig` for `chainId` (`EIP155` refactor) 170 | - Test improvements 171 | - (combined v1.2.2 and v1.2.1 release notes) 172 | 173 | [1.2.2]: https://github.com/ethereumjs/ethereumjs-tx/compare/v1.2.0...v1.2.2 174 | 175 | ## [1.2.0] - 2016-12-14 176 | 177 | - Added `EIP155` changes 178 | - Renamed `chain_id` to `chainId` 179 | - Node 4/5 compatibility 180 | - `ES6` standards 181 | 182 | [1.2.0]: https://github.com/ethereumjs/ethereumjs-tx/compare/v1.1.4...v1.2.0 183 | 184 | ## Older releases: 185 | 186 | - [1.1.4](https://github.com/ethereumjs/ethereumjs-tx/compare/v1.1.3...v1.1.4) - 2016-11-17 187 | - [1.1.3](https://github.com/ethereumjs/ethereumjs-tx/compare/v1.1.2...v1.1.3) - 2016-11-10 188 | - [1.1.2](https://github.com/ethereumjs/ethereumjs-tx/compare/v1.1.1...v1.1.2) - 2016-07-17 189 | - [1.1.1](https://github.com/ethereumjs/ethereumjs-tx/compare/v1.1.0...v1.1.1) - 2016-03-05 190 | - [1.1.0](https://github.com/ethereumjs/ethereumjs-tx/compare/v1.0.1...v1.1.0) - 2016-03-03 191 | - [1.0.1](https://github.com/ethereumjs/ethereumjs-tx/compare/v1.0.0...v1.0.1) - 2016-03-03 192 | - [1.0.0](https://github.com/ethereumjs/ethereumjs-tx/compare/v0.7.3...v1.0.0) - 2016-02-11 193 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 | # SYNOPSIS 8 | 9 | [![NPM Package](https://img.shields.io/npm/v/ethereumjs-tx.svg?style=flat-square)](https://www.npmjs.org/package/ethereumjs-tx) 10 | [![Actions Status](https://github.com/ethereumjs/ethereumjs-tx/workflows/tx-test/badge.svg)](https://github.com/ethereumjs/ethereumjs-tx/actions) 11 | [![Coverage Status](https://img.shields.io/coveralls/ethereumjs/ethereumjs-tx.svg?style=flat-square)](https://coveralls.io/r/ethereumjs/ethereumjs-tx) 12 | [![Gitter](https://img.shields.io/gitter/room/ethereum/ethereumjs-lib.svg?style=flat-square)](https://gitter.im/ethereum/ethereumjs-lib) or #ethereumjs on freenode 13 | 14 | # INSTALL 15 | 16 | `npm install ethereumjs-tx` 17 | 18 | # USAGE 19 | 20 | - [example](https://github.com/ethereumjs/ethereumjs-tx/blob/master/examples/transactions.ts) 21 | 22 | ```javascript 23 | const EthereumTx = require('ethereumjs-tx').Transaction 24 | const privateKey = Buffer.from( 25 | 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 26 | 'hex', 27 | ) 28 | 29 | const txParams = { 30 | nonce: '0x00', 31 | gasPrice: '0x09184e72a000', 32 | gasLimit: '0x2710', 33 | to: '0x0000000000000000000000000000000000000000', 34 | value: '0x00', 35 | data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057', 36 | } 37 | 38 | // The second parameter is not necessary if these values are used 39 | const tx = new EthereumTx(txParams, { chain: 'mainnet', hardfork: 'petersburg' }) 40 | tx.sign(privateKey) 41 | const serializedTx = tx.serialize() 42 | ``` 43 | 44 | # Chain and Hardfork Support 45 | 46 | The `Transaction` and `FakeTransaction` constructors receives a second parameter that lets you specify the chain and hardfork 47 | to be used. By default, `mainnet` and `petersburg` will be used. 48 | 49 | There are two ways of customizing these. The first one, as shown in the previous section, is by 50 | using an object with `chain` and `hardfork` names. You can see en example of this in [./examples/ropsten-tx.ts](./examples/ropsten-tx.ts). 51 | 52 | The second option is by passing the option `common` set to an instance of [ethereumjs-common](https://github.com/ethereumjs/ethereumjs-common)' Common. This is specially useful for custom networks or chains/hardforks not yet supported by `ethereumjs-common`. You can see en example of this in [./examples/custom-chain-tx.ts](./examples/custom-chain-tx.ts). 53 | 54 | ## MuirGlacier Support 55 | 56 | The `MuirGlacier` hardfork is supported by the library since the `v2.1.2` release. 57 | 58 | ## Istanbul Support 59 | 60 | Support for reduced non-zero call data gas prices from the `Istanbul` hardfork 61 | ([EIP-2028](https://eips.ethereum.org/EIPS/eip-2028)) has been added to the library 62 | along with the `v2.1.1` release. 63 | 64 | # EIP-155 support 65 | 66 | `EIP-155` replay protection is activated since the `spuriousDragon` hardfork. To disable it, set the 67 | hardfork in the `Transaction`'s constructor. 68 | 69 | # API 70 | 71 | [./docs/](./docs/README.md) 72 | 73 | # EthereumJS 74 | 75 | See our organizational [documentation](https://ethereumjs.readthedocs.io) for an introduction to `EthereumJS` as well as information on current standards and best practices. 76 | 77 | If you want to join for work or do improvements on the libraries have a look at our [contribution guidelines](https://ethereumjs.readthedocs.io/en/latest/contributing.html). 78 | 79 | # LICENSE 80 | 81 | [MPL-2.0]() 82 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # ethereumjs-tx 2 | 3 | ## Index 4 | 5 | ### Classes 6 | 7 | - [FakeTransaction](classes/faketransaction.md) 8 | - [Transaction](classes/transaction.md) 9 | 10 | ### Interfaces 11 | 12 | - [FakeTxData](interfaces/faketxdata.md) 13 | - [TransactionOptions](interfaces/transactionoptions.md) 14 | - [TransformableToBuffer](interfaces/transformabletobuffer.md) 15 | - [TxData](interfaces/txdata.md) 16 | 17 | ### Type aliases 18 | 19 | - [BufferLike](#bufferlike) 20 | - [PrefixedHexString](#prefixedhexstring) 21 | 22 | --- 23 | 24 | ## Type aliases 25 | 26 | 27 | 28 | ### BufferLike 29 | 30 | **Ƭ BufferLike**: _`Buffer` \| [TransformableToBuffer](interfaces/transformabletobuffer.md) \| [PrefixedHexString](#prefixedhexstring) \| `number`_ 31 | 32 | _Defined in [types.ts:19](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L19)_ 33 | 34 | A Buffer, hex string prefixed with `0x`, Number, or an object with a toBuffer method such as BN. 35 | 36 | --- 37 | 38 | 39 | 40 | ### PrefixedHexString 41 | 42 | **Ƭ PrefixedHexString**: _`string`_ 43 | 44 | _Defined in [types.ts:14](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L14)_ 45 | 46 | A hex string prefixed with `0x`. 47 | 48 | --- 49 | -------------------------------------------------------------------------------- /docs/classes/faketransaction.md: -------------------------------------------------------------------------------- 1 | [ethereumjs-tx](../README.md) > [FakeTransaction](../classes/faketransaction.md) 2 | 3 | # Class: FakeTransaction 4 | 5 | Creates a new transaction object that doesn't need to be signed. 6 | 7 | _**param**_: A transaction can be initialized with its rlp representation, an array containing the value of its fields in order, or an object containing them by name. 8 | 9 | _**param**_: The transaction's options, used to indicate the chain and hardfork the transactions belongs to. 10 | 11 | _**see**_: Transaction 12 | 13 | ## Hierarchy 14 | 15 | [Transaction](transaction.md) 16 | 17 | **↳ FakeTransaction** 18 | 19 | ## Index 20 | 21 | ### Constructors 22 | 23 | - [constructor](faketransaction.md#constructor) 24 | 25 | ### Properties 26 | 27 | - [\_from](faketransaction.md#_from) 28 | - [data](faketransaction.md#data) 29 | - [from](faketransaction.md#from) 30 | - [gasLimit](faketransaction.md#gaslimit) 31 | - [gasPrice](faketransaction.md#gasprice) 32 | - [nonce](faketransaction.md#nonce) 33 | - [r](faketransaction.md#r) 34 | - [raw](faketransaction.md#raw) 35 | - [s](faketransaction.md#s) 36 | - [to](faketransaction.md#to) 37 | - [v](faketransaction.md#v) 38 | - [value](faketransaction.md#value) 39 | 40 | ### Methods 41 | 42 | - [getBaseFee](faketransaction.md#getbasefee) 43 | - [getChainId](faketransaction.md#getchainid) 44 | - [getDataFee](faketransaction.md#getdatafee) 45 | - [getSenderAddress](faketransaction.md#getsenderaddress) 46 | - [getSenderPublicKey](faketransaction.md#getsenderpublickey) 47 | - [getUpfrontCost](faketransaction.md#getupfrontcost) 48 | - [hash](faketransaction.md#hash) 49 | - [serialize](faketransaction.md#serialize) 50 | - [sign](faketransaction.md#sign) 51 | - [toCreationAddress](faketransaction.md#tocreationaddress) 52 | - [toJSON](faketransaction.md#tojson) 53 | - [validate](faketransaction.md#validate) 54 | - [verifySignature](faketransaction.md#verifysignature) 55 | 56 | --- 57 | 58 | ## Constructors 59 | 60 | 61 | 62 | ### constructor 63 | 64 | ⊕ **new FakeTransaction**(data?: _`Buffer` \| [PrefixedHexString](../#prefixedhexstring) \| [BufferLike](../#bufferlike)[] \| [FakeTxData](../interfaces/faketxdata.md)_, opts?: _[TransactionOptions](../interfaces/transactionoptions.md)_): [FakeTransaction](faketransaction.md) 65 | 66 | _Overrides [Transaction](transaction.md).[constructor](transaction.md#constructor)_ 67 | 68 | _Defined in [fake.ts:22](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/fake.ts#L22)_ 69 | 70 | **Parameters:** 71 | 72 | | Name | Type | Default value | 73 | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------- | 74 | | `Default value` data | `Buffer` \| [PrefixedHexString](../#prefixedhexstring) \| [BufferLike](../#bufferlike)[] \| [FakeTxData](../interfaces/faketxdata.md) | {} | 75 | | `Default value` opts | [TransactionOptions](../interfaces/transactionoptions.md) | {} | 76 | 77 | **Returns:** [FakeTransaction](faketransaction.md) 78 | 79 | --- 80 | 81 | ## Properties 82 | 83 | 84 | 85 | ### ` `` ` \_from 86 | 87 | **● \_from**: _`Buffer`_ 88 | 89 | _Inherited from [Transaction](transaction.md).[\_from](transaction.md#_from)_ 90 | 91 | _Defined in [transaction.ts:37](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L37)_ 92 | 93 | --- 94 | 95 | 96 | 97 | ### data 98 | 99 | **● data**: _`Buffer`_ 100 | 101 | _Inherited from [Transaction](transaction.md).[data](transaction.md#data)_ 102 | 103 | _Defined in [transaction.ts:30](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L30)_ 104 | 105 | --- 106 | 107 | 108 | 109 | ### from 110 | 111 | **● from**: _`Buffer`_ 112 | 113 | _Defined in [fake.ts:22](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/fake.ts#L22)_ 114 | 115 | Set from address to bypass transaction signing. This is not an optional property, as its getter never returns undefined. 116 | 117 | --- 118 | 119 | 120 | 121 | ### gasLimit 122 | 123 | **● gasLimit**: _`Buffer`_ 124 | 125 | _Inherited from [Transaction](transaction.md).[gasLimit](transaction.md#gaslimit)_ 126 | 127 | _Defined in [transaction.ts:26](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L26)_ 128 | 129 | --- 130 | 131 | 132 | 133 | ### gasPrice 134 | 135 | **● gasPrice**: _`Buffer`_ 136 | 137 | _Inherited from [Transaction](transaction.md).[gasPrice](transaction.md#gasprice)_ 138 | 139 | _Defined in [transaction.ts:27](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L27)_ 140 | 141 | --- 142 | 143 | 144 | 145 | ### nonce 146 | 147 | **● nonce**: _`Buffer`_ 148 | 149 | _Inherited from [Transaction](transaction.md).[nonce](transaction.md#nonce)_ 150 | 151 | _Defined in [transaction.ts:25](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L25)_ 152 | 153 | --- 154 | 155 | 156 | 157 | ### r 158 | 159 | **● r**: _`Buffer`_ 160 | 161 | _Inherited from [Transaction](transaction.md).[r](transaction.md#r)_ 162 | 163 | _Defined in [transaction.ts:32](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L32)_ 164 | 165 | --- 166 | 167 | 168 | 169 | ### raw 170 | 171 | **● raw**: _`Buffer`[]_ 172 | 173 | _Inherited from [Transaction](transaction.md).[raw](transaction.md#raw)_ 174 | 175 | _Defined in [transaction.ts:24](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L24)_ 176 | 177 | --- 178 | 179 | 180 | 181 | ### s 182 | 183 | **● s**: _`Buffer`_ 184 | 185 | _Inherited from [Transaction](transaction.md).[s](transaction.md#s)_ 186 | 187 | _Defined in [transaction.ts:33](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L33)_ 188 | 189 | --- 190 | 191 | 192 | 193 | ### to 194 | 195 | **● to**: _`Buffer`_ 196 | 197 | _Inherited from [Transaction](transaction.md).[to](transaction.md#to)_ 198 | 199 | _Defined in [transaction.ts:28](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L28)_ 200 | 201 | --- 202 | 203 | 204 | 205 | ### v 206 | 207 | **● v**: _`Buffer`_ 208 | 209 | _Inherited from [Transaction](transaction.md).[v](transaction.md#v)_ 210 | 211 | _Defined in [transaction.ts:31](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L31)_ 212 | 213 | --- 214 | 215 | 216 | 217 | ### value 218 | 219 | **● value**: _`Buffer`_ 220 | 221 | _Inherited from [Transaction](transaction.md).[value](transaction.md#value)_ 222 | 223 | _Defined in [transaction.ts:29](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L29)_ 224 | 225 | --- 226 | 227 | ## Methods 228 | 229 | 230 | 231 | ### getBaseFee 232 | 233 | ▸ **getBaseFee**(): `BN` 234 | 235 | _Inherited from [Transaction](transaction.md).[getBaseFee](transaction.md#getbasefee)_ 236 | 237 | _Defined in [transaction.ts:296](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L296)_ 238 | 239 | the minimum amount of gas the tx must have (DataFee + TxFee + Creation Fee) 240 | 241 | **Returns:** `BN` 242 | 243 | --- 244 | 245 | 246 | 247 | ### getChainId 248 | 249 | ▸ **getChainId**(): `number` 250 | 251 | _Inherited from [Transaction](transaction.md).[getChainId](transaction.md#getchainid)_ 252 | 253 | _Defined in [transaction.ts:202](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L202)_ 254 | 255 | returns chain ID 256 | 257 | **Returns:** `number` 258 | 259 | --- 260 | 261 | 262 | 263 | ### getDataFee 264 | 265 | ▸ **getDataFee**(): `BN` 266 | 267 | _Inherited from [Transaction](transaction.md).[getDataFee](transaction.md#getdatafee)_ 268 | 269 | _Defined in [transaction.ts:282](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L282)_ 270 | 271 | The amount of gas paid for the data in this tx 272 | 273 | **Returns:** `BN` 274 | 275 | --- 276 | 277 | 278 | 279 | ### getSenderAddress 280 | 281 | ▸ **getSenderAddress**(): `Buffer` 282 | 283 | _Inherited from [Transaction](transaction.md).[getSenderAddress](transaction.md#getsenderaddress)_ 284 | 285 | _Defined in [transaction.ts:209](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L209)_ 286 | 287 | returns the sender's address 288 | 289 | **Returns:** `Buffer` 290 | 291 | --- 292 | 293 | 294 | 295 | ### getSenderPublicKey 296 | 297 | ▸ **getSenderPublicKey**(): `Buffer` 298 | 299 | _Inherited from [Transaction](transaction.md).[getSenderPublicKey](transaction.md#getsenderpublickey)_ 300 | 301 | _Defined in [transaction.ts:221](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L221)_ 302 | 303 | returns the public key of the sender 304 | 305 | **Returns:** `Buffer` 306 | 307 | --- 308 | 309 | 310 | 311 | ### getUpfrontCost 312 | 313 | ▸ **getUpfrontCost**(): `BN` 314 | 315 | _Inherited from [Transaction](transaction.md).[getUpfrontCost](transaction.md#getupfrontcost)_ 316 | 317 | _Defined in [transaction.ts:307](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L307)_ 318 | 319 | the up front amount that an account must have for this transaction to be valid 320 | 321 | **Returns:** `BN` 322 | 323 | --- 324 | 325 | 326 | 327 | ### hash 328 | 329 | ▸ **hash**(includeSignature?: _`boolean`_): `Buffer` 330 | 331 | _Overrides [Transaction](transaction.md).[hash](transaction.md#hash)_ 332 | 333 | _Defined in [fake.ts:53](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/fake.ts#L53)_ 334 | 335 | Computes a sha3-256 hash of the serialized tx, using the sender address to generate a fake signature. 336 | 337 | **Parameters:** 338 | 339 | | Name | Type | Default value | Description | 340 | | -------------------------------- | --------- | ------------- | --------------------------------------- | 341 | | `Default value` includeSignature | `boolean` | true | Whether or not to include the signature | 342 | 343 | **Returns:** `Buffer` 344 | 345 | --- 346 | 347 | 348 | 349 | ### serialize 350 | 351 | ▸ **serialize**(): `Buffer` 352 | 353 | _Inherited from [Transaction](transaction.md).[serialize](transaction.md#serialize)_ 354 | 355 | _Defined in [transaction.ts:337](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L337)_ 356 | 357 | Returns the rlp encoding of the transaction 358 | 359 | **Returns:** `Buffer` 360 | 361 | --- 362 | 363 | 364 | 365 | ### sign 366 | 367 | ▸ **sign**(privateKey: _`Buffer`_): `void` 368 | 369 | _Inherited from [Transaction](transaction.md).[sign](transaction.md#sign)_ 370 | 371 | _Defined in [transaction.ts:262](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L262)_ 372 | 373 | sign a transaction with a given private key 374 | 375 | **Parameters:** 376 | 377 | | Name | Type | Description | 378 | | ---------- | -------- | -------------------------- | 379 | | privateKey | `Buffer` | Must be 32 bytes in length | 380 | 381 | **Returns:** `void` 382 | 383 | --- 384 | 385 | 386 | 387 | ### toCreationAddress 388 | 389 | ▸ **toCreationAddress**(): `boolean` 390 | 391 | _Inherited from [Transaction](transaction.md).[toCreationAddress](transaction.md#tocreationaddress)_ 392 | 393 | _Defined in [transaction.ts:169](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L169)_ 394 | 395 | If the tx's `to` is to the creation address 396 | 397 | **Returns:** `boolean` 398 | 399 | --- 400 | 401 | 402 | 403 | ### toJSON 404 | 405 | ▸ **toJSON**(labels?: _`boolean`_): `object` \| `string`[] 406 | 407 | _Inherited from [Transaction](transaction.md).[toJSON](transaction.md#tojson)_ 408 | 409 | _Defined in [transaction.ts:346](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L346)_ 410 | 411 | Returns the transaction in JSON format 412 | 413 | _**see**_: [ethereumjs-util](https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/index.md#defineproperties) 414 | 415 | **Parameters:** 416 | 417 | | Name | Type | Default value | 418 | | ---------------------- | --------- | ------------- | 419 | | `Default value` labels | `boolean` | false | 420 | 421 | **Returns:** `object` \| `string`[] 422 | 423 | --- 424 | 425 | 426 | 427 | ### validate 428 | 429 | ▸ **validate**(): `boolean` 430 | 431 | ▸ **validate**(stringError: _`false`_): `boolean` 432 | 433 | ▸ **validate**(stringError: _`true`_): `string` 434 | 435 | _Inherited from [Transaction](transaction.md).[validate](transaction.md#validate)_ 436 | 437 | _Defined in [transaction.ts:314](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L314)_ 438 | 439 | Validates the signature and checks to see if it has enough gas. 440 | 441 | **Returns:** `boolean` 442 | 443 | _Inherited from [Transaction](transaction.md).[validate](transaction.md#validate)_ 444 | 445 | _Defined in [transaction.ts:315](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L315)_ 446 | 447 | **Parameters:** 448 | 449 | | Name | Type | 450 | | ----------- | ------- | 451 | | stringError | `false` | 452 | 453 | **Returns:** `boolean` 454 | 455 | _Inherited from [Transaction](transaction.md).[validate](transaction.md#validate)_ 456 | 457 | _Defined in [transaction.ts:316](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L316)_ 458 | 459 | **Parameters:** 460 | 461 | | Name | Type | 462 | | ----------- | ------ | 463 | | stringError | `true` | 464 | 465 | **Returns:** `string` 466 | 467 | --- 468 | 469 | 470 | 471 | ### verifySignature 472 | 473 | ▸ **verifySignature**(): `boolean` 474 | 475 | _Inherited from [Transaction](transaction.md).[verifySignature](transaction.md#verifysignature)_ 476 | 477 | _Defined in [transaction.ts:233](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L233)_ 478 | 479 | Determines if the signature is valid 480 | 481 | **Returns:** `boolean` 482 | 483 | --- 484 | -------------------------------------------------------------------------------- /docs/classes/transaction.md: -------------------------------------------------------------------------------- 1 | [ethereumjs-tx](../README.md) > [Transaction](../classes/transaction.md) 2 | 3 | # Class: Transaction 4 | 5 | An Ethereum transaction. 6 | 7 | ## Hierarchy 8 | 9 | **Transaction** 10 | 11 | ↳ [FakeTransaction](faketransaction.md) 12 | 13 | ## Index 14 | 15 | ### Constructors 16 | 17 | - [constructor](transaction.md#constructor) 18 | 19 | ### Properties 20 | 21 | - [\_common](transaction.md#_common) 22 | - [\_from](transaction.md#_from) 23 | - [\_senderPubKey](transaction.md#_senderpubkey) 24 | - [data](transaction.md#data) 25 | - [gasLimit](transaction.md#gaslimit) 26 | - [gasPrice](transaction.md#gasprice) 27 | - [nonce](transaction.md#nonce) 28 | - [r](transaction.md#r) 29 | - [raw](transaction.md#raw) 30 | - [s](transaction.md#s) 31 | - [to](transaction.md#to) 32 | - [v](transaction.md#v) 33 | - [value](transaction.md#value) 34 | 35 | ### Methods 36 | 37 | - [\_implementsEIP155](transaction.md#_implementseip155) 38 | - [\_isSigned](transaction.md#_issigned) 39 | - [\_overrideVSetterWithValidation](transaction.md#_overridevsetterwithvalidation) 40 | - [\_validateV](transaction.md#_validatev) 41 | - [getBaseFee](transaction.md#getbasefee) 42 | - [getChainId](transaction.md#getchainid) 43 | - [getDataFee](transaction.md#getdatafee) 44 | - [getSenderAddress](transaction.md#getsenderaddress) 45 | - [getSenderPublicKey](transaction.md#getsenderpublickey) 46 | - [getUpfrontCost](transaction.md#getupfrontcost) 47 | - [hash](transaction.md#hash) 48 | - [serialize](transaction.md#serialize) 49 | - [sign](transaction.md#sign) 50 | - [toCreationAddress](transaction.md#tocreationaddress) 51 | - [toJSON](transaction.md#tojson) 52 | - [validate](transaction.md#validate) 53 | - [verifySignature](transaction.md#verifysignature) 54 | 55 | --- 56 | 57 | ## Constructors 58 | 59 | 60 | 61 | ### constructor 62 | 63 | ⊕ **new Transaction**(data?: _`Buffer` \| [PrefixedHexString](../#prefixedhexstring) \| [BufferLike](../#bufferlike)[] \| [TxData](../interfaces/txdata.md)_, opts?: _[TransactionOptions](../interfaces/transactionoptions.md)_): [Transaction](transaction.md) 64 | 65 | _Defined in [transaction.ts:37](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L37)_ 66 | 67 | Creates a new transaction from an object with its fields' values. 68 | 69 | _**note**_: Transaction objects implement EIP155 by default. To disable it, use the constructor's second parameter to set a chain and hardfork before EIP155 activation (i.e. before Spurious Dragon.) 70 | 71 | _**example**_: 72 | 73 | ```js 74 | const txData = { 75 | nonce: '0x00', 76 | gasPrice: '0x09184e72a000', 77 | gasLimit: '0x2710', 78 | to: '0x0000000000000000000000000000000000000000', 79 | value: '0x00', 80 | data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057', 81 | v: '0x1c', 82 | r: '0x5e1d3a76fbf824220eafc8c79ad578ad2b67d01b0c2425eb1f1347e8f50882ab', 83 | s: '0x5bd428537f05f9830e93792f90ea6a3e2d1ee84952dd96edbae9f658f831ab13', 84 | } 85 | const tx = new Transaction(txData) 86 | ``` 87 | 88 | **Parameters:** 89 | 90 | | Name | Type | Default value | Description | 91 | | -------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | 92 | | `Default value` data | `Buffer` \| [PrefixedHexString](../#prefixedhexstring) \| [BufferLike](../#bufferlike)[] \| [TxData](../interfaces/txdata.md) | {} | A transaction can be initialized with its rlp representation, an array containing the value of its fields in order, or an object containing them by name. | 93 | | `Default value` opts | [TransactionOptions](../interfaces/transactionoptions.md) | {} | The transaction's options, used to indicate the chain and hardfork the transactions belongs to. | 94 | 95 | **Returns:** [Transaction](transaction.md) 96 | 97 | --- 98 | 99 | ## Properties 100 | 101 | 102 | 103 | ### `` \_common 104 | 105 | **● \_common**: _`Common`_ 106 | 107 | _Defined in [transaction.ts:35](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L35)_ 108 | 109 | --- 110 | 111 | 112 | 113 | ### ` `` ` \_from 114 | 115 | **● \_from**: _`Buffer`_ 116 | 117 | _Defined in [transaction.ts:37](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L37)_ 118 | 119 | --- 120 | 121 | 122 | 123 | ### ` `` ` \_senderPubKey 124 | 125 | **● \_senderPubKey**: _`Buffer`_ 126 | 127 | _Defined in [transaction.ts:36](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L36)_ 128 | 129 | --- 130 | 131 | 132 | 133 | ### data 134 | 135 | **● data**: _`Buffer`_ 136 | 137 | _Defined in [transaction.ts:30](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L30)_ 138 | 139 | --- 140 | 141 | 142 | 143 | ### gasLimit 144 | 145 | **● gasLimit**: _`Buffer`_ 146 | 147 | _Defined in [transaction.ts:26](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L26)_ 148 | 149 | --- 150 | 151 | 152 | 153 | ### gasPrice 154 | 155 | **● gasPrice**: _`Buffer`_ 156 | 157 | _Defined in [transaction.ts:27](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L27)_ 158 | 159 | --- 160 | 161 | 162 | 163 | ### nonce 164 | 165 | **● nonce**: _`Buffer`_ 166 | 167 | _Defined in [transaction.ts:25](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L25)_ 168 | 169 | --- 170 | 171 | 172 | 173 | ### r 174 | 175 | **● r**: _`Buffer`_ 176 | 177 | _Defined in [transaction.ts:32](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L32)_ 178 | 179 | --- 180 | 181 | 182 | 183 | ### raw 184 | 185 | **● raw**: _`Buffer`[]_ 186 | 187 | _Defined in [transaction.ts:24](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L24)_ 188 | 189 | --- 190 | 191 | 192 | 193 | ### s 194 | 195 | **● s**: _`Buffer`_ 196 | 197 | _Defined in [transaction.ts:33](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L33)_ 198 | 199 | --- 200 | 201 | 202 | 203 | ### to 204 | 205 | **● to**: _`Buffer`_ 206 | 207 | _Defined in [transaction.ts:28](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L28)_ 208 | 209 | --- 210 | 211 | 212 | 213 | ### v 214 | 215 | **● v**: _`Buffer`_ 216 | 217 | _Defined in [transaction.ts:31](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L31)_ 218 | 219 | --- 220 | 221 | 222 | 223 | ### value 224 | 225 | **● value**: _`Buffer`_ 226 | 227 | _Defined in [transaction.ts:29](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L29)_ 228 | 229 | --- 230 | 231 | ## Methods 232 | 233 | 234 | 235 | ### `` \_implementsEIP155 236 | 237 | ▸ **\_implementsEIP155**(): `boolean` 238 | 239 | _Defined in [transaction.ts:395](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L395)_ 240 | 241 | **Returns:** `boolean` 242 | 243 | --- 244 | 245 | 246 | 247 | ### `` \_isSigned 248 | 249 | ▸ **\_isSigned**(): `boolean` 250 | 251 | _Defined in [transaction.ts:376](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L376)_ 252 | 253 | **Returns:** `boolean` 254 | 255 | --- 256 | 257 | 258 | 259 | ### `` \_overrideVSetterWithValidation 260 | 261 | ▸ **\_overrideVSetterWithValidation**(): `void` 262 | 263 | _Defined in [transaction.ts:380](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L380)_ 264 | 265 | **Returns:** `void` 266 | 267 | --- 268 | 269 | 270 | 271 | ### `` \_validateV 272 | 273 | ▸ **\_validateV**(v?: _`Buffer`_): `void` 274 | 275 | _Defined in [transaction.ts:351](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L351)_ 276 | 277 | **Parameters:** 278 | 279 | | Name | Type | 280 | | ------------ | -------- | 281 | | `Optional` v | `Buffer` | 282 | 283 | **Returns:** `void` 284 | 285 | --- 286 | 287 | 288 | 289 | ### getBaseFee 290 | 291 | ▸ **getBaseFee**(): `BN` 292 | 293 | _Defined in [transaction.ts:296](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L296)_ 294 | 295 | the minimum amount of gas the tx must have (DataFee + TxFee + Creation Fee) 296 | 297 | **Returns:** `BN` 298 | 299 | --- 300 | 301 | 302 | 303 | ### getChainId 304 | 305 | ▸ **getChainId**(): `number` 306 | 307 | _Defined in [transaction.ts:202](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L202)_ 308 | 309 | returns chain ID 310 | 311 | **Returns:** `number` 312 | 313 | --- 314 | 315 | 316 | 317 | ### getDataFee 318 | 319 | ▸ **getDataFee**(): `BN` 320 | 321 | _Defined in [transaction.ts:282](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L282)_ 322 | 323 | The amount of gas paid for the data in this tx 324 | 325 | **Returns:** `BN` 326 | 327 | --- 328 | 329 | 330 | 331 | ### getSenderAddress 332 | 333 | ▸ **getSenderAddress**(): `Buffer` 334 | 335 | _Defined in [transaction.ts:209](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L209)_ 336 | 337 | returns the sender's address 338 | 339 | **Returns:** `Buffer` 340 | 341 | --- 342 | 343 | 344 | 345 | ### getSenderPublicKey 346 | 347 | ▸ **getSenderPublicKey**(): `Buffer` 348 | 349 | _Defined in [transaction.ts:221](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L221)_ 350 | 351 | returns the public key of the sender 352 | 353 | **Returns:** `Buffer` 354 | 355 | --- 356 | 357 | 358 | 359 | ### getUpfrontCost 360 | 361 | ▸ **getUpfrontCost**(): `BN` 362 | 363 | _Defined in [transaction.ts:307](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L307)_ 364 | 365 | the up front amount that an account must have for this transaction to be valid 366 | 367 | **Returns:** `BN` 368 | 369 | --- 370 | 371 | 372 | 373 | ### hash 374 | 375 | ▸ **hash**(includeSignature?: _`boolean`_): `Buffer` 376 | 377 | _Defined in [transaction.ts:177](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L177)_ 378 | 379 | Computes a sha3-256 hash of the serialized tx 380 | 381 | **Parameters:** 382 | 383 | | Name | Type | Default value | Description | 384 | | -------------------------------- | --------- | ------------- | --------------------------------------- | 385 | | `Default value` includeSignature | `boolean` | true | Whether or not to include the signature | 386 | 387 | **Returns:** `Buffer` 388 | 389 | --- 390 | 391 | 392 | 393 | ### serialize 394 | 395 | ▸ **serialize**(): `Buffer` 396 | 397 | _Defined in [transaction.ts:337](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L337)_ 398 | 399 | Returns the rlp encoding of the transaction 400 | 401 | **Returns:** `Buffer` 402 | 403 | --- 404 | 405 | 406 | 407 | ### sign 408 | 409 | ▸ **sign**(privateKey: _`Buffer`_): `void` 410 | 411 | _Defined in [transaction.ts:262](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L262)_ 412 | 413 | sign a transaction with a given private key 414 | 415 | **Parameters:** 416 | 417 | | Name | Type | Description | 418 | | ---------- | -------- | -------------------------- | 419 | | privateKey | `Buffer` | Must be 32 bytes in length | 420 | 421 | **Returns:** `void` 422 | 423 | --- 424 | 425 | 426 | 427 | ### toCreationAddress 428 | 429 | ▸ **toCreationAddress**(): `boolean` 430 | 431 | _Defined in [transaction.ts:169](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L169)_ 432 | 433 | If the tx's `to` is to the creation address 434 | 435 | **Returns:** `boolean` 436 | 437 | --- 438 | 439 | 440 | 441 | ### toJSON 442 | 443 | ▸ **toJSON**(labels?: _`boolean`_): `object` \| `string`[] 444 | 445 | _Defined in [transaction.ts:346](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L346)_ 446 | 447 | Returns the transaction in JSON format 448 | 449 | _**see**_: [ethereumjs-util](https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/index.md#defineproperties) 450 | 451 | **Parameters:** 452 | 453 | | Name | Type | Default value | 454 | | ---------------------- | --------- | ------------- | 455 | | `Default value` labels | `boolean` | false | 456 | 457 | **Returns:** `object` \| `string`[] 458 | 459 | --- 460 | 461 | 462 | 463 | ### validate 464 | 465 | ▸ **validate**(): `boolean` 466 | 467 | ▸ **validate**(stringError: _`false`_): `boolean` 468 | 469 | ▸ **validate**(stringError: _`true`_): `string` 470 | 471 | _Defined in [transaction.ts:314](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L314)_ 472 | 473 | Validates the signature and checks to see if it has enough gas. 474 | 475 | **Returns:** `boolean` 476 | 477 | _Defined in [transaction.ts:315](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L315)_ 478 | 479 | **Parameters:** 480 | 481 | | Name | Type | 482 | | ----------- | ------- | 483 | | stringError | `false` | 484 | 485 | **Returns:** `boolean` 486 | 487 | _Defined in [transaction.ts:316](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L316)_ 488 | 489 | **Parameters:** 490 | 491 | | Name | Type | 492 | | ----------- | ------ | 493 | | stringError | `true` | 494 | 495 | **Returns:** `string` 496 | 497 | --- 498 | 499 | 500 | 501 | ### verifySignature 502 | 503 | ▸ **verifySignature**(): `boolean` 504 | 505 | _Defined in [transaction.ts:233](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/transaction.ts#L233)_ 506 | 507 | Determines if the signature is valid 508 | 509 | **Returns:** `boolean` 510 | 511 | --- 512 | -------------------------------------------------------------------------------- /docs/interfaces/faketxdata.md: -------------------------------------------------------------------------------- 1 | [ethereumjs-tx](../README.md) > [FakeTxData](../interfaces/faketxdata.md) 2 | 3 | # Interface: FakeTxData 4 | 5 | The data of a fake (self-signing) transaction. 6 | 7 | ## Hierarchy 8 | 9 | [TxData](txdata.md) 10 | 11 | **↳ FakeTxData** 12 | 13 | ## Index 14 | 15 | ### Properties 16 | 17 | - [data](faketxdata.md#data) 18 | - [from](faketxdata.md#from) 19 | - [gasLimit](faketxdata.md#gaslimit) 20 | - [gasPrice](faketxdata.md#gasprice) 21 | - [nonce](faketxdata.md#nonce) 22 | - [r](faketxdata.md#r) 23 | - [s](faketxdata.md#s) 24 | - [to](faketxdata.md#to) 25 | - [v](faketxdata.md#v) 26 | - [value](faketxdata.md#value) 27 | 28 | --- 29 | 30 | ## Properties 31 | 32 | 33 | 34 | ### `` data 35 | 36 | **● data**: _[BufferLike](../#bufferlike)_ 37 | 38 | _Inherited from [TxData](txdata.md).[data](txdata.md#data)_ 39 | 40 | _Defined in [types.ts:48](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L48)_ 41 | 42 | This will contain the data of the message or the init of a contract 43 | 44 | --- 45 | 46 | 47 | 48 | ### `` from 49 | 50 | **● from**: _[BufferLike](../#bufferlike)_ 51 | 52 | _Defined in [types.ts:78](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L78)_ 53 | 54 | The sender of the Tx. 55 | 56 | --- 57 | 58 | 59 | 60 | ### `` gasLimit 61 | 62 | **● gasLimit**: _[BufferLike](../#bufferlike)_ 63 | 64 | _Inherited from [TxData](txdata.md).[gasLimit](txdata.md#gaslimit)_ 65 | 66 | _Defined in [types.ts:28](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L28)_ 67 | 68 | The transaction's gas limit. 69 | 70 | --- 71 | 72 | 73 | 74 | ### `` gasPrice 75 | 76 | **● gasPrice**: _[BufferLike](../#bufferlike)_ 77 | 78 | _Inherited from [TxData](txdata.md).[gasPrice](txdata.md#gasprice)_ 79 | 80 | _Defined in [types.ts:33](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L33)_ 81 | 82 | The transaction's gas price. 83 | 84 | --- 85 | 86 | 87 | 88 | ### `` nonce 89 | 90 | **● nonce**: _[BufferLike](../#bufferlike)_ 91 | 92 | _Inherited from [TxData](txdata.md).[nonce](txdata.md#nonce)_ 93 | 94 | _Defined in [types.ts:43](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L43)_ 95 | 96 | The transaction's nonce. 97 | 98 | --- 99 | 100 | 101 | 102 | ### `` r 103 | 104 | **● r**: _[BufferLike](../#bufferlike)_ 105 | 106 | _Inherited from [TxData](txdata.md).[r](txdata.md#r)_ 107 | 108 | _Defined in [types.ts:58](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L58)_ 109 | 110 | EC signature parameter. 111 | 112 | --- 113 | 114 | 115 | 116 | ### `` s 117 | 118 | **● s**: _[BufferLike](../#bufferlike)_ 119 | 120 | _Inherited from [TxData](txdata.md).[s](txdata.md#s)_ 121 | 122 | _Defined in [types.ts:63](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L63)_ 123 | 124 | EC signature parameter. 125 | 126 | --- 127 | 128 | 129 | 130 | ### `` to 131 | 132 | **● to**: _[BufferLike](../#bufferlike)_ 133 | 134 | _Inherited from [TxData](txdata.md).[to](txdata.md#to)_ 135 | 136 | _Defined in [types.ts:38](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L38)_ 137 | 138 | The transaction's the address is sent to. 139 | 140 | --- 141 | 142 | 143 | 144 | ### `` v 145 | 146 | **● v**: _[BufferLike](../#bufferlike)_ 147 | 148 | _Inherited from [TxData](txdata.md).[v](txdata.md#v)_ 149 | 150 | _Defined in [types.ts:53](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L53)_ 151 | 152 | EC recovery ID. 153 | 154 | --- 155 | 156 | 157 | 158 | ### `` value 159 | 160 | **● value**: _[BufferLike](../#bufferlike)_ 161 | 162 | _Inherited from [TxData](txdata.md).[value](txdata.md#value)_ 163 | 164 | _Defined in [types.ts:68](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L68)_ 165 | 166 | The amount of Ether sent. 167 | 168 | --- 169 | -------------------------------------------------------------------------------- /docs/interfaces/transactionoptions.md: -------------------------------------------------------------------------------- 1 | [ethereumjs-tx](../README.md) > [TransactionOptions](../interfaces/transactionoptions.md) 2 | 3 | # Interface: TransactionOptions 4 | 5 | The transaction's options. This could be specified using a Common object, or `chain` and `hardfork`. Defaults to mainnet. 6 | 7 | ## Hierarchy 8 | 9 | **TransactionOptions** 10 | 11 | ## Index 12 | 13 | ### Properties 14 | 15 | - [chain](transactionoptions.md#chain) 16 | - [common](transactionoptions.md#common) 17 | - [hardfork](transactionoptions.md#hardfork) 18 | 19 | --- 20 | 21 | ## Properties 22 | 23 | 24 | 25 | ### `` chain 26 | 27 | **● chain**: _`number` \| `string`_ 28 | 29 | _Defined in [types.ts:94](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L94)_ 30 | 31 | The chain of the transaction, default: 'mainnet' 32 | 33 | --- 34 | 35 | 36 | 37 | ### `` common 38 | 39 | **● common**: _`Common`_ 40 | 41 | _Defined in [types.ts:89](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L89)_ 42 | 43 | A Common object defining the chain and the hardfork a transaction belongs to. 44 | 45 | --- 46 | 47 | 48 | 49 | ### `` hardfork 50 | 51 | **● hardfork**: _`undefined` \| `string`_ 52 | 53 | _Defined in [types.ts:99](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L99)_ 54 | 55 | The hardfork of the transaction, default: 'petersburg' 56 | 57 | --- 58 | -------------------------------------------------------------------------------- /docs/interfaces/transformabletobuffer.md: -------------------------------------------------------------------------------- 1 | [ethereumjs-tx](../README.md) > [TransformableToBuffer](../interfaces/transformabletobuffer.md) 2 | 3 | # Interface: TransformableToBuffer 4 | 5 | Any object that can be transformed into a `Buffer` 6 | 7 | ## Hierarchy 8 | 9 | **TransformableToBuffer** 10 | 11 | ## Index 12 | 13 | ### Methods 14 | 15 | - [toBuffer](transformabletobuffer.md#tobuffer) 16 | 17 | --- 18 | 19 | ## Methods 20 | 21 | 22 | 23 | ### toBuffer 24 | 25 | ▸ **toBuffer**(): `Buffer` 26 | 27 | _Defined in [types.ts:8](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L8)_ 28 | 29 | **Returns:** `Buffer` 30 | 31 | --- 32 | -------------------------------------------------------------------------------- /docs/interfaces/txdata.md: -------------------------------------------------------------------------------- 1 | [ethereumjs-tx](../README.md) > [TxData](../interfaces/txdata.md) 2 | 3 | # Interface: TxData 4 | 5 | A transaction's data. 6 | 7 | ## Hierarchy 8 | 9 | **TxData** 10 | 11 | ↳ [FakeTxData](faketxdata.md) 12 | 13 | ## Index 14 | 15 | ### Properties 16 | 17 | - [data](txdata.md#data) 18 | - [gasLimit](txdata.md#gaslimit) 19 | - [gasPrice](txdata.md#gasprice) 20 | - [nonce](txdata.md#nonce) 21 | - [r](txdata.md#r) 22 | - [s](txdata.md#s) 23 | - [to](txdata.md#to) 24 | - [v](txdata.md#v) 25 | - [value](txdata.md#value) 26 | 27 | --- 28 | 29 | ## Properties 30 | 31 | 32 | 33 | ### `` data 34 | 35 | **● data**: _[BufferLike](../#bufferlike)_ 36 | 37 | _Defined in [types.ts:48](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L48)_ 38 | 39 | This will contain the data of the message or the init of a contract 40 | 41 | --- 42 | 43 | 44 | 45 | ### `` gasLimit 46 | 47 | **● gasLimit**: _[BufferLike](../#bufferlike)_ 48 | 49 | _Defined in [types.ts:28](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L28)_ 50 | 51 | The transaction's gas limit. 52 | 53 | --- 54 | 55 | 56 | 57 | ### `` gasPrice 58 | 59 | **● gasPrice**: _[BufferLike](../#bufferlike)_ 60 | 61 | _Defined in [types.ts:33](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L33)_ 62 | 63 | The transaction's gas price. 64 | 65 | --- 66 | 67 | 68 | 69 | ### `` nonce 70 | 71 | **● nonce**: _[BufferLike](../#bufferlike)_ 72 | 73 | _Defined in [types.ts:43](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L43)_ 74 | 75 | The transaction's nonce. 76 | 77 | --- 78 | 79 | 80 | 81 | ### `` r 82 | 83 | **● r**: _[BufferLike](../#bufferlike)_ 84 | 85 | _Defined in [types.ts:58](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L58)_ 86 | 87 | EC signature parameter. 88 | 89 | --- 90 | 91 | 92 | 93 | ### `` s 94 | 95 | **● s**: _[BufferLike](../#bufferlike)_ 96 | 97 | _Defined in [types.ts:63](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L63)_ 98 | 99 | EC signature parameter. 100 | 101 | --- 102 | 103 | 104 | 105 | ### `` to 106 | 107 | **● to**: _[BufferLike](../#bufferlike)_ 108 | 109 | _Defined in [types.ts:38](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L38)_ 110 | 111 | The transaction's the address is sent to. 112 | 113 | --- 114 | 115 | 116 | 117 | ### `` v 118 | 119 | **● v**: _[BufferLike](../#bufferlike)_ 120 | 121 | _Defined in [types.ts:53](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L53)_ 122 | 123 | EC recovery ID. 124 | 125 | --- 126 | 127 | 128 | 129 | ### `` value 130 | 131 | **● value**: _[BufferLike](../#bufferlike)_ 132 | 133 | _Defined in [types.ts:68](https://github.com/ethereumjs/ethereumjs-tx/blob/5c81b38/src/types.ts#L68)_ 134 | 135 | The amount of Ether sent. 136 | 137 | --- 138 | -------------------------------------------------------------------------------- /examples/custom-chain-tx.ts: -------------------------------------------------------------------------------- 1 | import { Transaction } from '../src' 2 | import Common from 'ethereumjs-common' 3 | import { bufferToHex, privateToAddress } from 'ethereumjs-util' 4 | 5 | // In this example we create a transaction for a custom network. 6 | // 7 | // All of these network's params are the same than mainnets', except for name, chainId, and 8 | // networkId, so we use the Common.forCustomChain method. 9 | const customCommon = Common.forCustomChain( 10 | 'mainnet', 11 | { 12 | name: 'my-network', 13 | networkId: 123, 14 | chainId: 2134, 15 | }, 16 | 'petersburg', 17 | ) 18 | 19 | // We pass our custom Common object whenever we create a transaction 20 | 21 | const tx = new Transaction( 22 | { 23 | nonce: 0, 24 | gasPrice: 100, 25 | gasLimit: 1000000000, 26 | value: 100000, 27 | }, 28 | { common: customCommon }, 29 | ) 30 | 31 | // Once we created the transaction using the custom Common object, we can use it as a normal tx. 32 | 33 | // Here we sign it and validate its signature 34 | const privateKey = new Buffer( 35 | 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 36 | 'hex', 37 | ) 38 | 39 | tx.sign(privateKey) 40 | 41 | if ( 42 | tx.validate() && 43 | bufferToHex(tx.getSenderAddress()) === bufferToHex(privateToAddress(privateKey)) 44 | ) { 45 | console.log('Valid signature') 46 | } else { 47 | console.log('Invalid signature') 48 | } 49 | 50 | console.log("The transaction's chain id is", tx.getChainId()) 51 | -------------------------------------------------------------------------------- /examples/ropsten-tx.ts: -------------------------------------------------------------------------------- 1 | import { Transaction } from '../src' 2 | import { bufferToHex } from 'ethereumjs-util' 3 | 4 | const tx = new Transaction( 5 | '0xf9010b82930284d09dc30083419ce0942d18de92e0f9aee1a29770c3b15c6cf8ac5498e580b8a42f43f4fb0000000000000000000000000000000000000000000000000000016b78998da900000000000000000000000000000000000000000000000000000000000cb1b70000000000000000000000000000000000000000000000000000000000000fa00000000000000000000000000000000000000000000000000000000001363e4f00000000000000000000000000000000000000000000000000000000000186a029a0fac36e66d329af0e831b2e61179b3ec8d7c7a8a2179e303cfed3364aff2bc3e4a07cb73d56e561ccbd838818dd3dea5fa0b5158577ffc61c0e6ec1f0ed55716891', 6 | { chain: 'ropsten', hardfork: 'petersburg' }, 7 | ) 8 | 9 | if ( 10 | tx.validate() && 11 | bufferToHex(tx.getSenderAddress()) === '0x9dfd2d2b2ed960923f7bf2e8883d73f213f3b24b' 12 | ) { 13 | console.log('Correctly created the tx') 14 | } else { 15 | console.error('Invalid tx') 16 | } 17 | -------------------------------------------------------------------------------- /examples/transactions.ts: -------------------------------------------------------------------------------- 1 | // This files contain examples on how to use this module. You can run them with ts-node, as this 2 | // project is developed in typescript. Install the dependencies and run `npx ts-node examples/transactions.ts` 3 | 4 | import { Transaction } from '../src' 5 | 6 | // We create an unsigned transaction. 7 | // Notice we don't set the `to` field because we are creating a new contract. 8 | // This transaction's chain is set to mainnet 9 | const tx = new Transaction({ 10 | nonce: 0, 11 | gasPrice: 100, 12 | gasLimit: 1000000000, 13 | value: 0, 14 | data: 15 | '0x7f4e616d65526567000000000000000000000000000000000000000000000000003057307f4e616d6552656700000000000000000000000000000000000000000000000000573360455760415160566000396000f20036602259604556330e0f600f5933ff33560f601e5960003356576000335700604158600035560f602b590033560f60365960003356573360003557600035335700', 16 | }) 17 | 18 | // We sign the transaction with this private key 19 | const privateKey = new Buffer( 20 | 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 21 | 'hex', 22 | ) 23 | tx.sign(privateKey) 24 | 25 | // We have a signed transaction, Now for it to be fully fundable the account that we signed 26 | // it with needs to have a certain amount of wei in to. To see how much this 27 | // account needs we can use the getUpfrontCost() method. 28 | const feeCost = tx.getUpfrontCost() 29 | console.log('Total Amount of wei needed:' + feeCost.toString()) 30 | 31 | // Lets serialize the transaction 32 | 33 | console.log('---Serialized TX----') 34 | console.log(tx.serialize().toString('hex')) 35 | console.log('--------------------') 36 | 37 | // Parsing & Validating transactions 38 | // If you have a transaction that you want to verify you can parse it. If you got 39 | // it directly from the network it will be rlp encoded. You can decode it with the rlp 40 | // module. After that you should have something like: 41 | const rawTx = [ 42 | '0x00', 43 | '0x09184e72a000', 44 | '0x2710', 45 | '0x0000000000000000000000000000000000000000', 46 | '0x00', 47 | '0x7f7465737432000000000000000000000000000000000000000000000000000000600057', 48 | '0x1c', 49 | '0x5e1d3a76fbf824220eafc8c79ad578ad2b67d01b0c2425eb1f1347e8f50882ab', 50 | '0x5bd428537f05f9830e93792f90ea6a3e2d1ee84952dd96edbae9f658f831ab13', 51 | ] 52 | 53 | const tx2 = new Transaction(rawTx) // This is also a maninnet transaction 54 | 55 | // Note rlp.decode will actually produce an array of buffers `new Transaction` will 56 | // take either an array of buffers or an array of hex strings. 57 | // So assuming that you were able to parse the transaction, we will now get the sender's 58 | // address 59 | 60 | console.log('Senders Address: ' + tx2.getSenderAddress().toString('hex')) 61 | 62 | // Cool now we know who sent the tx! Lets verify the signature to make sure it was not 63 | // some poser. 64 | 65 | if (tx2.verifySignature()) { 66 | console.log('Signature Checks out!') 67 | } 68 | 69 | // And hopefully its verified. For the transaction to be totally valid we would 70 | // also need to check the account of the sender and see if they have enough funds. 71 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | process.env.ethTest = 'TransactionTests' 2 | 3 | module.exports = function(config) { 4 | config.set({ 5 | browserNoActivityTimeout: 60000, 6 | frameworks: ['browserify', 'detectBrowsers', 'tap'], 7 | // the official transaction's test suite is disabled for now, see https://github.com/ethereumjs/ethereumjs-testing/issues/40 8 | files: ['./test-build/test/api.js', './test-build/test/fake.js'], 9 | preprocessors: { 10 | './test-build/**/*.js': ['browserify'], 11 | }, 12 | singleRun: true, 13 | detectBrowsers: { 14 | enabled: true, 15 | usePhantomJS: false, 16 | postDetection: function(availableBrowsers) { 17 | return ['FirefoxHeadless'] 18 | }, 19 | }, 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ethereumjs-tx", 3 | "version": "2.1.2", 4 | "description": "A simple module for creating, manipulating and signing Ethereum transactions", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "files": [ 8 | "dist" 9 | ], 10 | "scripts": { 11 | "build": "ethereumjs-config-build", 12 | "prepublishOnly": "npm run test && npm run build", 13 | "coverage": "ethereumjs-config-coverage", 14 | "coveralls": "ethereumjs-config-coveralls", 15 | "docs:build": "typedoc --out docs --mode file --readme none --theme markdown --mdEngine github --excludeNotExported src", 16 | "format": "ethereumjs-config-format", 17 | "format:fix": "ethereumjs-config-format-fix", 18 | "tslint": "ethereumjs-config-tslint", 19 | "tslint:fix": "ethereumjs-config-tslint-fix", 20 | "tsc": "ethereumjs-config-tsc", 21 | "lint": "ethereumjs-config-lint", 22 | "lint:fix": "ethereumjs-config-lint-fix", 23 | "test": "npm run test:node", 24 | "test:node": "ts-node node_modules/tape/bin/tape ./test/index.ts", 25 | "test:browser:build": "tsc && cp ./test/*.json test-build/test/", 26 | "test:browser": "npm run test:browser:build && karma start karma.conf.js" 27 | }, 28 | "husky": { 29 | "hooks": { 30 | "pre-push": "npm run lint" 31 | } 32 | }, 33 | "keywords": [ 34 | "ethereum", 35 | "transactions" 36 | ], 37 | "author": "mjbecze ", 38 | "license": "MPL-2.0", 39 | "dependencies": { 40 | "ethereumjs-common": "^1.5.0", 41 | "ethereumjs-util": "^6.0.0" 42 | }, 43 | "devDependencies": { 44 | "@ethereumjs/config-nyc": "^1.1.1", 45 | "@ethereumjs/config-prettier": "^1.1.1", 46 | "@ethereumjs/config-tsc": "^1.1.1", 47 | "@ethereumjs/config-tslint": "^1.1.1", 48 | "@types/bn.js": "^4.11.5", 49 | "@types/minimist": "^1.2.0", 50 | "@types/node": "^11.13.4", 51 | "@types/tape": "^4.2.33", 52 | "browserify": "^16.2.3", 53 | "contributor": "^0.1.25", 54 | "coveralls": "^2.11.4", 55 | "ethereumjs-testing": "git+https://github.com/ethereumjs/ethereumjs-testing.git#v1.3.0", 56 | "husky": "^2.1.0", 57 | "istanbul": "^0.4.1", 58 | "karma": "^4.1.0", 59 | "karma-browserify": "^6.0.0", 60 | "karma-detect-browsers": "^2.3.3", 61 | "karma-firefox-launcher": "^1.1.0", 62 | "karma-tap": "^4.1.4", 63 | "minimist": "^1.2.0", 64 | "nyc": "^14.0.0", 65 | "prettier": "^1.17.0", 66 | "tape": "^4.0.3", 67 | "ts-node": "^8.0.3", 68 | "tslint": "^5.15.0", 69 | "typedoc": "^0.14.2", 70 | "typedoc-plugin-markdown": "^1.2.0", 71 | "typescript": "^3.4.3", 72 | "typestrict": "^1.0.2" 73 | }, 74 | "repository": { 75 | "type": "git", 76 | "url": "https://github.com/ethereumjs/ethereumjs-tx.git" 77 | }, 78 | "bugs": { 79 | "url": "https://github.com/ethereumjs/ethereumjs-tx/issues" 80 | }, 81 | "homepage": "https://github.com/ethereumjs/ethereumjs-tx", 82 | "contributors": [ 83 | { 84 | "name": "<-c-g-> ", 85 | "email": "christophergewecke@gmail.com", 86 | "url": "https://github.com/cgewecke", 87 | "contributions": 1, 88 | "additions": 3, 89 | "deletions": 1, 90 | "hireable": true 91 | }, 92 | { 93 | "name": "Kirill Fomichev", 94 | "email": "fanatid@ya.ru", 95 | "url": "https://github.com/fanatid", 96 | "contributions": 1, 97 | "additions": 3, 98 | "deletions": 2, 99 | "hireable": true 100 | }, 101 | { 102 | "name": "Rick Behl", 103 | "email": null, 104 | "url": "https://github.com/Nexus7", 105 | "contributions": 1, 106 | "additions": 1, 107 | "deletions": 1, 108 | "hireable": null 109 | }, 110 | { 111 | "name": "Tim Coulter", 112 | "email": "tim@timothyjcoulter.com", 113 | "url": "https://github.com/tcoulter", 114 | "contributions": 1, 115 | "additions": 1, 116 | "deletions": 1, 117 | "hireable": null 118 | }, 119 | { 120 | "name": "kumavis", 121 | "email": "aaron@kumavis.me", 122 | "url": "https://github.com/kumavis", 123 | "contributions": 1, 124 | "additions": 6, 125 | "deletions": 6, 126 | "hireable": true 127 | }, 128 | { 129 | "name": "Jack Peterson", 130 | "email": "jack@tinybike.net", 131 | "url": "https://github.com/tinybike", 132 | "contributions": 2, 133 | "additions": 1, 134 | "deletions": 2, 135 | "hireable": null 136 | }, 137 | { 138 | "name": "Nick Dodson", 139 | "email": null, 140 | "url": "https://github.com/SilentCicero", 141 | "contributions": 2, 142 | "additions": 29, 143 | "deletions": 0, 144 | "hireable": true 145 | }, 146 | { 147 | "name": null, 148 | "email": null, 149 | "url": "https://github.com/ckeenan", 150 | "contributions": 2, 151 | "additions": 4, 152 | "deletions": 3, 153 | "hireable": null 154 | }, 155 | { 156 | "name": "Alex Beregszaszi", 157 | "email": "alex@rtfs.hu", 158 | "url": "https://github.com/axic", 159 | "contributions": 22, 160 | "additions": 27562, 161 | "deletions": 42613, 162 | "hireable": true 163 | }, 164 | { 165 | "name": null, 166 | "email": null, 167 | "url": "https://github.com/wanderer", 168 | "contributions": 171, 169 | "additions": 112706, 170 | "deletions": 96355, 171 | "hireable": null 172 | }, 173 | { 174 | "name": null, 175 | "email": null, 176 | "url": "https://github.com/kvhnuke", 177 | "contributions": 7, 178 | "additions": 268, 179 | "deletions": 53, 180 | "hireable": null 181 | } 182 | ] 183 | } 184 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@ethereumjs/config-prettier') 2 | -------------------------------------------------------------------------------- /src/fake.ts: -------------------------------------------------------------------------------- 1 | import { toBuffer } from 'ethereumjs-util' 2 | import { Buffer } from 'buffer' 3 | import { BufferLike, FakeTxData, PrefixedHexString, TransactionOptions } from './types' 4 | import Transaction from './transaction' 5 | 6 | /** 7 | * Creates a new transaction object that doesn't need to be signed. 8 | * 9 | * @param data - A transaction can be initialized with its rlp representation, an array containing 10 | * the value of its fields in order, or an object containing them by name. 11 | * 12 | * @param opts - The transaction's options, used to indicate the chain and hardfork the 13 | * transactions belongs to. 14 | * 15 | * @see Transaction 16 | */ 17 | export default class FakeTransaction extends Transaction { 18 | /** 19 | * Set from address to bypass transaction signing. 20 | * This is not an optional property, as its getter never returns undefined. 21 | */ 22 | public from!: Buffer 23 | 24 | constructor( 25 | data: Buffer | PrefixedHexString | BufferLike[] | FakeTxData = {}, 26 | opts: TransactionOptions = {}, 27 | ) { 28 | super(data, opts) 29 | 30 | Object.defineProperty(this, 'from', { 31 | enumerable: true, 32 | configurable: true, 33 | get: () => this.getSenderAddress(), 34 | set: val => { 35 | if (val) { 36 | this._from = toBuffer(val) 37 | } 38 | }, 39 | }) 40 | 41 | const txData = data as FakeTxData 42 | if (txData.from) { 43 | this.from = toBuffer(txData.from) 44 | } 45 | } 46 | 47 | /** 48 | * Computes a sha3-256 hash of the serialized tx, using the sender address to generate a fake 49 | * signature. 50 | * 51 | * @param includeSignature - Whether or not to include the signature 52 | */ 53 | hash(includeSignature = true): Buffer { 54 | if (includeSignature && this._from && this._from.toString('hex') !== '') { 55 | // include a fake signature using the from address as a private key 56 | const fakeKey = Buffer.concat([this._from, this._from.slice(0, 12)]) 57 | this.sign(fakeKey) 58 | } 59 | 60 | return super.hash(includeSignature) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Transaction } from './transaction' 2 | export { default as FakeTransaction } from './fake' 3 | export * from './types' 4 | -------------------------------------------------------------------------------- /src/transaction.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BN, 3 | defineProperties, 4 | bufferToInt, 5 | ecrecover, 6 | rlphash, 7 | publicToAddress, 8 | ecsign, 9 | toBuffer, 10 | rlp, 11 | stripZeros, 12 | } from 'ethereumjs-util' 13 | import Common from 'ethereumjs-common' 14 | import { Buffer } from 'buffer' 15 | import { BufferLike, PrefixedHexString, TxData, TransactionOptions } from './types' 16 | 17 | // secp256k1n/2 18 | const N_DIV_2 = new BN('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0', 16) 19 | 20 | /** 21 | * An Ethereum transaction. 22 | */ 23 | export default class Transaction { 24 | public raw!: Buffer[] 25 | public nonce!: Buffer 26 | public gasLimit!: Buffer 27 | public gasPrice!: Buffer 28 | public to!: Buffer 29 | public value!: Buffer 30 | public data!: Buffer 31 | public v!: Buffer 32 | public r!: Buffer 33 | public s!: Buffer 34 | 35 | private _common: Common 36 | private _senderPubKey?: Buffer 37 | protected _from?: Buffer 38 | 39 | /** 40 | * Creates a new transaction from an object with its fields' values. 41 | * 42 | * @param data - A transaction can be initialized with its rlp representation, an array containing 43 | * the value of its fields in order, or an object containing them by name. 44 | * 45 | * @param opts - The transaction's options, used to indicate the chain and hardfork the 46 | * transactions belongs to. 47 | * 48 | * @note Transaction objects implement EIP155 by default. To disable it, use the constructor's 49 | * second parameter to set a chain and hardfork before EIP155 activation (i.e. before Spurious 50 | * Dragon.) 51 | * 52 | * @example 53 | * ```js 54 | * const txData = { 55 | * nonce: '0x00', 56 | * gasPrice: '0x09184e72a000', 57 | * gasLimit: '0x2710', 58 | * to: '0x0000000000000000000000000000000000000000', 59 | * value: '0x00', 60 | * data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057', 61 | * v: '0x1c', 62 | * r: '0x5e1d3a76fbf824220eafc8c79ad578ad2b67d01b0c2425eb1f1347e8f50882ab', 63 | * s: '0x5bd428537f05f9830e93792f90ea6a3e2d1ee84952dd96edbae9f658f831ab13' 64 | * }; 65 | * const tx = new Transaction(txData); 66 | * ``` 67 | */ 68 | constructor( 69 | data: Buffer | PrefixedHexString | BufferLike[] | TxData = {}, 70 | opts: TransactionOptions = {}, 71 | ) { 72 | // instantiate Common class instance based on passed options 73 | if (opts.common) { 74 | if (opts.chain || opts.hardfork) { 75 | throw new Error( 76 | 'Instantiation with both opts.common, and opts.chain and opts.hardfork parameter not allowed!', 77 | ) 78 | } 79 | 80 | this._common = opts.common 81 | } else { 82 | const chain = opts.chain ? opts.chain : 'mainnet' 83 | const hardfork = opts.hardfork ? opts.hardfork : 'petersburg' 84 | 85 | this._common = new Common(chain, hardfork) 86 | } 87 | 88 | // Define Properties 89 | const fields = [ 90 | { 91 | name: 'nonce', 92 | length: 32, 93 | allowLess: true, 94 | default: new Buffer([]), 95 | }, 96 | { 97 | name: 'gasPrice', 98 | length: 32, 99 | allowLess: true, 100 | default: new Buffer([]), 101 | }, 102 | { 103 | name: 'gasLimit', 104 | alias: 'gas', 105 | length: 32, 106 | allowLess: true, 107 | default: new Buffer([]), 108 | }, 109 | { 110 | name: 'to', 111 | allowZero: true, 112 | length: 20, 113 | default: new Buffer([]), 114 | }, 115 | { 116 | name: 'value', 117 | length: 32, 118 | allowLess: true, 119 | default: new Buffer([]), 120 | }, 121 | { 122 | name: 'data', 123 | alias: 'input', 124 | allowZero: true, 125 | default: new Buffer([]), 126 | }, 127 | { 128 | name: 'v', 129 | allowZero: true, 130 | default: new Buffer([]), 131 | }, 132 | { 133 | name: 'r', 134 | length: 32, 135 | allowZero: true, 136 | allowLess: true, 137 | default: new Buffer([]), 138 | }, 139 | { 140 | name: 's', 141 | length: 32, 142 | allowZero: true, 143 | allowLess: true, 144 | default: new Buffer([]), 145 | }, 146 | ] 147 | 148 | // attached serialize 149 | defineProperties(this, fields, data) 150 | 151 | /** 152 | * @property {Buffer} from (read only) sender address of this transaction, mathematically derived from other parameters. 153 | * @name from 154 | * @memberof Transaction 155 | */ 156 | Object.defineProperty(this, 'from', { 157 | enumerable: true, 158 | configurable: true, 159 | get: this.getSenderAddress.bind(this), 160 | }) 161 | 162 | this._validateV(this.v) 163 | this._overrideVSetterWithValidation() 164 | } 165 | 166 | /** 167 | * If the tx's `to` is to the creation address 168 | */ 169 | toCreationAddress(): boolean { 170 | return this.to.toString('hex') === '' 171 | } 172 | 173 | /** 174 | * Computes a sha3-256 hash of the serialized tx 175 | * @param includeSignature - Whether or not to include the signature 176 | */ 177 | hash(includeSignature: boolean = true): Buffer { 178 | let items 179 | if (includeSignature) { 180 | items = this.raw 181 | } else { 182 | if (this._implementsEIP155()) { 183 | items = [ 184 | ...this.raw.slice(0, 6), 185 | toBuffer(this.getChainId()), 186 | // TODO: stripping zeros should probably be a responsibility of the rlp module 187 | stripZeros(toBuffer(0)), 188 | stripZeros(toBuffer(0)), 189 | ] 190 | } else { 191 | items = this.raw.slice(0, 6) 192 | } 193 | } 194 | 195 | // create hash 196 | return rlphash(items) 197 | } 198 | 199 | /** 200 | * returns chain ID 201 | */ 202 | getChainId(): number { 203 | return this._common.chainId() 204 | } 205 | 206 | /** 207 | * returns the sender's address 208 | */ 209 | getSenderAddress(): Buffer { 210 | if (this._from) { 211 | return this._from 212 | } 213 | const pubkey = this.getSenderPublicKey() 214 | this._from = publicToAddress(pubkey) 215 | return this._from 216 | } 217 | 218 | /** 219 | * returns the public key of the sender 220 | */ 221 | getSenderPublicKey(): Buffer { 222 | if (!this.verifySignature()) { 223 | throw new Error('Invalid Signature') 224 | } 225 | 226 | // If the signature was verified successfully the _senderPubKey field is defined 227 | return this._senderPubKey! 228 | } 229 | 230 | /** 231 | * Determines if the signature is valid 232 | */ 233 | verifySignature(): boolean { 234 | const msgHash = this.hash(false) 235 | // All transaction signatures whose s-value is greater than secp256k1n/2 are considered invalid. 236 | if (this._common.gteHardfork('homestead') && new BN(this.s).cmp(N_DIV_2) === 1) { 237 | return false 238 | } 239 | 240 | try { 241 | const v = bufferToInt(this.v) 242 | const useChainIdWhileRecoveringPubKey = 243 | v >= this.getChainId() * 2 + 35 && this._common.gteHardfork('spuriousDragon') 244 | this._senderPubKey = ecrecover( 245 | msgHash, 246 | v, 247 | this.r, 248 | this.s, 249 | useChainIdWhileRecoveringPubKey ? this.getChainId() : undefined, 250 | ) 251 | } catch (e) { 252 | return false 253 | } 254 | 255 | return !!this._senderPubKey 256 | } 257 | 258 | /** 259 | * sign a transaction with a given private key 260 | * @param privateKey - Must be 32 bytes in length 261 | */ 262 | sign(privateKey: Buffer) { 263 | // We clear any previous signature before signing it. Otherwise, _implementsEIP155's can give 264 | // different results if this tx was already signed. 265 | this.v = new Buffer([]) 266 | this.s = new Buffer([]) 267 | this.r = new Buffer([]) 268 | 269 | const msgHash = this.hash(false) 270 | const sig = ecsign(msgHash, privateKey) 271 | 272 | if (this._implementsEIP155()) { 273 | sig.v += this.getChainId() * 2 + 8 274 | } 275 | 276 | Object.assign(this, sig) 277 | } 278 | 279 | /** 280 | * The amount of gas paid for the data in this tx 281 | */ 282 | getDataFee(): BN { 283 | const data = this.raw[5] 284 | const cost = new BN(0) 285 | for (let i = 0; i < data.length; i++) { 286 | data[i] === 0 287 | ? cost.iaddn(this._common.param('gasPrices', 'txDataZero')) 288 | : cost.iaddn(this._common.param('gasPrices', 'txDataNonZero')) 289 | } 290 | return cost 291 | } 292 | 293 | /** 294 | * the minimum amount of gas the tx must have (DataFee + TxFee + Creation Fee) 295 | */ 296 | getBaseFee(): BN { 297 | const fee = this.getDataFee().iaddn(this._common.param('gasPrices', 'tx')) 298 | if (this._common.gteHardfork('homestead') && this.toCreationAddress()) { 299 | fee.iaddn(this._common.param('gasPrices', 'txCreation')) 300 | } 301 | return fee 302 | } 303 | 304 | /** 305 | * the up front amount that an account must have for this transaction to be valid 306 | */ 307 | getUpfrontCost(): BN { 308 | return new BN(this.gasLimit).imul(new BN(this.gasPrice)).iadd(new BN(this.value)) 309 | } 310 | 311 | /** 312 | * Validates the signature and checks to see if it has enough gas. 313 | */ 314 | validate(): boolean 315 | validate(stringError: false): boolean 316 | validate(stringError: true): string 317 | validate(stringError: boolean = false): boolean | string { 318 | const errors = [] 319 | if (!this.verifySignature()) { 320 | errors.push('Invalid Signature') 321 | } 322 | 323 | if (this.getBaseFee().cmp(new BN(this.gasLimit)) > 0) { 324 | errors.push([`gas limit is too low. Need at least ${this.getBaseFee()}`]) 325 | } 326 | 327 | if (stringError === false) { 328 | return errors.length === 0 329 | } else { 330 | return errors.join(' ') 331 | } 332 | } 333 | 334 | /** 335 | * Returns the rlp encoding of the transaction 336 | */ 337 | serialize(): Buffer { 338 | // Note: This never gets executed, defineProperties overwrites it. 339 | return rlp.encode(this.raw) 340 | } 341 | 342 | /** 343 | * Returns the transaction in JSON format 344 | * @see {@link https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/index.md#defineproperties|ethereumjs-util} 345 | */ 346 | toJSON(labels: boolean = false): { [key: string]: string } | string[] { 347 | // Note: This never gets executed, defineProperties overwrites it. 348 | return {} 349 | } 350 | 351 | private _validateV(v?: Buffer): void { 352 | if (v === undefined || v.length === 0) { 353 | return 354 | } 355 | 356 | if (!this._common.gteHardfork('spuriousDragon')) { 357 | return 358 | } 359 | 360 | const vInt = bufferToInt(v) 361 | 362 | if (vInt === 27 || vInt === 28) { 363 | return 364 | } 365 | 366 | const isValidEIP155V = 367 | vInt === this.getChainId() * 2 + 35 || vInt === this.getChainId() * 2 + 36 368 | 369 | if (!isValidEIP155V) { 370 | throw new Error( 371 | `Incompatible EIP155-based V ${vInt} and chain id ${this.getChainId()}. See the second parameter of the Transaction constructor to set the chain id.`, 372 | ) 373 | } 374 | } 375 | 376 | private _isSigned(): boolean { 377 | return this.v.length > 0 && this.r.length > 0 && this.s.length > 0 378 | } 379 | 380 | private _overrideVSetterWithValidation() { 381 | const vDescriptor = Object.getOwnPropertyDescriptor(this, 'v')! 382 | 383 | Object.defineProperty(this, 'v', { 384 | ...vDescriptor, 385 | set: v => { 386 | if (v !== undefined) { 387 | this._validateV(toBuffer(v)) 388 | } 389 | 390 | vDescriptor.set!(v) 391 | }, 392 | }) 393 | } 394 | 395 | private _implementsEIP155(): boolean { 396 | const onEIP155BlockOrLater = this._common.gteHardfork('spuriousDragon') 397 | 398 | if (!this._isSigned()) { 399 | // We sign with EIP155 all unsigned transactions after spuriousDragon 400 | return onEIP155BlockOrLater 401 | } 402 | 403 | // EIP155 spec: 404 | // If block.number >= 2,675,000 and v = CHAIN_ID * 2 + 35 or v = CHAIN_ID * 2 + 36, then when computing 405 | // the hash of a transaction for purposes of signing or recovering, instead of hashing only the first six 406 | // elements (i.e. nonce, gasprice, startgas, to, value, data), hash nine elements, with v replaced by 407 | // CHAIN_ID, r = 0 and s = 0. 408 | const v = bufferToInt(this.v) 409 | 410 | const vAndChainIdMeetEIP155Conditions = 411 | v === this.getChainId() * 2 + 35 || v === this.getChainId() * 2 + 36 412 | return vAndChainIdMeetEIP155Conditions && onEIP155BlockOrLater 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from 'buffer' 2 | import Common from 'ethereumjs-common' 3 | 4 | /** 5 | * Any object that can be transformed into a `Buffer` 6 | */ 7 | export interface TransformableToBuffer { 8 | toBuffer(): Buffer 9 | } 10 | 11 | /** 12 | * A hex string prefixed with `0x`. 13 | */ 14 | export type PrefixedHexString = string 15 | 16 | /** 17 | * A Buffer, hex string prefixed with `0x`, Number, or an object with a toBuffer method such as BN. 18 | */ 19 | export type BufferLike = Buffer | TransformableToBuffer | PrefixedHexString | number 20 | 21 | /** 22 | * A transaction's data. 23 | */ 24 | export interface TxData { 25 | /** 26 | * The transaction's gas limit. 27 | */ 28 | gasLimit?: BufferLike 29 | 30 | /** 31 | * The transaction's gas price. 32 | */ 33 | gasPrice?: BufferLike 34 | 35 | /** 36 | * The transaction's the address is sent to. 37 | */ 38 | to?: BufferLike 39 | 40 | /** 41 | * The transaction's nonce. 42 | */ 43 | nonce?: BufferLike 44 | 45 | /** 46 | * This will contain the data of the message or the init of a contract 47 | */ 48 | data?: BufferLike 49 | 50 | /** 51 | * EC recovery ID. 52 | */ 53 | v?: BufferLike 54 | 55 | /** 56 | * EC signature parameter. 57 | */ 58 | r?: BufferLike 59 | 60 | /** 61 | * EC signature parameter. 62 | */ 63 | s?: BufferLike 64 | 65 | /** 66 | * The amount of Ether sent. 67 | */ 68 | value?: BufferLike 69 | } 70 | 71 | /** 72 | * The data of a fake (self-signing) transaction. 73 | */ 74 | export interface FakeTxData extends TxData { 75 | /** 76 | * The sender of the Tx. 77 | */ 78 | from?: BufferLike 79 | } 80 | 81 | /** 82 | * The transaction's options. This could be specified using a Common object, or `chain` and `hardfork`. Defaults to 83 | * mainnet. 84 | */ 85 | export interface TransactionOptions { 86 | /** 87 | * A Common object defining the chain and the hardfork a transaction belongs to. 88 | */ 89 | common?: Common 90 | 91 | /** 92 | * The chain of the transaction, default: 'mainnet' 93 | */ 94 | chain?: number | string 95 | 96 | /** 97 | * The hardfork of the transaction, default: 'petersburg' 98 | */ 99 | hardfork?: string 100 | } 101 | -------------------------------------------------------------------------------- /test/api.ts: -------------------------------------------------------------------------------- 1 | import * as tape from 'tape' 2 | import { Buffer } from 'buffer' 3 | import { rlp, zeros, privateToPublic, toBuffer } from 'ethereumjs-util' 4 | 5 | import Transaction from '../src/transaction' 6 | import { FakeTxData, TxsJsonEntry, VitaliksTestsDataEntry } from './types' 7 | import Common from 'ethereumjs-common' 8 | import { TxData } from '../src' 9 | 10 | const txFixtures: TxsJsonEntry[] = require('./txs.json') 11 | const txFixturesEip155: VitaliksTestsDataEntry[] = require('./ttTransactionTestEip155VitaliksTests.json') 12 | 13 | tape('[Transaction]: Basic functions', function(t) { 14 | const transactions: Transaction[] = [] 15 | 16 | t.test('should decode transactions', function(st) { 17 | txFixtures.slice(0, 4).forEach(function(tx: any) { 18 | const pt = new Transaction(tx.raw) 19 | st.equal('0x' + pt.nonce.toString('hex'), tx.raw[0]) 20 | st.equal('0x' + pt.gasPrice.toString('hex'), tx.raw[1]) 21 | st.equal('0x' + pt.gasLimit.toString('hex'), tx.raw[2]) 22 | st.equal('0x' + pt.to.toString('hex'), tx.raw[3]) 23 | st.equal('0x' + pt.value.toString('hex'), tx.raw[4]) 24 | st.equal('0x' + pt.v.toString('hex'), tx.raw[6]) 25 | st.equal('0x' + pt.r.toString('hex'), tx.raw[7]) 26 | st.equal('0x' + pt.s.toString('hex'), tx.raw[8]) 27 | st.equal('0x' + pt.data.toString('hex'), tx.raw[5]) 28 | transactions.push(pt) 29 | }) 30 | st.end() 31 | }) 32 | 33 | t.test('should serialize', function(st) { 34 | transactions.forEach(function(tx) { 35 | st.deepEqual(tx.serialize(), rlp.encode(tx.raw)) 36 | }) 37 | st.end() 38 | }) 39 | 40 | t.test('should hash', function(st) { 41 | const tx = new Transaction(txFixtures[3].raw) 42 | st.deepEqual( 43 | tx.hash(), 44 | new Buffer('375a8983c9fc56d7cfd118254a80a8d7403d590a6c9e105532b67aca1efb97aa', 'hex'), 45 | ) 46 | st.deepEqual( 47 | tx.hash(false), 48 | new Buffer('61e1ec33764304dddb55348e7883d4437426f44ab3ef65e6da1e025734c03ff0', 'hex'), 49 | ) 50 | st.deepEqual( 51 | tx.hash(true), 52 | new Buffer('375a8983c9fc56d7cfd118254a80a8d7403d590a6c9e105532b67aca1efb97aa', 'hex'), 53 | ) 54 | st.end() 55 | }) 56 | 57 | t.test('should hash with defined chainId', function(st) { 58 | const tx = new Transaction(txFixtures[4].raw) 59 | st.equal( 60 | tx.hash().toString('hex'), 61 | '0f09dc98ea85b7872f4409131a790b91e7540953992886fc268b7ba5c96820e4', 62 | ) 63 | st.equal( 64 | tx.hash(true).toString('hex'), 65 | '0f09dc98ea85b7872f4409131a790b91e7540953992886fc268b7ba5c96820e4', 66 | ) 67 | st.equal( 68 | tx.hash(false).toString('hex'), 69 | 'f97c73fdca079da7652dbc61a46cd5aeef804008e057be3e712c43eac389aaf0', 70 | ) 71 | st.end() 72 | }) 73 | 74 | t.test('should verify Signatures', function(st) { 75 | transactions.forEach(function(tx) { 76 | st.equals(tx.verifySignature(), true) 77 | }) 78 | st.end() 79 | }) 80 | 81 | t.test('should not verify Signatures', function(st) { 82 | transactions.forEach(function(tx) { 83 | tx.s = zeros(32) 84 | st.equals(tx.verifySignature(), false) 85 | }) 86 | st.end() 87 | }) 88 | 89 | t.test('should give a string about not verifing Signatures', function(st) { 90 | transactions.forEach(function(tx) { 91 | st.equals( 92 | tx.validate(true).slice(0, 54), 93 | 'Invalid Signature gas limit is too low. Need at least ', 94 | ) 95 | }) 96 | st.end() 97 | }) 98 | 99 | t.test('should validate', function(st) { 100 | transactions.forEach(function(tx) { 101 | st.equals(tx.validate(), false) 102 | }) 103 | st.end() 104 | }) 105 | 106 | t.test('should sign tx', function(st) { 107 | transactions.forEach(function(tx, i) { 108 | if (txFixtures[i].privateKey) { 109 | const privKey = new Buffer(txFixtures[i].privateKey, 'hex') 110 | tx.sign(privKey) 111 | } 112 | }) 113 | st.end() 114 | }) 115 | 116 | t.test("should get sender's address after signing it", function(st) { 117 | transactions.forEach(function(tx, i) { 118 | if (txFixtures[i].privateKey) { 119 | st.equals(tx.getSenderAddress().toString('hex'), txFixtures[i].sendersAddress) 120 | } 121 | }) 122 | st.end() 123 | }) 124 | 125 | t.test("should get sender's public key after signing it", function(st) { 126 | transactions.forEach(function(tx, i) { 127 | if (txFixtures[i].privateKey) { 128 | st.equals( 129 | tx.getSenderPublicKey().toString('hex'), 130 | privateToPublic(new Buffer(txFixtures[i].privateKey, 'hex')).toString('hex'), 131 | ) 132 | } 133 | }) 134 | st.end() 135 | }) 136 | 137 | t.test("should get sender's address after signing it (second call should be cached)", function( 138 | st, 139 | ) { 140 | transactions.forEach(function(tx, i) { 141 | if (txFixtures[i].privateKey) { 142 | st.equals(tx.getSenderAddress().toString('hex'), txFixtures[i].sendersAddress) 143 | st.equals(tx.getSenderAddress().toString('hex'), txFixtures[i].sendersAddress) 144 | } 145 | }) 146 | st.end() 147 | }) 148 | 149 | t.test('should verify signing it', function(st) { 150 | transactions.forEach(function(tx, i) { 151 | if (txFixtures[i].privateKey) { 152 | st.equals(tx.verifySignature(), true) 153 | } 154 | }) 155 | st.end() 156 | }) 157 | 158 | t.test('should validate with string option', function(st) { 159 | transactions.forEach(function(tx) { 160 | tx.gasLimit = toBuffer(30000) 161 | st.equals(tx.validate(true), '') 162 | }) 163 | st.end() 164 | }) 165 | 166 | t.test('should round trip decode a tx', function(st) { 167 | const tx = new Transaction() 168 | tx.value = toBuffer(5000) 169 | const s1 = tx.serialize().toString('hex') 170 | const tx2 = new Transaction(s1) 171 | const s2 = tx2.serialize().toString('hex') 172 | st.equals(s1, s2) 173 | st.end() 174 | }) 175 | 176 | t.test('should accept lesser r values', function(st) { 177 | const tx = new Transaction() 178 | tx.r = toBuffer('0x0005') 179 | st.equals(tx.r.toString('hex'), '05') 180 | st.end() 181 | }) 182 | 183 | t.test('should return data fee', function(st) { 184 | let tx = new Transaction() 185 | st.equals(tx.getDataFee().toNumber(), 0) 186 | 187 | tx = new Transaction(txFixtures[3].raw) 188 | st.equals(tx.getDataFee().toNumber(), 2496) 189 | 190 | st.end() 191 | }) 192 | 193 | t.test('should return base fee', function(st) { 194 | const tx = new Transaction() 195 | st.equals(tx.getBaseFee().toNumber(), 53000) 196 | st.end() 197 | }) 198 | 199 | t.test('should return upfront cost', function(st) { 200 | const tx = new Transaction({ 201 | gasPrice: 1000, 202 | gasLimit: 10000000, 203 | value: 42, 204 | }) 205 | st.equals(tx.getUpfrontCost().toNumber(), 10000000042) 206 | st.end() 207 | }) 208 | 209 | t.test("Verify EIP155 Signature based on Vitalik's tests", function(st) { 210 | txFixturesEip155.forEach(function(tx) { 211 | const pt = new Transaction(tx.rlp) 212 | st.equal(pt.hash(false).toString('hex'), tx.hash) 213 | st.equal('0x' + pt.serialize().toString('hex'), tx.rlp) 214 | st.equal(pt.getSenderAddress().toString('hex'), tx.sender) 215 | }) 216 | st.end() 217 | }) 218 | 219 | t.test('Verify EIP155 Signature before and after signing with private key', function(st) { 220 | // Inputs and expected results for this test are taken directly from the example in https://eips.ethereum.org/EIPS/eip-155 221 | const txRaw = [ 222 | '0x09', 223 | '0x4a817c800', 224 | '0x5208', 225 | '0x3535353535353535353535353535353535353535', 226 | '0x0de0b6b3a7640000', 227 | '0x', 228 | ] 229 | const privateKey = Buffer.from( 230 | '4646464646464646464646464646464646464646464646464646464646464646', 231 | 'hex', 232 | ) 233 | const pt = new Transaction(txRaw) 234 | 235 | // Note that Vitalik's example has a very similar value denoted "signing data". It's not the 236 | // output of `serialize()`, but the pre-image of the hash returned by `tx.hash(false)`. 237 | // We don't have a getter for such a value in Transaction. 238 | st.equal( 239 | pt.serialize().toString('hex'), 240 | 'ec098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a764000080808080', 241 | ) 242 | pt.sign(privateKey) 243 | st.equal( 244 | pt.hash(false).toString('hex'), 245 | 'daf5a779ae972f972197303d7b574746c7ef83eadac0f2791ad23db92e4c8e53', 246 | ) 247 | st.equal( 248 | pt.serialize().toString('hex'), 249 | 'f86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83', 250 | ) 251 | st.end() 252 | }) 253 | 254 | t.test( 255 | 'Serialize correctly after being signed with EIP155 Signature for tx created on ropsten', 256 | function(st) { 257 | const txRaw = [ 258 | '0x1', 259 | '0x02540be400', 260 | '0x5208', 261 | '0xd7250824390ec5c8b71d856b5de895e271170d9d', 262 | '0x0de0b6b3a7640000', 263 | '0x', 264 | ] 265 | 266 | const privateKey = Buffer.from( 267 | 'DE3128752F183E8930D7F00A2AAA302DCB5E700B2CBA2D8CA5795660F07DEFD5', 268 | 'hex', 269 | ) 270 | const pt = new Transaction(txRaw, { chain: 3 }) 271 | pt.sign(privateKey) 272 | st.equal( 273 | pt.serialize().toString('hex'), 274 | 'f86c018502540be40082520894d7250824390ec5c8b71d856b5de895e271170d9d880de0b6b3a76400008029a0d3512c68099d184ccf54f44d9d6905bff303128574b663dcf10b4c726ddd8133a0628acc8f481dea593f13309dfc5f0340f83fdd40cf9fbe47f782668f6f3aec74', 275 | ) 276 | st.end() 277 | }, 278 | ) 279 | 280 | t.test('sign tx with chainId specified in params', function(st) { 281 | const tx = new Transaction({}, { chain: 42 }) 282 | st.equal(tx.getChainId(), 42) 283 | const privKey = new Buffer(txFixtures[0].privateKey, 'hex') 284 | tx.sign(privKey) 285 | const serialized = tx.serialize() 286 | const reTx = new Transaction(serialized, { chain: 42 }) 287 | st.equal(reTx.verifySignature(), true) 288 | st.equal(reTx.getChainId(), 42) 289 | st.end() 290 | }) 291 | 292 | t.test('throws when creating a a transaction with incompatible chainid and v value', function( 293 | st, 294 | ) { 295 | const tx = new Transaction({}, { chain: 42 }) 296 | st.equal(tx.getChainId(), 42) 297 | const privKey = new Buffer(txFixtures[0].privateKey, 'hex') 298 | tx.sign(privKey) 299 | const serialized = tx.serialize() 300 | st.throws(() => new Transaction(serialized)) 301 | st.end() 302 | }) 303 | 304 | t.test('Throws if chain/hardfork and commmon options are given', function(st) { 305 | st.throws( 306 | () => new Transaction({}, { common: new Common('mainnet', 'petersburg'), chain: 'mainnet' }), 307 | ) 308 | st.throws( 309 | () => new Transaction({}, { common: new Common('mainnet', 'petersburg'), chain: 'ropsten' }), 310 | ) 311 | st.throws( 312 | () => 313 | new Transaction( 314 | {}, 315 | { common: new Common('mainnet', 'petersburg'), hardfork: 'petersburg' }, 316 | ), 317 | ) 318 | st.end() 319 | }) 320 | 321 | t.test('Throws if v is set to an EIP155-encoded value incompatible with the chain id', function( 322 | st, 323 | ) { 324 | const tx = new Transaction({}, { chain: 42 }) 325 | const privKey = new Buffer(txFixtures[0].privateKey, 'hex') 326 | tx.sign(privKey) 327 | 328 | st.throws(() => (tx.v = toBuffer(1))) 329 | 330 | const unsignedTx = new Transaction(tx.raw.slice(0, 6)) 331 | st.throws(() => (unsignedTx.v = tx.v)) 332 | 333 | st.end() 334 | }) 335 | 336 | t.test('EIP155 hashing when singing', function(st) { 337 | txFixtures.slice(0, 3).forEach(function(txData) { 338 | const tx = new Transaction(txData.raw.slice(0, 6), { chain: 1 }) 339 | 340 | const privKey = new Buffer(txData.privateKey, 'hex') 341 | tx.sign(privKey) 342 | 343 | st.equal( 344 | tx.getSenderAddress().toString('hex'), 345 | txData.sendersAddress, 346 | "computed sender address should equal the fixture's one", 347 | ) 348 | }) 349 | 350 | st.end() 351 | }) 352 | 353 | t.test( 354 | 'Should ignore any previous signature when decided if EIP155 should be used in a new one', 355 | function(st) { 356 | const privateKey = Buffer.from( 357 | '4646464646464646464646464646464646464646464646464646464646464646', 358 | 'hex', 359 | ) 360 | 361 | const txData: TxData = { 362 | data: '0x7cf5dab00000000000000000000000000000000000000000000000000000000000000005', 363 | gasLimit: '0x15f90', 364 | gasPrice: '0x1', 365 | nonce: '0x01', 366 | to: '0xd9024df085d09398ec76fbed18cac0e1149f50dc', 367 | value: '0x0', 368 | } 369 | 370 | const fixtureTxSignedWithEIP155 = new Transaction(txData) 371 | fixtureTxSignedWithEIP155.sign(privateKey) 372 | 373 | const fixtureTxSignedWithoutEIP155 = new Transaction(txData, { hardfork: 'tangerineWhistle' }) 374 | fixtureTxSignedWithoutEIP155.sign(privateKey) 375 | 376 | let signedWithEIP155 = new Transaction(fixtureTxSignedWithEIP155.toJSON(true)) 377 | signedWithEIP155.sign(privateKey) 378 | st.true(signedWithEIP155.verifySignature()) 379 | st.notEqual(signedWithEIP155.v.toString('hex'), '1c') 380 | st.notEqual(signedWithEIP155.v.toString('hex'), '1b') 381 | 382 | signedWithEIP155 = new Transaction(fixtureTxSignedWithoutEIP155.toJSON(true)) 383 | signedWithEIP155.sign(privateKey) 384 | st.true(signedWithEIP155.verifySignature()) 385 | st.notEqual(signedWithEIP155.v.toString('hex'), '1c') 386 | st.notEqual(signedWithEIP155.v.toString('hex'), '1b') 387 | 388 | let signedWithoutEIP155 = new Transaction(fixtureTxSignedWithEIP155.toJSON(true), { 389 | hardfork: 'tangerineWhistle', 390 | }) 391 | signedWithoutEIP155.sign(privateKey) 392 | st.true(signedWithoutEIP155.verifySignature()) 393 | st.true( 394 | signedWithoutEIP155.v.toString('hex') == '1c' || 395 | signedWithoutEIP155.v.toString('hex') == '1b', 396 | "v shouldn' be EIP155 encoded", 397 | ) 398 | 399 | signedWithoutEIP155 = new Transaction(fixtureTxSignedWithoutEIP155.toJSON(true), { 400 | hardfork: 'tangerineWhistle', 401 | }) 402 | signedWithoutEIP155.sign(privateKey) 403 | st.true(signedWithoutEIP155.verifySignature()) 404 | st.true( 405 | signedWithoutEIP155.v.toString('hex') == '1c' || 406 | signedWithoutEIP155.v.toString('hex') == '1b', 407 | "v shouldn' be EIP155 encoded", 408 | ) 409 | 410 | st.end() 411 | }, 412 | ) 413 | 414 | t.test('should return correct data fee for istanbul', function(st) { 415 | let tx = new Transaction({}, { hardfork: 'istanbul' }) 416 | st.equals(tx.getDataFee().toNumber(), 0) 417 | 418 | tx = new Transaction(txFixtures[3].raw, { hardfork: 'istanbul' }) 419 | st.equals(tx.getDataFee().toNumber(), 1716) 420 | 421 | st.end() 422 | }) 423 | }) 424 | -------------------------------------------------------------------------------- /test/fake.ts: -------------------------------------------------------------------------------- 1 | import * as tape from 'tape' 2 | import { Buffer } from 'buffer' 3 | import { bufferToHex } from 'ethereumjs-util' 4 | import Common from 'ethereumjs-common' 5 | import { FakeTransaction } from '../src' 6 | import { FakeTxData } from './types' 7 | 8 | // Use private key 0x0000000000000000000000000000000000000000000000000000000000000001 as 'from' Account 9 | const txData: FakeTxData = { 10 | data: '0x7cf5dab00000000000000000000000000000000000000000000000000000000000000005', 11 | gasLimit: '0x15f90', 12 | gasPrice: '0x1', 13 | nonce: '0x01', 14 | to: '0xd9024df085d09398ec76fbed18cac0e1149f50dc', 15 | value: '0x0', 16 | from: '0x7e5f4552091a69125d5dfcb7b8c2659029395bdf', 17 | v: '0x1c', 18 | r: '0x25641558260ac737ea6d800906c6d085a801e5e0f0952bf93978d6fa468fbdfe', 19 | s: '0x5d0904b8f9cfc092805df0cde2574d25e2c5fc28907a9a4741b3e857b68b0778', 20 | } 21 | 22 | tape('[FakeTransaction]: Basic functions', function(t) { 23 | t.test('instantiate with from / create a hash', function(st) { 24 | st.plan(3) 25 | // This test doesn't use EIP155 26 | const tx = new FakeTransaction(txData, { chain: 'mainnet', hardfork: 'homestead' }) 27 | const hash = tx.hash() 28 | const cmpHash = Buffer.from( 29 | 'f74b039f6361c4351a99a7c6a10867369fe6701731d85dc07c15671ac1c1b648', 30 | 'hex', 31 | ) 32 | st.deepEqual(hash, cmpHash, 'should create hash with includeSignature=true (default)') 33 | const hash2 = tx.hash(false) 34 | const cmpHash2 = Buffer.from( 35 | '0401bf740d698674be321d0064f92cd6ebba5d73d1e5e5189c0bebbda33a85fe', 36 | 'hex', 37 | ) 38 | st.deepEqual(hash2, cmpHash2, 'should create hash with includeSignature=false') 39 | st.notDeepEqual(hash, hash2, 'previous hashes should be different') 40 | }) 41 | 42 | t.test('instantiate without from / create a hash', function(st) { 43 | const txDataNoFrom = Object.assign({}, txData) 44 | delete txDataNoFrom['from'] 45 | st.plan(3) 46 | const tx = new FakeTransaction(txDataNoFrom) 47 | const hash = tx.hash() 48 | const cmpHash = Buffer.from( 49 | '80a2ca70509414908881f718502e6bbb3bc67f416abdf972ea7c0888579be7b9', 50 | 'hex', 51 | ) 52 | st.deepEqual(hash, cmpHash, 'should create hash with includeSignature=true (default)') 53 | const hash2 = tx.hash(false) 54 | const cmpHash2 = Buffer.from( 55 | '0401bf740d698674be321d0064f92cd6ebba5d73d1e5e5189c0bebbda33a85fe', 56 | 'hex', 57 | ) 58 | st.deepEqual(hash2, cmpHash2, 'should create hash with includeSignature=false') 59 | st.notDeepEqual(hash, hash2, 'previous hashes should be different') 60 | }) 61 | 62 | t.test('should not produce hash collsions for different senders', function(st) { 63 | st.plan(1) 64 | const txDataModFrom = Object.assign({}, txData, { 65 | from: '0x2222222222222222222222222222222222222222', 66 | }) 67 | const tx = new FakeTransaction(txData) 68 | const txModFrom = new FakeTransaction(txDataModFrom) 69 | const hash = bufferToHex(tx.hash()) 70 | const hashModFrom = bufferToHex(txModFrom.hash()) 71 | st.notEqual( 72 | hash, 73 | hashModFrom, 74 | 'FakeTransactions with different `from` addresses but otherwise identical data should have different hashes', 75 | ) 76 | }) 77 | 78 | t.test('should retrieve "from" from signature if transaction is signed', function(st) { 79 | const txDataNoFrom = Object.assign({}, txData) 80 | delete txDataNoFrom['from'] 81 | st.plan(1) 82 | 83 | const tx = new FakeTransaction(txDataNoFrom) 84 | st.equal(bufferToHex(tx.from), txData.from) 85 | }) 86 | 87 | t.test('should throw if common and chain options are passed to constructor', function(st) { 88 | const txOptsInvalid = { 89 | chain: 'mainnet', 90 | common: new Common('mainnet', 'chainstart'), 91 | } 92 | st.plan(1) 93 | st.throws(() => new FakeTransaction(txData, txOptsInvalid)) 94 | }) 95 | 96 | t.test('should return toCreationAddress', st => { 97 | const tx = new FakeTransaction(txData) 98 | const txNoTo = new FakeTransaction({ ...txData, to: undefined }) 99 | st.plan(2) 100 | st.equal(tx.toCreationAddress(), false, 'tx is not "to" creation address') 101 | st.equal(txNoTo.toCreationAddress(), true, 'tx is "to" creation address') 102 | }) 103 | 104 | t.test('should return getChainId', st => { 105 | const tx = new FakeTransaction(txData) 106 | const txWithChain = new FakeTransaction(txData, { chain: 3 }) 107 | st.plan(2) 108 | st.equal(tx.getChainId(), 1, 'should return correct chainId') 109 | st.equal(txWithChain.getChainId(), 3, 'should return correct chainId') 110 | }) 111 | 112 | t.test('should getSenderAddress and getSenderPublicKey', st => { 113 | const tx = new FakeTransaction(txData) 114 | st.plan(2) 115 | st.equal( 116 | tx.from.toString('hex'), 117 | '7e5f4552091a69125d5dfcb7b8c2659029395bdf', 118 | 'this._from is set in FakeTransaction', 119 | ) 120 | st.equal( 121 | tx.getSenderAddress().toString('hex'), 122 | '7e5f4552091a69125d5dfcb7b8c2659029395bdf', 123 | 'should return correct address', 124 | ) 125 | }) 126 | 127 | t.test('should verifySignature', st => { 128 | const tx = new FakeTransaction(txData) 129 | const txWithWrongSignature = new FakeTransaction({ 130 | ...txData, 131 | r: Buffer.from('abcd1558260ac737ea6d800906c6d085a801e5e0f0952bf93978d6fa468fbdff', 'hex'), 132 | }) 133 | st.plan(2) 134 | st.true(tx.verifySignature(), 'signature is valid') 135 | st.false(txWithWrongSignature.verifySignature(), 'signature is not valid') 136 | }) 137 | 138 | t.test('should sign', st => { 139 | const tx = new FakeTransaction(txData, { hardfork: 'tangerineWhistle' }) 140 | tx.sign(Buffer.from('164122e5d39e9814ca723a749253663bafb07f6af91704d9754c361eb315f0c1', 'hex')) 141 | st.plan(3) 142 | st.equal( 143 | tx.r.toString('hex'), 144 | 'c10062450d68caa5a688e2b6930f34f8302064afe6e1ba7f6ca459115a31d3b8', 145 | 'r should be valid', 146 | ) 147 | st.equal( 148 | tx.s.toString('hex'), 149 | '31718e6bf821a98d35b0d9cd66ea86f91f420c3c4658f60c607222de925d222a', 150 | 's should be valid', 151 | ) 152 | st.equal(tx.v.toString('hex'), '1c', 'v should be valid') 153 | }) 154 | 155 | t.test('should getDataFee', st => { 156 | const tx = new FakeTransaction({ ...txData, data: '0x00000001' }) 157 | st.plan(1) 158 | st.equal(tx.getDataFee().toString(), '80', 'data fee should be correct') 159 | }) 160 | 161 | t.test('should getBaseFee', st => { 162 | const tx = new FakeTransaction({ ...txData, data: '0x00000001' }) 163 | st.plan(1) 164 | st.equal(tx.getBaseFee().toString(), '21080', 'base fee should be correct') 165 | }) 166 | 167 | t.test('should getUpfrontCost', st => { 168 | const tx = new FakeTransaction({ ...txData, gasLimit: '0x6464', gasPrice: '0x2' }) 169 | st.plan(1) 170 | st.equal(tx.getUpfrontCost().toString(), '51400', 'base fee should be correct') 171 | }) 172 | 173 | t.test('should validate', st => { 174 | const tx = new FakeTransaction(txData) 175 | const txWithWrongSignature = new FakeTransaction({ 176 | ...txData, 177 | r: Buffer.from('abcd1558260ac737ea6d800906c6d085a801e5e0f0952bf93978d6fa468fbdff', 'hex'), 178 | }) 179 | const txWithLowLimit = new FakeTransaction({ 180 | ...txData, 181 | gasLimit: '0x1', 182 | }) 183 | st.plan(6) 184 | st.true(tx.validate(), 'tx should be valid') 185 | st.false(txWithWrongSignature.validate(), 'tx should be invalid') 186 | st.false(txWithLowLimit.validate(), 'tx should be invalid') 187 | st.equal(tx.validate(true), '', 'tx should return no errors') 188 | st.equal( 189 | txWithWrongSignature.validate(true), 190 | 'Invalid Signature', 191 | 'tx should return correct error', 192 | ) 193 | st.equal( 194 | txWithLowLimit.validate(true), 195 | 'gas limit is too low. Need at least 21464', 196 | 'tx should return correct error', 197 | ) 198 | }) 199 | }) 200 | -------------------------------------------------------------------------------- /test/index.ts: -------------------------------------------------------------------------------- 1 | import * as minimist from 'minimist' 2 | 3 | const argv = minimist(process.argv.slice(2)) 4 | 5 | if (argv.f) { 6 | require('./fake') 7 | } else if (argv.a) { 8 | require('./api') 9 | } else if (argv.t) { 10 | require('./transactionRunner') 11 | } else { 12 | require('./fake') 13 | require('./api') 14 | require('./transactionRunner') 15 | } 16 | -------------------------------------------------------------------------------- /test/transactionRunner.ts: -------------------------------------------------------------------------------- 1 | import Tx from '../src/transaction' 2 | import * as tape from 'tape' 3 | import { toBuffer } from 'ethereumjs-util' 4 | import * as minimist from 'minimist' 5 | import { ForkName, ForkNamesMap, OfficialTransactionTestData } from './types' 6 | 7 | // We use require here because this module doesn't have types and this works better with ts-node. 8 | const testing = require('ethereumjs-testing') 9 | 10 | const argv = minimist(process.argv.slice(2)) 11 | const file: string | undefined = argv.file 12 | 13 | const forkNames: ForkName[] = [ 14 | 'Istanbul', 15 | 'Byzantium', 16 | 'Constantinople', 17 | 'EIP150', 18 | 'EIP158', 19 | 'Frontier', 20 | 'Homestead', 21 | ] 22 | 23 | const forkNameMap: ForkNamesMap = { 24 | Istanbul: 'istanbul', 25 | Byzantium: 'byzantium', 26 | Constantinople: 'constantinople', 27 | EIP150: 'tangerineWhistle', 28 | EIP158: 'spuriousDragon', 29 | Frontier: 'chainstart', 30 | Homestead: 'homestead', 31 | } 32 | 33 | tape('TransactionTests', t => { 34 | const fileFilterRegex = file ? new RegExp(file + '[^\\w]') : undefined 35 | 36 | testing 37 | .getTests( 38 | 'TransactionTests', 39 | (_filename: string, testName: string, testData: OfficialTransactionTestData) => { 40 | t.test(testName, st => { 41 | forkNames.forEach(forkName => { 42 | const forkTestData = testData[forkName] 43 | const shouldBeInvalid = Object.keys(forkTestData).length === 0 44 | try { 45 | const rawTx = toBuffer(testData.rlp) 46 | const tx = new Tx(rawTx, { 47 | hardfork: forkNameMap[forkName], 48 | chain: 1, 49 | }) 50 | 51 | const sender = tx.getSenderAddress().toString('hex') 52 | const hash = tx.hash().toString('hex') 53 | 54 | const validationErrors = tx.validate(true) 55 | const transactionIsValid = validationErrors.length === 0 56 | const hashAndSenderAreCorrect = 57 | forkTestData && sender === forkTestData.sender && hash === forkTestData.hash 58 | 59 | if (shouldBeInvalid) { 60 | st.assert(!transactionIsValid, `Transaction should be invalid on ${forkName}`) 61 | } else { 62 | st.assert( 63 | hashAndSenderAreCorrect && transactionIsValid, 64 | `Transaction should be valid on ${forkName}`, 65 | ) 66 | } 67 | } catch (e) { 68 | if (shouldBeInvalid) { 69 | st.assert(shouldBeInvalid, `Transaction should be invalid on ${forkName}`) 70 | } else { 71 | st.fail(`Transaction should be valid on ${forkName}`) 72 | } 73 | } 74 | }) 75 | st.end() 76 | }) 77 | }, 78 | fileFilterRegex, 79 | ) 80 | .then(() => { 81 | t.end() 82 | }) 83 | }) 84 | -------------------------------------------------------------------------------- /test/ttTransactionTestEip155VitaliksTests.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "blocknumber": "3500000", 4 | "hash": "e0be81f8d506dbe3a5549e720b51eb79492378d6638087740824f168667e5239", 5 | "rlp": "0xf864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", 6 | "sender": "f0f6f18bca1b28cd68e4357452947e021241e9ce", 7 | "transaction": { 8 | "data": "", 9 | "gasLimit": "0x5208", 10 | "gasPrice": "0x04a817c800", 11 | "nonce": "0x00", 12 | "r": "0x044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", 13 | "s": "0x044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", 14 | "to": "0x3535353535353535353535353535353535353535", 15 | "v": "0x25", 16 | "value": "0x00" 17 | } 18 | }, 19 | { 20 | "blocknumber": "3500000", 21 | "hash": "50b6e7b58320c885ab7b2ee0d0b5813a697268bd2494a06de792790b13668c08", 22 | "rlp": "0xf867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", 23 | "sender": "9bddad43f934d313c2b79ca28a432dd2b7281029", 24 | "transaction": { 25 | "data": "", 26 | "gasLimit": "0x02e248", 27 | "gasPrice": "0x04a817c808", 28 | "nonce": "0x08", 29 | "r": "0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12", 30 | "s": "0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", 31 | "to": "0x3535353535353535353535353535353535353535", 32 | "v": "0x25", 33 | "value": "0x0200" 34 | } 35 | }, 36 | { 37 | "blocknumber": "3500000", 38 | "hash": "24fd18c70146a2b002254810473fa26b744f7899258a1f32924cc73e7a8f4d4f", 39 | "rlp": "0xf867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", 40 | "sender": "3c24d7329e92f84f08556ceb6df1cdb0104ca49f", 41 | "transaction": { 42 | "data": "", 43 | "gasLimit": "0x033450", 44 | "gasPrice": "0x04a817c809", 45 | "nonce": "0x09", 46 | "r": "0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", 47 | "s": "0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", 48 | "to": "0x3535353535353535353535353535353535353535", 49 | "v": "0x25", 50 | "value": "0x02d9" 51 | } 52 | }, 53 | { 54 | "blocknumber": "3500000", 55 | "hash": "42973b488dbb3aa237db3d1a3bad18a8d2148af795fb6cdbbbeef5c736df97b9", 56 | "rlp": "0xf864018504a817c80182a410943535353535353535353535353535353535353535018025a0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bcaa0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", 57 | "sender": "23ef145a395ea3fa3deb533b8a9e1b4c6c25d112", 58 | "transaction": { 59 | "data": "", 60 | "gasLimit": "0xa410", 61 | "gasPrice": "0x04a817c801", 62 | "nonce": "0x01", 63 | "r": "0x489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bca", 64 | "s": "0x489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", 65 | "to": "0x3535353535353535353535353535353535353535", 66 | "v": "0x25", 67 | "value": "0x01" 68 | } 69 | }, 70 | { 71 | "blocknumber": "3500000", 72 | "hash": "e68afed5d359c7e60a0408093da23c57b63e84acb2e368ac7c47630518d6f4d9", 73 | "rlp": "0xf864028504a817c80282f618943535353535353535353535353535353535353535088025a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5", 74 | "sender": "2e485e0c23b4c3c542628a5f672eeab0ad4888be", 75 | "transaction": { 76 | "data": "", 77 | "gasLimit": "0xf618", 78 | "gasPrice": "0x04a817c802", 79 | "nonce": "0x02", 80 | "r": "0x2d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5", 81 | "s": "0x2d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5", 82 | "to": "0x3535353535353535353535353535353535353535", 83 | "v": "0x25", 84 | "value": "0x08" 85 | } 86 | }, 87 | { 88 | "blocknumber": "3500000", 89 | "hash": "bcb6f653e06c276a080e9d68e5a967847a896cf52a6dc81917dc2c57ae0a31ef", 90 | "rlp": "0xf865038504a817c803830148209435353535353535353535353535353535353535351b8025a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4e0a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de", 91 | "sender": "82a88539669a3fd524d669e858935de5e5410cf0", 92 | "transaction": { 93 | "data": "", 94 | "gasLimit": "0x014820", 95 | "gasPrice": "0x04a817c803", 96 | "nonce": "0x03", 97 | "r": "0x2a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4e0", 98 | "s": "0x2a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de", 99 | "to": "0x3535353535353535353535353535353535353535", 100 | "v": "0x25", 101 | "value": "0x1b" 102 | } 103 | }, 104 | { 105 | "blocknumber": "3500000", 106 | "hash": "244e4b57522352c3e9f93ad8ac8a47d1b46c3dcda6da2522caedad009ac9afb7", 107 | "rlp": "0xf865048504a817c80483019a28943535353535353535353535353535353535353535408025a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c063a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c060", 108 | "sender": "f9358f2538fd5ccfeb848b64a96b743fcc930554", 109 | "transaction": { 110 | "data": "", 111 | "gasLimit": "0x019a28", 112 | "gasPrice": "0x04a817c804", 113 | "nonce": "0x04", 114 | "r": "0x13600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c063", 115 | "s": "0x13600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c060", 116 | "to": "0x3535353535353535353535353535353535353535", 117 | "v": "0x25", 118 | "value": "0x40" 119 | } 120 | }, 121 | { 122 | "blocknumber": "3500000", 123 | "hash": "581c0b79498b1cf1b8fa4f69bc5f21c0c60371cd08d4682b15c4334aac1cccfd", 124 | "rlp": "0xf865058504a817c8058301ec309435353535353535353535353535353535353535357d8025a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", 125 | "sender": "a8f7aba377317440bc5b26198a363ad22af1f3a4", 126 | "transaction": { 127 | "data": "", 128 | "gasLimit": "0x01ec30", 129 | "gasPrice": "0x04a817c805", 130 | "nonce": "0x05", 131 | "r": "0x4eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", 132 | "s": "0x4eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", 133 | "to": "0x3535353535353535353535353535353535353535", 134 | "v": "0x25", 135 | "value": "0x7d" 136 | } 137 | }, 138 | { 139 | "blocknumber": "3500000", 140 | "hash": "581c0b79498b1cf1b8fa4f69bc5f21c0c60371cd08d4682b15c4334aac1cccfd", 141 | "rlp": "0xf865058504a817c8058301ec309435353535353535353535353535353535353535357d8025a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", 142 | "sender": "a8f7aba377317440bc5b26198a363ad22af1f3a4", 143 | "transaction": { 144 | "data": "", 145 | "gasLimit": "0x01ec30", 146 | "gasPrice": "0x04a817c805", 147 | "nonce": "0x05", 148 | "r": "0x4eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", 149 | "s": "0x4eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", 150 | "to": "0x3535353535353535353535353535353535353535", 151 | "v": "0x25", 152 | "value": "0x7d" 153 | } 154 | }, 155 | { 156 | "blocknumber": "3500000", 157 | "hash": "678ae2053a840f5fe550a63d724d1c85420d2955a0ccc4f868dd59e27afdf279", 158 | "rlp": "0xf866068504a817c80683023e3894353535353535353535353535353535353535353581d88025a06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2fa06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2d", 159 | "sender": "f1f571dc362a0e5b2696b8e775f8491d3e50de35", 160 | "transaction": { 161 | "data": "", 162 | "gasLimit": "0x023e38", 163 | "gasPrice": "0x04a817c806", 164 | "nonce": "0x06", 165 | "r": "0x6455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2f", 166 | "s": "0x6455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2d", 167 | "to": "0x3535353535353535353535353535353535353535", 168 | "v": "0x25", 169 | "value": "0xd8" 170 | } 171 | }, 172 | { 173 | "blocknumber": "3500000", 174 | "hash": "81aa03ada1474ff3ca4b86afb8e8c0f8b22791e156e706231a695ef8c51515ab", 175 | "rlp": "0xf867078504a817c807830290409435353535353535353535353535353535353535358201578025a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", 176 | "sender": "d37922162ab7cea97c97a87551ed02c9a38b7332", 177 | "transaction": { 178 | "data": "", 179 | "gasLimit": "0x029040", 180 | "gasPrice": "0x04a817c807", 181 | "nonce": "0x07", 182 | "r": "0x52f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", 183 | "s": "0x52f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", 184 | "to": "0x3535353535353535353535353535353535353535", 185 | "v": "0x25", 186 | "value": "0x0157" 187 | } 188 | } 189 | ] 190 | -------------------------------------------------------------------------------- /test/txs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "privateKey": "164122e5d39e9814ca723a749253663bafb07f6af91704d9754c361eb315f0c1", 4 | "sendersAddress": "1f36f546477cda21bf2296c50976f2740247906f", 5 | "type": "contract", 6 | "cost": 680, 7 | "raw": [ 8 | "0x", 9 | "0x09184e72a000", 10 | "0x2710", 11 | "0x0000000000000000000000000000000000000000", 12 | "0x", 13 | "0x7f7465737432000000000000000000000000000000000000000000000000000000600057", 14 | "0x1c", 15 | "0x5e1d3a76fbf824220eafc8c79ad578ad2b67d01b0c2425eb1f1347e8f50882ab", 16 | "0x5bd428537f05f9830e93792f90ea6a3e2d1ee84952dd96edbae9f658f831ab13" 17 | ] 18 | }, 19 | { 20 | "privateKey": "4646464646464646464646464646464646464646464646464646464646464646", 21 | "sendersAddress": "9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f", 22 | "type": "message", 23 | "cost": 500, 24 | "raw": [ 25 | "0x09", 26 | "0x04a817c800", 27 | "0x2710", 28 | "0x3535353535353535353535353535353535353535", 29 | "0x0de0b6b3a7640000", 30 | "0x", 31 | "0x25", 32 | "0x28ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276", 33 | "0x67cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83" 34 | ] 35 | }, 36 | { 37 | "privateKey": "e0a462586887362a18a318b128dbc1e3a0cae6d4b0739f5d0419ec25114bc722", 38 | "sendersAddress": "d13d825eb15c87b247c4c26331d66f225a5f632e", 39 | "type": "message", 40 | "cost": 500, 41 | "raw": [ 42 | "0x06", 43 | "0x09184e72a000", 44 | "0x01f4", 45 | "0xbe862ad9abfe6f22bcb087716c7d89a26051f74c", 46 | "0x016345785d8a0000", 47 | "0x", 48 | "0x1c", 49 | "0x24a484bfa7380860e9fa0a9f5e4b64b985e860ca31abd36e66583f9030c2e29d", 50 | "0x4d5ef07d9e73fa2fbfdad059591b4f13d0aa79e7634a2bb00174c9200cabb04d" 51 | ] 52 | }, 53 | { 54 | "privateKey": "164122e5d39e9814ca723a749253663bafb07f6af91704d9754c361eb315f0c1", 55 | "sendersAddress": "1f36f546477cda21bf2296c50976f2740247906f", 56 | "type": "message", 57 | "cost": 2420, 58 | "raw": [ 59 | "0x06", 60 | "0x09184e72a000", 61 | "0x0974", 62 | "0xbe862ad9abfe6f22bcb087716c7d89a26051f74c", 63 | "0x016345785d8a0000", 64 | "0x00000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000fafa0000000000000000000000000000000000000000000000000000000000000dfa0000000000000000000000000000000000000000000000000000000000000dfa00000000000000000000000000000000000000000000000000000000000000ad000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000df000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000d", 65 | "0x1c", 66 | "0x5e9361ca27e14f3af0e6b28466406ad8be026d3b0f2ae56e3c064043fb73ec77", 67 | "0x29ae9893dac4f9afb1af743e25fbb6a63f7879a61437203cb48c997b0fcefc3a" 68 | ] 69 | }, 70 | { 71 | "privateKey": "not-available", 72 | "sendersAddress": "TODO", 73 | "type": "message", 74 | "cost": 12312, 75 | "raw": [ 76 | "0x0b", 77 | "0x051f4d5c00", 78 | "0x5208", 79 | "0x656e929d6fc0cac52d3d9526d288fe02dcd56fbd", 80 | "0x2386f26fc10000", 81 | "0x", 82 | "0x26", 83 | "0xef903f6bbcb7d6214d478df27db6591d857b1063954eade1bb24e69e58511f96", 84 | "0x5433f8e1abf886cbec64891f38a2ea6fd9f9ffe078421f5e238b9fec03eea97a" 85 | ] 86 | } 87 | ] 88 | -------------------------------------------------------------------------------- /test/types.ts: -------------------------------------------------------------------------------- 1 | export type ForkName = 2 | | 'Istanbul' 3 | | 'Byzantium' 4 | | 'Constantinople' 5 | | 'EIP150' 6 | | 'EIP158' 7 | | 'Frontier' 8 | | 'Homestead' 9 | 10 | export type ForkNamesMap = { [forkName in ForkName]: string } 11 | 12 | export interface TxData { 13 | data: string 14 | gasLimit: string 15 | gasPrice: string 16 | nonce: string 17 | to: string 18 | value: string 19 | 20 | v: string 21 | r: string 22 | s: string 23 | } 24 | 25 | export interface FakeTxData extends TxData { 26 | from: string 27 | } 28 | 29 | // The type of each entry from ./ttTransactionTestEip155VitaliksTests.json 30 | export interface VitaliksTestsDataEntry { 31 | blocknumber: string 32 | hash: string 33 | rlp: string 34 | sender: string 35 | transaction: TxData 36 | } 37 | 38 | // The type of ./txs.json 39 | export type TxsJsonEntry = { 40 | privateKey: string 41 | sendersAddress: string 42 | type: string 43 | cost: number 44 | raw: string[] 45 | } 46 | 47 | export type ForksData = { [forkName in ForkName]: { hash?: string; sender?: string } } 48 | 49 | export type OfficialTransactionTestData = ForksData & { 50 | _info: { 51 | comment: string 52 | filledwith: string 53 | lllcversion: string 54 | source: string 55 | sourceHash: string 56 | } 57 | rlp: string 58 | } 59 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@ethereumjs/config-tsc", 3 | "include": ["src/**/*.ts", "test/**/*.ts"], 4 | "compilerOptions": { 5 | "outDir": "test-build" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@ethereumjs/config-tsc", 3 | "compilerOptions": { 4 | "outDir": "./dist" 5 | }, 6 | "include": ["src/**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@ethereumjs/config-tslint" 3 | } 4 | --------------------------------------------------------------------------------