├── .babelrc ├── .eslintrc ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── work_item.md ├── PULL_REQUEST_TEMPLATE.md └── workflow │ └── checkin-actions ├── .gitignore ├── .npmignore ├── .npmrc.template ├── .prettierrc ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── cypress └── integration │ └── index.spec.js ├── docs ├── 2.-Transaction-Examples.md ├── 3.-Browsers.md ├── 4.-Reading blockchain-Examples.md ├── 5.-Testing and Building with DUNE.md ├── Testing ReadOnly.md └── design │ └── Cryptography.md ├── package-lock.json ├── package.json ├── scripts ├── is_latest.sh ├── publish-edge.sh ├── publish-tag.sh ├── publish-utils.sh ├── run-cypress.sh └── simple-publish.sh ├── src ├── ChainSemanticVersion.ts ├── PrivateKey.ts ├── PublicKey.ts ├── Signature.ts ├── abi.abi.json ├── eosjs-api-interfaces.ts ├── eosjs-api.ts ├── eosjs-jsonrpc.ts ├── eosjs-jssig.ts ├── eosjs-key-conversions.ts ├── eosjs-numeric.ts ├── eosjs-rpc-interfaces.ts ├── eosjs-rpcerror.ts ├── eosjs-serialize.ts ├── eosjs-webauthn-sig.ts ├── index.ts ├── ripemd.es5.js ├── ripemd.js ├── rpc-web.ts ├── tests │ ├── TestConfig.ts │ ├── eosjs-api.test.ts │ ├── eosjs-jsonrpc.test.ts │ ├── eosjs-jssig.test.ts │ ├── eosjs-util.test.ts │ ├── logo.svg │ ├── node.js │ ├── node.test.ts │ ├── readonly_contract │ │ ├── contract.cpp │ │ └── include │ │ │ └── contract.hpp │ ├── serialization.test.ts │ ├── setupJest.js │ ├── strict-serialization.test.ts │ ├── web.css │ └── web.html └── transaction.abi.json ├── tsconfig.json ├── tsconfig.web.json ├── tslint.json ├── typedoc.json ├── webpack.debug.js ├── webpack.prod.js └── workflows └── unit-tests.yml /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "targets": { 5 | "browsers": ["last 2 versions"] 6 | } 7 | }], 8 | "stage-1" 9 | ], 10 | "plugins": [ 11 | [ 12 | "transform-runtime", 13 | { 14 | "polyfill": false, 15 | "regenerator": true 16 | } 17 | ] 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "plugins": ["@typescript-eslint", "es-x"], 5 | "ignorePatterns": ["lib/*", "node_modules/**"], 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:prettier/recommended", 9 | "plugin:@typescript-eslint/eslint-recommended", 10 | "plugin:@typescript-eslint/recommended", 11 | "plugin:es-x/no-new-in-es2022" 12 | ], 13 | "rules": { 14 | "prettier/prettier": "warn", 15 | "no-console": "warn", 16 | "sort-imports": [ 17 | "warn", 18 | { 19 | "ignoreCase": true, 20 | "ignoreDeclarationSort": true 21 | } 22 | ], 23 | "@typescript-eslint/explicit-module-boundary-types": "off", 24 | "@typescript-eslint/no-explicit-any": "off", 25 | "@typescript-eslint/no-namespace": "off", 26 | "@typescript-eslint/no-non-null-assertion": "off", 27 | "@typescript-eslint/no-empty-function": "warn", 28 | "@typescript-eslint/no-this-alias": "off", 29 | "no-inner-declarations": "off", 30 | "es-x/no-class-fields": "OFF", 31 | "es-x/no-export-ns-from": "OFF" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | --- 5 | 6 | ## Version of EOSJS 7 | _which version of eosjs exhibits the issue_ 8 | 9 | ### Bug 10 | A clear and concise title 11 | **Expected behavior** What you expected to happen. 12 | 13 | #### `To Reproduce` 14 | Steps to reproduce the behavior. 15 | 16 | #### `Screenshots` 17 | Always Helpful 18 | 19 | #### `Platform` 20 | - [ ] Node 21 | - [ ] Web Browser 22 | - [ ] Mobile 23 | 24 | #### `Additional Details` 25 | _version of node, version of browser, mobile os version, anything else_ 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/work_item.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Work Item 3 | about: Describes planned features and updates 4 | 5 | --- 6 | 7 | ### Work Title 8 | Summarize Desired Outcome 9 | 10 | #### `Requirements` 11 | One Sentence 12 | 13 | #### `Scenarios` 14 | 15 | ### Additional Considerations 16 | _The Following Are Optional_ 17 | 18 | #### `Design Notes` 19 | Tradeoffs, compatibility, encapsulation 20 | 21 | #### `Coding Notes` 22 | How to code it 23 | 24 | #### `Additional context` 25 | Add any other context about the problem here. 26 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Change 2 | short description 3 | 4 | ### Listing of Commits 5 | 6 | 7 | ### Listing of Files Changed 8 | 9 | 10 | ### API Changes 11 | 12 | ### Documentation Additions 13 | -------------------------------------------------------------------------------- /.github/workflow/checkin-actions: -------------------------------------------------------------------------------- 1 | name: checkin-actions 2 | on: 3 | push: 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | strategy: 10 | matrix: 11 | node-version: [18.x 19.x] 12 | 13 | steps: 14 | - name: Checkout code 15 | uses: actions/checkout@v3 16 | - name: Use Node.js ${{ matrix.node-version }} 17 | uses: actions/setup-node@v3 18 | with: 19 | node-version: ${{ matrix.node-version }} 20 | - run: npm ci 21 | - run: npm run build 22 | - run: npm run test 23 | - run: npm run test-serialization -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | # ignore webstorm IDE 3 | .idea 4 | dist/ 5 | dist-web/ 6 | node_modules/ 7 | docs-build/ 8 | *.tgz 9 | 10 | #cypress artifacts 11 | cypress/screenshots/ 12 | cypress/videos/ 13 | reports/ 14 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Exclude all files by default 2 | * 3 | 4 | # Include distribution bundle but exclude test files if they are built into dist 5 | !dist/** 6 | *.test.* 7 | 8 | # Include documentation and version information in bundle 9 | !CONTRIBUTING.md 10 | 11 | # Include any additional source files which should be bundled 12 | !src/**/*.abi.json 13 | -------------------------------------------------------------------------------- /.npmrc.template: -------------------------------------------------------------------------------- 1 | //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | arrowParens: "always" 2 | bracketSpacing: false 3 | endOfLine: "lf" 4 | printWidth: 100 5 | semi: false 6 | singleQuote: true 7 | tabWidth: 4 8 | trailingComma: "es5" -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | env: 2 | global: 3 | PUBLISH_NPM_LATEST_FROM="master" 4 | sudo: false 5 | language: node_js 6 | node_js: 7 | - '16.0.0' 8 | before_install: 9 | - npm i -g npm@8.0.0 10 | - npm install -g typescript 11 | - npm install -g webpack 12 | before_script: 13 | - source ./scripts/is_latest.sh 14 | script: 15 | - npm run lint 16 | - npm run test 17 | deploy: 18 | - provider: script 19 | skip_cleanup: true 20 | script: 21 | - ./scripts/publish-edge.sh 22 | on: 23 | branch: develop 24 | - provider: script 25 | skip_cleanup: true 26 | script: 27 | - ./scripts/publish-tag.sh $PUBLISH_NPM_LATEST_FROM 28 | on: 29 | tags: true 30 | condition: $TRAVIS_IS_LATEST_TAG = true # sourced from ./scripts/is_latest.sh 31 | notifications: 32 | webhooks: 33 | secure: bBIpgJmtb4WbXgGTD71INlC7LqscHKOWZMiBmRtkUD1X9fjNzgNVKsjf4ZlTWpq9YtKFox0bAWjS00feRYlHZZal5tZEt9wRKJbkZEgnCa32YF2YOng0Q5JxoIBskH0SSUf/qocwjPmYQu+2Y3Y9KoLoV2C72qedGgSrrMmLWSVPA91tyqPl4gOU0HS6/9KU1QNf7Uv0v7Fo10+V+JwQC03MoC2+1dkz799LuUr2SmmN3JuLWSXl9KIq7CCF7wkcqzq1vMk176mmEH1/26InNXKLXIW/MqIjMfkZq4j+IjW+JbuWz/Qh3EY+rbQAMT+++tIYHNsh2wZppvAAPjf4vqO3m9Q4WBB2KbL6EDvE/ySDURxLzZl618u8WUbJh2o61k0R0rxPPl6yFdkl9jXV48IVTHEDYHkgghtLSSENMUmjK8kshA2qreG79Mj2l2jicZ5Vn7jv4iORQHS0PUXg4ouds+5dY0SPm9aLIop6f9WD0mcQFP9mEfagWA6EnGUxTPFQDQmNVGkpZk2afYNAT4LbOd8wrqDTsNWXRvA3QLLOiqBbhajY17Fvrh24ecJ79TERABLscFkYtke8Xx2K/lKg/T10TZuaL9VbTg4rKrD+59OTZev6JlNdGG8FR31SuJK8Ds3zmiyojCoCay54BDUbmZ0STJ1/6ocUvFka0YE= 34 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to EOSJS 2 | 3 | eosjs is deprecated. Please see [WharfKit](https://github.com/wharfkit/) for an updated SDK and library. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | eosnetworkfoundation/mandel-eosjs 2 | 3 | Copyright (c) 2021-2022 EOS Network Foundation (ENF) and its contributors. All rights reserved. 4 | This ENF software is based upon: 5 | 6 | EOSIO/eosjs 7 | 8 | Copyright (c) 2017-2019 block.one and its contributors. All rights reserved. 9 | 10 | The MIT License 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | enf-eosjs ![npm](https://img.shields.io/npm/dw/enf-eosjs.svg) 2 | 3 | ## ⚠ enf-eosjs is deprecated please use [WharfKit](https://github.com/wharfkit/) as the latest EOS SDK. For a basic SDK similar to eosjs check out [WharfKit Antelope](https://github.com/wharfkit/antelope) 4 | 5 | ## Installation 6 | 7 | ### NPM 8 | 9 | [enf-eosjs](https://www.npmjs.com/package/enf-eosjs) has been updated to support latest features in EOS blockchain. This is an updated version of the popular eosjs package. 10 | 11 | ### NodeJS Dependency 12 | 13 | `npm install enf-eosjs` 14 | 15 | ### Using with Typescript 16 | 17 | If you're using Node (not a browser) then you'll also need to make sure the `dom` lib is referenced in your `tsconfig.json`: 18 | 19 | ``` 20 | { 21 | "compilerOptions": { 22 | "lib": [..., "dom"] 23 | } 24 | } 25 | ``` 26 | 27 | ### Browser Distribution 28 | 29 | Clone this repository locally then run `npm run build-web`. The browser distribution will be located in `dist-web` and can be directly copied into your project repository. The `dist-web` folder contains minified bundles ready for production, along with source mapped versions of the library for debugging. 30 | 31 | ## Getting Started 32 | 33 | Very simple example of using **enf-eosjs**. Included unused imports as examples. 34 | 35 | ```shell 36 | npm init es6 37 | npm install enf-eosjs 38 | node node_test 39 | ``` 40 | 41 | ```js 42 | /* 43 | * @module test_enf_eosjs 44 | * PUT THIS INTO A FILE NAMED node_test.js 45 | */ 46 | 47 | import { Api, JsonRpc, RpcError } from 'enf-eosjs'; 48 | import fetch from 'node-fetch' 49 | 50 | const rpc = new JsonRpc('https://localhost:443', { fetch }); 51 | const api = new Api({ rpc, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() }); 52 | 53 | var info = await rpc.get_info(); 54 | 55 | console.log(info); 56 | ``` 57 | 58 | ## Import 59 | 60 | ### Signature Providers 61 | 62 | It best to use a secure well supported secret store. Some examples of providers include: 63 | * Azure Key Vault 64 | * Hashicorp Vault 65 | * Google Cloud Secret Manager 66 | * AWS Secrets Management 67 | 68 | *JsSignatureProvider* is included as an example, and it is not provided by enf-eosjs. 69 | 70 | ### ES Modules 71 | 72 | Importing using ES6 module syntax in the browser is supported if you have a transpiler, such as Babel. 73 | ```js 74 | import { Api, JsonRpc, RpcError } from 'enf-eosjs'; 75 | import { JsSignatureProvider } from 'enf-eosjs/dist/eosjs-jssig'; // development only 76 | ``` 77 | 78 | ### CommonJS 79 | 80 | Importing using commonJS syntax is supported by NodeJS out of the box. 81 | ```js 82 | const { Api, JsonRpc, RpcError } = require('enf-eosjs'); 83 | const fetch = require('node-fetch'); // node only; not needed in browsers 84 | ``` 85 | 86 | ## Basic Usage 87 | 88 | ### Signature Provider 89 | 90 | The Signature Provider holds private keys and is responsible for signing transactions. 91 | 92 | ***Using the JsSignatureProvider in the browser is not secure and should only be used for development purposes. Use a secure vault outside of the context of the webpage to ensure security when signing transactions in production*** 93 | 94 | ```js 95 | const defaultPrivateKey = "5JtUScZK2XEp3g9gh7F8bwtPTRAkASmNrrftmx4AxDKD5K4zDnr"; // bob 96 | const signatureProvider = new JsSignatureProvider([defaultPrivateKey]); 97 | ``` 98 | 99 | ### JSON-RPC 100 | 101 | Open a connection to JSON-RPC, include `fetch` when on NodeJS. 102 | ```js 103 | const rpc = new JsonRpc('http://127.0.0.1:8888', { fetch }); 104 | ``` 105 | 106 | ### API 107 | 108 | No longer need to include textDecoder and textEncoder when using in Node, React Native, IE11 or Edge Browsers. 109 | ```js 110 | const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() }); 111 | ``` 112 | 113 | ### Sending a transaction 114 | 115 | `transact()` is used to sign and push transactions onto the blockchain with an optional configuration object parameter. This parameter can override the default value of `broadcast: true`, and can be used to fill TAPOS fields given `blocksBehind` and `expireSeconds`. Given no configuration options, transactions are expected to be unpacked with TAPOS fields (`expiration`, `ref_block_num`, `ref_block_prefix`) and will automatically be broadcast onto the chain. 116 | 117 | With the introduction of Leap v3.1 the retry transaction feature also adds 5 new optional fields to the configuration object: 118 | 119 | - `useOldRPC`: use old RPC `push_transaction`, rather than new RPC send_transaction 120 | - `useOldSendRPC`: use old RPC `/v1/chain/send_transaction`, rather than new RPC `/v1/chain/send_transaction2` 121 | - `returnFailureTrace`: return partial traces on failed transactions 122 | - `retryTrxNumBlocks`: request node to retry transaction until in a block of given height, blocking call 123 | - `retryIrreversible`: request node to retry transaction until it is irreversible or expires, blocking call 124 | 125 | ```js 126 | (async () => { 127 | const result = await api.transact({ 128 | actions: [{ 129 | account: 'eosio.token', 130 | name: 'transfer', 131 | authorization: [{ 132 | actor: 'useraaaaaaaa', 133 | permission: 'active', 134 | }], 135 | data: { 136 | from: 'useraaaaaaaa', 137 | to: 'useraaaaaaab', 138 | quantity: '0.0001 SYS', 139 | memo: '', 140 | }, 141 | }] 142 | }, { 143 | blocksBehind: 3, 144 | expireSeconds: 30 145 | }); 146 | console.dir(result); 147 | })(); 148 | ``` 149 | 150 | ### Read Only Transactions 151 | Leap 4.0 introduced read only transaction. A read-only transaction does not change the state and is not added into the blockchain. It is useful for users to retrieve complex chain information. 152 | 153 | ```js 154 | /* 155 | * Read Only transaciton can not modify state 156 | * In this example a special read only action in a custom contract is executed 157 | * Note the empty fields for authoriziation and data. 158 | */ 159 | const readonlyTransfer = async () => 160 | await api.transact( 161 | { 162 | actions: [ 163 | { 164 | account: testActor, 165 | name: 'getvalue', 166 | authorization: [], 167 | data: {}, 168 | }, 169 | ], 170 | }, 171 | { 172 | broadcast: true, 173 | readOnly: true, 174 | blocksBehind: 3, 175 | expireSeconds: 72, 176 | } 177 | ) 178 | // execute the read only transaction 179 | const transactionReadOnlyResponse = await readonlyTransfer(); 180 | // processed.receipt has status,cpu_usage_us,net_usage_words 181 | console.log(`Transaction Id ${transactionReadOnlyResponse.transaction_id} CPU Usage ${transactionReadOnlyResponse.processed.receipt.cpu_usage_us}`) 182 | ``` 183 | 184 | ### Error handling 185 | 186 | use `RpcError` for handling RPC Errors 187 | ```js 188 | ... 189 | try { 190 | const result = await api.transact({ 191 | ... 192 | } catch (e) { 193 | console.log('\nCaught exception: ' + e); 194 | if (e instanceof RpcError) 195 | console.log(JSON.stringify(e.json, null, 2)); 196 | } 197 | ... 198 | ``` 199 | 200 | ## Contributing 201 | 202 | [Contributing Guide](./CONTRIBUTING.md) 203 | 204 | [Code of Conduct](./CONTRIBUTING.md#conduct) 205 | 206 | ## License 207 | 208 | [MIT](./LICENSE) 209 | 210 | ## Important 211 | 212 | See LICENSE for copyright and license terms. This work is made on a voluntary basis as a member of the EOSIO community and is not responsible for ensuring the overall performance of the software or any related applications. We make no representation, warranty, guarantee or undertaking in respect of the software or any related documentation, whether expressed or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall we be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or documentation or the use or other dealings in the software or documentation. Any test results or performance figures are indicative and will not reflect performance under all conditions. Any reference to any third party or third-party product, service or other resource is not an endorsement or recommendation by Block.one. We are not responsible, and disclaim any and all responsibility and liability, for your use of or reliance on any of these resources. Third-party resources may be updated, changed or terminated at any time, so the information here may be out of date or inaccurate. Any person using or offering this software in connection with providing software, goods or services to third parties shall advise such third parties of these license terms, disclaimers and exclusions of liability. Block.one, EOSIO, EOSIO Labs, EOS, EOS Network Foundation. 213 | 214 | Wallets and related components are complex software that require the highest levels of security. If incorrectly built or used, they may compromise users’ private keys and digital assets. Wallet applications and related components should undergo thorough security evaluations before being used. Only experienced developers should work with this software. 215 | -------------------------------------------------------------------------------- /cypress/integration/index.spec.js: -------------------------------------------------------------------------------- 1 | describe('eosjs web test', () => { 2 | it('loads', () => { 3 | cy.visit(('./src/tests/web.html')); 4 | }); 5 | it('runs all tests successfully', () => { 6 | cy.visit(('./src/tests/web.html')) 7 | cy.get('div.tests>div>button').each((test) => { // iterate through all the tests 8 | cy.wrap(test).click(); // click the button to start the test 9 | cy.wrap(test).contains('Success', { timeout: 5000 }); // wait 5 seconds for success or treat as failure 10 | cy.wait(500); // allow time for transaction to confirm (prevents duplicate transactions) 11 | }); 12 | }); 13 | }) 14 | -------------------------------------------------------------------------------- /docs/2.-Transaction-Examples.md: -------------------------------------------------------------------------------- 1 | # Transactions 2 | 3 | To send transactions and trigger actions on the blockchain, you must have an instance of `Api`. 4 | 5 | The signature provider must contain the private keys corresponding to the actors and permission requirements of the actions being executed. 6 | 7 | 8 | ## CommonJS 9 | 10 | ```javascript 11 | const { Api, JsonRpc } = require('eosjs'); 12 | const { JsSignatureProvider } = require('eosjs/dist/eosjs-jssig'); // development only 13 | const fetch = require('node-fetch'); // node only 14 | const { TextDecoder, TextEncoder } = require('util'); // node only 15 | const { TextEncoder, TextDecoder } = require('text-util'); // React Native, IE11, and Edge Browsers only 16 | 17 | const privateKeys = [privateKey1]; 18 | 19 | const signatureProvider = new JsSignatureProvider(privateKeys); 20 | const rpc = new JsonRpc('http://127.0.0.1:8888', { fetch }); 21 | const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() }); 22 | ``` 23 | 24 | ## ES Modules 25 | 26 | ```javascript 27 | import { Api, JsonRpc } from 'eosjs'; 28 | import { JsSignatureProvider } from 'eosjs/dist/eosjs-jssig'; // development only 29 | 30 | const privateKeys = [privateKey1]; 31 | 32 | const signatureProvider = new JsSignatureProvider(privateKeys); 33 | const rpc = new JsonRpc('http://127.0.0.1:8888'); 34 | const api = new Api({ rpc, signatureProvider }) 35 | ``` 36 | 37 | ## Examples 38 | 39 | ### Buy ram 40 | 41 | ```javascript 42 | const result = await api.transact({ 43 | actions: [{ 44 | account: 'eosio', 45 | name: 'buyrambytes', 46 | authorization: [{ 47 | actor: 'useraaaaaaaa', 48 | permission: 'active', 49 | }], 50 | data: { 51 | payer: 'useraaaaaaaa', 52 | receiver: 'useraaaaaaaa', 53 | bytes: 8192, 54 | }, 55 | }] 56 | }, { 57 | blocksBehind: 3, 58 | expireSeconds: 30, 59 | }); 60 | ``` 61 | 62 | ### Stake 63 | 64 | ```javascript 65 | const result = await api.transact({ 66 | actions: [{ 67 | account: 'eosio', 68 | name: 'delegatebw', 69 | authorization: [{ 70 | actor: 'useraaaaaaaa', 71 | permission: 'active', 72 | }], 73 | data: { 74 | from: 'useraaaaaaaa', 75 | receiver: 'useraaaaaaaa', 76 | stake_net_quantity: '1.0000 SYS', 77 | stake_cpu_quantity: '1.0000 SYS', 78 | transfer: false, 79 | } 80 | }] 81 | }, { 82 | blocksBehind: 3, 83 | expireSeconds: 30, 84 | }); 85 | ``` 86 | 87 | ## Example: Unstake 88 | 89 | ```javascript 90 | const result = await api.transact({ 91 | actions: [{ 92 | account: 'eosio', 93 | name: 'undelegatebw', 94 | authorization: [{ 95 | actor: 'useraaaaaaaa', 96 | permission: 'active', 97 | }], 98 | data: { 99 | from: 'useraaaaaaaa', 100 | receiver: 'useraaaaaaaa', 101 | unstake_net_quantity: '1.0000 SYS', 102 | unstake_cpu_quantity: '1.0000 SYS', 103 | transfer: false, 104 | } 105 | }] 106 | }, { 107 | blocksBehind: 3, 108 | expireSeconds: 30, 109 | }); 110 | ``` 111 | 112 | ### Create New Account (multiple actions) 113 | 114 | ```javascript 115 | const result = await api.transact({ 116 | actions: [{ 117 | account: 'eosio', 118 | name: 'newaccount', 119 | authorization: [{ 120 | actor: 'useraaaaaaaa', 121 | permission: 'active', 122 | }], 123 | data: { 124 | creator: 'useraaaaaaaa', 125 | name: 'mynewaccount', 126 | owner: { 127 | threshold: 1, 128 | keys: [{ 129 | key: 'PUB_R1_6FPFZqw5ahYrR9jD96yDbbDNTdKtNqRbze6oTDLntrsANgQKZu', 130 | weight: 1 131 | }], 132 | accounts: [], 133 | waits: [] 134 | }, 135 | active: { 136 | threshold: 1, 137 | keys: [{ 138 | key: 'PUB_R1_6FPFZqw5ahYrR9jD96yDbbDNTdKtNqRbze6oTDLntrsANgQKZu', 139 | weight: 1 140 | }], 141 | accounts: [], 142 | waits: [] 143 | }, 144 | }, 145 | }, 146 | { 147 | account: 'eosio', 148 | name: 'buyrambytes', 149 | authorization: [{ 150 | actor: 'useraaaaaaaa', 151 | permission: 'active', 152 | }], 153 | data: { 154 | payer: 'useraaaaaaaa', 155 | receiver: 'mynewaccount', 156 | bytes: 8192, 157 | }, 158 | }, 159 | { 160 | account: 'eosio', 161 | name: 'delegatebw', 162 | authorization: [{ 163 | actor: 'useraaaaaaaa', 164 | permission: 'active', 165 | }], 166 | data: { 167 | from: 'useraaaaaaaa', 168 | receiver: 'mynewaccount', 169 | stake_net_quantity: '1.0000 SYS', 170 | stake_cpu_quantity: '1.0000 SYS', 171 | transfer: false, 172 | } 173 | }] 174 | }, { 175 | blocksBehind: 3, 176 | expireSeconds: 30, 177 | }); 178 | ``` 179 | ## Old RPC Behavior 180 | 181 | By default, transactions use the send_transaction2 endpoint and the updated transaction behavior. If you would like to revert to the previous behavior pass in the boolean **useOldSendRPC** with value True. 182 | [See Readme *Sending A Transaction*](../README.md#Sending%20a%20transaction) for additional paramaters. 183 | 184 | ```javascript 185 | const result = await api.transact({ 186 | actions: [{ 187 | account: 'eosio', 188 | name: 'delegatebw', 189 | authorization: [{ 190 | actor: 'useraaaaaaaa', 191 | permission: 'active', 192 | }], 193 | data: { 194 | from: 'useraaaaaaaa', 195 | receiver: 'useraaaaaaaa', 196 | stake_net_quantity: '1.0000 SYS', 197 | stake_cpu_quantity: '1.0000 SYS', 198 | transfer: false, 199 | } 200 | }] 201 | }, { 202 | blocksBehind: 3, 203 | expireSeconds: 30, 204 | useOldSendRPC: true, 205 | }); 206 | ``` -------------------------------------------------------------------------------- /docs/3.-Browsers.md: -------------------------------------------------------------------------------- 1 | # Browsers 2 | 3 | ## Usage 4 | `npm run build-web` 5 | 6 | Reuse the `api` object for all transactions; it caches ABIs to reduce network usage. Only call `new eosjs_api.Api(...)` once. 7 | 8 | ```html 9 |

10 | 
11 | 
12 | 
13 | 
14 | 
50 | ```
51 | 
52 | ## Debugging
53 | 
54 | If you would like readable source files for debugging, change the file reference to the `-debug.js` files inside `dist-web/debug` directory.  These files should only be used for development as they are over 10 times as large as the minified versions, and importing the debug versions will increase loading times for the end user.
55 | 
56 | ## IE11 and Edge Support
57 | If you need to support IE11 or Edge you will also need to install a text-encoding polyfill as eosjs Signing is dependent on the TextEncoder which IE11 and Edge do not provide.  Pass the TextEncoder and TextDecoder to the API constructor as demonstrated in the [ES 2015 example](#node-es-2015).  Refer to the documentation here https://github.com/inexorabletash/text-encoding to determine the best way to include it in your project.
58 | 


--------------------------------------------------------------------------------
/docs/4.-Reading blockchain-Examples.md:
--------------------------------------------------------------------------------
  1 | # Reading blockchain
  2 | 
  3 | Reading blockchain state only requires an instance of `JsonRpc` connected to a node.
  4 | 
  5 | ```javascript
  6 | const { JsonRpc } = require('eosjs');
  7 | const fetch = require('node-fetch');           // node only; not needed in browsers
  8 | const rpc = new JsonRpc('http://localhost:8888', { fetch });
  9 | ```
 10 | 
 11 | ## Examples
 12 | 
 13 | ### Get table rows
 14 | 
 15 | Get the first 10 token balances of account _testacc_.
 16 | 
 17 | ```javascript
 18 | const resp = await rpc.get_table_rows({
 19 |     json: true,              // Get the response as json
 20 |     code: 'eosio.token',     // Contract that we target
 21 |     scope: 'testacc',        // Account that owns the data
 22 |     table: 'accounts',       // Table name
 23 |     limit: 10,               // Maximum number of rows that we want to get
 24 |     reverse: false,          // Optional: Get reversed data
 25 |     show_payer: false,       // Optional: Show ram payer
 26 | });
 27 | 
 28 | console.log(resp.rows);
 29 | ```
 30 | Output:
 31 | 
 32 | ```json
 33 | {
 34 |   "rows": [{
 35 |       "balance": "100.0000 HAK"
 36 |     }
 37 |   ],
 38 |   "more": false
 39 | }
 40 | ```
 41 | 
 42 | ### Get one row by index
 43 | 
 44 | ```javascript
 45 | const resp = await rpc.get_table_rows({
 46 |     json: true,                 // Get the response as json
 47 |     code: 'contract',           // Contract that we target
 48 |     scope: 'contract',          // Account that owns the data
 49 |     table: 'profiles',          // Table name
 50 |     lower_bound: 'testacc',     // Table primary key value
 51 |     limit: 1,                   // Here we limit to 1 to get only the
 52 |     reverse: false,             // Optional: Get reversed data
 53 |     show_payer: false,          // Optional: Show ram payer
 54 | });
 55 | console.log(resp.rows);
 56 | ```
 57 | Output:
 58 | 
 59 | ```json
 60 | {
 61 |   "rows": [{
 62 |       "user": "testacc",
 63 |       "age": 21,
 64 |       "surname": "Martin"
 65 |     }
 66 |   ],
 67 |   "more": false
 68 | }
 69 | ```
 70 | 
 71 | ### Get one row by secondary index
 72 | 
 73 | ```javascript
 74 | const resp = await rpc.get_table_rows({
 75 |     json: true,                 // Get the response as json
 76 |     code: 'contract',           // Contract that we target
 77 |     scope: 'contract',          // Account that owns the data
 78 |     table: 'profiles',          // Table name
 79 |     table_key: 'age',           // Table secondaray key name
 80 |     lower_bound: 21,            // Table secondary key value
 81 |     limit: 1,                   // Here we limit to 1 to get only row
 82 |     reverse: false,             // Optional: Get reversed data
 83 |     show_payer: false,          // Optional: Show ram payer
 84 | });
 85 | console.log(resp.rows);
 86 | ```
 87 | Output:
 88 | 
 89 | ```json
 90 | {
 91 |   "rows": [{
 92 |       "user": "testacc",
 93 |       "age": 21,
 94 |       "surname": "Martin"
 95 |     }
 96 |   ],
 97 |   "more": false
 98 | }
 99 | ```
100 | 
101 | ### Get currency balance
102 | 
103 | ```javascript
104 | console.log(await rpc.get_currency_balance('eosio.token', 'testacc', 'HAK'));
105 | ```
106 | Output:
107 | 
108 | ```json
109 | [ "1000000000.0000 HAK" ]
110 | ```
111 | 
112 | ### Get account info
113 | 
114 | ```javascript
115 | console.log(await rpc.get_account('testacc'));
116 | ```
117 | Output:
118 | 
119 | ```json
120 | { "account_name": "testacc",
121 |   "head_block_num": 1079,
122 |   "head_block_time": "2018-11-10T00:45:53.500",
123 |   "privileged": false,
124 |   "last_code_update": "1970-01-01T00:00:00.000",
125 |   "created": "2018-11-10T00:37:05.000",
126 |   "ram_quota": -1,
127 |   "net_weight": -1,
128 |   "cpu_weight": -1,
129 |   "net_limit": { "used": -1, "available": -1, "max": -1 },
130 |   "cpu_limit": { "used": -1, "available": -1, "max": -1 },
131 |   "ram_usage": 2724,
132 |   "permissions":
133 |    [ { "perm_name": "active", "parent": "owner", "required_auth": [] },
134 |      { "perm_name": "owner", "parent": "", "required_auth": [] } ],
135 |   "total_resources": null,
136 |   "self_delegated_bandwidth": null,
137 |   "refund_request": null,
138 |   "voter_info": null }
139 | ```
140 | 
141 | ### Get block
142 | 
143 | ```javascript
144 | console.log(await rpc.get_block(1));
145 | ```
146 | Output:
147 | 
148 | ```json
149 | { "timestamp": "2018-06-01T12:00:00.000",
150 |   "producer": "",
151 |   "confirmed": 1,
152 |   "previous": "0000000000000000000000000000000000000000000000000000000000000000",
153 |   "transaction_mroot": "0000000000000000000000000000000000000000000000000000000000000000",
154 |   "action_mroot": "cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f",
155 |   "schedule_version": 0,
156 |   "new_producers": null,
157 |   "header_extensions": [],
158 |   "producer_signature": "SIG_K1_111111111111111111111111111111111111111111111111111111111111111116uk5ne",
159 |   "transactions": [],
160 |   "block_extensions": [],
161 |   "id": "00000001bcf2f448225d099685f14da76803028926af04d2607eafcf609c265c",
162 |   "block_num": 1,
163 |   "ref_block_prefix": 2517196066 }
164 | ```
165 | 


--------------------------------------------------------------------------------
/docs/5.-Testing and Building with DUNE.md:
--------------------------------------------------------------------------------
 1 | # Testing and Building with DUNE
 2 | 
 3 | DUNE makes it easier to test locally. Performing integration tests with DUNE requires some setup.
 4 | [DUNE may be installed from git hub](https://github.com/eosnetworkfoundation/DUNE)
 5 | 
 6 | ## Open Local Node Port
 7 | 
 8 | Need to change **scripts/config.ini** from `http-server-address = 127.0.0.1:8888` to `http-server-address = 0.0.0.0:8888`. This will enable port 8888 to listen on all ports, and that is needed because docker runs on a different network.
 9 | 
10 | This is part of the docker image, so this must be completed before running `bootstrap`. If you already have a docker image you can
11 | * Destroy the docker container
12 | * Remove docker image
13 | * Re-run bootstrap
14 | 
15 | An alternative option is to enter the docker container, change the configuration, and restart the node.
16 | 
17 | ## DUNE Keys
18 | 
19 | Once you follow the directions you need to grap the keys for the existing eosio account.
20 | 
21 | ```
22 | egrep 'priv_key|pub_key' src/dune/*.py
23 | ```
24 | 
25 | ## Start a Node
26 | 
27 | Start a node if you haven't already
28 | ```
29 | dune --start test_node
30 | ```
31 | 
32 | ## Create Wallet
33 | Start a Docker shell. Must be done locally due to permission problems with DUNE. 
34 | ```
35 | docker exec -it dune_container /bin/bash
36 | ```
37 | Commands to make wallet 
38 | ```
39 | cleos wallet create -n bob -f jungle4-wallet/bob.wallet
40 | cleos wallet unlock -n bobtestlion1 --password $(cat jungle4-wallet/bob.wallet)
41 | ```
42 | 
43 | ## Create Accounts
44 | 
45 | Now we can create our test accounts. In the examples below replace, **priv_key** and **pub_key** with the values from [DUNE Keys](#DUNE Keys)
46 | 
47 | ```
48 | dune --create-key
49 | dune --create-account bob eosio pub_key priv_key
50 | dune --create-key
51 | dune --create-account alice eosio pub_key priv_key
52 | ```
53 | 
54 | ## Add Private Key to Wallet
55 | 
56 | Use bob's priv_key
57 | Note done locally
58 | ```
59 | cleos wallet import -n bobtestlion1 --private-key priv_key
60 | ```
61 | 
62 | ## Test Transfer
63 | Note done locally
64 | ```
65 | cleos transfer bob alice "0.001 EOS" "Hodl!" -p bob
66 | ```
67 | 
68 | ## Private Keys in Tests
69 | 
70 | Look at `src/tests/node.js` and `src/tests/web.html` to make sure the private key matches DUNE's.
71 | 
72 | ## Run Tests
73 | 
74 | ```
75 | npm run test node
76 | ```
77 | 
78 | If you want just the integration tests run.
79 | ```angular2html
80 | npm run test-node
81 | ```
82 | 


--------------------------------------------------------------------------------
/docs/Testing ReadOnly.md:
--------------------------------------------------------------------------------
1 | The read only contract requires a special contract. You can find the source code under `src/tests/readonly_contract`. 
2 | Once compiled the contracted is loaded via the command `cleos -u https://jungle4.cryptolions.io set contract hokieshokies ./ contract.wasm contract.abi`
3 | The action on `read-only` test will refer to `mycontract`, and with the contract loaded you will be able to run the test


--------------------------------------------------------------------------------
/docs/design/Cryptography.md:
--------------------------------------------------------------------------------
1 | # Summary
2 | 
3 | Place holder for future notes on better design patterns.
4 | 


--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "enf-eosjs",
 3 |   "version": "23.0.0",
 4 |   "description": "JS API to talk to eos blockchain",
 5 |   "main": "dist/index.js",
 6 |   "scripts": {
 7 |     "cypress": "cypress run --spec 'cypress/integration/index.spec.js'",
 8 |     "cypress-ui": "cypress open",
 9 |     "prepare": "npm run build",
10 |     "lint": "eslint --ext .js,.jsx,.ts,.tsx src",
11 |     "test": "jest src/tests/*eosjs*",
12 |     "test-serialization": "jest src/tests/serialization.test.ts",
13 |     "test-node": "jest src/tests/node.test.ts",
14 |     "test-all": "npm run test && npm run test-node && npm run test-serialization && npm run cypress",
15 |     "build": "tsc -p ./tsconfig.json && cp src/ripemd.es5.js dist/ripemd.js",
16 |     "build-web": "webpack --config webpack.prod.js && webpack --config webpack.debug.js",
17 |     "build-production": "npm run build && npm run build-web && npm run test-all",
18 |     "clean": "rm -rf dist",
19 |     "docs-init": "sh .docs/scripts/init.sh",
20 |     "docs-build": "sh .docs/scripts/build.sh",
21 |     "docs-serve": "python -m SimpleHTTPServer",
22 |     "docs-publish": "sh .docs/scripts/publish.sh"
23 |   },
24 |   "author": "eosnetworkfoundation",
25 |   "license": "MIT",
26 |   "repository": {
27 |     "type": "git",
28 |     "url": "https://github.com/eosnetworkfoundation/mandel-eosjs"
29 |   },
30 |   "dependencies": {
31 |     "bn.js": "5.2.0",
32 |     "elliptic": "6.5.4",
33 |     "hash.js": "1.1.7",
34 |     "node-fetch": "2.6.7"
35 |   },
36 |   "devDependencies": {
37 |     "@types/elliptic": "^6.4.13",
38 |     "@types/jest": "^26.0.24",
39 |     "@types/node-fetch": "^2.6.3",
40 |     "@typescript-eslint/eslint-plugin": "^5.51.0",
41 |     "@typescript-eslint/parser": "^5.51.0",
42 |     "buffer": "^6.0.3",
43 |     "cypress": "^7.7.0",
44 |     "eslint": "^8.33.0",
45 |     "eslint-config-prettier": "^8.6.0",
46 |     "eslint-plugin-es-x": "^6.0.0",
47 |     "eslint-plugin-prettier": "^4.2.1",
48 |     "jest": "^26.6.3",
49 |     "jest-extended": "^0.11.5",
50 |     "jest-fetch-mock": "^3.0.3",
51 |     "none": "^1.0.0",
52 |     "prettier": "2.8.4",
53 |     "text-encoding": "^0.7.0",
54 |     "ts-jest": "^26.5.6",
55 |     "ts-loader": "^9.4.3",
56 |     "typedoc": "^0.24.6",
57 |     "typedoc-plugin-markdown": "^3.15.2",
58 |     "typescript": "^4.9.5",
59 |     "webpack": "^5.44.0",
60 |     "webpack-cli": "^5.1.3"
61 |   },
62 |   "jest": {
63 |     "automock": false,
64 |     "setupFiles": [
65 |       "./src/tests/setupJest.js"
66 |     ],
67 |     "setupFilesAfterEnv": [
68 |       "jest-extended"
69 |     ],
70 |     "moduleFileExtensions": [
71 |       "ts",
72 |       "tsx",
73 |       "js"
74 |     ],
75 |     "transform": {
76 |       "^.+\\.(tsx?)$": "ts-jest"
77 |     },
78 |     "globals": {
79 |       "ts-jest": {
80 |         "tsconfig": "tsconfig.json"
81 |       }
82 |     },
83 |     "testRegex": "(/src/.*(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
84 |     "testEnvironment": "node"
85 |   }
86 | }
87 | 


--------------------------------------------------------------------------------
/scripts/is_latest.sh:
--------------------------------------------------------------------------------
 1 | is_latest=false;
 2 | 
 3 | current_commit="$(git rev-parse HEAD)";
 4 | tags="$(git tag --sort=-creatordate)";
 5 | 
 6 | IFS='\n' read -ra arry <<< "$tags"
 7 | 
 8 | latest_tag="${arry[0]}"
 9 | 
10 | if [ "$latest_tag" == "" ]; then 
11 |     latest_tag="v0.0.0";
12 | else
13 |     tag_commit="$(git rev-list -n 1 ${latest_tag})";
14 |     if [ "$tag_commit" == "$current_commit" ]; then
15 |         is_latest=true;
16 |     fi
17 | fi
18 | 
19 | echo "tag_commit: ${tag_commit}";
20 | echo "current_commit: ${current_commit}";
21 | echo "is_latest: ${is_latest}";
22 | 
23 | export TRAVIS_IS_LATEST_TAG="$is_latest"


--------------------------------------------------------------------------------
/scripts/publish-edge.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/bash
 2 | 
 3 | . "${TRAVIS_BUILD_DIR}/scripts/publish-utils.sh";
 4 | 
 5 | echo "Running on branch/tag ${TRAVIS_BRANCH}":
 6 | 
 7 | echo "Setting up git"
 8 | setup_git
 9 | 
10 | echo "Creating new version"
11 | git checkout -- .
12 | 
13 | git status 
14 | 
15 | # get the short commit hash to include in the npm package
16 | current_commit="$(git rev-parse --short HEAD)";
17 | 
18 | npm version prerelease -preid "${current_commit}" -no-git-tag-version
19 | 
20 | git commit -a -m "Updating version [skip ci]"
21 | 
22 | echo "Publish to NPM"
23 | 
24 | cp .npmrc.template $HOME/.npmrc 
25 | 
26 | npm publish --tag edge


--------------------------------------------------------------------------------
/scripts/publish-tag.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/bash
 2 | 
 3 | . "${TRAVIS_BUILD_DIR}/scripts/publish-utils.sh";
 4 | 
 5 | if [[ "$TRAVIS_TAG" == "" ]]; then
 6 |   echo "No tag specified, skipping...";
 7 | else
 8 |   echo "Running on branch/tag ${TRAVIS_TAG}":
 9 | 
10 |   echo "Setting up git"
11 |   setup_git
12 | 
13 |   echo "Creating new version"
14 |   git checkout -- .
15 | 
16 |   git status
17 | 
18 |   npm version -no-git-tag-version $TRAVIS_TAG
19 | 
20 |   echo "Pushing to git"
21 |   git commit -a -m "Publishing version ${TRAVIS_TAG} [skip ci]"
22 | 
23 |   git push origin HEAD:${1}
24 | 
25 |   echo "Build and Publish to NPM"
26 | 
27 |   cp .npmrc.template $HOME/.npmrc 
28 | 
29 |   if [[ "$TRAVIS_TAG" == *"-beta"* ]]; then
30 |     echo "Publishing with beta tag to npm"
31 |     npm publish --tag beta
32 |   else
33 |     echo "Publishing with latest tag to npm"
34 |     npm publish
35 |   fi
36 | fi
37 | 
38 | 


--------------------------------------------------------------------------------
/scripts/publish-utils.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/bash
 2 | 
 3 | setup_git() {
 4 |   # Set the user name and email to match the API token holder
 5 |   # This will make sure the git commits will have the correct photo
 6 |   # and the user gets the credit for a checkin
 7 |   git config --global user.email "eric.passmore@gmail.com"
 8 |   git config --global user.name "ericpassmore"
 9 |   git config --global push.default matching
10 |   
11 |   # Get the credentials from a file
12 |   git config credential.helper "store --file=.git/credentials"
13 |   
14 |   # This associates the API Key with the account
15 |   echo "https://${GITHUB_API_KEY}:@github.com" > .git/credentials
16 | }


--------------------------------------------------------------------------------
/scripts/run-cypress.sh:
--------------------------------------------------------------------------------
 1 | RUNMODE=$1
 2 | 
 3 | if [ "$RUNMODE" == "" ]; then
 4 |   RUNMODE="headless"
 5 | fi
 6 | 
 7 | if [ "$RUNMODE" == "ui" ]; then
 8 |   echo
 9 |   echo -e "\033[34mOpen Cypress UI...\033[0m"
10 |   cypress open
11 | else
12 |   {
13 |     echo
14 |     echo -e "\033[34mCypress run...\033[0m"
15 |     cypress run --reporter mochawesome --spec 'cypress/integration/index.spec.js'
16 |   } || {
17 |     EXIT_CODE=1
18 |   }
19 | fi
20 | 
21 | exit $EXIT_CODE
22 | 


--------------------------------------------------------------------------------
/scripts/simple-publish.sh:
--------------------------------------------------------------------------------
1 | 
2 | 
3 | npm login
4 | npm publish


--------------------------------------------------------------------------------
/src/ChainSemanticVersion.ts:
--------------------------------------------------------------------------------
  1 | interface CleanedVersion {
  2 |     version: string
  3 |     hasReleaseCandidate: boolean
  4 |     parsingError: boolean
  5 | }
  6 | 
  7 | interface MajorMinorPatch {
  8 |     major: number
  9 |     minor: number
 10 |     patch?: number
 11 | }
 12 | 
 13 | export class ChainSemanticVersion {
 14 |     public semverString: CleanedVersion
 15 | 
 16 |     /**
 17 |      *
 18 |      * @param info is a version string, starts with 'v' and followed by semver seperated by '. Example 'v4.0.1'
 19 |      *
 20 |      */
 21 |     constructor(info: string) {
 22 |         this.semverString = this.stripReleaseCandidate(this.stripLeadingV(info))
 23 |     }
 24 | 
 25 |     public supportsLeap3Features(): boolean {
 26 |         const versionObject = this.getMajorMinorVersion()
 27 |         // must be major version 3 with minor version 1 or better
 28 |         // note v3.1.0-rc1 is a pre-v3.1.0 release and does not support 3.0 features
 29 |         return (
 30 |             // better then 3 ok!
 31 |             versionObject.major > 3 ||
 32 |             // version 3 must be version 1 or better
 33 |             (versionObject.major == 3 &&
 34 |                 ((versionObject.minor == 1 && !this.semverString.hasReleaseCandidate)
 35 |                 ||
 36 |                 versionObject.minor > 1)
 37 |             )
 38 |         )
 39 |     }
 40 | 
 41 |     public supportsLeap4Features(): boolean {
 42 |         const versionObject = this.getMajorMinorVersion()
 43 |         // must be major version 4 with minor version 0 or better
 44 |         // note v4.0.0-rc1 is a pre-v4.0.0 release and does not support 4.0 features
 45 |         return (
 46 |             // better then 4 ok!
 47 |             versionObject.major > 4 ||
 48 |             (versionObject.major == 4 && versionObject.minor > 0) ||
 49 |             // RC versions of v4.0.0 will not work. RC version of other version will work
 50 |             // Treat patch level undefined as patch level 0
 51 |             (versionObject.major == 4 &&
 52 |                 !(
 53 |                     versionObject.minor == 0 &&
 54 |                     (versionObject.patch == 0 || versionObject.patch == null) &&
 55 |                     this.semverString.hasReleaseCandidate
 56 |                 ))
 57 |         )
 58 |     }
 59 | 
 60 |     private stripLeadingV(info: string): string {
 61 |         if (info.startsWith('v')) {
 62 |             return info.slice(1)
 63 |         } else {
 64 |             return info
 65 |         }
 66 |     }
 67 | 
 68 |     private stripReleaseCandidate(info: string): CleanedVersion {
 69 |         const versionString = info.split('-')
 70 |         if (versionString.length > 1) {
 71 |             return {
 72 |                 version: versionString[0],
 73 |                 hasReleaseCandidate: true,
 74 |                 parsingError: false,
 75 |             }
 76 |         }
 77 |         return {
 78 |             version: info,
 79 |             hasReleaseCandidate: false,
 80 |             parsingError: false,
 81 |         }
 82 |     }
 83 | 
 84 |     private getMajorMinorVersion(): MajorMinorPatch {
 85 |         const semVersions = this.semverString.version.split('.')
 86 |         // expect at least major and minor version
 87 |         if (semVersions.length < 2) {
 88 |             this.semverString.parsingError = true
 89 |             return {major: 0, minor: 0}
 90 |         }
 91 |         // expect a number
 92 |         if (isNaN(parseInt(semVersions[0])) || isNaN(parseInt(semVersions[1]))) {
 93 |             this.semverString.parsingError = true
 94 |             return {major: 0, minor: 0}
 95 |         }
 96 |         let patch = undefined
 97 |         if (semVersions.length > 2 && !isNaN(parseInt(semVersions[2]))) {
 98 |             patch = parseInt(semVersions[2])
 99 |         }
100 |         return {major: parseInt(semVersions[0]), minor: parseInt(semVersions[1]), patch: patch}
101 |     }
102 | }
103 | 


--------------------------------------------------------------------------------
/src/PrivateKey.ts:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright (c) 2022 EOS Network Foundation (ENF) and its contributors.  All rights reserved.
  3 |  * Copyright (c) 2017-2020 block.one and its contributors.  All rights reserved.
  4 |  * MIT License
  5 |  * Oct 12, 2022 sourced from https://github.com/EOSIO/eosjs/archive/refs/tags/v22.1.0.zip
  6 |  */
  7 | 
  8 | import { BNInput, ec as EC } from 'elliptic';
  9 | import {
 10 |     Key,
 11 |     KeyType,
 12 |     privateKeyToLegacyString,
 13 |     privateKeyToString,
 14 |     stringToPrivateKey,
 15 | } from './eosjs-numeric';
 16 | import { constructElliptic, PublicKey, Signature } from './eosjs-key-conversions';
 17 | 
 18 | /** Represents/stores a private key and provides easy conversion for use with `elliptic` lib */
 19 | export class PrivateKey {
 20 |     constructor(private key: Key, private ec: EC) {}
 21 | 
 22 |     /** Instantiate private key from an `elliptic`-format private key */
 23 |     public static fromElliptic(privKey: EC.KeyPair, keyType: KeyType, ec?: EC): PrivateKey {
 24 |         if (!ec) {
 25 |             ec = constructElliptic(keyType);
 26 |         }
 27 |         return new PrivateKey({
 28 |             type: keyType,
 29 |             data: privKey.getPrivate().toArrayLike(Buffer, 'be', 32),
 30 |         }, ec);
 31 |     }
 32 | 
 33 |     /** Instantiate private key from an EOS-format private key */
 34 |     public static fromString(keyString: string, ec?: EC): PrivateKey {
 35 |         const privateKey = stringToPrivateKey(keyString);
 36 |         if (!ec) {
 37 |             ec = constructElliptic(privateKey.type);
 38 |         }
 39 |         return new PrivateKey(privateKey, ec);
 40 |     }
 41 | 
 42 |     /** Export private key as `elliptic`-format private key */
 43 |     public toElliptic(): EC.KeyPair {
 44 |         return this.ec.keyFromPrivate(this.key.data);
 45 |     }
 46 | 
 47 |     public toLegacyString(): string {
 48 |         return privateKeyToLegacyString(this.key);
 49 |     }
 50 | 
 51 |     /** Export private key as EOS-format private key */
 52 |     public toString(): string {
 53 |         return privateKeyToString(this.key);
 54 |     }
 55 | 
 56 |     /** Get key type from key */
 57 |     public getType(): KeyType {
 58 |         return this.key.type;
 59 |     }
 60 | 
 61 |     /** Retrieve the public key from a private key */
 62 |     public getPublicKey(): PublicKey {
 63 |         const ellipticPrivateKey = this.toElliptic();
 64 |         return PublicKey.fromElliptic(ellipticPrivateKey, this.getType(), this.ec);
 65 |     }
 66 | 
 67 |     /** Sign a message or hashed message digest with private key */
 68 |     public sign(data: BNInput, shouldHash: boolean = true, encoding: BufferEncoding = 'utf8'): Signature {
 69 |         if (shouldHash) {
 70 |             if (typeof data === 'string') {
 71 |                 data = Buffer.from(data, encoding);
 72 |             }
 73 |             data = this.ec.hash().update(data).digest();
 74 |         }
 75 |         let tries = 0;
 76 |         let signature: Signature;
 77 |         const isCanonical = (sigData: Uint8Array): boolean =>
 78 |             !(sigData[1] & 0x80) && !(sigData[1] === 0 && !(sigData[2] & 0x80))
 79 |             && !(sigData[33] & 0x80) && !(sigData[33] === 0 && !(sigData[34] & 0x80));
 80 |         const constructSignature = (options: EC.SignOptions): Signature => {
 81 |             const ellipticPrivateKey = this.toElliptic();
 82 |             const ellipticSignature = ellipticPrivateKey.sign(data, options);
 83 |             return Signature.fromElliptic(ellipticSignature, this.getType(), this.ec);
 84 |         };
 85 | 
 86 |         if (this.key.type === KeyType.k1) {
 87 |             do {
 88 |                 signature = constructSignature({canonical: true, pers: [++tries]});
 89 |             } while (!isCanonical(signature.toBinary()));
 90 |         } else {
 91 |             signature = constructSignature({canonical: true});
 92 |         }
 93 |         return signature;
 94 |     }
 95 | 
 96 |     /** Validate a private key */
 97 |     public isValid(): boolean {
 98 |         try {
 99 |             const ellipticPrivateKey = this.toElliptic();
100 |             const validationObj = ellipticPrivateKey.validate();
101 |             return validationObj.result;
102 |         } catch {
103 |             return false;
104 |         }
105 |     }
106 | }
107 | 


--------------------------------------------------------------------------------
/src/PublicKey.ts:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2022 EOS Network Foundation (ENF) and its contributors.  All rights reserved.
 3 |  * Copyright (c) 2017-2020 block.one and its contributors.  All rights reserved.
 4 |  * MIT License
 5 |  * Oct 12, 2022 sourced from https://github.com/EOSIO/eosjs/archive/refs/tags/v22.1.0.zip
 6 |  */
 7 | 
 8 | import { ec as EC } from 'elliptic';
 9 | import {
10 |     Key,
11 |     KeyType,
12 |     publicKeyToLegacyString,
13 |     publicKeyToString,
14 |     stringToPublicKey,
15 | } from './eosjs-numeric';
16 | import { constructElliptic } from './eosjs-key-conversions';
17 | 
18 | /** Represents/stores a public key and provides easy conversion for use with `elliptic` lib */
19 | export class PublicKey {
20 |     constructor(private key: Key, private ec: EC) {}
21 | 
22 |     /** Instantiate public key from an EOS-format public key */
23 |     public static fromString(publicKeyStr: string, ec?: EC): PublicKey {
24 |         const key = stringToPublicKey(publicKeyStr);
25 |         if (!ec) {
26 |             ec = constructElliptic(key.type);
27 |         }
28 |         return new PublicKey(key, ec);
29 |     }
30 | 
31 |     /** Instantiate public key from an `elliptic`-format public key */
32 |     public static fromElliptic(publicKey: EC.KeyPair, keyType: KeyType, ec?: EC): PublicKey {
33 |         const x = publicKey.getPublic().getX().toArray('be', 32);
34 |         const y = publicKey.getPublic().getY().toArray('be', 32);
35 |         if (!ec) {
36 |             ec = constructElliptic(keyType);
37 |         }
38 |         return new PublicKey({
39 |             type: keyType,
40 |             data: new Uint8Array([(y[31] & 1) ? 3 : 2].concat(x)),
41 |         }, ec);
42 |     }
43 | 
44 |     /** Export public key as EOSIO-format public key */
45 |     public toString(): string {
46 |         return publicKeyToString(this.key);
47 |     }
48 | 
49 |     /** Export public key as Legacy EOS-format public key */
50 |     public toLegacyString(): string {
51 |         return publicKeyToLegacyString(this.key);
52 |     }
53 | 
54 |     /** Export public key as `elliptic`-format public key */
55 |     public toElliptic(): EC.KeyPair {
56 |         return this.ec.keyPair({
57 |             pub: Buffer.from(this.key.data),
58 |         });
59 |     }
60 | 
61 |     /** Get key type from key */
62 |     public getType(): KeyType {
63 |         return this.key.type;
64 |     }
65 | 
66 |     /** Validate a public key */
67 |     public isValid(): boolean {
68 |         try {
69 |             const ellipticPublicKey = this.toElliptic();
70 |             const validationObj = ellipticPublicKey.validate();
71 |             return validationObj.result;
72 |         } catch {
73 |             return false;
74 |         }
75 |     }
76 | }
77 | 


--------------------------------------------------------------------------------
/src/Signature.ts:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright (c) 2022 EOS Network Foundation (ENF) and its contributors.  All rights reserved.
  3 |  * Copyright (c) 2017-2020 block.one and its contributors.  All rights reserved.
  4 |  * MIT License
  5 |  * Oct 12, 2022 sourced from https://github.com/EOSIO/eosjs/archive/refs/tags/v22.1.0.zip
  6 |  */
  7 | 
  8 | import { BNInput, ec as EC } from 'elliptic';
  9 | import BN = require('bn.js');
 10 | 
 11 | import {
 12 |     Key,
 13 |     KeyType,
 14 |     signatureToString,
 15 |     stringToSignature,
 16 | } from './eosjs-numeric';
 17 | import { constructElliptic, PublicKey } from './eosjs-key-conversions';
 18 | 
 19 | /** Represents/stores a Signature and provides easy conversion for use with `elliptic` lib */
 20 | export class Signature {
 21 |     constructor(private signature: Key, private ec: EC) {}
 22 | 
 23 |     /** Instantiate Signature from an EOS-format Signature */
 24 |     public static fromString(sig: string, ec?: EC): Signature {
 25 |         const signature = stringToSignature(sig);
 26 |         if (!ec) {
 27 |             ec = constructElliptic(signature.type);
 28 |         }
 29 |         return new Signature(signature, ec);
 30 |     }
 31 | 
 32 |     /** Instantiate Signature from an `elliptic`-format Signature */
 33 |     public static fromElliptic(ellipticSig: EC.Signature, keyType: KeyType, ec?: EC): Signature {
 34 |         const r = ellipticSig.r.toArray('be', 32);
 35 |         const s = ellipticSig.s.toArray('be', 32);
 36 |         let eosioRecoveryParam;
 37 |         if (keyType === KeyType.k1 || keyType === KeyType.r1) {
 38 |             eosioRecoveryParam = ellipticSig.recoveryParam + 27;
 39 |             if (ellipticSig.recoveryParam <= 3) {
 40 |                 eosioRecoveryParam += 4;
 41 |             }
 42 |         } else if (keyType === KeyType.wa) {
 43 |             eosioRecoveryParam = ellipticSig.recoveryParam;
 44 |         }
 45 |         const sigData = new Uint8Array([eosioRecoveryParam].concat(r, s));
 46 |         if (!ec) {
 47 |             ec = constructElliptic(keyType);
 48 |         }
 49 |         return new Signature({
 50 |             type: keyType,
 51 |             data: sigData,
 52 |         }, ec);
 53 |     }
 54 | 
 55 |     /** Export Signature as `elliptic`-format Signature
 56 |      * NOTE: This isn't an actual elliptic-format Signature, as ec.Signature is not exported by the library.
 57 |      * That's also why the return type is `any`.  We're *actually* returning an object with the 3 params
 58 |      * not an ec.Signature.
 59 |      * Further NOTE: @types/elliptic shows ec.Signature as exported; it is *not*.  Hence the `any`.
 60 |      */
 61 |     public toElliptic(): any {
 62 |         const lengthOfR = 32;
 63 |         const lengthOfS = 32;
 64 |         const r = new BN(this.signature.data.slice(1, lengthOfR + 1));
 65 |         const s = new BN(this.signature.data.slice(lengthOfR + 1, lengthOfR + lengthOfS + 1));
 66 | 
 67 |         let ellipticRecoveryBitField;
 68 |         if (this.signature.type === KeyType.k1 || this.signature.type === KeyType.r1) {
 69 |             ellipticRecoveryBitField = this.signature.data[0] - 27;
 70 |             if (ellipticRecoveryBitField > 3) {
 71 |                 ellipticRecoveryBitField -= 4;
 72 |             }
 73 |         } else if (this.signature.type === KeyType.wa) {
 74 |             ellipticRecoveryBitField = this.signature.data[0];
 75 |         }
 76 |         const recoveryParam = ellipticRecoveryBitField & 3;
 77 |         return { r, s, recoveryParam };
 78 |     }
 79 | 
 80 |     /** Export Signature as EOSIO-format Signature */
 81 |     public toString(): string {
 82 |         return signatureToString(this.signature);
 83 |     }
 84 | 
 85 |     /** Export Signature in binary format */
 86 |     public toBinary(): Uint8Array {
 87 |         return this.signature.data;
 88 |     }
 89 | 
 90 |     /** Get key type from signature */
 91 |     public getType(): KeyType {
 92 |         return this.signature.type;
 93 |     }
 94 | 
 95 |     /** Verify a signature with a message or hashed message digest and public key */
 96 |     public verify(data: BNInput, publicKey: PublicKey, shouldHash: boolean = true, encoding: BufferEncoding = 'utf8'): boolean {
 97 |         if (shouldHash) {
 98 |             if (typeof data === 'string') {
 99 |                 data = Buffer.from(data, encoding);
100 |             }
101 |             data = this.ec.hash().update(data).digest();
102 |         }
103 |         const ellipticSignature = this.toElliptic();
104 |         const ellipticPublicKey = publicKey.toElliptic();
105 |         return this.ec.verify(data, ellipticSignature, ellipticPublicKey, encoding);
106 |     }
107 | 
108 |     /** Recover a public key from a message or hashed message digest and signature */
109 |     public recover(data: BNInput, shouldHash: boolean = true, encoding: BufferEncoding = 'utf8'): PublicKey {
110 |         if (shouldHash) {
111 |             if (typeof data === 'string') {
112 |                 data = Buffer.from(data, encoding);
113 |             }
114 |             data = this.ec.hash().update(data).digest();
115 |         }
116 |         const ellipticSignature = this.toElliptic();
117 |         const recoveredPublicKey = this.ec.recoverPubKey(
118 |             data,
119 |             ellipticSignature,
120 |             ellipticSignature.recoveryParam,
121 |             encoding
122 |         );
123 |         const ellipticKPub = this.ec.keyFromPublic(recoveredPublicKey);
124 |         return PublicKey.fromElliptic(ellipticKPub, this.getType(), this.ec);
125 |     }
126 | }
127 | 


--------------------------------------------------------------------------------
/src/abi.abi.json:
--------------------------------------------------------------------------------
  1 | {
  2 |     "version": "eosio::abi/1.1",
  3 |     "structs": [
  4 |         {
  5 |             "name": "extensions_entry",
  6 |             "base": "",
  7 |             "fields": [
  8 |                 {
  9 |                     "name": "tag",
 10 |                     "type": "uint16"
 11 |                 },
 12 |                 {
 13 |                     "name": "value",
 14 |                     "type": "bytes"
 15 |                 }
 16 |             ]
 17 |         },
 18 |         {
 19 |             "name": "type_def",
 20 |             "base": "",
 21 |             "fields": [
 22 |                 {
 23 |                     "name": "new_type_name",
 24 |                     "type": "string"
 25 |                 },
 26 |                 {
 27 |                     "name": "type",
 28 |                     "type": "string"
 29 |                 }
 30 |             ]
 31 |         },
 32 |         {
 33 |             "name": "field_def",
 34 |             "base": "",
 35 |             "fields": [
 36 |                 {
 37 |                     "name": "name",
 38 |                     "type": "string"
 39 |                 },
 40 |                 {
 41 |                     "name": "type",
 42 |                     "type": "string"
 43 |                 }
 44 |             ]
 45 |         },
 46 |         {
 47 |             "name": "struct_def",
 48 |             "base": "",
 49 |             "fields": [
 50 |                 {
 51 |                     "name": "name",
 52 |                     "type": "string"
 53 |                 },
 54 |                 {
 55 |                     "name": "base",
 56 |                     "type": "string"
 57 |                 },
 58 |                 {
 59 |                     "name": "fields",
 60 |                     "type": "field_def[]"
 61 |                 }
 62 |             ]
 63 |         },
 64 |         {
 65 |             "name": "action_def",
 66 |             "base": "",
 67 |             "fields": [
 68 |                 {
 69 |                     "name": "name",
 70 |                     "type": "name"
 71 |                 },
 72 |                 {
 73 |                     "name": "type",
 74 |                     "type": "string"
 75 |                 },
 76 |                 {
 77 |                     "name": "ricardian_contract",
 78 |                     "type": "string"
 79 |                 }
 80 |             ]
 81 |         },
 82 |         {
 83 |             "name": "table_def",
 84 |             "base": "",
 85 |             "fields": [
 86 |                 {
 87 |                     "name": "name",
 88 |                     "type": "name"
 89 |                 },
 90 |                 {
 91 |                     "name": "index_type",
 92 |                     "type": "string"
 93 |                 },
 94 |                 {
 95 |                     "name": "key_names",
 96 |                     "type": "string[]"
 97 |                 },
 98 |                 {
 99 |                     "name": "key_types",
100 |                     "type": "string[]"
101 |                 },
102 |                 {
103 |                     "name": "type",
104 |                     "type": "string"
105 |                 }
106 |             ]
107 |         },
108 |         {
109 |             "name": "clause_pair",
110 |             "base": "",
111 |             "fields": [
112 |                 {
113 |                     "name": "id",
114 |                     "type": "string"
115 |                 },
116 |                 {
117 |                     "name": "body",
118 |                     "type": "string"
119 |                 }
120 |             ]
121 |         },
122 |         {
123 |             "name": "error_message",
124 |             "base": "",
125 |             "fields": [
126 |                 {
127 |                     "name": "error_code",
128 |                     "type": "uint64"
129 |                 },
130 |                 {
131 |                     "name": "error_msg",
132 |                     "type": "string"
133 |                 }
134 |             ]
135 |         },
136 |         {
137 |             "name": "variant_def",
138 |             "base": "",
139 |             "fields": [
140 |                 {
141 |                     "name": "name",
142 |                     "type": "string"
143 |                 },
144 |                 {
145 |                     "name": "types",
146 |                     "type": "string[]"
147 |                 }
148 |             ]
149 |         },
150 |         {
151 |             "name": "abi_def",
152 |             "base": "",
153 |             "fields": [
154 |                 {
155 |                     "name": "version",
156 |                     "type": "string"
157 |                 },
158 |                 {
159 |                     "name": "types",
160 |                     "type": "type_def[]"
161 |                 },
162 |                 {
163 |                     "name": "structs",
164 |                     "type": "struct_def[]"
165 |                 },
166 |                 {
167 |                     "name": "actions",
168 |                     "type": "action_def[]"
169 |                 },
170 |                 {
171 |                     "name": "tables",
172 |                     "type": "table_def[]"
173 |                 },
174 |                 {
175 |                     "name": "ricardian_clauses",
176 |                     "type": "clause_pair[]"
177 |                 },
178 |                 {
179 |                     "name": "error_messages",
180 |                     "type": "error_message[]"
181 |                 },
182 |                 {
183 |                     "name": "abi_extensions",
184 |                     "type": "extensions_entry[]"
185 |                 },
186 |                 {
187 |                     "name": "variants",
188 |                     "type": "variant_def[]$"
189 |                 }
190 |             ]
191 |         }
192 |     ]
193 | }
194 | 


--------------------------------------------------------------------------------
/src/eosjs-api-interfaces.ts:
--------------------------------------------------------------------------------
 1 | // copyright defined in eosjs/LICENSE.txt
 2 | 
 3 | import { Abi, PushTransactionArgs } from './eosjs-rpc-interfaces';
 4 | 
 5 | /** Arguments to `getRequiredKeys` */
 6 | export interface AuthorityProviderArgs {
 7 |     /** Transaction that needs to be signed */
 8 |     transaction: any;
 9 | 
10 |     /** Public keys associated with the private keys that the `SignatureProvider` holds */
11 |     availableKeys: string[];
12 | }
13 | 
14 | /** Get subset of `availableKeys` needed to meet authorities in `transaction` */
15 | export interface AuthorityProvider {
16 |     /** Get subset of `availableKeys` needed to meet authorities in `transaction` */
17 |     getRequiredKeys: (args: AuthorityProviderArgs) => Promise;
18 | }
19 | 
20 | /** Retrieves raw ABIs for a specified accountName */
21 | export interface AbiProvider {
22 |     /** Retrieve the BinaryAbi */
23 |     getRawAbi: (accountName: string) => Promise;
24 | }
25 | 
26 | /** Structure for the raw form of ABIs */
27 | export interface BinaryAbi {
28 |     /** account which has deployed the ABI */
29 |     accountName: string;
30 | 
31 |     /** abi in binary form */
32 |     abi: Uint8Array;
33 | }
34 | 
35 | /** Holds a fetched abi */
36 | export interface CachedAbi {
37 |     /** abi in binary form */
38 |     rawAbi: Uint8Array;
39 | 
40 |     /** abi in structured form */
41 |     abi: Abi;
42 | }
43 | 
44 | /** Arguments to `sign` */
45 | export interface SignatureProviderArgs {
46 |     /** Chain transaction is for */
47 |     chainId: string;
48 | 
49 |     /** Public keys associated with the private keys needed to sign the transaction */
50 |     requiredKeys: string[];
51 | 
52 |     /** Transaction to sign */
53 |     serializedTransaction: Uint8Array;
54 | 
55 |     /** Context-free data to sign */
56 |     serializedContextFreeData?: Uint8Array;
57 | 
58 |     /** ABIs for all contracts with actions included in `serializedTransaction` */
59 |     abis: BinaryAbi[];
60 | }
61 | 
62 | /** Signs transactions */
63 | export interface SignatureProvider {
64 |     /** Public keys associated with the private keys that the `SignatureProvider` holds */
65 |     getAvailableKeys: () => Promise;
66 | 
67 |     /** Sign a transaction */
68 |     sign: (args: SignatureProviderArgs) => Promise;
69 | }
70 | 


--------------------------------------------------------------------------------
/src/eosjs-jsonrpc.ts:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * @module JSON-RPC
  3 |  */
  4 | // copyright defined in eosjs/LICENSE.txt
  5 | 
  6 | import {
  7 |     AbiProvider,
  8 |     AuthorityProvider,
  9 |     AuthorityProviderArgs,
 10 |     BinaryAbi,
 11 | } from './eosjs-api-interfaces'
 12 | import { base64ToBinary, convertLegacyPublicKeys } from './eosjs-numeric'
 13 | import {
 14 |     GetAbiResult,
 15 |     GetBlockHeaderStateResult,
 16 |     GetBlockResult,
 17 |     GetCodeResult,
 18 |     GetInfoResult,
 19 |     GetRawCodeAndAbiResult,
 20 |     PushTransactionArgs,
 21 |     SendTransaction2Args,
 22 | } from './eosjs-rpc-interfaces' // tslint:disable-line
 23 | import { RpcError } from './eosjs-rpcerror'
 24 | 
 25 | function arrayToHex(data: Uint8Array) {
 26 |     let result = ''
 27 |     for (const x of data) {
 28 |         result += ('00' + x.toString(16)).slice(-2)
 29 |     }
 30 |     return result
 31 | }
 32 | 
 33 | /** Make RPC calls */
 34 | export class JsonRpc implements AuthorityProvider, AbiProvider {
 35 |     public endpoint: string
 36 |     public fetchBuiltin: (input?: Request | string, init?: RequestInit) => Promise
 37 | 
 38 |     /**
 39 |      * @param endpoint
 40 |      * @param args
 41 |      *    * `fetch`:
 42 |      *    * browsers: leave `null` or `undefined`
 43 |      *    * node: provide an implementation
 44 |      */
 45 |     constructor(
 46 |         endpoint: string,
 47 |         args: {fetch?: (input?: string | Request, init?: RequestInit) => Promise} = {}
 48 |     ) {
 49 |         this.endpoint = endpoint.replace(/\/$/, '')
 50 |         if (args.fetch) {
 51 |             this.fetchBuiltin = args.fetch
 52 |         } else {
 53 |             this.fetchBuiltin = (global as any).fetch
 54 |         }
 55 |     }
 56 | 
 57 |     /** Post `body` to `endpoint + path`. Throws detailed error information in `RpcError` when available. */
 58 |     public async fetch(path: string, body: any) {
 59 |         let response
 60 |         let json
 61 |         try {
 62 |             const f = this.fetchBuiltin
 63 |             response = await f(this.endpoint + path, {
 64 |                 body: JSON.stringify(body),
 65 |                 method: 'POST',
 66 |             })
 67 |             json = await response.json()
 68 |             if (json.processed && json.processed.except) {
 69 |                 throw new RpcError(json)
 70 |             }
 71 |         } catch (e) {
 72 |             e.isFetchError = true
 73 |             throw e
 74 |         }
 75 |         if (!response.ok) {
 76 |             throw new RpcError(json)
 77 |         }
 78 |         return json
 79 |     }
 80 | 
 81 |     /** Raw call to `/v1/chain/get_abi` */
 82 |     public async get_abi(accountName: string): Promise {
 83 |         return await this.fetch('/v1/chain/get_abi', {account_name: accountName})
 84 |     }
 85 | 
 86 |     /** Raw call to `/v1/chain/get_account` */
 87 |     public async get_account(accountName: string): Promise {
 88 |         return await this.fetch('/v1/chain/get_account', {account_name: accountName})
 89 |     }
 90 | 
 91 |     /** Raw call to `/v1/chain/get_block_header_state` */
 92 |     public async get_block_header_state(
 93 |         blockNumOrId: number | string
 94 |     ): Promise {
 95 |         return await this.fetch('/v1/chain/get_block_header_state', {block_num_or_id: blockNumOrId})
 96 |     }
 97 | 
 98 |     /** Raw call to `/v1/chain/get_block` */
 99 |     public async get_block(blockNumOrId: number | string): Promise {
100 |         return await this.fetch('/v1/chain/get_block', {block_num_or_id: blockNumOrId})
101 |     }
102 | 
103 |     /** Raw call to `/v1/chain/get_code` */
104 |     public async get_code(accountName: string): Promise {
105 |         return await this.fetch('/v1/chain/get_code', {account_name: accountName})
106 |     }
107 | 
108 |     /** Raw call to `/v1/chain/get_currency_balance` */
109 |     public async get_currency_balance(
110 |         code: string,
111 |         account: string,
112 |         symbol: string = null
113 |     ): Promise {
114 |         return await this.fetch('/v1/chain/get_currency_balance', {code, account, symbol})
115 |     }
116 | 
117 |     /** Raw call to `/v1/chain/get_currency_stats` */
118 |     public async get_currency_stats(code: string, symbol: string): Promise {
119 |         return await this.fetch('/v1/chain/get_currency_stats', {code, symbol})
120 |     }
121 | 
122 |     /** Raw call to `/v1/chain/get_info` */
123 |     public async get_info(): Promise {
124 |         return await this.fetch('/v1/chain/get_info', {})
125 |     }
126 | 
127 |     /** Raw call to `/v1/chain/get_producer_schedule` */
128 |     public async get_producer_schedule(): Promise {
129 |         return await this.fetch('/v1/chain/get_producer_schedule', {})
130 |     }
131 | 
132 |     /** Raw call to `/v1/chain/get_producers` */
133 |     public async get_producers(json = true, lowerBound = '', limit = 50): Promise {
134 |         return await this.fetch('/v1/chain/get_producers', {json, lower_bound: lowerBound, limit})
135 |     }
136 | 
137 |     /** Raw call to `/v1/chain/get_raw_code_and_abi` */
138 |     public async get_raw_code_and_abi(accountName: string): Promise {
139 |         return await this.fetch('/v1/chain/get_raw_code_and_abi', {account_name: accountName})
140 |     }
141 | 
142 |     /** calls `/v1/chain/get_raw_code_and_abi` and pulls out unneeded raw wasm code */
143 |     // TODO: use `/v1/chain/get_raw_abi` directly when it becomes available
144 |     public async getRawAbi(accountName: string): Promise {
145 |         const rawCodeAndAbi = await this.get_raw_code_and_abi(accountName)
146 |         const abi = base64ToBinary(rawCodeAndAbi.abi)
147 |         return {accountName: rawCodeAndAbi.account_name, abi}
148 |     }
149 | 
150 |     /** Raw call to `/v1/chain/get_scheduled_transactions` */
151 |     public async get_scheduled_transactions(
152 |         json = true,
153 |         lowerBound = '',
154 |         limit = 50
155 |     ): Promise {
156 |         return await this.fetch('/v1/chain/get_scheduled_transactions', {
157 |             json,
158 |             lower_bound: lowerBound,
159 |             limit,
160 |         })
161 |     }
162 | 
163 |     /** Raw call to `/v1/chain/get_table_rows` */
164 |     public async get_table_rows({
165 |         json = true,
166 |         code,
167 |         scope,
168 |         table,
169 |         table_key = '',
170 |         lower_bound = '',
171 |         upper_bound = '',
172 |         index_position = 1,
173 |         key_type = '',
174 |         limit = 10,
175 |         reverse = false,
176 |         show_payer = false,
177 |     }: any): Promise {
178 |         return await this.fetch('/v1/chain/get_table_rows', {
179 |             json,
180 |             code,
181 |             scope,
182 |             table,
183 |             table_key,
184 |             lower_bound,
185 |             upper_bound,
186 |             index_position,
187 |             key_type,
188 |             limit,
189 |             reverse,
190 |             show_payer,
191 |         })
192 |     }
193 | 
194 |     /** Raw call to `/v1/chain/get_table_by_scope` */
195 |     public async get_table_by_scope({
196 |         code,
197 |         table,
198 |         lower_bound = '',
199 |         upper_bound = '',
200 |         limit = 10,
201 |     }: any): Promise {
202 |         return await this.fetch('/v1/chain/get_table_by_scope', {
203 |             code,
204 |             table,
205 |             lower_bound,
206 |             upper_bound,
207 |             limit,
208 |         })
209 |     }
210 | 
211 |     /** Get subset of `availableKeys` needed to meet authorities in `transaction`. Implements `AuthorityProvider` */
212 |     public async getRequiredKeys(args: AuthorityProviderArgs): Promise {
213 |         return convertLegacyPublicKeys(
214 |             (
215 |                 await this.fetch('/v1/chain/get_required_keys', {
216 |                     transaction: args.transaction,
217 |                     available_keys: args.availableKeys,
218 |                 })
219 |             ).required_keys
220 |         )
221 |     }
222 | 
223 |     /** Push a serialized transaction (replaced by send_transaction, but returned format has changed) */
224 |     public async push_transaction({
225 |         signatures,
226 |         serializedTransaction,
227 |         serializedContextFreeData,
228 |     }: PushTransactionArgs): Promise {
229 |         return await this.fetch('/v1/chain/push_transaction', {
230 |             signatures,
231 |             compression: 0,
232 |             packed_context_free_data: arrayToHex(serializedContextFreeData || new Uint8Array(0)),
233 |             packed_trx: arrayToHex(serializedTransaction),
234 |         })
235 |     }
236 | 
237 |     /** Send a serialized transaction */
238 |     public async send_transaction({
239 |         signatures,
240 |         serializedTransaction,
241 |         serializedContextFreeData,
242 |     }: PushTransactionArgs): Promise {
243 |         return await this.fetch('/v1/chain/send_transaction', {
244 |             signatures,
245 |             compression: 0,
246 |             packed_context_free_data: arrayToHex(serializedContextFreeData || new Uint8Array(0)),
247 |             packed_trx: arrayToHex(serializedTransaction),
248 |         })
249 |     }
250 | 
251 |     /** Send a serialized transaction2 */
252 |     public async send_transaction2({
253 |         return_failure_trace,
254 |         retry_trx,
255 |         retry_trx_num_blocks,
256 |         transaction: {signatures, serializedTransaction, serializedContextFreeData},
257 |     }: SendTransaction2Args): Promise {
258 |         return await this.fetch('/v1/chain/send_transaction2', {
259 |             return_failure_trace,
260 |             retry_trx,
261 |             retry_trx_num_blocks,
262 |             transaction: {
263 |                 signatures,
264 |                 compression: 0,
265 |                 packed_context_free_data: arrayToHex(
266 |                     serializedContextFreeData || new Uint8Array(0)
267 |                 ),
268 |                 packed_trx: arrayToHex(serializedTransaction),
269 |             },
270 |         })
271 |     }
272 | 
273 |     /** Send readonly transaction */
274 |     public async send_readonly_transaction({
275 |         signatures,
276 |         serializedTransaction,
277 |         serializedContextFreeData,
278 |     }: PushTransactionArgs): Promise {
279 |         return await this.fetch('/v1/chain/send_read_only_transaction', {
280 |             transaction: {
281 |                 signatures,
282 |                 compression: 0,
283 |                 packed_context_free_data: arrayToHex(
284 |                     serializedContextFreeData || new Uint8Array(0)
285 |                 ),
286 |                 packed_trx: arrayToHex(serializedTransaction),
287 |             },
288 |         })
289 |     }
290 | 
291 |     /** Raw call to `/v1/db_size/get` */
292 |     public async db_size_get() {
293 |         return await this.fetch('/v1/db_size/get', {})
294 |     }
295 | 
296 |     /** Raw call to `/v1/history/get_actions` */
297 |     public async history_get_actions(
298 |         accountName: string,
299 |         pos: number = null,
300 |         offset: number = null
301 |     ) {
302 |         return await this.fetch('/v1/history/get_actions', {account_name: accountName, pos, offset})
303 |     }
304 | 
305 |     /** Raw call to `/v1/history/get_transaction` */
306 |     public async history_get_transaction(id: string, blockNumHint: number = null) {
307 |         return await this.fetch('/v1/history/get_transaction', {id, block_num_hint: blockNumHint})
308 |     }
309 | 
310 |     /** Raw call to `/v1/history/get_key_accounts` */
311 |     public async history_get_key_accounts(publicKey: string) {
312 |         return await this.fetch('/v1/history/get_key_accounts', {public_key: publicKey})
313 |     }
314 | 
315 |     /** Raw call to `/v1/history/get_controlled_accounts` */
316 |     public async history_get_controlled_accounts(controllingAccount: string) {
317 |         return await this.fetch('/v1/history/get_controlled_accounts', {
318 |             controlling_account: controllingAccount,
319 |         })
320 |     }
321 | } // JsonRpc
322 | 


--------------------------------------------------------------------------------
/src/eosjs-jssig.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @module JS-Sig
 3 |  */
 4 | 
 5 | /*
 6 |  * Copyright (c) 2022 EOS Network Foundation (ENF) and its contributors.  All rights reserved.
 7 |  * Copyright (c) 2017-2020 block.one and its contributors.  All rights reserved.
 8 |  * MIT License
 9 |  * Oct 12, 2022 modified using source from https://github.com/EOSIO/eosjs/archive/refs/tags/v22.1.0.zip
10 |  */
11 | 
12 | import { ec } from 'elliptic';
13 | 
14 | import { SignatureProvider, SignatureProviderArgs } from './eosjs-api-interfaces';
15 | import { PushTransactionArgs } from './eosjs-rpc-interfaces';
16 | import {
17 |     PrivateKey,
18 |     PublicKey,
19 |     Signature,
20 | } from './eosjs-key-conversions';
21 | import { convertLegacyPublicKey } from './eosjs-numeric';
22 | 
23 | /** expensive to construct; so we do it once and reuse it */
24 | const defaultEc = new ec('secp256k1');
25 | 
26 | /** Construct the digest from transaction details */
27 | const digestFromSerializedData = (
28 |     chainId: string,
29 |     serializedTransaction: Uint8Array,
30 |     serializedContextFreeData?: Uint8Array,
31 |     e = defaultEc): string => {
32 |     const signBuf = Buffer.concat([
33 |         Buffer.from(chainId, 'hex'),
34 |         Buffer.from(serializedTransaction),
35 |         Buffer.from(
36 |             serializedContextFreeData ?
37 |                 new Uint8Array(e.hash().update(serializedContextFreeData).digest()) :
38 |                 new Uint8Array(32)
39 |         ),
40 |     ]);
41 |     return e.hash().update(signBuf).digest();
42 | };
43 | 
44 | /** Signs transactions using in-process private keys */
45 | class JsSignatureProvider implements SignatureProvider {
46 |     /** map public to private keys */
47 |     public keys = new Map();
48 | 
49 |     /** public keys */
50 |     public availableKeys = [] as string[];
51 | 
52 |     /** @param privateKeys private keys to sign with */
53 |     constructor(privateKeys: string[]) {
54 |         for (const k of privateKeys) {
55 |             const priv = PrivateKey.fromString(k);
56 |             const privElliptic = priv.toElliptic();
57 |             const pubStr = priv.getPublicKey().toString();
58 |             this.keys.set(pubStr, privElliptic);
59 |             this.availableKeys.push(pubStr);
60 |         }
61 |     }
62 | 
63 |     /** Public keys associated with the private keys that the `SignatureProvider` holds */
64 |     public async getAvailableKeys(): Promise {
65 |         return this.availableKeys;
66 |     }
67 | 
68 |     /** Sign a transaction */
69 |     public async sign(
70 |         { chainId, requiredKeys, serializedTransaction, serializedContextFreeData }: SignatureProviderArgs,
71 |     ): Promise {
72 |         const digest = digestFromSerializedData( chainId, serializedTransaction, serializedContextFreeData, defaultEc);
73 | 
74 |         const signatures = [] as string[];
75 |         for (const key of requiredKeys) {
76 |             const publicKey = PublicKey.fromString(key);
77 |             const ellipticPrivateKey = this.keys.get(convertLegacyPublicKey(key));
78 |             const privateKey = PrivateKey.fromElliptic(ellipticPrivateKey, publicKey.getType());
79 |             const signature = privateKey.sign(digest, false);
80 |             signatures.push(signature.toString());
81 |         }
82 | 
83 |         return { signatures, serializedTransaction, serializedContextFreeData };
84 |     }
85 | }
86 | 
87 | export {
88 |     PrivateKey,
89 |     PublicKey,
90 |     Signature,
91 |     digestFromSerializedData,
92 |     JsSignatureProvider,
93 | };
94 | 


--------------------------------------------------------------------------------
/src/eosjs-key-conversions.ts:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright (c) 2022 EOS Network Foundation (ENF) and its contributors.  All rights reserved.
 3 |  * Copyright (c) 2017-2020 block.one and its contributors.  All rights reserved.
 4 |  * MIT License
 5 |  * Oct 12, 2022 sourced from https://github.com/EOSIO/eosjs/archive/refs/tags/v22.1.0.zip
 6 |  */
 7 | 
 8 | import {ec as EC} from 'elliptic';
 9 | import * as hash from 'hash.js';
10 | import {KeyType} from './eosjs-numeric';
11 | import { PublicKey } from './PublicKey';
12 | import { PrivateKey } from './PrivateKey';
13 | 
14 | export { PrivateKey } from './PrivateKey';
15 | export { PublicKey } from './PublicKey';
16 | export { Signature } from './Signature';
17 | 
18 | /** Construct the elliptic curve object based on key type */
19 | export const constructElliptic = (type: KeyType): EC => {
20 |     if (type === KeyType.k1) {
21 |         return new EC('secp256k1');
22 |     }
23 |     return new EC('p256');
24 | };
25 | 
26 | export const generateKeyPair = (
27 |     type: KeyType, options: { secureEnv?: boolean, ecOptions?: EC.GenKeyPairOptions } = {}
28 | ): { publicKey: PublicKey, privateKey: PrivateKey } => {
29 |     if (!options.secureEnv) {
30 |         throw new Error('Key generation is completely INSECURE in production environments in the browser. ' +
31 |             'If you are absolutely certain this does NOT describe your environment, set `secureEnv` in your ' +
32 |             'options to `true`.  If this does describe your environment and you set `secureEnv` to `true`, ' +
33 |             'YOU DO SO AT YOUR OWN RISK AND THE RISK OF YOUR USERS.');
34 |     }
35 |     let ec;
36 |     if (type === KeyType.k1) {
37 |         ec = new EC('secp256k1');
38 |     } else {
39 |         ec = new EC('p256');
40 |     }
41 |     const ellipticKeyPair = ec.genKeyPair(options.ecOptions);
42 |     const publicKey = PublicKey.fromElliptic(ellipticKeyPair, type, ec);
43 |     const privateKey = PrivateKey.fromElliptic(ellipticKeyPair, type, ec);
44 |     return {publicKey, privateKey};
45 | };
46 | 
47 | export const sha256 = (data: string|Buffer): number[]|string => {
48 |     return hash.sha256().update(data).digest();
49 | };
50 | 


--------------------------------------------------------------------------------
/src/eosjs-numeric.ts:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * @module Numeric
  3 |  */
  4 | 
  5 | /*
  6 |  * Copyright (c) 2022 EOS Network Foundation (ENF) and its contributors.  All rights reserved.
  7 |  * Copyright (c) 2017-2020 block.one and its contributors.  All rights reserved.
  8 |  * MIT License
  9 |  * Oct 12, 2022 modified using source from https://github.com/EOSIO/eosjs/archive/refs/tags/v22.1.0.zip
 10 |  */
 11 | 
 12 | import { sha256 } from 'hash.js';
 13 | 
 14 | // copyright defined in eosjs/LICENSE.txt
 15 | 
 16 | const ripemd160 = require('./ripemd').RIPEMD160.hash as (a: Uint8Array) => ArrayBuffer;
 17 | 
 18 | const base58Chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
 19 | const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 20 | 
 21 | const create_base58_map = (): number[] => {
 22 |     const base58M = Array(256).fill(-1) as number[];
 23 |     for (let i = 0; i < base58Chars.length; ++i) {
 24 |         base58M[base58Chars.charCodeAt(i)] = i;
 25 |     }
 26 |     return base58M;
 27 | };
 28 | 
 29 | const base58Map = create_base58_map();
 30 | 
 31 | const create_base64_map = (): number[] => {
 32 |     const base64M = Array(256).fill(-1) as number[];
 33 |     for (let i = 0; i < base64Chars.length; ++i) {
 34 |         base64M[base64Chars.charCodeAt(i)] = i;
 35 |     }
 36 |     base64M['='.charCodeAt(0)] = 0;
 37 |     return base64M;
 38 | };
 39 | 
 40 | const base64Map = create_base64_map();
 41 | 
 42 | /** Is `bignum` a negative number? */
 43 | export const isNegative = (bignum: Uint8Array): boolean => {
 44 |     return (bignum[bignum.length - 1] & 0x80) !== 0;
 45 | };
 46 | 
 47 | /** Negate `bignum` */
 48 | export const negate = (bignum: Uint8Array): void => {
 49 |     let carry = 1;
 50 |     for (let i = 0; i < bignum.length; ++i) {
 51 |         const x = (~bignum[i] & 0xff) + carry;
 52 |         bignum[i] = x;
 53 |         carry = x >> 8;
 54 |     }
 55 | };
 56 | 
 57 | /**
 58 |  * Convert an unsigned decimal number in `str` to a bignum
 59 |  *
 60 |  * @param size bignum size (bytes)
 61 |  */
 62 | export const decimalToBinary = (size: number, str: string): Uint8Array => {
 63 |     const result = new Uint8Array(size);
 64 |     for (let i = 0; i < str.length; ++i) {
 65 |         const srcDigit = str.charCodeAt(i);
 66 |         if (srcDigit < '0'.charCodeAt(0) || srcDigit > '9'.charCodeAt(0)) {
 67 |             throw new Error('invalid number');
 68 |         }
 69 |         let carry = srcDigit - '0'.charCodeAt(0);
 70 |         for (let j = 0; j < size; ++j) {
 71 |             const x = result[j] * 10 + carry;
 72 |             result[j] = x;
 73 |             carry = x >> 8;
 74 |         }
 75 |         if (carry) {
 76 |             throw new Error('number is out of range');
 77 |         }
 78 |     }
 79 |     return result;
 80 | };
 81 | 
 82 | /**
 83 |  * Convert a signed decimal number in `str` to a bignum
 84 |  *
 85 |  * @param size bignum size (bytes)
 86 |  */
 87 | export const signedDecimalToBinary = (size: number, str: string): Uint8Array => {
 88 |     const negative = str[0] === '-';
 89 |     if (negative) {
 90 |         str = str.substring(1);
 91 |     }
 92 |     const result = decimalToBinary(size, str);
 93 |     if (negative) {
 94 |         negate(result);
 95 |         if (!isNegative(result)) {
 96 |             throw new Error('number is out of range');
 97 |         }
 98 |     } else if (isNegative(result)) {
 99 |         throw new Error('number is out of range');
100 |     }
101 |     return result;
102 | };
103 | 
104 | /**
105 |  * Convert `bignum` to an unsigned decimal number
106 |  *
107 |  * @param minDigits 0-pad result to this many digits
108 |  */
109 | export const binaryToDecimal = (bignum: Uint8Array, minDigits = 1): string => {
110 |     const result = Array(minDigits).fill('0'.charCodeAt(0)) as number[];
111 |     for (let i = bignum.length - 1; i >= 0; --i) {
112 |         let carry = bignum[i];
113 |         for (let j = 0; j < result.length; ++j) {
114 |             const x = ((result[j] - '0'.charCodeAt(0)) << 8) + carry;
115 |             result[j] = '0'.charCodeAt(0) + x % 10;
116 |             carry = (x / 10) | 0;
117 |         }
118 |         while (carry) {
119 |             result.push('0'.charCodeAt(0) + carry % 10);
120 |             carry = (carry / 10) | 0;
121 |         }
122 |     }
123 |     result.reverse();
124 |     return String.fromCharCode(...result);
125 | };
126 | 
127 | /**
128 |  * Convert `bignum` to a signed decimal number
129 |  *
130 |  * @param minDigits 0-pad result to this many digits
131 |  */
132 | export const signedBinaryToDecimal = (bignum: Uint8Array, minDigits = 1): string => {
133 |     if (isNegative(bignum)) {
134 |         const x = bignum.slice();
135 |         negate(x);
136 |         return '-' + binaryToDecimal(x, minDigits);
137 |     }
138 |     return binaryToDecimal(bignum, minDigits);
139 | };
140 | 
141 | const base58ToBinaryVarSize = (str: string): Uint8Array => {
142 |     const result = [] as number[];
143 |     for (let i = 0; i < str.length; ++i) {
144 |         let carry = base58Map[str.charCodeAt(i)];
145 |         if (carry < 0) {
146 |             throw new Error('invalid base-58 value');
147 |         }
148 |         for (let j = 0; j < result.length; ++j) {
149 |             const x = result[j] * 58 + carry;
150 |             result[j] = x & 0xff;
151 |             carry = x >> 8;
152 |         }
153 |         if (carry) {
154 |             result.push(carry);
155 |         }
156 |     }
157 |     for (const ch of str) {
158 |         if (ch === '1') {
159 |             result.push(0);
160 |         } else {
161 |             break;
162 |         }
163 |     }
164 |     result.reverse();
165 |     return new Uint8Array(result);
166 | };
167 | 
168 | /**
169 |  * Convert an unsigned base-58 number in `str` to a bignum
170 |  *
171 |  * @param size bignum size (bytes)
172 |  */
173 | export const base58ToBinary = (size: number, str: string): Uint8Array => {
174 |     if (!size) {
175 |         return base58ToBinaryVarSize(str);
176 |     }
177 |     const result = new Uint8Array(size);
178 |     for (let i = 0; i < str.length; ++i) {
179 |         let carry = base58Map[str.charCodeAt(i)];
180 |         if (carry < 0) {
181 |             throw new Error('invalid base-58 value');
182 |         }
183 |         for (let j = 0; j < size; ++j) {
184 |             const x = result[j] * 58 + carry;
185 |             result[j] = x;
186 |             carry = x >> 8;
187 |         }
188 |         if (carry) {
189 |             throw new Error('base-58 value is out of range');
190 |         }
191 |     }
192 |     result.reverse();
193 |     return result;
194 | };
195 | 
196 | /**
197 |  * Convert `bignum` to a base-58 number
198 |  *
199 |  * @param minDigits 0-pad result to this many digits
200 |  */
201 | export const binaryToBase58 = (bignum: Uint8Array, minDigits = 1): string => {
202 |     const result = [] as number[];
203 |     for (const byte of bignum) {
204 |         let carry = byte;
205 |         for (let j = 0; j < result.length; ++j) {
206 |             const x = (base58Map[result[j]] << 8) + carry;
207 |             result[j] = base58Chars.charCodeAt(x % 58);
208 |             carry = (x / 58) | 0;
209 |         }
210 |         while (carry) {
211 |             result.push(base58Chars.charCodeAt(carry % 58));
212 |             carry = (carry / 58) | 0;
213 |         }
214 |     }
215 |     for (const byte of bignum) {
216 |         if (byte) {
217 |             break;
218 |         } else {
219 |             result.push('1'.charCodeAt(0));
220 |         }
221 |     }
222 |     result.reverse();
223 |     return String.fromCharCode(...result);
224 | };
225 | 
226 | /** Convert an unsigned base-64 number in `str` to a bignum */
227 | export const base64ToBinary = (str: string): Uint8Array => {
228 |     let len = str.length;
229 |     if ((len & 3) === 1 && str[len - 1] === '=') {
230 |         len -= 1;
231 |     } // fc appends an extra '='
232 |     if ((len & 3) !== 0) {
233 |         throw new Error('base-64 value is not padded correctly');
234 |     }
235 |     const groups = len >> 2;
236 |     let bytes = groups * 3;
237 |     if (len > 0 && str[len - 1] === '=') {
238 |         if (str[len - 2] === '=') {
239 |             bytes -= 2;
240 |         } else {
241 |             bytes -= 1;
242 |         }
243 |     }
244 |     const result = new Uint8Array(bytes);
245 | 
246 |     for (let group = 0; group < groups; ++group) {
247 |         const digit0 = base64Map[str.charCodeAt(group * 4 + 0)];
248 |         const digit1 = base64Map[str.charCodeAt(group * 4 + 1)];
249 |         const digit2 = base64Map[str.charCodeAt(group * 4 + 2)];
250 |         const digit3 = base64Map[str.charCodeAt(group * 4 + 3)];
251 |         result[group * 3 + 0] = (digit0 << 2) | (digit1 >> 4);
252 |         if (group * 3 + 1 < bytes) {
253 |             result[group * 3 + 1] = ((digit1 & 15) << 4) | (digit2 >> 2);
254 |         }
255 |         if (group * 3 + 2 < bytes) {
256 |             result[group * 3 + 2] = ((digit2 & 3) << 6) | digit3;
257 |         }
258 |     }
259 |     return result;
260 | };
261 | 
262 | /** Key types this library supports */
263 | export enum KeyType {
264 |     k1 = 0,
265 |     r1 = 1,
266 |     wa = 2,
267 | }
268 | 
269 | /** Public key data size, excluding type field */
270 | export const publicKeyDataSize = 33;
271 | 
272 | /** Private key data size, excluding type field */
273 | export const privateKeyDataSize = 32;
274 | 
275 | /** Signature data size, excluding type field */
276 | export const signatureDataSize = 65;
277 | 
278 | /** Public key, private key, or signature in binary form */
279 | export interface Key {
280 |     type: KeyType;
281 |     data: Uint8Array;
282 | }
283 | 
284 | const digestSuffixRipemd160 = (data: Uint8Array, suffix: string): ArrayBuffer => {
285 |     const d = new Uint8Array(data.length + suffix.length);
286 |     for (let i = 0; i < data.length; ++i) {
287 |         d[i] = data[i];
288 |     }
289 |     for (let i = 0; i < suffix.length; ++i) {
290 |         d[data.length + i] = suffix.charCodeAt(i);
291 |     }
292 |     return ripemd160(d);
293 | };
294 | 
295 | const stringToKey = (s: string, type: KeyType, size: number, suffix: string): Key => {
296 |     const whole = base58ToBinary(size ? size + 4 : 0, s);
297 |     const result = { type, data: new Uint8Array(whole.buffer, 0, whole.length - 4) };
298 |     const digest = new Uint8Array(digestSuffixRipemd160(result.data, suffix));
299 |     if (digest[0] !== whole[whole.length - 4] || digest[1] !== whole[whole.length - 3]
300 |         || digest[2] !== whole[whole.length - 2] || digest[3] !== whole[whole.length - 1]) {
301 |         throw new Error('checksum doesn\'t match');
302 |     }
303 |     return result;
304 | };
305 | 
306 | const keyToString = (key: Key, suffix: string, prefix: string): string => {
307 |     const digest = new Uint8Array(digestSuffixRipemd160(key.data, suffix));
308 |     const whole = new Uint8Array(key.data.length + 4);
309 |     for (let i = 0; i < key.data.length; ++i) {
310 |         whole[i] = key.data[i];
311 |     }
312 |     for (let i = 0; i < 4; ++i) {
313 |         whole[i + key.data.length] = digest[i];
314 |     }
315 |     return prefix + binaryToBase58(whole);
316 | };
317 | 
318 | /** Convert key in `str` to binary form */
319 | export const stringToPublicKey = (str: string): Key => {
320 |     if (typeof str !== 'string') {
321 |         throw new Error('expected string containing public key');
322 |     }
323 |     if (str.substring(0, 3) === 'EOS') {
324 |         const whole = base58ToBinary(publicKeyDataSize + 4, str.substring(3));
325 |         const key = { type: KeyType.k1, data: new Uint8Array(publicKeyDataSize) };
326 |         for (let i = 0; i < publicKeyDataSize; ++i) {
327 |             key.data[i] = whole[i];
328 |         }
329 |         const digest = new Uint8Array(ripemd160(key.data));
330 |         if (digest[0] !== whole[publicKeyDataSize] || digest[1] !== whole[34]
331 |             || digest[2] !== whole[35] || digest[3] !== whole[36]) {
332 |             throw new Error('checksum doesn\'t match');
333 |         }
334 |         return key;
335 |     } else if (str.substring(0, 7) === 'PUB_K1_') {
336 |         return stringToKey(str.substring(7), KeyType.k1, publicKeyDataSize, 'K1');
337 |     } else if (str.substring(0, 7) === 'PUB_R1_') {
338 |         return stringToKey(str.substring(7), KeyType.r1, publicKeyDataSize, 'R1');
339 |     } else if (str.substring(0, 7) === 'PUB_WA_') {
340 |         return stringToKey(str.substring(7), KeyType.wa, 0, 'WA');
341 |     } else {
342 |         throw new Error('unrecognized public key format');
343 |     }
344 | };
345 | 
346 | /** Convert public `key` to legacy string (base-58) form */
347 | export const publicKeyToLegacyString = (key: Key): string => {
348 |     if (key.type === KeyType.k1 && key.data.length === publicKeyDataSize) {
349 |         return keyToString(key, '', 'EOS');
350 |     } else if (key.type === KeyType.r1 || key.type === KeyType.wa) {
351 |         throw new Error('Key format not supported in legacy conversion');
352 |     } else {
353 |         throw new Error('unrecognized public key format');
354 |     }
355 | };
356 | 
357 | /** Convert `key` to string (base-58) form */
358 | export const publicKeyToString = (key: Key): string => {
359 |     if (key.type === KeyType.k1 && key.data.length === publicKeyDataSize) {
360 |         return keyToString(key, 'K1', 'PUB_K1_');
361 |     } else if (key.type === KeyType.r1 && key.data.length === publicKeyDataSize) {
362 |         return keyToString(key, 'R1', 'PUB_R1_');
363 |     } else if (key.type === KeyType.wa) {
364 |         return keyToString(key, 'WA', 'PUB_WA_');
365 |     } else {
366 |         throw new Error('unrecognized public key format');
367 |     }
368 | };
369 | 
370 | /** If a key is in the legacy format (`EOS` prefix), then convert it to the new format (`PUB_K1_`).
371 |  * Leaves other formats untouched
372 |  */
373 | export const convertLegacyPublicKey = (str: string): string => {
374 |     if (str.substring(0, 3) === 'EOS') {
375 |         return publicKeyToString(stringToPublicKey(str));
376 |     }
377 |     return str;
378 | };
379 | 
380 | /** If a key is in the legacy format (`EOS` prefix), then convert it to the new format (`PUB_K1_`).
381 |  * Leaves other formats untouched
382 |  */
383 | export const convertLegacyPublicKeys = (keys: string[]): string[] => {
384 |     return keys.map(convertLegacyPublicKey);
385 | };
386 | 
387 | /** Convert key in `str` to binary form */
388 | export const stringToPrivateKey = (str: string): Key => {
389 |     if (typeof str !== 'string') {
390 |         throw new Error('expected string containing private key');
391 |     }
392 |     if (str.substring(0, 7) === 'PVT_R1_') {
393 |         return stringToKey(str.substring(7), KeyType.r1, privateKeyDataSize, 'R1');
394 |     } else if (str.substring(0, 7) === 'PVT_K1_') {
395 |         return stringToKey(str.substring(7), KeyType.k1, privateKeyDataSize, 'K1');
396 |     } else {
397 |         // todo: Verify checksum: sha256(sha256(key.data)).
398 |         //       Not critical since a bad key will fail to produce a
399 |         //       valid signature anyway.
400 |         const whole = base58ToBinary(privateKeyDataSize + 5, str);
401 |         const key = { type: KeyType.k1, data: new Uint8Array(privateKeyDataSize) };
402 |         if (whole[0] !== 0x80) {
403 |             throw new Error('unrecognized private key type');
404 |         }
405 |         for (let i = 0; i < privateKeyDataSize; ++i) {
406 |             key.data[i] = whole[i + 1];
407 |         }
408 |         return key;
409 |     }
410 | };
411 | 
412 | /** Convert private `key` to legacy string (base-58) form */
413 | export const privateKeyToLegacyString = (key: Key): string => {
414 |     if (key.type === KeyType.k1 && key.data.length === privateKeyDataSize) {
415 |         const whole = [] as number[];
416 |         whole.push(128);
417 |         key.data.forEach((byte) => whole.push(byte));
418 |         const digest = new Uint8Array(
419 |             sha256().update(
420 |                 sha256().update(whole).digest()
421 |             ).digest()
422 |         );
423 | 
424 |         const result = new Uint8Array(privateKeyDataSize + 5);
425 |         for (let i = 0; i < whole.length; i++) {
426 |             result[i] = whole[i];
427 |         }
428 |         for (let i = 0; i < 4; i++) {
429 |             result[i + whole.length] = digest[i];
430 |         }
431 |         return binaryToBase58(result);
432 |     } else if (key.type === KeyType.r1 || key.type === KeyType.wa) {
433 |         throw new Error('Key format not supported in legacy conversion');
434 |     } else {
435 |         throw new Error('unrecognized public key format');
436 |     }
437 | };
438 | 
439 | /** Convert `key` to string (base-58) form */
440 | export const privateKeyToString = (key: Key): string => {
441 |     if (key.type === KeyType.r1) {
442 |         return keyToString(key, 'R1', 'PVT_R1_');
443 |     } else if (key.type === KeyType.k1) {
444 |         return keyToString(key, 'K1', 'PVT_K1_');
445 |     } else {
446 |         throw new Error('unrecognized private key format');
447 |     }
448 | };
449 | 
450 | /** Convert key in `str` to binary form */
451 | export const stringToSignature = (str: string): Key => {
452 |     if (typeof str !== 'string') {
453 |         throw new Error('expected string containing signature');
454 |     }
455 |     if (str.substring(0, 7) === 'SIG_K1_') {
456 |         return stringToKey(str.substring(7), KeyType.k1, signatureDataSize, 'K1');
457 |     } else if (str.substring(0, 7) === 'SIG_R1_') {
458 |         return stringToKey(str.substring(7), KeyType.r1, signatureDataSize, 'R1');
459 |     } else if (str.substring(0, 7) === 'SIG_WA_') {
460 |         return stringToKey(str.substring(7), KeyType.wa, 0, 'WA');
461 |     } else {
462 |         throw new Error('unrecognized signature format');
463 |     }
464 | };
465 | 
466 | /** Convert `signature` to string (base-58) form */
467 | export const signatureToString = (signature: Key): string => {
468 |     if (signature.type === KeyType.k1) {
469 |         return keyToString(signature, 'K1', 'SIG_K1_');
470 |     } else if (signature.type === KeyType.r1) {
471 |         return keyToString(signature, 'R1', 'SIG_R1_');
472 |     } else if (signature.type === KeyType.wa) {
473 |         return keyToString(signature, 'WA', 'SIG_WA_');
474 |     } else {
475 |         throw new Error('unrecognized signature format');
476 |     }
477 | };
478 | 


--------------------------------------------------------------------------------
/src/eosjs-rpc-interfaces.ts:
--------------------------------------------------------------------------------
  1 | // copyright defined in eosjs/LICENSE.txt
  2 | 
  3 | /** Structured format for abis */
  4 | export interface Abi {
  5 |     version: string;
  6 |     types: Array<{ new_type_name: string, type: string }>;
  7 |     structs: Array<{ name: string, base: string, fields: Array<{ name: string, type: string }> }>;
  8 |     actions: Array<{ name: string, type: string, ricardian_contract: string }>;
  9 |     tables: Array<{ name: string, type: string, index_type: string, key_names: string[], key_types: string[] }>;
 10 |     ricardian_clauses: Array<{ id: string, body: string }>;
 11 |     error_messages: Array<{ error_code: string, error_msg: string }>;
 12 |     abi_extensions: Array<{ tag: number, value: string }>;
 13 |     variants?: Array<{ name: string, types: string[] }>;
 14 | }
 15 | 
 16 | export interface BlockHeader {
 17 |     timestamp: string;
 18 |     producer: string;
 19 |     confirmed: number;
 20 |     previous: string;
 21 |     transaction_mroot: string;
 22 |     action_mroot: string;
 23 |     schedule_version: number;
 24 |     new_producers: any;
 25 |     header_extensions: any;
 26 | }
 27 | 
 28 | export interface SignedBlockHeader extends BlockHeader {
 29 |     producer_signature: string;
 30 | }
 31 | 
 32 | /** Return value of `/v1/chain/get_abi` */
 33 | export interface GetAbiResult {
 34 |     account_name: string;
 35 |     abi: Abi;
 36 | }
 37 | 
 38 | /** Return value of `/v1/chain/get_block` */
 39 | export interface GetBlockResult {
 40 |     timestamp: string;
 41 |     producer: string;
 42 |     confirmed: number;
 43 |     previous: string;
 44 |     transaction_mroot: string;
 45 |     action_mroot: string;
 46 |     schedule_version: number;
 47 |     producer_signature: string;
 48 |     id: string;
 49 |     block_num: number;
 50 |     ref_block_prefix: number;
 51 | }
 52 | 
 53 | /** Used to calculate TAPoS fields in transactions */
 54 | export interface BlockTaposInfo {
 55 |     block_num: number;
 56 |     id: string;
 57 |     timestamp?: string;
 58 |     header?: BlockHeader;
 59 | }
 60 | 
 61 | /** Return value of `v1/chain/get_block_header_state */
 62 | export interface GetBlockHeaderStateResult {
 63 |     id: string;
 64 |     header: SignedBlockHeader;
 65 |     pending_schedule: any;
 66 |     activated_protocol_features: any;
 67 |     block_num: number;
 68 |     dpos_proposed_irreversible_blocknum: number;
 69 |     dpos_irreversible_blocknum: number;
 70 |     active_schedule: any;
 71 |     blockroot_merkle: any;
 72 |     producer_to_last_produced: any;
 73 |     producer_to_last_implied_irb: any;
 74 |     block_signing_key: string;
 75 |     confirm_count: any;
 76 | }
 77 | 
 78 | /** Subset of `GetBlockHeaderStateResult` used to calculate TAPoS fields in transactions */
 79 | export interface BlockHeaderStateTaposInfo {
 80 |     block_num: number;
 81 |     id: string;
 82 |     header: SignedBlockHeader;
 83 | }
 84 | 
 85 | /** Return value of `/v1/chain/get_code` */
 86 | export interface GetCodeResult {
 87 |     account_name: string;
 88 |     code_hash: string;
 89 |     wast: string;
 90 |     wasm: string;
 91 |     abi: Abi;
 92 | }
 93 | 
 94 | /** Return value of `/v1/chain/get_info` */
 95 | export interface GetInfoResult {
 96 |     server_version: string;
 97 |     chain_id: string;
 98 |     head_block_num: number;
 99 |     last_irreversible_block_num: number;
100 |     last_irreversible_block_id: string;
101 |     head_block_id: string;
102 |     head_block_time: string;
103 |     head_block_producer: string;
104 |     virtual_block_cpu_limit: number;
105 |     virtual_block_net_limit: number;
106 |     block_cpu_limit: number;
107 |     block_net_limit: number;
108 |     server_version_string: string;
109 |     fork_db_head_block_num: number,
110 |     fork_db_head_block_id: string,
111 |     server_full_version_string: string,
112 |     total_cpu_weight: string,
113 |     total_net_weight: string,
114 |     earliest_available_block_num: number,
115 |     last_irreversible_block_time: string
116 | }
117 | 
118 | /** Return value of `/v1/chain/get_raw_code_and_abi` */
119 | export interface GetRawCodeAndAbiResult {
120 |     account_name: string;
121 |     wasm: string;
122 |     abi: string;
123 | }
124 | 
125 | /** Arguments for `push_transaction` */
126 | export interface PushTransactionArgs {
127 |     signatures: string[];
128 |     serializedTransaction: Uint8Array;
129 |     serializedContextFreeData?: Uint8Array;
130 | }
131 | 
132 | /** Arguments for `send_transaction2` */
133 | export interface SendTransaction2Args {
134 |     return_failure_trace: boolean,
135 |     retry_trx: boolean,
136 |     retry_trx_num_blocks?: number,
137 |     transaction: PushTransactionArgs
138 | }


--------------------------------------------------------------------------------
/src/eosjs-rpcerror.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @module RPC-Error
 3 |  */
 4 | // copyright defined in eosjs/LICENSE.txt
 5 | 
 6 | /** Holds detailed error information */
 7 | export class RpcError extends Error {
 8 |   /** Detailed error information */
 9 |     public json: any;
10 | 
11 |     constructor(json: any) {
12 |         if (json.error && json.error.details && json.error.details.length && json.error.details[0].message) {
13 |             let errorMessage = json.error.details[0].message
14 |             // errors typically have multiple messages
15 |             if (json.error.details.length > 1) {
16 |                 for (let i = 1; i < json.error.details.length; i++) {
17 |                     errorMessage = errorMessage + '\n' + json.error.details[i].message
18 |                 }
19 |             }
20 |             super(errorMessage);
21 |         } else if (json.processed && json.processed.except && json.processed.except.message) {
22 |             super(json.processed.except.message);
23 |         } else {
24 |             super(json.message);
25 |         }
26 |         Object.setPrototypeOf(this, RpcError.prototype);
27 |         this.json = json;
28 |     }
29 | }
30 | 


--------------------------------------------------------------------------------
/src/eosjs-webauthn-sig.ts:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * @module WebAuthn-Sig
  3 |  */
  4 | // copyright defined in eosjs/LICENSE.txt
  5 | 
  6 | import { SignatureProvider, SignatureProviderArgs } from './eosjs-api-interfaces';
  7 | import * as ser from './eosjs-serialize';
  8 | import * as numeric from './eosjs-numeric';
  9 | import { ec } from 'elliptic';
 10 | 
 11 | /** Signs transactions using WebAuthn */
 12 | export class WebAuthnSignatureProvider implements SignatureProvider {
 13 |     /** Map public key to credential ID (hex). User must populate this. */
 14 |     public keys = new Map();
 15 | 
 16 |     /** Public keys that the `SignatureProvider` holds */
 17 |     public async getAvailableKeys() {
 18 |         return Array.from(this.keys.keys());
 19 |     }
 20 | 
 21 |     /** Sign a transaction */
 22 |     public async sign(
 23 |         { chainId, requiredKeys, serializedTransaction, serializedContextFreeData }:
 24 |             SignatureProviderArgs,
 25 |     ) {
 26 |         const signBuf = new ser.SerialBuffer();
 27 |         signBuf.pushArray(ser.hexToUint8Array(chainId));
 28 |         signBuf.pushArray(serializedTransaction);
 29 |         if (serializedContextFreeData) {
 30 |             signBuf.pushArray(new Uint8Array(await crypto.subtle.digest('SHA-256', serializedContextFreeData.buffer)));
 31 |         } else {
 32 |             signBuf.pushArray(new Uint8Array(32));
 33 |         }
 34 |         const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', signBuf.asUint8Array().slice().buffer));
 35 | 
 36 |         const signatures = [] as string[];
 37 |         for (const key of requiredKeys) {
 38 |             const id = ser.hexToUint8Array(this.keys.get(key));
 39 |             const assertion = await (navigator as any).credentials.get({
 40 |                 publicKey: {
 41 |                     timeout: 60000,
 42 |                     allowCredentials: [{
 43 |                         id,
 44 |                         type: 'public-key',
 45 |                     }],
 46 |                     challenge: digest.buffer,
 47 |                 },
 48 |             });
 49 |             const e = new ec('p256') as any;
 50 |             const pubKey = e.keyFromPublic(numeric.stringToPublicKey(key).data.subarray(0, 33)).getPublic();
 51 | 
 52 |             const fixup = (x: Uint8Array) => {
 53 |                 const a = Array.from(x);
 54 |                 while (a.length < 32) {
 55 |                     a.unshift(0);
 56 |                 }
 57 |                 while (a.length > 32) {
 58 |                     if (a.shift() !== 0) {
 59 |                         throw new Error('Signature has an r or s that is too big');
 60 |                     }
 61 |                 }
 62 |                 return new Uint8Array(a);
 63 |             };
 64 | 
 65 |             const der = new ser.SerialBuffer({ array: new Uint8Array(assertion.response.signature) });
 66 |             if (der.get() !== 0x30) {
 67 |                 throw new Error('Signature missing DER prefix');
 68 |             }
 69 |             if (der.get() !== der.array.length - 2) {
 70 |                 throw new Error('Signature has bad length');
 71 |             }
 72 |             if (der.get() !== 0x02) {
 73 |                 throw new Error('Signature has bad r marker');
 74 |             }
 75 |             const r = fixup(der.getUint8Array(der.get()));
 76 |             if (der.get() !== 0x02) {
 77 |                 throw new Error('Signature has bad s marker');
 78 |             }
 79 |             const s = fixup(der.getUint8Array(der.get()));
 80 | 
 81 |             const whatItReallySigned = new ser.SerialBuffer();
 82 |             whatItReallySigned.pushArray(new Uint8Array(assertion.response.authenticatorData));
 83 |             whatItReallySigned.pushArray(new Uint8Array(
 84 |                 await crypto.subtle.digest('SHA-256', assertion.response.clientDataJSON)));
 85 |             const hash = new Uint8Array(
 86 |                 await crypto.subtle.digest('SHA-256', whatItReallySigned.asUint8Array().slice()));
 87 |             const recid = e.getKeyRecoveryParam(hash, new Uint8Array(assertion.response.signature), pubKey);
 88 | 
 89 |             const sigData = new ser.SerialBuffer();
 90 |             sigData.push(recid + 27 + 4);
 91 |             sigData.pushArray(r);
 92 |             sigData.pushArray(s);
 93 |             sigData.pushBytes(new Uint8Array(assertion.response.authenticatorData));
 94 |             sigData.pushBytes(new Uint8Array(assertion.response.clientDataJSON));
 95 | 
 96 |             const sig = numeric.signatureToString({
 97 |                 type: numeric.KeyType.wa,
 98 |                 data: sigData.asUint8Array().slice(),
 99 |             });
100 |             signatures.push(sig);
101 |         }
102 |         return { signatures, serializedTransaction, serializedContextFreeData };
103 |     }
104 | }
105 | 


--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
 1 | import { Api } from './eosjs-api';
 2 | import * as ApiInterfaces from './eosjs-api-interfaces';
 3 | import { JsonRpc } from './eosjs-jsonrpc';
 4 | import * as Numeric from './eosjs-numeric';
 5 | import * as RpcInterfaces from './eosjs-rpc-interfaces';
 6 | import { RpcError } from './eosjs-rpcerror';
 7 | import * as Serialize from './eosjs-serialize';
 8 | 
 9 | export { Api, ApiInterfaces, JsonRpc, Numeric, RpcInterfaces, RpcError, Serialize };
10 | 


--------------------------------------------------------------------------------
/src/ripemd.es5.js:
--------------------------------------------------------------------------------
  1 | // https://gist.githubusercontent.com/wlzla000/bac83df6d3c51916c4dd0bc947e46947/raw/7ee3462b095ab22580ddaf191f44a590da6fe33b/RIPEMD-160.js
  2 | 
  3 | /*
  4 | 	RIPEMD-160.js
  5 | 
  6 | 		developed
  7 | 			by K. (https://github.com/wlzla000)
  8 | 			on December 27-29, 2017,
  9 | 
 10 | 		licensed under
 11 | 
 12 | 
 13 | 		the MIT license
 14 | 
 15 | 		Copyright (c) 2017 K.
 16 | 
 17 | 		 Permission is hereby granted, free of charge, to any person
 18 | 		obtaining a copy of this software and associated documentation
 19 | 		files (the "Software"), to deal in the Software without
 20 | 		restriction, including without limitation the rights to use,
 21 | 		copy, modify, merge, publish, distribute, sublicense, and/or
 22 | 		sell copies of the Software, and to permit persons to whom the
 23 | 		Software is furnished to do so, subject to the following
 24 | 		conditions:
 25 | 
 26 | 		 The above copyright notice and this permission notice shall be
 27 | 		included in all copies or substantial portions of the Software.
 28 | 
 29 | 		 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 30 | 		EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 31 | 		OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 32 | 		NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 33 | 		HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 34 | 		WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 35 | 		FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 36 | 		OTHER DEALINGS IN THE SOFTWARE.
 37 | */
 38 | 
 39 | "use strict";
 40 | 
 41 | var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
 42 | 
 43 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
 44 | 
 45 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
 46 | 
 47 | var RIPEMD160 = function () {
 48 | 	function RIPEMD160() {
 49 | 		// https://webcache.googleusercontent.com/search?q=cache:CnLOgolTHYEJ:https://www.cosic.esat.kuleuven.be/publications/article-317.pdf
 50 | 		// http://shodhganga.inflibnet.ac.in/bitstream/10603/22978/13/13_appendix.pdf
 51 | 
 52 | 		_classCallCheck(this, RIPEMD160);
 53 | 	}
 54 | 
 55 | 	_createClass(RIPEMD160, null, [{
 56 | 		key: "get_n_pad_bytes",
 57 | 		value: function get_n_pad_bytes(message_size /* in bytes, 1 byte is 8 bits. */) {
 58 | 			//  Obtain the number of bytes needed to pad the message.
 59 | 			// It does not contain the size of the message size information.
 60 | 			/*
 61 |    	https://webcache.googleusercontent.com/search?q=cache:CnLOgolTHYEJ:https://www.cosic.esat.kuleuven.be/publications/article-317.pdf
 62 |    		The Cryptographic Hash Function RIPEMD-160
 63 |    		written by
 64 |    		Bart Preneel,
 65 |    		Hans Dobbertin,
 66 |    		Antoon Bosselaers
 67 |    	in
 68 |    		1997.
 69 |    		--------------------------------------------------
 70 |    		§5     Description of RIPEMD-160
 71 |    		......
 72 |    		 In order to guarantee that the total input size is a
 73 |    	multiple of 512 bits, the input is padded in the same
 74 |    	way as for all the members of the MD4-family: one
 75 |    	appends a single 1 followed by a string of 0s (the
 76 |    	number of 0s lies between 0 and 511); the last 64 bits
 77 |    	of the extended input contain the binary representation
 78 |    	of the input size in bits, least significant byte first.
 79 |    */
 80 | 			/*
 81 |    	https://tools.ietf.org/rfc/rfc1186.txt
 82 |    		RFC 1186: MD4 Message Digest Algorithm.
 83 |    		written by
 84 |    		Ronald Linn Rivest
 85 |    	in
 86 |    		October 1990.
 87 |    		--------------------------------------------------
 88 |    		§3     MD4 Algorithm Description
 89 |    		......
 90 |    		Step 1. Append padding bits
 91 |    		 The message is "padded" (extended) so that its length
 92 |    	(in bits) is congruent to 448, modulo 512. That is, the
 93 |    	message is extended so that it is just 64 bits shy of
 94 |    	being a multiple of 512 bits long. Padding is always
 95 |    	performed, even if the length of the message is already
 96 |    	congruent to 448, modulo 512 (in which case 512 bits of
 97 |    	padding are added).
 98 |    		 Padding is performed as follows: a single "1" bit is
 99 |    	appended to the message, and then enough zero bits are
100 |    	appended so that the length in bits of the padded
101 |    	message becomes congruent to 448, modulo 512.
102 |    		Step 2. Append length
103 |    		 A 64-bit representation of b (the length of the message
104 |    	before the padding bits were added) is appended to the
105 |    	result of the previous step. In the unlikely event that
106 |    	b is greater than 2^64, then only the low-order 64 bits
107 |    	of b are used. (These bits are appended as two 32-bit
108 |    	words and appended low-order word first in accordance
109 |    	with the previous conventions.)
110 |    		 At this point the resulting message (after padding with
111 |    	bits and with b) has a length that is an exact multiple
112 |    	of 512 bits. Equivalently, this message has a length
113 |    	that is an exact multiple of 16 (32-bit) words. Let
114 |    	M[0 ... N-1] denote the words of the resulting message,
115 |    	where N is a multiple of 16.
116 |    */
117 | 			// https://crypto.stackexchange.com/a/32407/54568
118 | 			/*
119 |    	Example case  # 1
120 |    		[0 bit: message.]
121 |    		[1 bit: 1.]
122 |    		[447 bits: 0.]
123 |    		[64 bits: message size information.]
124 |    		Example case  # 2
125 |    		[512-bits: message]
126 |    		[1 bit: 1.]
127 |    		[447 bits: 0.]
128 |    		[64 bits: message size information.]
129 |    		Example case  # 3
130 |    		[(512 - 64 = 448) bits: message.]
131 |    		[1 bit: 1.]
132 |    		[511 bits: 0.]
133 |    		[64 bits: message size information.]
134 |    		Example case  # 4
135 |    		[(512 - 65 = 447) bits: message.]
136 |    		[1 bit: 1.]
137 |    		[0 bit: 0.]
138 |    		[64 bits: message size information.]
139 |    */
140 | 			// The number of padding zero bits:
141 | 			//      511 - [{(message size in bits) + 64} (mod 512)]
142 | 			return 64 - (message_size + 8 & 63 /* 63 */);
143 | 		}
144 | 	}, {
145 | 		key: "pad",
146 | 		value: function pad(message /* An ArrayBuffer. */) {
147 | 			var message_size = message.byteLength;
148 | 			var n_pad = RIPEMD160.get_n_pad_bytes(message_size);
149 | 
150 | 			//  `Number.MAX_SAFE_INTEGER` is ((2 ** 53) - 1) and
151 | 			// bitwise operation in Javascript is done on 32-bits operands.
152 | 			var divmod = function divmod(dividend, divisor) {
153 | 				return [Math.floor(dividend / divisor), dividend % divisor];
154 | 			};
155 | 			/*
156 |    To shift
157 |      00000000 000????? ???????? ???????? ???????? ???????? ???????? ????????
158 |                                       t o
159 |     00000000 ???????? ???????? ???????? ???????? ???????? ???????? ?????000
160 |    --------------------------------------------------------------------------------
161 |    Method #1
162 |       00000000 000????? ???????? ????????  ???????? ???????? ???????? ????????
163 |     [00000000 000AAAAA AAAAAAAA AAAAAAAA] ( captured)
164 |     [00000000 AAAAAAAA AAAAAAAA AAAAA000] ( shifted)
165 |                           ( captured) [BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB]
166 |                       ( shifted) [BBB][BBBBBBBB BBBBBBBB BBBBBBBB BBBBB000]
167 |     [00000000 AAAAAAAA AAAAAAAA AAAAABBB] ( &  merged)
168 |     [00000000 AAAAAAAA AAAAAAAA AAAAABBB][BBBBBBBB BBBBBBBB BBBBBBBB BBBBB000]
169 |      00000000 ???????? ???????? ????????  ???????? ???????? ???????? ?????000
170 |    	const uint32_max_plus_1 = 0x100000000; // (2 ** 32)
171 |    const [
172 |    	msg_byte_size_most, // Value range [0, (2 ** 21) - 1].
173 |    	msg_byte_size_least // Value range [0, (2 ** 32) - 1].
174 |    ] = divmod(message_size, uint32_max_plus_1);
175 |    const [
176 |    	carry, // Value range [0, 7].
177 |    	msg_bit_size_least // Value range [0, (2 ** 32) - 8].
178 |    ] = divmod(message_byte_size_least * 8, uint32_max_plus_1);
179 |    const message_bit_size_most = message_byte_size_most * 8
180 |    	+ carry; // Value range [0, (2 ** 24) - 1].
181 |    --------------------------------------------------------------------------------
182 |    Method #2
183 |      00000000 000????? ???????? ????????  ???????? ???????? ???????? ????????
184 |        [00000 000AAAAA AAAAAAAA AAAAAAAA  AAA] ( captured)
185 |                           ( captured) [000BBBBB BBBBBBBB BBBBBBBB BBBBBBBB]
186 |                            ( shifted) [BBBBBBBB BBBBBBBB BBBBBBBB BBBBB000]
187 |     [00000000 AAAAAAAA AAAAAAAA AAAAAAAA][BBBBBBBB BBBBBBBB BBBBBBBB BBBBB000]
188 |      00000000 ???????? ???????? ????????  ???????? ???????? ???????? ?????000
189 |    	*/
190 | 
191 | 			var _divmod$map = divmod(message_size, 536870912 /* (2 ** 29) */).map(function (x, index) {
192 | 				return index ? x * 8 : x;
193 | 			}),
194 | 			    _divmod$map2 = _slicedToArray(_divmod$map, 2),
195 | 			    msg_bit_size_most = _divmod$map2[0],
196 | 			    msg_bit_size_least = _divmod$map2[1];
197 | 
198 | 			// `ArrayBuffer.transfer()` is not supported.
199 | 
200 | 
201 | 			var padded = new Uint8Array(message_size + n_pad + 8);
202 | 			padded.set(new Uint8Array(message), 0);
203 | 			var data_view = new DataView(padded.buffer);
204 | 			data_view.setUint8(message_size, 128);
205 | 			data_view.setUint32(message_size + n_pad, msg_bit_size_least, true // Little-endian
206 | 			);
207 | 			data_view.setUint32(message_size + n_pad + 4, msg_bit_size_most, true // Little-endian
208 | 			);
209 | 
210 | 			return padded.buffer;
211 | 		}
212 | 	}, {
213 | 		key: "f",
214 | 		value: function f(j, x, y, z) {
215 | 			if (0 <= j && j <= 15) {
216 | 				// Exclusive-OR
217 | 				return x ^ y ^ z;
218 | 			}
219 | 			if (16 <= j && j <= 31) {
220 | 				// Multiplexing (muxing)
221 | 				return x & y | ~x & z;
222 | 			}
223 | 			if (32 <= j && j <= 47) {
224 | 				return (x | ~y) ^ z;
225 | 			}
226 | 			if (48 <= j && j <= 63) {
227 | 				// Multiplexing (muxing)
228 | 				return x & z | y & ~z;
229 | 			}
230 | 			if (64 <= j && j <= 79) {
231 | 				return x ^ (y | ~z);
232 | 			}
233 | 		}
234 | 	}, {
235 | 		key: "K",
236 | 		value: function K(j) {
237 | 			if (0 <= j && j <= 15) {
238 | 				return 0x00000000;
239 | 			}
240 | 			if (16 <= j && j <= 31) {
241 | 				// Math.floor((2 ** 30) * Math.SQRT2)
242 | 				return 0x5A827999;
243 | 			}
244 | 			if (32 <= j && j <= 47) {
245 | 				// Math.floor((2 ** 30) * Math.sqrt(3))
246 | 				return 0x6ED9EBA1;
247 | 			}
248 | 			if (48 <= j && j <= 63) {
249 | 				// Math.floor((2 ** 30) * Math.sqrt(5))
250 | 				return 0x8F1BBCDC;
251 | 			}
252 | 			if (64 <= j && j <= 79) {
253 | 				// Math.floor((2 ** 30) * Math.sqrt(7))
254 | 				return 0xA953FD4E;
255 | 			}
256 | 		}
257 | 	}, {
258 | 		key: "KP",
259 | 		value: function KP(j) // K'
260 | 		{
261 | 			if (0 <= j && j <= 15) {
262 | 				// Math.floor((2 ** 30) * Math.cbrt(2))
263 | 				return 0x50A28BE6;
264 | 			}
265 | 			if (16 <= j && j <= 31) {
266 | 				// Math.floor((2 ** 30) * Math.cbrt(3))
267 | 				return 0x5C4DD124;
268 | 			}
269 | 			if (32 <= j && j <= 47) {
270 | 				// Math.floor((2 ** 30) * Math.cbrt(5))
271 | 				return 0x6D703EF3;
272 | 			}
273 | 			if (48 <= j && j <= 63) {
274 | 				// Math.floor((2 ** 30) * Math.cbrt(7))
275 | 				return 0x7A6D76E9;
276 | 			}
277 | 			if (64 <= j && j <= 79) {
278 | 				return 0x00000000;
279 | 			}
280 | 		}
281 | 	}, {
282 | 		key: "add_modulo32",
283 | 		value: function add_modulo32() /* ...... */{
284 | 			// 1.  Modulo addition (addition modulo) is associative.
285 | 			//    https://proofwiki.org/wiki/Modulo_Addition_is_Associative
286 | 			// 2.  Bitwise operation in Javascript
287 | 			//    is done on 32-bits operands
288 | 			//    and results in a 32-bits value.
289 | 			return Array.from(arguments).reduce(function (a, b) {
290 | 				return a + b;
291 | 			}, 0) | 0;
292 | 		}
293 | 	}, {
294 | 		key: "rol32",
295 | 		value: function rol32(value, count) {
296 | 			// Cyclic left shift (rotate) on 32-bits value.
297 | 			return value << count | value >>> 32 - count;
298 | 		}
299 | 	}, {
300 | 		key: "hash",
301 | 		value: function hash(message /* An ArrayBuffer. */) {
302 | 			//////////       Padding       //////////
303 | 
304 | 			// The padded message.
305 | 			var padded = RIPEMD160.pad(message);
306 | 
307 | 			//////////     Compression     //////////
308 | 
309 | 			// Message word selectors.
310 | 			var r = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13];
311 | 			var rP = [// r'
312 | 			5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11];
313 | 
314 | 			// Amounts for 'rotate left' operation.
315 | 			var s = [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6];
316 | 			var sP = [// s'
317 | 			8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11];
318 | 
319 | 			// The size, in bytes, of a word.
320 | 			var word_size = 4;
321 | 
322 | 			// The size, in bytes, of a 16-words block.
323 | 			var block_size = 64;
324 | 
325 | 			// The number of the 16-words blocks.
326 | 			var t = padded.byteLength / block_size;
327 | 
328 | 			//  The message after padding consists of t 16-word blocks that
329 | 			// are denoted with X_i[j], with 0≤i≤(t − 1) and 0≤j≤15.
330 | 			var X = new Array(t).fill(undefined).map(function (_, i) {
331 | 				return function (j) {
332 | 					return new DataView(padded, i * block_size, block_size).getUint32(j * word_size, true // Little-endian
333 | 					);
334 | 				};
335 | 			});
336 | 
337 | 			//  The result of RIPEMD-160 is contained in five 32-bit words,
338 | 			// which form the internal state of the algorithm. The final
339 | 			// content of these five 32-bit words is converted to a 160-bit
340 | 			// string, again using the little-endian convention.
341 | 			var h = [0x67452301, // h_0
342 | 			0xEFCDAB89, // h_1
343 | 			0x98BADCFE, // h_2
344 | 			0x10325476, // h_3
345 | 			0xC3D2E1F0 // h_4
346 | 			];
347 | 
348 | 			for (var i = 0; i < t; ++i) {
349 | 				var A = h[0],
350 | 				    B = h[1],
351 | 				    C = h[2],
352 | 				    D = h[3],
353 | 				    E = h[4];
354 | 				var AP = A,
355 | 				    BP = B,
356 | 				    CP = C,
357 | 				    DP = D,
358 | 				    EP = E;
359 | 				for (var j = 0; j < 80; ++j) {
360 | 					// Left rounds
361 | 					var _T = RIPEMD160.add_modulo32(RIPEMD160.rol32(RIPEMD160.add_modulo32(A, RIPEMD160.f(j, B, C, D), X[i](r[j]), RIPEMD160.K(j)), s[j]), E);
362 | 					A = E;
363 | 					E = D;
364 | 					D = RIPEMD160.rol32(C, 10);
365 | 					C = B;
366 | 					B = _T;
367 | 
368 | 					// Right rounds
369 | 					_T = RIPEMD160.add_modulo32(RIPEMD160.rol32(RIPEMD160.add_modulo32(AP, RIPEMD160.f(79 - j, BP, CP, DP), X[i](rP[j]), RIPEMD160.KP(j)), sP[j]), EP);
370 | 					AP = EP;
371 | 					EP = DP;
372 | 					DP = RIPEMD160.rol32(CP, 10);
373 | 					CP = BP;
374 | 					BP = _T;
375 | 				}
376 | 				var T = RIPEMD160.add_modulo32(h[1], C, DP);
377 | 				h[1] = RIPEMD160.add_modulo32(h[2], D, EP);
378 | 				h[2] = RIPEMD160.add_modulo32(h[3], E, AP);
379 | 				h[3] = RIPEMD160.add_modulo32(h[4], A, BP);
380 | 				h[4] = RIPEMD160.add_modulo32(h[0], B, CP);
381 | 				h[0] = T;
382 | 			}
383 | 
384 | 			//  The final output string then consists of the concatenatation
385 | 			// of h_0, h_1, h_2, h_3, and h_4 after converting each h_i to a
386 | 			// 4-byte string using the little-endian convention.
387 | 			var result = new ArrayBuffer(20);
388 | 			var data_view = new DataView(result);
389 | 			h.forEach(function (h_i, i) {
390 | 				return data_view.setUint32(i * 4, h_i, true);
391 | 			});
392 | 			return result;
393 | 		}
394 | 	}]);
395 | 
396 | 	return RIPEMD160;
397 | }();
398 | 
399 | module.exports = {
400 | 	RIPEMD160: RIPEMD160
401 | };
402 | 


--------------------------------------------------------------------------------
/src/ripemd.js:
--------------------------------------------------------------------------------
  1 | // https://gist.githubusercontent.com/wlzla000/bac83df6d3c51916c4dd0bc947e46947/raw/7ee3462b095ab22580ddaf191f44a590da6fe33b/RIPEMD-160.js
  2 | 
  3 | /*
  4 | 	RIPEMD-160.js
  5 | 
  6 | 		developed
  7 | 			by K. (https://github.com/wlzla000)
  8 | 			on December 27-29, 2017,
  9 | 
 10 | 		licensed under
 11 | 
 12 | 
 13 | 		the MIT license
 14 | 
 15 | 		Copyright (c) 2017 K.
 16 | 
 17 | 		 Permission is hereby granted, free of charge, to any person
 18 | 		obtaining a copy of this software and associated documentation
 19 | 		files (the "Software"), to deal in the Software without
 20 | 		restriction, including without limitation the rights to use,
 21 | 		copy, modify, merge, publish, distribute, sublicense, and/or
 22 | 		sell copies of the Software, and to permit persons to whom the
 23 | 		Software is furnished to do so, subject to the following
 24 | 		conditions:
 25 | 
 26 | 		 The above copyright notice and this permission notice shall be
 27 | 		included in all copies or substantial portions of the Software.
 28 | 
 29 | 		 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 30 | 		EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 31 | 		OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 32 | 		NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 33 | 		HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 34 | 		WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 35 | 		FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 36 | 		OTHER DEALINGS IN THE SOFTWARE.
 37 | */
 38 | 
 39 | "use strict";
 40 | 
 41 | class RIPEMD160
 42 | {
 43 | 	constructor()
 44 | 	{
 45 | 		// https://webcache.googleusercontent.com/search?q=cache:CnLOgolTHYEJ:https://www.cosic.esat.kuleuven.be/publications/article-317.pdf
 46 | 		// http://shodhganga.inflibnet.ac.in/bitstream/10603/22978/13/13_appendix.pdf
 47 | 	}
 48 | 
 49 | 	static get_n_pad_bytes(message_size /* in bytes, 1 byte is 8 bits. */)
 50 | 	{
 51 | 		//  Obtain the number of bytes needed to pad the message.
 52 | 		// It does not contain the size of the message size information.
 53 | 		/*
 54 | 			https://webcache.googleusercontent.com/search?q=cache:CnLOgolTHYEJ:https://www.cosic.esat.kuleuven.be/publications/article-317.pdf
 55 | 
 56 | 			The Cryptographic Hash Function RIPEMD-160
 57 | 
 58 | 			written by
 59 | 				Bart Preneel,
 60 | 				Hans Dobbertin,
 61 | 				Antoon Bosselaers
 62 | 			in
 63 | 				1997.
 64 | 
 65 | 			--------------------------------------------------
 66 | 
 67 | 			§5     Description of RIPEMD-160
 68 | 
 69 | 			......
 70 | 
 71 | 			 In order to guarantee that the total input size is a
 72 | 			multiple of 512 bits, the input is padded in the same
 73 | 			way as for all the members of the MD4-family: one
 74 | 			appends a single 1 followed by a string of 0s (the
 75 | 			number of 0s lies between 0 and 511); the last 64 bits
 76 | 			of the extended input contain the binary representation
 77 | 			of the input size in bits, least significant byte first.
 78 | 		*/
 79 | 		/*
 80 | 			https://tools.ietf.org/rfc/rfc1186.txt
 81 | 
 82 | 			RFC 1186: MD4 Message Digest Algorithm.
 83 | 
 84 | 			written by
 85 | 				Ronald Linn Rivest
 86 | 			in
 87 | 				October 1990.
 88 | 
 89 | 			--------------------------------------------------
 90 | 
 91 | 			§3     MD4 Algorithm Description
 92 | 
 93 | 			......
 94 | 
 95 | 			Step 1. Append padding bits
 96 | 
 97 | 			 The message is "padded" (extended) so that its length
 98 | 			(in bits) is congruent to 448, modulo 512. That is, the
 99 | 			message is extended so that it is just 64 bits shy of
100 | 			being a multiple of 512 bits long. Padding is always
101 | 			performed, even if the length of the message is already
102 | 			congruent to 448, modulo 512 (in which case 512 bits of
103 | 			padding are added).
104 | 
105 | 			 Padding is performed as follows: a single "1" bit is
106 | 			appended to the message, and then enough zero bits are
107 | 			appended so that the length in bits of the padded
108 | 			message becomes congruent to 448, modulo 512.
109 | 
110 | 			Step 2. Append length
111 | 
112 | 			 A 64-bit representation of b (the length of the message
113 | 			before the padding bits were added) is appended to the
114 | 			result of the previous step. In the unlikely event that
115 | 			b is greater than 2^64, then only the low-order 64 bits
116 | 			of b are used. (These bits are appended as two 32-bit
117 | 			words and appended low-order word first in accordance
118 | 			with the previous conventions.)
119 | 
120 | 			 At this point the resulting message (after padding with
121 | 			bits and with b) has a length that is an exact multiple
122 | 			of 512 bits. Equivalently, this message has a length
123 | 			that is an exact multiple of 16 (32-bit) words. Let
124 | 			M[0 ... N-1] denote the words of the resulting message,
125 | 			where N is a multiple of 16.
126 | 		*/
127 | 		// https://crypto.stackexchange.com/a/32407/54568
128 | 		/*
129 | 			Example case  # 1
130 | 				[0 bit: message.]
131 | 				[1 bit: 1.]
132 | 				[447 bits: 0.]
133 | 				[64 bits: message size information.]
134 | 
135 | 			Example case  # 2
136 | 				[512-bits: message]
137 | 				[1 bit: 1.]
138 | 				[447 bits: 0.]
139 | 				[64 bits: message size information.]
140 | 
141 | 			Example case  # 3
142 | 				[(512 - 64 = 448) bits: message.]
143 | 				[1 bit: 1.]
144 | 				[511 bits: 0.]
145 | 				[64 bits: message size information.]
146 | 
147 | 			Example case  # 4
148 | 				[(512 - 65 = 447) bits: message.]
149 | 				[1 bit: 1.]
150 | 				[0 bit: 0.]
151 | 				[64 bits: message size information.]
152 | 		*/
153 | 		// The number of padding zero bits:
154 | 		//      511 - [{(message size in bits) + 64} (mod 512)]
155 | 		return 64 - ((message_size + 8) & 0b00111111 /* 63 */);
156 | 	}
157 | 	static pad(message /* An ArrayBuffer. */)
158 | 	{
159 | 		const message_size = message.byteLength;
160 | 		const n_pad = RIPEMD160.get_n_pad_bytes(message_size);
161 | 
162 | 		//  `Number.MAX_SAFE_INTEGER` is ((2 ** 53) - 1) and
163 | 		// bitwise operation in Javascript is done on 32-bits operands.
164 | 		const divmod = (dividend, divisor) => [
165 | 			Math.floor(dividend / divisor),
166 | 			dividend % divisor
167 | 		];
168 | 		/*
169 | To shift
170 | 
171 |    00000000 000????? ???????? ???????? ???????? ???????? ???????? ????????
172 |                                      t o
173 |    00000000 ???????? ???????? ???????? ???????? ???????? ???????? ?????000
174 | 
175 | --------------------------------------------------------------------------------
176 | 
177 | Method #1
178 | 
179 |     00000000 000????? ???????? ????????  ???????? ???????? ???????? ????????
180 |    [00000000 000AAAAA AAAAAAAA AAAAAAAA] ( captured)
181 |    [00000000 AAAAAAAA AAAAAAAA AAAAA000] ( shifted)
182 |                          ( captured) [BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB]
183 |                      ( shifted) [BBB][BBBBBBBB BBBBBBBB BBBBBBBB BBBBB000]
184 |    [00000000 AAAAAAAA AAAAAAAA AAAAABBB] ( &  merged)
185 |    [00000000 AAAAAAAA AAAAAAAA AAAAABBB][BBBBBBBB BBBBBBBB BBBBBBBB BBBBB000]
186 |     00000000 ???????? ???????? ????????  ???????? ???????? ???????? ?????000
187 | 
188 | 		const uint32_max_plus_1 = 0x100000000; // (2 ** 32)
189 | 		const [
190 | 			msg_byte_size_most, // Value range [0, (2 ** 21) - 1].
191 | 			msg_byte_size_least // Value range [0, (2 ** 32) - 1].
192 | 		] = divmod(message_size, uint32_max_plus_1);
193 | 		const [
194 | 			carry, // Value range [0, 7].
195 | 			msg_bit_size_least // Value range [0, (2 ** 32) - 8].
196 | 		] = divmod(message_byte_size_least * 8, uint32_max_plus_1);
197 | 		const message_bit_size_most = message_byte_size_most * 8
198 | 			+ carry; // Value range [0, (2 ** 24) - 1].
199 | 
200 | --------------------------------------------------------------------------------
201 | 
202 | Method #2
203 |     00000000 000????? ???????? ????????  ???????? ???????? ???????? ????????
204 |       [00000 000AAAAA AAAAAAAA AAAAAAAA  AAA] ( captured)
205 |                          ( captured) [000BBBBB BBBBBBBB BBBBBBBB BBBBBBBB]
206 |                           ( shifted) [BBBBBBBB BBBBBBBB BBBBBBBB BBBBB000]
207 |    [00000000 AAAAAAAA AAAAAAAA AAAAAAAA][BBBBBBBB BBBBBBBB BBBBBBBB BBBBB000]
208 |     00000000 ???????? ???????? ????????  ???????? ???????? ???????? ?????000
209 | 
210 | 		*/
211 | 		const [
212 | 			msg_bit_size_most,
213 | 			msg_bit_size_least
214 | 		] = divmod(message_size, 536870912 /* (2 ** 29) */)
215 | 			.map((x, index) => (index ? (x * 8) : x));
216 | 
217 | 		// `ArrayBuffer.transfer()` is not supported.
218 | 		const padded = new Uint8Array(message_size + n_pad + 8);
219 | 		padded.set(new Uint8Array(message), 0);
220 | 		const data_view = new DataView(padded.buffer);
221 | 		data_view.setUint8(message_size, 0b10000000);
222 | 		data_view.setUint32(
223 | 			message_size + n_pad,
224 | 			msg_bit_size_least,
225 | 			true // Little-endian
226 | 		);
227 | 		data_view.setUint32(
228 | 			message_size + n_pad + 4,
229 | 			msg_bit_size_most,
230 | 			true // Little-endian
231 | 		);
232 | 
233 | 		return padded.buffer;
234 | 	}
235 | 
236 | 	static f(j, x, y, z)
237 | 	{
238 | 		if(0 <= j && j <= 15)
239 | 		{ // Exclusive-OR
240 | 			return x ^ y ^ z;
241 | 		}
242 | 		if(16 <= j && j <= 31)
243 | 		{ // Multiplexing (muxing)
244 | 			return (x & y) | (~x & z);
245 | 		}
246 | 		if(32 <= j && j <= 47)
247 | 		{
248 | 			return (x | ~y) ^ z;
249 | 		}
250 | 		if(48 <= j && j <= 63)
251 | 		{ // Multiplexing (muxing)
252 | 			return (x & z) | (y & ~z);
253 | 		}
254 | 		if(64 <= j && j <= 79)
255 | 		{
256 | 			return x ^ (y | ~z);
257 | 		}
258 | 	}
259 | 	static K(j)
260 | 	{
261 | 		if(0 <= j && j <= 15)
262 | 		{
263 | 			return 0x00000000;
264 | 		}
265 | 		if(16 <= j && j <= 31)
266 | 		{
267 | 			// Math.floor((2 ** 30) * Math.SQRT2)
268 | 			return 0x5A827999;
269 | 		}
270 | 		if(32 <= j && j <= 47)
271 | 		{
272 | 			// Math.floor((2 ** 30) * Math.sqrt(3))
273 | 			return 0x6ED9EBA1;
274 | 		}
275 | 		if(48 <= j && j <= 63)
276 | 		{
277 | 			// Math.floor((2 ** 30) * Math.sqrt(5))
278 | 			return 0x8F1BBCDC;
279 | 		}
280 | 		if(64 <= j && j <= 79)
281 | 		{
282 | 			// Math.floor((2 ** 30) * Math.sqrt(7))
283 | 			return 0xA953FD4E;
284 | 		}
285 | 	}
286 | 	static KP(j) // K'
287 | 	{
288 | 		if(0 <= j && j <= 15)
289 | 		{
290 | 			// Math.floor((2 ** 30) * Math.cbrt(2))
291 | 			return 0x50A28BE6;
292 | 		}
293 | 		if(16 <= j && j <= 31)
294 | 		{
295 | 			// Math.floor((2 ** 30) * Math.cbrt(3))
296 | 			return 0x5C4DD124;
297 | 		}
298 | 		if(32 <= j && j <= 47)
299 | 		{
300 | 			// Math.floor((2 ** 30) * Math.cbrt(5))
301 | 			return 0x6D703EF3;
302 | 		}
303 | 		if(48 <= j && j <= 63)
304 | 		{
305 | 			// Math.floor((2 ** 30) * Math.cbrt(7))
306 | 			return 0x7A6D76E9;
307 | 		}
308 | 		if(64 <= j && j <= 79)
309 | 		{
310 | 			return 0x00000000;
311 | 		}
312 | 	}
313 | 	static add_modulo32(/* ...... */)
314 | 	{
315 | 		// 1.  Modulo addition (addition modulo) is associative.
316 | 		//    https://proofwiki.org/wiki/Modulo_Addition_is_Associative
317 |  		// 2.  Bitwise operation in Javascript
318 | 		//    is done on 32-bits operands
319 | 		//    and results in a 32-bits value.
320 | 		return Array
321 | 			.from(arguments)
322 | 			.reduce((a, b) => (a + b), 0) | 0;
323 | 	}
324 | 	static rol32(value, count)
325 | 	{ // Cyclic left shift (rotate) on 32-bits value.
326 | 		return (value << count) | (value >>> (32 - count));
327 | 	}
328 | 	static hash(message /* An ArrayBuffer. */)
329 | 	{
330 | 		//////////       Padding       //////////
331 | 
332 | 		// The padded message.
333 | 		const padded = RIPEMD160.pad(message);
334 | 
335 | 		//////////     Compression     //////////
336 | 
337 | 		// Message word selectors.
338 | 		const r = [
339 | 			0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
340 | 			7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
341 | 			3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
342 | 			1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
343 | 			4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
344 | 		];
345 | 		const rP = [ // r'
346 | 			5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
347 | 			6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
348 | 			15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
349 | 			8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
350 | 			12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
351 | 		];
352 | 
353 | 		// Amounts for 'rotate left' operation.
354 | 		const s = [
355 | 			11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
356 | 			7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
357 | 			11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
358 | 			11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
359 | 			9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
360 | 		];
361 | 		const sP = [ // s'
362 | 			8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
363 | 			9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
364 | 			9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
365 | 			15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
366 | 			8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
367 | 		];
368 | 
369 | 		// The size, in bytes, of a word.
370 | 		const word_size = 4;
371 | 
372 | 		// The size, in bytes, of a 16-words block.
373 | 		const block_size = 64;
374 | 
375 | 		// The number of the 16-words blocks.
376 | 		const t = padded.byteLength / block_size;
377 | 
378 | 		//  The message after padding consists of t 16-word blocks that
379 | 		// are denoted with X_i[j], with 0≤i≤(t − 1) and 0≤j≤15.
380 | 		const X = (new Array(t))
381 | 			.fill(undefined)
382 | 			.map((_, i) => j => (
383 | 				new DataView(
384 | 					padded, i * block_size, block_size
385 | 				).getUint32(
386 | 					j * word_size,
387 | 					true // Little-endian
388 | 				)
389 | 			));
390 | 
391 | 		//  The result of RIPEMD-160 is contained in five 32-bit words,
392 | 		// which form the internal state of the algorithm. The final
393 | 		// content of these five 32-bit words is converted to a 160-bit
394 | 		// string, again using the little-endian convention.
395 | 		let h = [
396 | 			0x67452301, // h_0
397 | 			0xEFCDAB89, // h_1
398 | 			0x98BADCFE, // h_2
399 | 			0x10325476, // h_3
400 | 			0xC3D2E1F0  // h_4
401 | 		];
402 | 
403 | 		for(let i = 0; i < t; ++i)
404 | 		{
405 | 			let A = h[0], B = h[1], C = h[2], D = h[3], E = h[4];
406 | 			let AP = A, BP = B, CP = C, DP = D, EP = E;
407 | 			for(let j = 0; j < 80; ++j)
408 | 			{
409 | 				// Left rounds
410 | 				let T = RIPEMD160.add_modulo32(
411 | 					RIPEMD160.rol32(
412 | 						RIPEMD160.add_modulo32(
413 | 							A,
414 | 							RIPEMD160.f(j, B, C, D),
415 | 							X[i](r[j]),
416 | 							RIPEMD160.K(j)
417 | 						),
418 | 						s[j]
419 | 					),
420 | 					E
421 | 				);
422 | 				A = E;
423 | 				E = D;
424 | 				D = RIPEMD160.rol32(C, 10);
425 | 				C = B;
426 | 				B = T;
427 | 
428 | 				// Right rounds
429 | 				T = RIPEMD160.add_modulo32(
430 | 					RIPEMD160.rol32(
431 | 						RIPEMD160.add_modulo32(
432 | 							AP,
433 | 							RIPEMD160.f(
434 | 								79 - j,
435 | 								BP,
436 | 								CP,
437 | 								DP
438 | 							),
439 | 							X[i](rP[j]),
440 | 							RIPEMD160.KP(j)
441 | 						),
442 | 						sP[j]
443 | 					),
444 | 					EP
445 | 				);
446 | 				AP = EP;
447 | 				EP = DP;
448 | 				DP = RIPEMD160.rol32(CP, 10);
449 | 				CP = BP;
450 | 				BP = T;
451 | 			}
452 | 			let T = RIPEMD160.add_modulo32(h[1], C, DP);
453 | 			h[1] = RIPEMD160.add_modulo32(h[2], D, EP);
454 | 			h[2] = RIPEMD160.add_modulo32(h[3], E, AP);
455 | 			h[3] = RIPEMD160.add_modulo32(h[4], A, BP);
456 | 			h[4] = RIPEMD160.add_modulo32(h[0], B, CP);
457 | 			h[0] = T;
458 | 		}
459 | 
460 | 		//  The final output string then consists of the concatenatation
461 | 		// of h_0, h_1, h_2, h_3, and h_4 after converting each h_i to a
462 | 		// 4-byte string using the little-endian convention.
463 | 		const result = new ArrayBuffer(20);
464 | 		const data_view = new DataView(result);
465 | 		h.forEach((h_i, i) => data_view.setUint32(i * 4, h_i, true));
466 | 		return result;
467 | 	}
468 | }
469 | 
470 | module.exports = {
471 | 	RIPEMD160
472 | }
473 | 


--------------------------------------------------------------------------------
/src/rpc-web.ts:
--------------------------------------------------------------------------------
1 | import { JsonRpc } from './eosjs-jsonrpc';
2 | import { RpcError } from './eosjs-rpcerror';
3 | 
4 | export { JsonRpc, RpcError };
5 | 


--------------------------------------------------------------------------------
/src/tests/TestConfig.ts:
--------------------------------------------------------------------------------
 1 | enum TestNet {
 2 |     Local,
 3 |     Jungle,
 4 |     HomeBrew
 5 | }
 6 | 
 7 | class TestConfig {
 8 |     // URL to Nodeos
 9 |     public endpoint: string
10 |     // look at finalized header block to get chain information
11 |     public blocksBehind: number
12 |     // timeout
13 |     public expireSeconds: number
14 |     // on very fast single producer system need a search ahead for Tapos Block
15 |     public searchBlockAhead: number
16 |     public sleep: boolean
17 | 
18 |     constructor(type: TestNet) {
19 |         if (type === TestNet.Local) {
20 |             this.endpoint = 'http://127.0.0.1:8888'
21 |             this.blocksBehind = 1
22 |             this.expireSeconds = 30
23 |             this.searchBlockAhead = 1
24 |             this.sleep = true
25 |             return
26 |         }
27 |         if (type === TestNet.HomeBrew) {
28 |             this.endpoint = 'http://10.3.0.1:8888'
29 |             this.blocksBehind = 1
30 |             this.expireSeconds = 720
31 |             this.searchBlockAhead = 1
32 |             this.sleep = true
33 |             return
34 |         }
35 |         // Default
36 |         this.endpoint = 'https://jungle4.cryptolions.io'
37 |         this.blocksBehind = 3
38 |         this.expireSeconds = 30
39 |         this.searchBlockAhead = 0
40 |         this.sleep = false
41 |     }
42 | }
43 | 
44 | export {TestConfig, TestNet}
45 | 


--------------------------------------------------------------------------------
/src/tests/eosjs-api.test.ts:
--------------------------------------------------------------------------------
  1 | import { TextDecoder, TextEncoder } from 'util';
  2 | import { Api } from '../eosjs-api';
  3 | import { JsonRpc } from '../eosjs-jsonrpc';
  4 | import { JsSignatureProvider } from '../eosjs-jssig';
  5 | 
  6 | const transaction = {
  7 |     expiration: '2018-09-04T18:42:49',
  8 |     ref_block_num: 38096,
  9 |     ref_block_prefix: 505360011,
 10 |     max_net_usage_words: 0,
 11 |     max_cpu_usage_ms: 0,
 12 |     delay_sec: 0,
 13 |     context_free_actions: [] as any,
 14 |     actions: [
 15 |         {
 16 |             account: 'testeostoken',
 17 |             name: 'transfer',
 18 |             authorization: [
 19 |                 {
 20 |                     actor: 'thegazelle',
 21 |                     permission: 'active',
 22 |                 },
 23 |             ],
 24 |             data: {
 25 |                 from: 'thegazelle',
 26 |                 to: 'remasteryoda',
 27 |                 quantity: '1.0000 EOS',
 28 |                 memo: 'For a secure future.',
 29 |             },
 30 |             hex_data: `00808a517dc354cb6012f557656ca4ba102700000000000004454f530000000014466f722
 31 |         06120736563757265206675747572652e`,
 32 |         },
 33 |         {
 34 |             account: 'testeostoken',
 35 |             name: 'transfer',
 36 |             authorization: [
 37 |                 {
 38 |                     actor: 'thegazelle',
 39 |                     permission: 'active',
 40 |                 },
 41 |             ],
 42 |             data: {
 43 |                 from: 'thegazelle',
 44 |                 to: 'remasteryoda',
 45 |                 quantity: '2.0000 EOS',
 46 |                 memo: 'For a second secure future (multiverse?)',
 47 |             },
 48 |             hex_data: `00808a517dc354cb6012f557656ca4ba204e00000000000004454f530000000028466f722061207365636f6e642073656
 49 |         37572652066757475726520286d756c746976657273653f29`,
 50 |         },
 51 |     ],
 52 |     transaction_extensions: [] as any,
 53 | };
 54 | 
 55 | const serializedTx = [
 56 |     41, 210, 142, 91, 208, 148, 139, 46, 31, 30, 0, 0, 0, 0, 2, 48, 21, 164,
 57 |     25, 83, 149, 177, 202, 0, 0, 0, 87, 45, 60, 205, 205, 1, 0, 128, 138, 81,
 58 |     125, 195, 84, 203, 0, 0, 0, 0, 168, 237, 50, 50, 0, 48, 21, 164, 25, 83,
 59 |     149, 177, 202, 0, 0, 0, 87, 45, 60, 205, 205, 1, 0, 128, 138, 81, 125,
 60 |     195, 84, 203, 0, 0, 0, 0, 168, 237, 50, 50, 0, 0,
 61 | ];
 62 | 
 63 | const deserializedTx = {
 64 |     actions: [
 65 |         {
 66 |             account: 'testeostoken',
 67 |             authorization: [{ actor: 'thegazelle', permission: 'active' }],
 68 |             data: '',
 69 |             name: 'transfer',
 70 |         },
 71 |         {
 72 |             account: 'testeostoken',
 73 |             authorization: [{ actor: 'thegazelle', permission: 'active' }],
 74 |             data: '',
 75 |             name: 'transfer',
 76 |         },
 77 |     ],
 78 |     context_free_actions: [] as any,
 79 |     delay_sec: 0,
 80 |     expiration: '2018-09-04T18:42:49.000',
 81 |     max_cpu_usage_ms: 0,
 82 |     max_net_usage_words: 0,
 83 |     ref_block_num: 38096,
 84 |     ref_block_prefix: 505360011,
 85 |     transaction_extensions: [] as any,
 86 | };
 87 | 
 88 | const serializedActions = [
 89 |     {
 90 |         account: 'testeostoken',
 91 |         authorization: [{ actor: 'thegazelle', permission: 'active' }],
 92 |         data: "00808A517DC354CB6012F557656CA4BA102700000000000004454F530000000014466F72206120736563757265206675747572652E", // tslint:disable-line
 93 |         name: 'transfer',
 94 |     },
 95 |     {
 96 |         account: 'testeostoken',
 97 |         authorization: [{ actor: 'thegazelle', permission: 'active' }],
 98 |         data: "00808A517DC354CB6012F557656CA4BA204E00000000000004454F530000000028466F722061207365636F6E64207365637572652066757475726520286D756C746976657273653F29", // tslint:disable-line
 99 |         name: 'transfer',
100 |     },
101 | ];
102 | 
103 | const deserializedActions = [
104 |     {
105 |         account: 'testeostoken',
106 |         authorization: [{ actor: 'thegazelle', permission: 'active' }],
107 |         data: {
108 |             from: 'thegazelle',
109 |             memo: 'For a secure future.',
110 |             quantity: '1.0000 EOS',
111 |             to: 'remasteryoda',
112 |         },
113 |         name: 'transfer',
114 |     },
115 |     {
116 |         account: 'testeostoken',
117 |         authorization: [{ actor: 'thegazelle', permission: 'active' }],
118 |         data: {
119 |             from: 'thegazelle',
120 |             memo: 'For a second secure future (multiverse?)',
121 |             quantity: '2.0000 EOS',
122 |             to: 'remasteryoda',
123 |         },
124 |         name: 'transfer',
125 |     },
126 | ];
127 | 
128 | describe('eosjs-api', () => {
129 |     let api: any;
130 |     const fetch = async (input: any, init: any): Promise => ({
131 |         ok: true,
132 |         json: async () => {
133 |             if (input === '/v1/chain/get_raw_code_and_abi') {
134 |                 return {
135 |                     account_name: 'testeostoken',
136 |                     abi: "DmVvc2lvOjphYmkvMS4wAQxhY2NvdW50X25hbWUEbmFtZQUIdHJhbnNmZXIABARmcm9tDGFjY291bnRfbmFtZQJ0bwxhY2NvdW50X25hbWUIcXVhbnRpdHkFYXNzZXQEbWVtbwZzdHJpbmcGY3JlYXRlAAIGaXNzdWVyDGFjY291bnRfbmFtZQ5tYXhpbXVtX3N1cHBseQVhc3NldAVpc3N1ZQADAnRvDGFjY291bnRfbmFtZQhxdWFudGl0eQVhc3NldARtZW1vBnN0cmluZwdhY2NvdW50AAEHYmFsYW5jZQVhc3NldA5jdXJyZW5jeV9zdGF0cwADBnN1cHBseQVhc3NldAptYXhfc3VwcGx5BWFzc2V0Bmlzc3VlcgxhY2NvdW50X25hbWUDAAAAVy08zc0IdHJhbnNmZXLnBSMjIFRyYW5zZmVyIFRlcm1zICYgQ29uZGl0aW9ucwoKSSwge3tmcm9tfX0sIGNlcnRpZnkgdGhlIGZvbGxvd2luZyB0byBiZSB0cnVlIHRvIHRoZSBiZXN0IG9mIG15IGtub3dsZWRnZToKCjEuIEkgY2VydGlmeSB0aGF0IHt7cXVhbnRpdHl9fSBpcyBub3QgdGhlIHByb2NlZWRzIG9mIGZyYXVkdWxlbnQgb3IgdmlvbGVudCBhY3Rpdml0aWVzLgoyLiBJIGNlcnRpZnkgdGhhdCwgdG8gdGhlIGJlc3Qgb2YgbXkga25vd2xlZGdlLCB7e3RvfX0gaXMgbm90IHN1cHBvcnRpbmcgaW5pdGlhdGlvbiBvZiB2aW9sZW5jZSBhZ2FpbnN0IG90aGVycy4KMy4gSSBoYXZlIGRpc2Nsb3NlZCBhbnkgY29udHJhY3R1YWwgdGVybXMgJiBjb25kaXRpb25zIHdpdGggcmVzcGVjdCB0byB7e3F1YW50aXR5fX0gdG8ge3t0b319LgoKSSB1bmRlcnN0YW5kIHRoYXQgZnVuZHMgdHJhbnNmZXJzIGFyZSBub3QgcmV2ZXJzaWJsZSBhZnRlciB0aGUge3t0cmFuc2FjdGlvbi5kZWxheX19IHNlY29uZHMgb3Igb3RoZXIgZGVsYXkgYXMgY29uZmlndXJlZCBieSB7e2Zyb219fSdzIHBlcm1pc3Npb25zLgoKSWYgdGhpcyBhY3Rpb24gZmFpbHMgdG8gYmUgaXJyZXZlcnNpYmx5IGNvbmZpcm1lZCBhZnRlciByZWNlaXZpbmcgZ29vZHMgb3Igc2VydmljZXMgZnJvbSAne3t0b319JywgSSBhZ3JlZSB0byBlaXRoZXIgcmV0dXJuIHRoZSBnb29kcyBvciBzZXJ2aWNlcyBvciByZXNlbmQge3txdWFudGl0eX19IGluIGEgdGltZWx5IG1hbm5lci4KAAAAAAClMXYFaXNzdWUAAAAAAKhs1EUGY3JlYXRlAAIAAAA4T00RMgNpNjQBCGN1cnJlbmN5AQZ1aW50NjQHYWNjb3VudAAAAAAAkE3GA2k2NAEIY3VycmVuY3kBBnVpbnQ2NA5jdXJyZW5jeV9zdGF0cwAAAA===", // tslint:disable-line
137 |                 };
138 |             }
139 | 
140 |             return transaction;
141 |         },
142 |     });
143 | 
144 |     beforeEach(() => {
145 |         const rpc = new JsonRpc('', { fetch });
146 |         const signatureProvider = new JsSignatureProvider(['5JtUScZK2XEp3g9gh7F8bwtPTRAkASmNrrftmx4AxDKD5K4zDnr']);
147 |         const chainId = '038f4b0fc8ff18a4f0842a8f0564611f6e96e8535901dd45e43ac8691a1c4dca';
148 |         api = new Api({
149 |             rpc, signatureProvider, chainId, textDecoder: new TextDecoder(), textEncoder: new TextEncoder(),
150 |         });
151 |     });
152 | 
153 |     it('Doesnt crash', () => {
154 |         expect(api).toBeTruthy();
155 |     });
156 | 
157 |     it('getAbi returns an abi', async () => {
158 |         const response = await api.getAbi('testeostoken');
159 |         expect(response).toBeTruthy();
160 |     });
161 | 
162 |     it('getTransactionAbis returns abis by transactions', async () => {
163 |         const response = await api.getTransactionAbis(transaction);
164 |         expect(response[0].abi.length).toBeGreaterThan(0);
165 |     });
166 | 
167 |     it('getContract returns a contract', async () => {
168 |         const response = await api.getContract('testeostoken');
169 |         expect(response.actions).toBeTruthy();
170 |     });
171 | 
172 |     it('deserializeTransaction converts tx from binary', () => {
173 |         const tx = api.deserializeTransaction(serializedTx);
174 |         expect(tx).toEqual(deserializedTx);
175 |     });
176 | 
177 |     it('serializeActions converts actions to hex', async () => {
178 |         const response = await api.serializeActions(transaction.actions);
179 | 
180 |         expect(response).toEqual(serializedActions);
181 |     });
182 | 
183 |     it('deserializeActions converts actions from hex', async () => {
184 |         const response = await api.deserializeActions(serializedActions);
185 | 
186 |         expect(response).toEqual(deserializedActions);
187 |     });
188 | 
189 |     it('hasRequiredTaposFields returns true, if required fields are present', () => {
190 |         const response = api.hasRequiredTaposFields(transaction);
191 | 
192 |         expect(response).toEqual(true);
193 |     });
194 | });
195 | 


--------------------------------------------------------------------------------
/src/tests/eosjs-jssig.test.ts:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright (c) 2022 EOS Network Foundation (ENF) and its contributors.  All rights reserved.
  3 |  * Copyright (c) 2017-2020 block.one and its contributors.  All rights reserved.
  4 |  * MIT License
  5 |  * Oct 12, 2022 modified using source from https://github.com/EOSIO/eosjs/archive/refs/tags/v22.1.0.zip
  6 |  */
  7 | 
  8 | import {ec} from 'elliptic';
  9 | 
 10 | import {generateKeyPair, PrivateKey, PublicKey, sha256, Signature} from '../eosjs-key-conversions';
 11 | import {digestFromSerializedData, JsSignatureProvider} from '../eosjs-jssig';
 12 | import {KeyType} from '../eosjs-numeric';
 13 | import {SignatureProviderArgs} from '../eosjs-api-interfaces';
 14 | 
 15 | describe('JsSignatureProvider', () => {
 16 |     const privateKeys = [
 17 |         '5Juww5SS6aLWxopXBAWzwqrwadiZKz7XpKAiktXTKcfBGi1DWg8',
 18 |         '5JnHjSFwe4r7xyqAUAaVs51G7HmzE86DWGa3VAA5VvQriGYnSUr',
 19 |         '5K4XZH5XR2By7Q5KTcZnPAmUMU5yjUNBdoKzzXyrLfmiEZJqoKE',
 20 |     ];
 21 |     const privateKeysK1 = [
 22 |         'PVT_K1_26fMPzM27mXhoSF8y56ro7pN2te7rFT6W6wXiUi5joY79NHfZf',
 23 |         'PVT_K1_y19korZcH8hyStRy8bn2G8tgx51zE8nTWGFz7LG3ZDYkaELTY',
 24 |         'PVT_K1_2FEybdSLZcyrPh3RR7tJ82M8sG4XLW6uzGDmMw76nv54xk8FLu',
 25 |     ];
 26 |     const privateKeysR1 = [
 27 |         'PVT_R1_GrfEfbv5at9kbeHcGagQmvbFLdm6jqEpgE1wsGbrfbZNjpVgT',
 28 |         'PVT_R1_wCpPsaY9o8NU9ZsuwaYVQUDkCfj1aWJZGVcmMM6XyYHJVqvqp',
 29 |         'PVT_R1_eXWyndem7NE1L5jkbpL9JychLgHfwKnLkfpF2n9KXPCqdeikx'
 30 |     ];
 31 |     const legacyPublicKeys = [
 32 |         'EOS7tgwU6E7pAUQJgqEJt66Yi8cWvanTUW8ZfBjeXeJBQvhTU9ypi',
 33 |         'EOS8VaY5CiTexYqgQZyPTJkc3qvWuZUi12QrZL9ssjqW2es6aQk2F',
 34 |         'EOS7VGhqctkKprW1VUj19DZZiiZLX3YcJqUJCuEcahJmUCw3wJEMu',
 35 |     ];
 36 |     const k1FormatPublicKeys = [
 37 |         'PUB_K1_7tgwU6E7pAUQJgqEJt66Yi8cWvanTUW8ZfBjeXeJBQvhYTBFvY',
 38 |         'PUB_K1_8VaY5CiTexYqgQZyPTJkc3qvWuZUi12QrZL9ssjqW2es7e7bRJ',
 39 |         'PUB_K1_7VGhqctkKprW1VUj19DZZiiZLX3YcJqUJCuEcahJmUCw9RT8v2',
 40 |     ];
 41 |     const r1FormatPublicKeys = [
 42 |         'PUB_R1_4ztaVy8L9zbmzTdpfq5GcaFYwGwXTNmN3qW7qcgHMmfUZhpzQQ',
 43 |         'PUB_R1_5xawnnr3mWayv2wkiqBGWqu4RQLNJffLSXHiL3BofdY7ortMy4',
 44 |         'PUB_R1_87HfdXmvbBfJoSd3hDNYJXdu9tkJvmFPJuUa95GXgKm9cUUVJX'
 45 |     ];
 46 |     const signatures = [
 47 |         'SIG_K1_HKkqi3zray76i63ZQwAHWMjoLk3wTa1ajZWPcUnrhgmSWQYEHDJsxkny6VDTWEmVdfktxpGoTA81qe6QuCrDmazeQndmxh',
 48 |         'SIG_K1_HCaY9Y9qdjnkRhE9hokAyp3pFtkMmjpxF6xTd514Vo8vLVSWKek5m5aHfCaka9TqZUbajkhhd4BfBLxSwCwZUEmy8cvt1x',
 49 |         'SIG_K1_GrZqp9ZkuhBeNpeQ5b2L2UWUUrNU1gHbTyMzkyWRhiXNkxPP84Aq9eziU399eBf9xJw8MqHHjz7R2wMTMXhXjHLgpZYFeA',
 50 |     ];
 51 |     const eccSignatures = [
 52 |         'SIG_K1_KeEyJFpkp63Qq5E1zRD9aNZtTjpStvdkdnL31Z7wVmhYtrKGtpVdMBJnXyEUXNkNEyo4d4i4Q79qmRpCUsCRdFqhV6KAeF',
 53 |         'SIG_K1_JvgMmFSDhipS1SeBLNBMdAxayAsWS3GuVGSHS7YQth5Z5ZpijxnZgaa23dYD1efQhpEgtEggdRfHMmp31RDXjmJdZYoKLm',
 54 |         'SIG_K1_JwMqV2nbEntHSq9AuG3Zq1JBc5YqD2SftMHCTGK4A8DYGn1VPQ8QAduwCNksT5JhYgAmGMzPyJdZ2Ws4p8TCvQ16LeNhrw',
 55 |     ];
 56 | 
 57 |     // These are simplified tests simply to verify a refactor didn't mess with existing code
 58 |     describe('secp256k1 elliptic', () => {
 59 |         it('generates a private and public key pair', () => {
 60 |             const {privateKey, publicKey} = generateKeyPair(KeyType.k1, { secureEnv: true });
 61 |             expect(privateKey).toBeInstanceOf(PrivateKey);
 62 |             expect(privateKey.isValid()).toBeTruthy();
 63 |             expect(publicKey).toBeInstanceOf(PublicKey);
 64 |             expect(publicKey.isValid()).toBeTruthy();
 65 |         });
 66 | 
 67 |         it('throws error with no options.secureEnv variable', () => {
 68 |             expect(() => generateKeyPair(KeyType.k1)).toThrowError();
 69 |         });
 70 | 
 71 |         it('Retrieves the public key from a private key', () => {
 72 |             const privateKey = PrivateKey.fromString(privateKeys[0]);
 73 |             const publicKey = privateKey.getPublicKey();
 74 |             expect(publicKey.toString()).toEqual(k1FormatPublicKeys[0]);
 75 |         });
 76 | 
 77 |         it('builds public keys from private when constructed', async () => {
 78 |             const provider = new JsSignatureProvider(privateKeys);
 79 |             const actualPublicKeys = await provider.getAvailableKeys();
 80 |             expect(actualPublicKeys).toEqual(k1FormatPublicKeys);
 81 |         });
 82 | 
 83 |         it('signs a transaction', async () => {
 84 |             const provider = new JsSignatureProvider(privateKeys);
 85 |             const chainId = '12345';
 86 |             const requiredKeys = k1FormatPublicKeys;
 87 |             const serializedTransaction = new Uint8Array([
 88 |                 0, 16, 32, 128, 255,
 89 |             ]);
 90 | 
 91 |             const signOutput = await provider.sign(
 92 |                 { chainId, requiredKeys, serializedTransaction } as SignatureProviderArgs
 93 |             );
 94 | 
 95 |             expect(signOutput).toEqual({
 96 |                 signatures: expect.any(Array),
 97 |                 serializedTransaction,
 98 |                 serializedContextFreeData: undefined
 99 |             });
100 |         });
101 | 
102 |         it('confirm elliptic conversion functions are actually reciprocal', async () => {
103 |             const provider = new JsSignatureProvider(privateKeys);
104 |             const chainId = '12345';
105 |             const requiredKeys = k1FormatPublicKeys;
106 |             const serializedTransaction = new Uint8Array([
107 |                 0, 16, 32, 128, 255,
108 |             ]);
109 | 
110 |             const signOutput = await provider.sign(
111 |                 { chainId, requiredKeys, serializedTransaction } as SignatureProviderArgs
112 |             );
113 | 
114 |             const sig: Signature = Signature.fromString(signOutput.signatures[0]);
115 |             const ellipticSig: ec.Signature = sig.toElliptic();
116 |             const eosSig = Signature.fromElliptic(ellipticSig, KeyType.k1);
117 |             expect(sig).toEqual(eosSig);
118 |         });
119 | 
120 |         it('verify a transaction', async () => {
121 |             const provider = new JsSignatureProvider([privateKeys[0]]);
122 |             const chainId = '12345';
123 |             const requiredKeys = [k1FormatPublicKeys[0]];
124 |             const serializedTransaction = new Uint8Array([
125 |                 0, 16, 32, 128, 255,
126 |             ]);
127 | 
128 |             const signOutput = await provider.sign(
129 |                 { chainId, requiredKeys, serializedTransaction } as SignatureProviderArgs
130 |             );
131 | 
132 |             const signature = Signature.fromString(signOutput.signatures[0]);
133 |             expect(
134 |                 signature.verify(
135 |                     digestFromSerializedData(chainId, serializedTransaction),
136 |                     PublicKey.fromString(k1FormatPublicKeys[0]),
137 |                     false
138 |                 )
139 |             ).toEqual(true);
140 |         });
141 | 
142 |         it('ensure public key functions are actual inverses of each other', async () => {
143 |             const eosioPubKey = PublicKey.fromString(k1FormatPublicKeys[0]);
144 |             const ellipticPubKey = eosioPubKey.toElliptic();
145 |             const finalEosioKeyAsK1String = PublicKey.fromElliptic(ellipticPubKey, KeyType.k1).toString();
146 |             expect(finalEosioKeyAsK1String).toEqual(k1FormatPublicKeys[0]);
147 |         });
148 | 
149 |         it('verify that PUB_K1_ and Legacy pub formats are consistent', () => {
150 |             const eosioLegacyPubKey = legacyPublicKeys[0];
151 |             const ellipticPubKey = PublicKey.fromString(eosioLegacyPubKey).toElliptic();
152 |             expect(PublicKey.fromElliptic(ellipticPubKey, KeyType.k1).toString()).toEqual(k1FormatPublicKeys[0]);
153 |         });
154 | 
155 |         it('verify that privateKey toLegacyString() and toString() are consistent', () => {
156 |             const privKeyFromK1 = PrivateKey.fromString(privateKeysK1[0]);
157 |             const privKeyFromLegacy = PrivateKey.fromString(privateKeys[0]);
158 |             expect(privKeyFromK1.toLegacyString()).toEqual(privateKeys[0]);
159 |             expect(privKeyFromLegacy.toString()).toEqual(privateKeysK1[0]);
160 |         });
161 | 
162 |         it('verify that publicKey toLegacyString() and toString() are consistent', () => {
163 |             const pubKeyFromK1 = PublicKey.fromString(k1FormatPublicKeys[0]);
164 |             const pubKeyFromLegacy = PublicKey.fromString(legacyPublicKeys[0]);
165 |             expect(pubKeyFromK1.toLegacyString()).toEqual(legacyPublicKeys[0]);
166 |             expect(pubKeyFromLegacy.toString()).toEqual(k1FormatPublicKeys[0]);
167 |         });
168 | 
169 |         it('ensure private key functions are actual inverses of each other', async () => {
170 |             const priv = privateKeys[0];
171 |             const privEosioKey = PrivateKey.fromString(priv);
172 |             const privEllipticKey = privEosioKey.toElliptic();
173 |             const finalEosioKeyAsString = PrivateKey.fromElliptic(privEllipticKey, KeyType.k1).toString();
174 |             expect(privEosioKey.toString()).toEqual(finalEosioKeyAsString);
175 |         });
176 | 
177 |         it('verify that public key validate function correctly assesses public keys', () => {
178 |             const publicKey = PublicKey.fromString(k1FormatPublicKeys[0]);
179 |             expect(publicKey.isValid()).toEqual(true);
180 |         });
181 | 
182 |         it('Ensure elliptic sign, recover, verify flow works', () => {
183 |             const KPrivStr = privateKeys[0];
184 |             const KPriv = PrivateKey.fromString(KPrivStr);
185 | 
186 |             const dataAsString = 'some string';
187 |             const ellipticHashedString = sha256(dataAsString);
188 |             const sig = KPriv.sign(ellipticHashedString);
189 |             const KPub = sig.recover(ellipticHashedString);
190 | 
191 |             expect(KPub.toString()).toEqual(k1FormatPublicKeys[0]);
192 |             const valid = sig.verify(ellipticHashedString, KPub);
193 |             expect(valid).toEqual(true);
194 |         });
195 | 
196 |         it('Ensure elliptic sign, recover, verify flow works with shouldHash', () => {
197 |             const KPrivStr = privateKeys[0];
198 |             const KPriv = PrivateKey.fromString(KPrivStr);
199 | 
200 |             const dataAsString = 'some string';
201 |             const sig = KPriv.sign(dataAsString, true);
202 |             const KPub = sig.recover(dataAsString, true);
203 | 
204 |             expect(KPub.toString()).toEqual(k1FormatPublicKeys[0]);
205 |             const valid = sig.verify(dataAsString, KPub, true);
206 |             expect(valid).toEqual(true);
207 |         });
208 | 
209 |         it('Ensure elliptic sign, recover, verify flow works with shouldHash and encoding', () => {
210 |             const KPrivStr = privateKeys[0];
211 |             const KPriv = PrivateKey.fromString(KPrivStr);
212 | 
213 |             const dataAsString = 'some string';
214 |             const sig = KPriv.sign(dataAsString, true, 'utf8');
215 |             const KPub = sig.recover(dataAsString, true, 'utf8');
216 | 
217 |             expect(KPub.toString()).toEqual(k1FormatPublicKeys[0]);
218 |             const valid = sig.verify(dataAsString, KPub, true, 'utf8');
219 |             expect(valid).toEqual(true);
220 |         });
221 |     });
222 | 
223 |     describe('p256 elliptic', () => {
224 |         it('generates a private and public key pair', () => {
225 |             const {privateKey, publicKey} = generateKeyPair(KeyType.r1, { secureEnv: true });
226 |             expect(privateKey).toBeInstanceOf(PrivateKey);
227 |             expect(privateKey.isValid()).toBeTruthy();
228 |             expect(publicKey).toBeInstanceOf(PublicKey);
229 |             expect(publicKey.isValid()).toBeTruthy();
230 |         });
231 | 
232 |         it('throws error with no options.secureEnv variable', () => {
233 |             expect(() => generateKeyPair(KeyType.r1)).toThrowError();
234 |         });
235 | 
236 |         it('throws error when attempting a legacy private key from r1 format', () => {
237 |             const privateKey = PrivateKey.fromString(privateKeysR1[0]);
238 |             expect(() => privateKey.toLegacyString()).toThrowError('Key format not supported in legacy conversion');
239 |         });
240 | 
241 |         it('throws error when attempting a legacy public key from r1 format', () => {
242 |             const publicKey = PublicKey.fromString(r1FormatPublicKeys[0]);
243 |             expect(() => publicKey.toLegacyString()).toThrowError('Key format not supported in legacy conversion');
244 |         });
245 | 
246 |         it('Retrieves the public key from a private key', () => {
247 |             const privateKey = PrivateKey.fromString(privateKeysR1[0]);
248 |             const publicKey = privateKey.getPublicKey();
249 |             expect(publicKey.toString()).toEqual(r1FormatPublicKeys[0]);
250 |         });
251 | 
252 |         it('builds public keys from private when constructed', async () => {
253 |             const provider = new JsSignatureProvider(privateKeysR1);
254 |             const actualPublicKeys = await provider.getAvailableKeys();
255 |             expect(actualPublicKeys).toEqual(r1FormatPublicKeys);
256 |         });
257 | 
258 |         it('signs a transaction', async () => {
259 |             const provider = new JsSignatureProvider(privateKeysR1);
260 |             const chainId = '12345';
261 |             const requiredKeys = r1FormatPublicKeys;
262 |             const serializedTransaction = new Uint8Array([
263 |                 0, 16, 32, 128, 255,
264 |             ]);
265 | 
266 |             const signOutput = await provider.sign(
267 |                 { chainId, requiredKeys, serializedTransaction } as SignatureProviderArgs
268 |             );
269 | 
270 |             expect(signOutput).toEqual({
271 |                 signatures: expect.any(Array),
272 |                 serializedTransaction,
273 |                 serializedContextFreeData: undefined
274 |             });
275 |         });
276 | 
277 |         it('confirm elliptic conversion functions are actually reciprocal', async () => {
278 |             const provider = new JsSignatureProvider(privateKeysR1);
279 |             const chainId = '12345';
280 |             const requiredKeys = r1FormatPublicKeys;
281 |             const serializedTransaction = new Uint8Array([
282 |                 0, 16, 32, 128, 255,
283 |             ]);
284 | 
285 |             const signOutput = await provider.sign(
286 |                 { chainId, requiredKeys, serializedTransaction } as SignatureProviderArgs
287 |             );
288 | 
289 |             const sig: Signature = Signature.fromString(signOutput.signatures[0]);
290 |             const ellipticSig: ec.Signature = sig.toElliptic();
291 |             const eosSig = Signature.fromElliptic(ellipticSig, KeyType.r1);
292 |             expect(sig).toEqual(eosSig);
293 |         });
294 | 
295 |         it('verify a transaction', async () => {
296 |             const provider = new JsSignatureProvider([privateKeysR1[0]]);
297 |             const chainId = '12345';
298 |             const requiredKeys = [r1FormatPublicKeys[0]];
299 |             const serializedTransaction = new Uint8Array([
300 |                 0, 16, 32, 128, 255,
301 |             ]);
302 | 
303 |             const signOutput = await provider.sign(
304 |                 { chainId, requiredKeys, serializedTransaction } as SignatureProviderArgs
305 |             );
306 | 
307 |             const signature = Signature.fromString(signOutput.signatures[0]);
308 |             expect(
309 |                 signature.verify(
310 |                     digestFromSerializedData(chainId, serializedTransaction),
311 |                     PublicKey.fromString(r1FormatPublicKeys[0]),
312 |                     false
313 |                 )
314 |             ).toEqual(true);
315 |         });
316 | 
317 |         it('ensure public key functions using p256 format are actual inverses of each other', async () => {
318 |             const eosioPubKey = PublicKey.fromString(r1FormatPublicKeys[0]);
319 |             const ellipticPubKey = eosioPubKey.toElliptic();
320 |             const finalEosioKeyAsR1String = PublicKey.fromElliptic(ellipticPubKey, KeyType.r1).toString();
321 |             expect(finalEosioKeyAsR1String).toEqual(r1FormatPublicKeys[0]);
322 |         });
323 | 
324 |         it('ensure private key functions using p256 format are actual inverses of each other', async () => {
325 |             const priv = privateKeysR1[0];
326 |             const privEosioKey = PrivateKey.fromString(priv);
327 |             const privEllipticKey = privEosioKey.toElliptic();
328 |             const finalEosioKeyAsString = PrivateKey.fromElliptic(privEllipticKey, KeyType.r1).toString();
329 |             expect(privEosioKey.toString()).toEqual(finalEosioKeyAsString);
330 |         });
331 | 
332 |         it('verify that public key validate function correctly assesses public keys', () => {
333 |             const publicKey = PublicKey.fromString(r1FormatPublicKeys[0]);
334 |             expect(publicKey.isValid()).toEqual(true);
335 |         });
336 | 
337 |         it('Ensure elliptic sign, recover, verify flow works', () => {
338 |             const KPrivStr = privateKeysR1[0];
339 |             const KPriv = PrivateKey.fromString(KPrivStr);
340 | 
341 |             const dataAsString = 'some string';
342 |             const ellipticHashedString = sha256(dataAsString);
343 |             const sig = KPriv.sign(ellipticHashedString);
344 |             const KPub = sig.recover(ellipticHashedString);
345 | 
346 |             expect(KPub.toString()).toEqual(r1FormatPublicKeys[0]);
347 |             const valid = sig.verify(ellipticHashedString, KPub);
348 |             expect(valid).toEqual(true);
349 |         });
350 | 
351 |         it('Ensure elliptic sign, recover, verify flow works with shouldHash', () => {
352 |             const KPrivStr = privateKeysR1[0];
353 |             const KPriv = PrivateKey.fromString(KPrivStr);
354 | 
355 |             const dataAsString = 'some string';
356 |             const sig = KPriv.sign(dataAsString, true);
357 |             const KPub = sig.recover(dataAsString, true);
358 | 
359 |             expect(KPub.toString()).toEqual(r1FormatPublicKeys[0]);
360 |             const valid = sig.verify(dataAsString, KPub, true);
361 |             expect(valid).toEqual(true);
362 |         });
363 | 
364 |         it('Ensure elliptic sign, recover, verify flow works with shouldHash and encoding', () => {
365 |             const KPrivStr = privateKeysR1[0];
366 |             const KPriv = PrivateKey.fromString(KPrivStr);
367 | 
368 |             const dataAsString = 'some string';
369 |             const sig = KPriv.sign(dataAsString, true, 'utf8');
370 |             const KPub = sig.recover(dataAsString, true, 'utf8');
371 | 
372 |             expect(KPub.toString()).toEqual(r1FormatPublicKeys[0]);
373 |             const valid = sig.verify(dataAsString, KPub, true, 'utf8');
374 |             expect(valid).toEqual(true);
375 |         });
376 |     });
377 | });
378 | 


--------------------------------------------------------------------------------
/src/tests/eosjs-util.test.ts:
--------------------------------------------------------------------------------
 1 | import {ChainSemanticVersion} from '../ChainSemanticVersion'
 2 | 
 3 | const version3NoSupport = ['v3.1.0-rc4', 'v3.0.99-rc1', 'v3.0.99']
 4 | const version3WithSupport = [
 5 |     'v3.2.0-rc1',
 6 |     'v3.2.0-rc2',
 7 |     'v3.2.0-rc3',
 8 |     'v3.1.0',
 9 |     'v3.1.1',
10 |     'v3.1.2',
11 |     'v3.1.3',
12 |     'v3.1.4',
13 |     'v3.2.0',
14 |     'v3.2.1',
15 |     'v3.2.2',
16 |     'v3.2.3',
17 | ]
18 | const version4NoSupport = ['v4.0.0-rc1', 'v4.0.0-rc2', 'v4.0.0-rc3']
19 | const version4WithSupport = ['v4.0.0', 'v4.0.1-rc1', 'v4.0.1']
20 | 
21 | describe('test parse semver string', () => {
22 |     it('Lacks Version 3 Support', () => {
23 |         version3NoSupport.forEach((version) => {
24 |             const thisService = new ChainSemanticVersion(version)
25 |             expect(thisService.supportsLeap3Features()).not.toBeTruthy()
26 |             expect(thisService.supportsLeap4Features()).not.toBeTruthy()
27 |         })
28 |     })
29 |     it('Has Version 3 Support', () => {
30 |         version3WithSupport.forEach((version) => {
31 |             const thisService = new ChainSemanticVersion(version)
32 |             expect(thisService.supportsLeap3Features()).toBeTruthy()
33 |             expect(thisService.supportsLeap4Features()).not.toBeTruthy()
34 |         })
35 |     })
36 |     it('Lacks Version 4 Support', () => {
37 |         version4NoSupport.forEach((version) => {
38 |             const thisService = new ChainSemanticVersion(version)
39 |             expect(thisService.supportsLeap3Features()).toBeTruthy()
40 |             expect(thisService.supportsLeap4Features()).not.toBeTruthy()
41 |         })
42 |     })
43 |     it('Has Version 4 Support', () => {
44 |         version4WithSupport.forEach((version) => {
45 |             const thisService = new ChainSemanticVersion(version)
46 |             expect(thisService.supportsLeap3Features()).toBeTruthy()
47 |             expect(thisService.supportsLeap4Features()).toBeTruthy()
48 |         })
49 |     })
50 |     it('Check V4 No Patch with RC', () => {
51 |         // check version 4.0 no patch level will pass
52 |         const thisService = new ChainSemanticVersion('v4.0-rc12')
53 |         expect(thisService.supportsLeap3Features()).toBeTruthy()
54 |         expect(thisService.supportsLeap4Features()).not.toBeTruthy()
55 |     })
56 |     it('Check V4 No Patch', () => {
57 |         // check version 4.0 no patch level will pass
58 |         const thisServiceZero = new ChainSemanticVersion('v4.0')
59 |         expect(thisServiceZero.supportsLeap3Features()).toBeTruthy()
60 |         expect(thisServiceZero.supportsLeap4Features()).toBeTruthy()
61 |         // check version 4.1 no patch level will pass
62 |         const thisServiceOne = new ChainSemanticVersion('v4.1')
63 |         expect(thisServiceOne.supportsLeap3Features()).toBeTruthy()
64 |         expect(thisServiceOne.supportsLeap4Features()).toBeTruthy()
65 |     })
66 | })
67 | 


--------------------------------------------------------------------------------
/src/tests/logo.svg:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |     
 4 |         
 5 |             
 6 |                 
 7 |                 
 8 |             
 9 |         
10 |     
11 | 
12 | 


--------------------------------------------------------------------------------
/src/tests/node.js:
--------------------------------------------------------------------------------
  1 | const { JsonRpc, RpcError, Api } = require('../../dist');
  2 | const { JsSignatureProvider } = require('../../dist/eosjs-jssig');
  3 | const fetch = require('node-fetch');
  4 | const { TextEncoder, TextDecoder } = require('util');
  5 | const { TestConfig, TestNet } = require('./TestConfig.ts');
  6 | 
  7 | const privateKey = '5JJBHqug5hX1cH91R5u3oMiA3ncHYW395PPmHQbfUshJikGDCBv';
  8 | const testActor = 'hokieshokies'
  9 | const testRecipient = 'alicetestlio'
 10 | /* new accounts for testing can be created
 11 |  * see docs/5.-Testing and Building with DUNE.md
 12 |  *      OR  by unlocking a cleos wallet then calling:
 13 |  * 1) cleos create key --to-console (copy this privateKey & publicKey)
 14 |  * 2) cleos wallet import
 15 |  * 3) cleos create account bob publicKey
 16 |  * 4) cleos create account alice publicKey
 17 |  */
 18 | 
 19 | // TestNet.Local or TestNet.Jungle sets endpoint, blocksBehind, and expireSeconds
 20 | const config = new TestConfig(TestNet.HomeBrew);
 21 | const rpc = new JsonRpc(config.endpoint, { fetch });
 22 | const signatureProvider = new JsSignatureProvider([privateKey]);
 23 | const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() });
 24 | 
 25 | const transactWithConfig = async () => await api.transact({
 26 |     actions: [{
 27 |         account: 'eosio.token',
 28 |         name: 'transfer',
 29 |         authorization: [{
 30 |             actor: testActor,
 31 |             permission: 'active',
 32 |         }],
 33 |         data: {
 34 |             from: testActor,
 35 |             to: testRecipient,
 36 |             quantity: '0.0001 EOS',
 37 |             memo: '',
 38 |         },
 39 |     }]
 40 | }, {
 41 |     blocksBehind: config.blocksBehind,
 42 |     searchBlocksAhead: config.searchBlockAhead,
 43 |     expireSeconds: config.expireSeconds,
 44 | });
 45 | 
 46 | const transactWithoutConfig = async () => {
 47 |     const transactionResponse = await transactWithConfig();
 48 |     const blockInfo = await rpc.get_block(transactionResponse.processed.block_num - 3);
 49 |     const currentDate = new Date();
 50 |     const timePlusTen = currentDate.getTime() + 10000;
 51 |     const timeInISOString = (new Date(timePlusTen)).toISOString();
 52 |     const expiration = timeInISOString.substring(0, timeInISOString.length - 1);
 53 | 
 54 |     return await api.transact({
 55 |         expiration,
 56 |         ref_block_num: blockInfo.block_num & 0xffff,
 57 |         ref_block_prefix: blockInfo.ref_block_prefix,
 58 |         actions: [{
 59 |             account: 'eosio.token',
 60 |             name: 'transfer',
 61 |             authorization: [{
 62 |                 actor: testActor,
 63 |                 permission: 'active',
 64 |             }],
 65 |             data: {
 66 |                 from: testActor,
 67 |                 to: testRecipient,
 68 |                 quantity: '0.0001 EOS',
 69 |                 memo: '',
 70 |             },
 71 |         }]
 72 |     });
 73 | };
 74 | 
 75 | 
 76 | const transactWithoutBroadcast = async () => await api.transact({
 77 |   actions: [{
 78 |         account: 'eosio.token',
 79 |         name: 'transfer',
 80 |         authorization: [{
 81 |             actor: testActor,
 82 |             permission: 'active',
 83 |         }],
 84 |         data: {
 85 |             from: testActor,
 86 |             to: testRecipient,
 87 |             quantity: '0.0001 EOS',
 88 |             memo: '',
 89 |         },
 90 |     }]
 91 | }, {
 92 |     broadcast: false,
 93 |     blocksBehind: config.blocksBehind,
 94 |     searchBlocksAhead: config.searchBlockAhead,
 95 |     expireSeconds: config.expireSeconds,
 96 | });
 97 | 
 98 | 
 99 | const transactWithRetry = async () =>
100 |     await api.transact(
101 |         {
102 |             actions: [
103 |                 {
104 |                     account: 'eosio.token',
105 |                     name: 'transfer',
106 |                     authorization: [
107 |                         {
108 |                             actor: testActor,
109 |                             permission: 'active',
110 |                         }],
111 |                     data: {
112 |                         from: testActor,
113 |                         to: testRecipient,
114 |                         quantity: '0.0001 EOS',
115 |                         memo: '',
116 |                     },
117 |                 }],
118 |         },
119 |         {
120 |             broadcast: false,
121 |             blocksBehind: config.blocksBehind,
122 |             searchBlocksAhead: config.searchBlockAhead,
123 |             expireSeconds: config.expireSeconds,
124 |             retryTrxNumBlocks: 10,
125 |         }
126 |     )
127 | 
128 | const transactWithRetryIrreversible = async () =>
129 |     await api.transact(
130 |         {
131 |             actions: [
132 |                 {
133 |                     account: 'eosio.token',
134 |                     name: 'transfer',
135 |                     authorization: [
136 |                         {
137 |                             actor: testActor,
138 |                             permission: 'active',
139 |                         }],
140 |                     data: {
141 |                         from: testActor,
142 |                         to: testRecipient,
143 |                         quantity: '0.0001 EOS',
144 |                         memo: '',
145 |                     },
146 |                 }],
147 |         },
148 |         {
149 |             broadcast: false,
150 |             blocksBehind: config.blocksBehind,
151 |             searchBlocksAhead: config.searchBlockAhead,
152 |             expireSeconds: config.expireSeconds,
153 |             retryIrreversible: true,
154 |         }
155 |     )
156 | 
157 | // change this to read
158 | const readonlyTransfer = async () =>
159 |     await api.transact(
160 |         {
161 |             actions: [
162 |                 {
163 |                     account: testActor,
164 |                     name: 'getvalue',
165 |                     authorization: [],
166 |                     data: {},
167 |                 },
168 |             ],
169 |         },
170 |         {
171 |             broadcast: true,
172 |             readOnly: true,
173 |             blocksBehind: config.blocksBehind,
174 |             searchBlocksAhead: config.searchBlockAhead,
175 |             expireSeconds: config.expireSeconds,
176 |         }
177 |     )
178 | 
179 | const broadcastResult = async (signaturesAndPackedTransaction) => await api.pushSignedTransaction(signaturesAndPackedTransaction);
180 | 
181 | const transactShouldFail = async () => await api.transact({
182 |     actions: [{
183 |         account: 'eosio.token',
184 |         name: 'transfer',
185 |         authorization: [{
186 |             actor: testActor,
187 |             permission: 'active',
188 |         }],
189 |         data: {
190 |             from: testActor,
191 |             to: testRecipient,
192 |             quantity: '0.0001 EOS',
193 |             memo: '',
194 |         },
195 |     }]
196 | });
197 | 
198 | const rpcShouldFail = async () => await rpc.get_block(-1);
199 | 
200 | module.exports = {
201 |     transactWithConfig,
202 |     transactWithoutConfig,
203 |     transactWithoutBroadcast,
204 |     transactWithRetry,
205 |     transactWithRetryIrreversible,
206 |     readonlyTransfer,
207 |     broadcastResult,
208 |     transactShouldFail,
209 |     rpcShouldFail,
210 |     config,
211 | };
212 | 


--------------------------------------------------------------------------------
/src/tests/node.test.ts:
--------------------------------------------------------------------------------
 1 | const tests = require('./node');
 2 | 
 3 | const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
 4 | const sleepToAvoidDuplicatesInSameBlock = tests.config.sleep;
 5 | 
 6 | describe('Node JS environment', () => {
 7 |     let transactionResponse: any;
 8 |     let transactionSignatures: any;
 9 |     let failedAsPlanned: boolean;
10 | 
11 |     it('transacts with configuration object', async () => {
12 |         transactionResponse = await tests.transactWithConfig();
13 |         expect(Object.keys(transactionResponse)).toContain('transaction_id');
14 |     });
15 | 
16 |     it('read only transaction', async () => {
17 |         transactionResponse = await tests.readonlyTransfer();
18 |         expect(Object.keys(transactionResponse)).toContain('transaction_id');
19 |         expect(Object.keys(transactionResponse.processed.receipt)).toContain('cpu_usage_us');
20 |     });
21 | 
22 |     it('transacts with manually configured TAPOS fields', async () => {
23 |         // needed for local tests to avoid duplicate transactions in same block
24 |         if (sleepToAvoidDuplicatesInSameBlock) await sleep(700)
25 |         transactionResponse = await tests.transactWithoutConfig();
26 |         expect(Object.keys(transactionResponse)).toContain('transaction_id');
27 |     }, 10000);
28 | 
29 |     it('transacts without broadcasting, returning signatures and packed transaction', async () => {
30 |         transactionSignatures = await tests.transactWithoutBroadcast();
31 |         expect(Object.keys(transactionSignatures)).toContain('signatures');
32 |         expect(Object.keys(transactionSignatures)).toContain('serializedTransaction');
33 |     });
34 | 
35 |     it('broadcasts packed transaction, given valid signatures', async () => {
36 |         // needed for local tests to avoid duplicate transactions in same block
37 |         if (sleepToAvoidDuplicatesInSameBlock) await sleep(700)
38 |         transactionSignatures = await tests.transactWithoutBroadcast();
39 |         transactionResponse = await tests.broadcastResult(transactionSignatures);
40 |         expect(Object.keys(transactionResponse)).toContain('transaction_id');
41 |     });
42 | 
43 |     it('retry transaction', async () => {
44 |         // needed for local tests to avoid duplicate transactions in same block
45 |         if (sleepToAvoidDuplicatesInSameBlock) await sleep(700)
46 |         transactionSignatures = await tests.transactWithRetry();
47 |         transactionResponse = await tests.broadcastResult(transactionSignatures);
48 |         expect(Object.keys(transactionResponse)).toContain('transaction_id');
49 |     });
50 | 
51 |     it('retry transaction irreversible', async () => {
52 |         // needed for local tests to avoid duplicate transaction in same block
53 |         await sleep(700)
54 |         transactionSignatures = await tests.transactWithRetryIrreversible();
55 |         transactionResponse = await tests.broadcastResult(transactionSignatures);
56 |         expect(Object.keys(transactionResponse)).toContain('transaction_id');
57 |     });
58 | 
59 |     it('throws appropriate error message without configuration object or TAPOS in place', async () => {
60 |         try {
61 |             failedAsPlanned = true;
62 |             await tests.transactShouldFail();
63 |             failedAsPlanned = false;
64 |         } catch (e) {
65 |             if (e.message !== 'Required configuration or TAPOS fields are not present') {
66 |                 failedAsPlanned = false;
67 |             }
68 |         }
69 |         expect(failedAsPlanned).toEqual(true);
70 |     });
71 | 
72 |     it('throws an an error with RpcError structure for invalid RPC calls', async () => {
73 |         try {
74 |             failedAsPlanned = true;
75 |             await tests.rpcShouldFail();
76 |             failedAsPlanned = false;
77 |         } catch (e) {
78 |             if (!e.json || !e.json.error || !(e.json.error.hasOwnProperty('details'))) {
79 |                 failedAsPlanned = false;
80 |             }
81 |         }
82 |         expect(failedAsPlanned).toEqual(true);
83 |     });
84 | });
85 | 


--------------------------------------------------------------------------------
/src/tests/readonly_contract/contract.cpp:
--------------------------------------------------------------------------------
 1 | #include 
 2 | using namespace eosio;
 3 | 
 4 | // Welcome to your new EOS Smart Contract.
 5 | // If you're just learning follow our Getting Started guide here:
 6 | // https://docs.eosnetwork.com/docs/latest/smart-contracts/getting-started/smart_contract_basics
 7 | 
 8 | CONTRACT mycontract : public contract {
 9 |    public:
10 |       using contract::contract;
11 | 
12 |       [[eosio::action]] uint64_t getvalue(){
13 |          return 42;
14 |       }
15 | };


--------------------------------------------------------------------------------
/src/tests/readonly_contract/include/contract.hpp:
--------------------------------------------------------------------------------
1 | #include 
2 | 


--------------------------------------------------------------------------------
/src/tests/setupJest.js:
--------------------------------------------------------------------------------
1 | global.fetch = require("jest-fetch-mock");
2 | 


--------------------------------------------------------------------------------
/src/tests/strict-serialization.test.ts:
--------------------------------------------------------------------------------
 1 | import { TextDecoder, TextEncoder } from 'util';
 2 | import * as ser from "../eosjs-serialize";
 3 | import {SerialBuffer} from "../eosjs-serialize";
 4 | const transactionAbi = require('../transaction.abi.json');
 5 | 
 6 | // setup shared buffer re-established before every test
 7 | let buffer: SerialBuffer;
 8 | describe('Strict Deserialization Tests', () => {
 9 |     let textEncoder = new TextEncoder();
10 |     let textDecoder = new TextDecoder();
11 |     let transactionType: Map = ser.getTypesFromAbi(ser.createInitialTypes(), transactionAbi);
12 | 
13 |     beforeEach( () => {
14 |         buffer = new ser.SerialBuffer({
15 |             textEncoder: textEncoder,
16 |             textDecoder: textDecoder,
17 |         });
18 |     });
19 | 
20 |     it('out of range int8 128', () => {
21 |         expect (() => {
22 |             const hex = "80";
23 |             const type = "int8";
24 |             buffer.pushArray(ser.hexToUint8Array(hex));
25 |             const thisType = ser.getType(transactionType, type);
26 |             const testValue: number = thisType.deserialize(buffer);
27 |             expect(testValue).toBeTruthy();
28 |         }).toThrow();
29 |     });
30 | 
31 |     it('out of range int8 -129', () => {
32 |         expect ( () => {
33 |             const hex = "7FFF";
34 |             const expected = "-129";
35 |             const type = "int8";
36 |             buffer.pushArray(ser.hexToUint8Array(hex));
37 |             const thisType = ser.getType(transactionType, type);
38 |             const testValue: number = thisType.deserialize(buffer);
39 |             expect(expected).toBeTruthy();
40 |         }).toThrow();
41 |     });
42 | 
43 |     it('out of range uint8 256', () => {
44 |         expect ( () => {
45 |             const hex = "0001";
46 |             const expected = "256";
47 |             const type = "uint8";
48 |             buffer.pushArray(ser.hexToUint8Array(hex));
49 |             const testValue = transactionType.get(type).deserialize(buffer);
50 |             expect(expected).toBeTruthy();
51 |         }).toThrow();
52 |     });
53 | 
54 | 
55 | 
56 | });


--------------------------------------------------------------------------------
/src/tests/web.css:
--------------------------------------------------------------------------------
  1 | * {
  2 |   box-sizing: border-box;
  3 | }
  4 | 
  5 | html,
  6 | body {
  7 |   margin: 0;
  8 |   padding: 0;
  9 |   font-family: 'Source Sans Pro', sans-serif;
 10 | }
 11 | 
 12 | button {
 13 |   font-family: 'Source Sans Pro', sans-serif;
 14 |   font-size: .9rem;
 15 |   font-weight: 600;
 16 |   cursor: pointer;
 17 | }
 18 | 
 19 | button:active, button:focus {
 20 |   outline: none;
 21 | }
 22 | 
 23 | .header-container {
 24 |   margin: 0;
 25 |   background-color: #F6F6F8;
 26 | }
 27 | 
 28 | .header {
 29 |   display: flex;
 30 |   flex-direction: column;
 31 |   align-items: center;
 32 |   text-align: center;
 33 |   max-width: 1200px;
 34 |   margin : 0 auto;
 35 |   padding: 2rem;
 36 | }
 37 | 
 38 | .header > img { 
 39 |   max-width: 8rem;
 40 | }
 41 | 
 42 | .header > h1 {
 43 |   font-size: 3.5rem;
 44 |   font-weight: lighter;
 45 |   color: #202035;
 46 |   margin: 2rem 0;
 47 | }
 48 | 
 49 | .header > button {
 50 |   padding: 1rem 6rem;
 51 |   border-radius: .4rem;
 52 |   color: white;
 53 |   background: #15087E;
 54 |   letter-spacing: 1px;
 55 | }
 56 | 
 57 | .header > button:hover {
 58 |   background: #15089E;
 59 | }
 60 | 
 61 | .tests {
 62 |   max-width: 1200px;
 63 |   display: flex;
 64 |   flex-direction: row;
 65 |   flex-wrap: wrap;
 66 |   margin: 0 auto;
 67 |   padding: 0 1rem;
 68 | }
 69 | 
 70 | .tests > div {
 71 |   display: flex;
 72 |   flex-direction: column;
 73 |   justify-content: space-between;
 74 |   align-items: center;
 75 |   text-align: center;
 76 |   width: 30%;
 77 |   margin: 1rem auto;
 78 | }
 79 | 
 80 | .tests > div > h2 {
 81 |   font-weight: normal;
 82 |   margin: 1.5rem 0;
 83 |   font-size: .9rem;
 84 | }
 85 | 
 86 | .tests > div > button {
 87 |   width: 6.5rem;
 88 |   height: 6.5rem;
 89 |   margin: 1rem;;
 90 |   padding: 0;
 91 |   border: .15rem solid #15087E;
 92 |   border-radius: 5rem;
 93 | }
 94 | 
 95 | .tests > div > button:hover {
 96 |   background: #F6F6F8;
 97 | }
 98 | 
 99 | .tests > div > button.success {
100 |   color: #7ED321;
101 |   border: .15rem solid #7ED321;
102 | }
103 | 
104 | .tests > div > button.failed {
105 |   color: #FF6363;
106 |   border: .15rem solid #FF6363;
107 | }
108 | 
109 | @media (min-width: 1200px) {
110 |   html, body {
111 |     font-size: 20px;
112 |   }
113 | }
114 | 
115 | @media (max-width: 800px) {
116 |   html, body {
117 |     font-size: 14px;
118 |   }
119 | }
120 | 


--------------------------------------------------------------------------------
/src/tests/web.html:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 |     
  4 |         
  5 |         
  6 |         
  7 |         
  8 |         
260 |     
261 |     
262 |         
263 |
264 | 265 |

Web Build Integration Tests

266 | 267 |
268 |
269 |
270 |

Transact with Configuration Parameter

271 |

Transact with Manually Configured TAPOS

272 |

Transact without Broadcasting

273 |

Broadcast Transaction

274 |

Invalid Transaction Throws Error

275 |

Invalid Rpc Call Throws Rpc Error

276 |
277 | 278 | 279 | -------------------------------------------------------------------------------- /src/transaction.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "eosio::abi/1.0", 3 | "types": [ 4 | { 5 | "new_type_name": "account_name", 6 | "type": "name" 7 | }, 8 | { 9 | "new_type_name": "action_name", 10 | "type": "name" 11 | }, 12 | { 13 | "new_type_name": "permission_name", 14 | "type": "name" 15 | } 16 | ], 17 | "structs": [ 18 | { 19 | "name": "permission_level", 20 | "base": "", 21 | "fields": [ 22 | { 23 | "name": "actor", 24 | "type": "account_name" 25 | }, 26 | { 27 | "name": "permission", 28 | "type": "permission_name" 29 | } 30 | ] 31 | }, 32 | { 33 | "name": "action", 34 | "base": "", 35 | "fields": [ 36 | { 37 | "name": "account", 38 | "type": "account_name" 39 | }, 40 | { 41 | "name": "name", 42 | "type": "action_name" 43 | }, 44 | { 45 | "name": "authorization", 46 | "type": "permission_level[]" 47 | }, 48 | { 49 | "name": "data", 50 | "type": "bytes" 51 | } 52 | ] 53 | }, 54 | { 55 | "name": "extension", 56 | "base": "", 57 | "fields": [ 58 | { 59 | "name": "type", 60 | "type": "uint16" 61 | }, 62 | { 63 | "name": "data", 64 | "type": "bytes" 65 | } 66 | ] 67 | }, 68 | { 69 | "name": "transaction_header", 70 | "base": "", 71 | "fields": [ 72 | { 73 | "name": "expiration", 74 | "type": "time_point_sec" 75 | }, 76 | { 77 | "name": "ref_block_num", 78 | "type": "uint16" 79 | }, 80 | { 81 | "name": "ref_block_prefix", 82 | "type": "uint32" 83 | }, 84 | { 85 | "name": "max_net_usage_words", 86 | "type": "varuint32" 87 | }, 88 | { 89 | "name": "max_cpu_usage_ms", 90 | "type": "uint8" 91 | }, 92 | { 93 | "name": "delay_sec", 94 | "type": "varuint32" 95 | } 96 | ] 97 | }, 98 | { 99 | "name": "transaction", 100 | "base": "transaction_header", 101 | "fields": [ 102 | { 103 | "name": "context_free_actions", 104 | "type": "action[]" 105 | }, 106 | { 107 | "name": "actions", 108 | "type": "action[]" 109 | }, 110 | { 111 | "name": "transaction_extensions", 112 | "type": "extension[]" 113 | } 114 | ] 115 | } 116 | ] 117 | } 118 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "CommonJS", 5 | "outDir": "dist", 6 | "alwaysStrict": true, 7 | "sourceMap": true, 8 | "noImplicitAny": true, 9 | "moduleResolution": "node", 10 | "declaration": true, 11 | "downlevelIteration": true, 12 | "skipLibCheck": true, 13 | "lib": [ 14 | "es2017", 15 | "dom" 16 | ] 17 | }, 18 | "include": [ 19 | "src/**/*.ts", 20 | "src/**/*.js" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /tsconfig.web.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "CommonJS", 5 | "outDir": "dist", 6 | "alwaysStrict": true, 7 | "sourceMap": false, 8 | "noImplicitAny": true, 9 | "moduleResolution": "node", 10 | "declaration": false, 11 | "downlevelIteration": true, 12 | "lib": [ 13 | "es2017", 14 | "dom" 15 | ] 16 | }, 17 | "include": [ 18 | "src/**/*.ts", 19 | "src/**/*.js" 20 | ], 21 | "exclude": [ 22 | "src/**/*.test.ts", 23 | "src/tests/" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "@blockone/tslint-config-blockone/tslint-config" 5 | ], 6 | "jsRules": {}, 7 | "rules": { 8 | "no-bitwise": false, 9 | "no-var-requires": false, 10 | "semicolon": [true, "always"], 11 | "ter-indent": [true, 4] 12 | }, 13 | "rulesDirectory": [] 14 | } 15 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "EOSIO Javascript", 3 | "entryPoints": ["./src/index.ts"], 4 | "excludeProtected": true, 5 | "excludePrivate": true, 6 | "externalPattern": "**/node_modules/**", 7 | "out": "typedoc-out", 8 | "theme": "default", 9 | "exclude": ["**/*.test.ts","**/*.test.js","**/node_modules/"], 10 | "readme": "README.md", 11 | "hideGenerator": true, 12 | "gitRemote": "https://github.com/eosnetworkfoundation/mandel-eosjs" 13 | } 14 | -------------------------------------------------------------------------------- /webpack.debug.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: { 5 | eosjs_api: './src/eosjs-api.ts', 6 | eosjs_jsonrpc: './src/rpc-web.ts', 7 | eosjs_jssig: './src/eosjs-jssig.ts', 8 | eosjs_numeric: './src/eosjs-numeric.ts', 9 | }, 10 | devtool: 'inline-source-map', 11 | mode: 'development', 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.tsx?$/, 16 | use: { 17 | loader: 'ts-loader', 18 | options: { 19 | configFile: 'tsconfig.web.json' 20 | } 21 | }, 22 | exclude: /node_modules/, 23 | } 24 | ] 25 | }, 26 | resolve: { 27 | extensions: ['.tsx', '.ts', '.js'] 28 | }, 29 | output: { 30 | filename: x => x.chunk.name.replace('_', '-') + '-debug.js', 31 | library: '[name]', 32 | path: path.resolve(__dirname, 'dist-web', 'debug'), 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /webpack.prod.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: { 5 | eosjs_api: './src/eosjs-api.ts', 6 | eosjs_jsonrpc: './src/rpc-web.ts', 7 | eosjs_jssig: './src/eosjs-jssig.ts', 8 | eosjs_numeric: './src/eosjs-numeric.ts', 9 | }, 10 | mode: 'production', 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.tsx?$/, 15 | use: { 16 | loader: 'ts-loader', 17 | options: { 18 | configFile: 'tsconfig.web.json' 19 | } 20 | }, 21 | exclude: /node_modules/, 22 | } 23 | ] 24 | }, 25 | resolve: { 26 | extensions: ['.tsx', '.ts', '.js'] 27 | }, 28 | output: { 29 | filename: x => x.chunk.name.replace('_', '-') + '.js', 30 | library: '[name]', 31 | path: path.resolve(__dirname, 'dist-web'), 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /workflows/unit-tests.yml: -------------------------------------------------------------------------------- 1 | name: unit-tests 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | unit-tests-job: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | - uses: actions/setup-node@v3 12 | with: 13 | node-version: '16' 14 | - run: npm run build 15 | - run: npm run test --------------------------------------------------------------------------------