├── .github └── workflows │ └── main.yml ├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.hbs ├── README.md ├── jsdoc2md.json ├── package.json ├── src ├── balances │ ├── GenericBalance.ts │ ├── GenericBalanceDriver.ts │ ├── IBalance.ts │ ├── drivers │ │ ├── BSC_Driver.ts │ │ ├── BTC_Driver.ts │ │ ├── ETH_Driver.ts │ │ ├── POLYGON_Driver.ts │ │ └── WEB3_Driver.ts │ └── index.ts ├── chains.ts ├── constants.ts ├── currencies.ts ├── currencyFunctions.ts ├── fees │ ├── GenericDriver.ts │ ├── GenericTxProposal.ts │ ├── IFee.ts │ ├── drivers │ │ ├── BSC_Driver.ts │ │ ├── BTC_Driver.ts │ │ ├── ETH_Driver.ts │ │ ├── POLYGON_Driver.ts │ │ └── WEB3_Driver.ts │ ├── index.ts │ └── types │ │ ├── BitcoinFee.ts │ │ ├── BnbFee.ts │ │ ├── EthereumFee.ts │ │ └── PolygonFee.ts ├── generators │ ├── GenericGenerator.ts │ ├── drivers │ │ ├── bitcoin.ts │ │ ├── bsc.ts │ │ ├── ethereum.ts │ │ └── polygon.ts │ └── index.ts ├── index.ts ├── market │ └── getCoins.ts ├── transactions │ ├── GenericTransactionDriver.ts │ ├── drivers │ │ ├── BSC_Driver.ts │ │ ├── BTC_Driver.ts │ │ ├── ETH_Driver.ts │ │ ├── POLYGON_Driver.ts │ │ └── WEB3_Driver.ts │ └── index.ts ├── utils │ ├── coins.ts │ ├── config.mainnet.json │ ├── config.testnet.json │ ├── config.ts │ └── registry.json ├── walletFactory.ts ├── walletGenerator.ts └── wallets │ ├── GenericWallet.ts │ ├── IWallet.ts │ ├── IWalletConfig.ts │ ├── index.ts │ ├── signing │ └── web3.ts │ └── types │ ├── BitcoinWallet.ts │ ├── BscWallet.ts │ ├── EthereumWallet.ts │ └── PolygonWallet.ts ├── test ├── balances.test.ts ├── bscWallet.test.ts ├── btcWallet.test.ts ├── ethWallet.test.ts ├── factory.test.ts ├── fees.test.ts ├── fixtures.sample.ts ├── generator.test.ts ├── market.test.ts ├── polygonWallet.test.ts ├── transactionTokensBSC.test.ts ├── transactionTokensETH.test.ts ├── transactionTokensPOLYGON.test.ts └── transactions.test.ts ├── tsconfig.json └── yarn.lock /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push,pull_request] 3 | jobs: 4 | build-lint-audit-test: 5 | name: Build and Lint 6 | runs-on: ubuntu-20.04 7 | strategy: 8 | matrix: 9 | node-version: [14.x] 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Use Node.js ${{ matrix.node-version }} 13 | uses: actions/setup-node@v2 14 | with: 15 | node-version: ${{ matrix.node-version }} 16 | - name: Get Yarn cache directory 17 | run: | 18 | YARN_CACHE_DIR=$(yarn cache dir) 19 | echo $YARN_CACHE_DIR 20 | echo "::set-output name=YARN_CACHE_DIR::$YARN_CACHE_DIR" 21 | id: yarn-cache-dir 22 | - name: Get Node version 23 | run: | 24 | node -v 25 | - name: Get Yarn version 26 | run: | 27 | YARN_VERSION=$(yarn --version) 28 | echo $YARN_VERSION 29 | echo "::set-output name=YARN_VERSION::$YARN_VERSION" 30 | id: yarn-version 31 | - name: Cache yarn dependencies 32 | uses: actions/cache@v2 33 | with: 34 | path: ${{ steps.yarn-cache-dir.outputs.YARN_CACHE_DIR }} 35 | key: yarn-cache-${{ runner.os }}-${{ steps.yarn-version.outputs.YARN_VERSION }}-${{ hashFiles('yarn.lock') }} 36 | - run: yarn --frozen-lockfile 37 | - run: yarn lint 38 | # - run: yarn audit:ci 39 | all-jobs-pass: 40 | name: All jobs pass 41 | runs-on: ubuntu-20.04 42 | needs: 43 | - build-lint-audit-test 44 | steps: 45 | - run: echo "Great success!" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | dist 5 | .env 6 | test/fixtures.ts 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "editor.codeActionsOnSave": { 4 | "source.fixAll.eslint": true, 5 | }, 6 | "eslint.validate": [ 7 | "javascript" 8 | ] 9 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG.md 2 | 3 | ## 1.3.1 4 | 5 | Features: 6 | 7 | - Allow list of endpoints instead of one endpoint for BTC connectors 8 | 9 | ## 1.3.0 10 | 11 | Features: 12 | 13 | - WalletConnect support 14 | - ERC20 Tokens support 15 | 16 | ## 1.2.0 17 | 18 | Features: 19 | 20 | - Tokens support on Binance Smart Chain (balance, fees, transactions) 21 | - Tokens support on Polygon (balance, fees, transactions) 22 | 23 | ## 1.1.0 24 | 25 | Features: 26 | 27 | - Tokens support on ETH chain (balance, fees, transactions) 28 | 29 | ## 1.0.0 30 | 31 | Features: 32 | 33 | - BTC Wallet management (creation, balance, fees, transactions) 34 | - ETH Wallet management (creation, balance, fees, transactions) 35 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributor Covenant Code of Conduct 3 | 4 | ## Our Pledge 5 | 6 | We as members, contributors, and leaders pledge to make participation in our 7 | community a harassment-free experience for everyone, regardless of age, body 8 | size, visible or invisible disability, ethnicity, sex characteristics, gender 9 | identity and expression, level of experience, education, socio-economic status, 10 | nationality, personal appearance, race, religion, or sexual identity 11 | and orientation. 12 | 13 | We pledge to act and interact in ways that contribute to an open, welcoming, 14 | diverse, inclusive, and healthy community. 15 | 16 | ## Our Standards 17 | 18 | Examples of behavior that contributes to a positive environment for our 19 | community include: 20 | 21 | * Demonstrating empathy and kindness toward other people 22 | * Being respectful of differing opinions, viewpoints, and experiences 23 | * Giving and gracefully accepting constructive feedback 24 | * Accepting responsibility and apologizing to those affected by our mistakes, 25 | and learning from the experience 26 | * Focusing on what is best not just for us as individuals, but for the 27 | overall community 28 | 29 | Examples of unacceptable behavior include: 30 | 31 | * The use of sexualized language or imagery, and sexual attention or 32 | advances of any kind 33 | * Trolling, insulting or derogatory comments, and personal or political attacks 34 | * Public or private harassment 35 | * Publishing others' private information, such as a physical or email 36 | address, without their explicit permission 37 | * Other conduct which could reasonably be considered inappropriate in a 38 | professional setting 39 | 40 | ## Enforcement Responsibilities 41 | 42 | Community leaders are responsible for clarifying and enforcing our standards of 43 | acceptable behavior and will take appropriate and fair corrective action in 44 | response to any behavior that they deem inappropriate, threatening, offensive, 45 | or harmful. 46 | 47 | Community leaders have the right and responsibility to remove, edit, or reject 48 | comments, commits, code, wiki edits, issues, and other contributions that are 49 | not aligned to this Code of Conduct, and will communicate reasons for moderation 50 | decisions when appropriate. 51 | 52 | ## Scope 53 | 54 | This Code of Conduct applies within all community spaces, and also applies when 55 | an individual is officially representing the community in public spaces. 56 | Examples of representing our community include using an official e-mail address, 57 | posting via an official social media account, or acting as an appointed 58 | representative at an online or offline event. 59 | 60 | ## Enforcement 61 | 62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 63 | reported to the community leaders responsible for enforcement at 64 | [INSERT CONTACT METHOD]. 65 | All complaints will be reviewed and investigated promptly and fairly. 66 | 67 | All community leaders are obligated to respect the privacy and security of the 68 | reporter of any incident. 69 | 70 | ## Enforcement Guidelines 71 | 72 | Community leaders will follow these Community Impact Guidelines in determining 73 | the consequences for any action they deem in violation of this Code of Conduct: 74 | 75 | ### 1. Correction 76 | 77 | **Community Impact**: Use of inappropriate language or other behavior deemed 78 | unprofessional or unwelcome in the community. 79 | 80 | **Consequence**: A private, written warning from community leaders, providing 81 | clarity around the nature of the violation and an explanation of why the 82 | behavior was inappropriate. A public apology may be requested. 83 | 84 | ### 2. Warning 85 | 86 | **Community Impact**: A violation through a single incident or series 87 | of actions. 88 | 89 | **Consequence**: A warning with consequences for continued behavior. No 90 | interaction with the people involved, including unsolicited interaction with 91 | those enforcing the Code of Conduct, for a specified period of time. This 92 | includes avoiding interactions in community spaces as well as external channels 93 | like social media. Violating these terms may lead to a temporary or 94 | permanent ban. 95 | 96 | ### 3. Temporary Ban 97 | 98 | **Community Impact**: A serious violation of community standards, including 99 | sustained inappropriate behavior. 100 | 101 | **Consequence**: A temporary ban from any sort of interaction or public 102 | communication with the community for a specified period of time. No public or 103 | private interaction with the people involved, including unsolicited interaction 104 | with those enforcing the Code of Conduct, is allowed during this period. 105 | Violating these terms may lead to a permanent ban. 106 | 107 | ### 4. Permanent Ban 108 | 109 | **Community Impact**: Demonstrating a pattern of violation of community 110 | standards, including sustained inappropriate behavior, harassment of an 111 | individual, or aggression toward or disparagement of classes of individuals. 112 | 113 | **Consequence**: A permanent ban from any sort of public interaction within 114 | the community. 115 | 116 | ## Attribution 117 | 118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 119 | version 2.0, available at 120 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 121 | 122 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 123 | enforcement ladder](https://github.com/mozilla/diversity). 124 | 125 | [homepage]: https://www.contributor-covenant.org 126 | 127 | For answers to common questions about this code of conduct, see the FAQ at 128 | https://www.contributor-covenant.org/faq. Translations are available at 129 | https://www.contributor-covenant.org/translations. 130 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributing to Coingrig Core 3 | 4 | 5 | ## How to contribute 6 | 7 | You can contribute to Coingrig Core in various ways, including: 8 | 9 | - [Reporting bugs or issues](https://github.com/coingrig/core/issues/new) on GitHub. Please make sure to include fill in all the details in the issue template to make sure the issue can be addressed as quickly as possible. 10 | 11 | - Submitting improvements to the documentation 12 | Updates, enhancements, new guides, spelling fixes... 13 | 14 | - Helping other people on the [discussions](https://github.com/coingrig/core/discussions). 15 | 16 | - Looking at existing [issues](https://github.com/coingrig/core/issues) and adding more information, particularly helping to reproduce the issues. 17 | 18 | - [Submitting a pull request](#submitting-a-pull-request) with a bug fix or an improvement. 19 | 20 | 21 | 22 | ## Coingrig Core repository 23 | 24 | 25 | 26 | The [Coingrig Core GitHub repository](https://github.com/coingrig/core) contains the packages that make up Coingrig Core. 27 | 28 | 29 | ### Branches 30 | 31 | The `develop` branch of the repository should be kept releasable at any time, even if it is not the realease branch. 32 | 33 | Keeping the `develop` releasable means that changes merged to it need to be: 34 | 35 | - **Backwards compatible**: Coingrig Core should work with _every currently supported Coingrig Wallet version_. If the code you're adding depends on a feature only present in newer or unreleased Coingrig Wallet versions, it needs to check which version is being used and not assume the latest version is being used. 36 | 37 | - **Non-breaking**: If code that is unreleasable or fails the test suite ends up in `develop`, it should be reverted. 38 | 39 | - **Tested**: Always include a test plan in pull requests. Do not merge code that doesn't pass all automated tests. 40 | 41 | 42 | 43 | ## Setting up the repository for development 44 | 45 | 46 | 47 | 1. Clone the repository. 48 | 49 | 2. Run `yarn`. (Installs dependencies and links packages in the workspace.) 50 | 51 | 3. Run `yarn build` to build the lib before start watching. 52 | 53 | 4. Run `yarn start` in the root folder. (Start watching and automatically re-building when there are new changes.) 54 | 55 | 5. Jest tests are set up to run with `TESTNET=true yarn test`. 56 | 57 | 58 | ## Submitting a pull request 59 | 60 | To submit a pull request: 61 | 62 | 1. Fork the [repository](https://github.com/coingrig/core) and create a feature branch. (Existing contributors can create feature branches without forking. Prefix the branch name with `@your-github-username/`.) 63 | 64 | 2. Write the description of your pull request. Make sure to include a test plan and test your changes. 65 | 66 | 3. Wait for a review and adjust the code if necessary. 67 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright © Qubevo Software SRL, 2021. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.hbs: -------------------------------------------------------------------------------- 1 | ## 🅒🅖🅒 Coingrig Core 2 | The Coingrig Core library handling the wallet interactions 3 | 4 | ### Setup 5 | Run `yarn`. (Installs dependencies and links packages in the workspace.) 6 | 7 | ### Compilation 8 | Create an `.env` file to configure the platform: `TESTNET=true|false`. 9 | The default value is `TESTNET=false`. 10 | 11 | ### Test 12 | Jest tests are set up to run with `TESTNET=true yarn test`. 13 | 14 | --- 15 | 16 | ## Documentation 17 | {{>main}} 18 | 19 | * * * 20 | 21 | ## Code of Conduct 22 | 23 | This library has adopted a Code of Conduct that we expect project participants to adhere to. Please read the [full text](CODE_OF_CONDUCT.md) so that you can understand what actions will and will not be tolerated. 24 | 25 | ## License 26 | 27 | The Coingrig Core Library is licensed under the [MIT License](LICENSE). 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 🅒🅖🅒 Coingrig Core 2 | The Coingrig Core library handling the wallet interactions 3 | 4 | ### Usage in your project 5 | Import the library in your project with `yarn add @coingrig/core` 6 | 7 | ### Library Development setup 8 | Run `yarn`. (Installs dependencies and links packages in the workspace.) 9 | 10 | #### Compilation 11 | Create an `.env` file to configure the platform: `TESTNET=true|false`. 12 | The default value is `TESTNET=false`. 13 | 14 | #### Test 15 | Jest tests are set up to run with `TESTNET=true yarn test`. 16 | 17 | 18 | --- 19 | 20 | ## Documentation 21 | ## Classes 22 | 23 |
24 |
BitcoinGeneratorGenericGenerator
25 |
26 |
BscGeneratorEthereumGenerator
27 |
28 |
EthereumGeneratorGenericGenerator
29 |
30 |
PolygonGeneratorEthereumGenerator
31 |
32 |
GenericGenerator
33 |
34 |
WalletFactory
35 |
36 |
WalletGenerator
37 |
38 |
GenericWallet
39 |

Don't use the generic wallet, for a new coin write an implementation

40 |
41 | 42 | 43 | 44 | ## BitcoinGenerator ⇐ [GenericGenerator](#GenericGenerator) 45 | **Kind**: global class 46 | **Extends**: [GenericGenerator](#GenericGenerator) 47 | 48 | 49 | ## BscGenerator ⇐ [EthereumGenerator](#EthereumGenerator) 50 | **Kind**: global class 51 | **Extends**: [EthereumGenerator](#EthereumGenerator) 52 | 53 | 54 | ## EthereumGenerator ⇐ [GenericGenerator](#GenericGenerator) 55 | **Kind**: global class 56 | **Extends**: [GenericGenerator](#GenericGenerator) 57 | 58 | 59 | ## PolygonGenerator ⇐ [EthereumGenerator](#EthereumGenerator) 60 | **Kind**: global class 61 | **Extends**: [EthereumGenerator](#EthereumGenerator) 62 | 63 | 64 | ## GenericGenerator 65 | **Kind**: global class 66 | 67 | * [GenericGenerator](#GenericGenerator) 68 | * [.generateWalletXpub(mnemonic, config)](#GenericGenerator.generateWalletXpub) ⇒ string 69 | * [.generatePrivateKeyFromMnemonic(mnemonic, derivation, config)](#GenericGenerator.generatePrivateKeyFromMnemonic) ⇒ string 70 | * [.generateAddressFromXPub(xpub, derivation, config)](#GenericGenerator.generateAddressFromXPub) ⇒ string 71 | 72 | 73 | 74 | ### GenericGenerator.generateWalletXpub(mnemonic, config) ⇒ string 75 |

Generate the wallet's XPUB

76 | 77 | **Kind**: static method of [GenericGenerator](#GenericGenerator) 78 | **Returns**: string -

The XPUB value

79 | 80 | | Param | Type | 81 | | --- | --- | 82 | | mnemonic | string | 83 | | config | \* | 84 | 85 | 86 | 87 | ### GenericGenerator.generatePrivateKeyFromMnemonic(mnemonic, derivation, config) ⇒ string 88 |

Generate the wallet's Private Key

89 | 90 | **Kind**: static method of [GenericGenerator](#GenericGenerator) 91 | **Returns**: string -

The Private Key

92 | 93 | | Param | Type | 94 | | --- | --- | 95 | | mnemonic | string | 96 | | derivation | integer | 97 | | config | \* | 98 | 99 | 100 | 101 | ### GenericGenerator.generateAddressFromXPub(xpub, derivation, config) ⇒ string 102 |

Generate teh wallet's Public Address

103 | 104 | **Kind**: static method of [GenericGenerator](#GenericGenerator) 105 | **Returns**: string -

The Public Key

106 | 107 | | Param | Type | 108 | | --- | --- | 109 | | xpub | string | 110 | | derivation | integer | 111 | | config | \* | 112 | 113 | 114 | 115 | ## WalletFactory 116 | **Kind**: global class 117 | 118 | 119 | ### new WalletFactory() 120 |

Implements the Factory pattern to help generate easily wallets 121 | for the supported blockchains.

122 | 123 | 124 | 125 | ## WalletGenerator 126 | **Kind**: global class 127 | 128 | * [WalletGenerator](#WalletGenerator) 129 | * [.generateMnemonic([size])](#WalletGenerator.generateMnemonic) ⇒ string 130 | * [.getDriver(chain)](#WalletGenerator.getDriver) ⇒ [GenericGenerator](#GenericGenerator) 131 | * [.generateWalletXpub(chain, mnemonic, [config])](#WalletGenerator.generateWalletXpub) ⇒ string 132 | * [.generatePrivateKeyFromMnemonic(chain, mnemonic, derivation, [config])](#WalletGenerator.generatePrivateKeyFromMnemonic) ⇒ string 133 | * [.generateAddressFromXPub(chain, xpub, derivation, [config])](#WalletGenerator.generateAddressFromXPub) ⇒ string 134 | 135 | 136 | 137 | ### WalletGenerator.generateMnemonic([size]) ⇒ string 138 |

Generates a string containing the 12 words used as a mnemonic 139 | to create the private and public wallet keys.

140 | 141 | **Kind**: static method of [WalletGenerator](#WalletGenerator) 142 | **Returns**: string -

The mnemonic

143 | 144 | | Param | Type | Default | Description | 145 | | --- | --- | --- | --- | 146 | | [size] | number | 128 |

Or use 256 for 24 words

| 147 | 148 | 149 | 150 | ### WalletGenerator.getDriver(chain) ⇒ [GenericGenerator](#GenericGenerator) 151 |

Offers direct access to the drivers that offer the key generation.

152 | 153 | **Kind**: static method of [WalletGenerator](#WalletGenerator) 154 | 155 | | Param | Type | 156 | | --- | --- | 157 | | chain | [Chains](#Chains) | 158 | 159 | 160 | 161 | ### WalletGenerator.generateWalletXpub(chain, mnemonic, [config]) ⇒ string 162 |

Generate the wallet's XPUB address. 163 | The source of all addresses to be generated for the public.

164 | 165 | **Kind**: static method of [WalletGenerator](#WalletGenerator) 166 | **Returns**: string -

The wallet's XPUB address

167 | 168 | | Param | Type | Default | Description | 169 | | --- | --- | --- | --- | 170 | | chain | [Chains](#Chains) | |

The type of chain

| 171 | | mnemonic | string | | | 172 | | [config] | \* | CONFIG | | 173 | 174 | 175 | 176 | ### WalletGenerator.generatePrivateKeyFromMnemonic(chain, mnemonic, derivation, [config]) ⇒ string 177 |

Generate the wallet's private key.

178 | 179 | **Kind**: static method of [WalletGenerator](#WalletGenerator) 180 | **Returns**: string -

The wallet's private key

181 | 182 | | Param | Type | Default | Description | 183 | | --- | --- | --- | --- | 184 | | chain | [Chains](#Chains) | |

The type of chain

| 185 | | mnemonic | string | | | 186 | | derivation | integer | |

The derivation key to allow generation of more private keys for the same chain

| 187 | | [config] | \* | CONFIG | | 188 | 189 | 190 | 191 | ### WalletGenerator.generateAddressFromXPub(chain, xpub, derivation, [config]) ⇒ string 192 |

Generate the public wallet address for the specified chain

193 | 194 | **Kind**: static method of [WalletGenerator](#WalletGenerator) 195 | **Returns**: string -

The wallet's public address

196 | 197 | | Param | Type | Default | Description | 198 | | --- | --- | --- | --- | 199 | | chain | [Chains](#Chains) | |

The type of chain

| 200 | | xpub | string | | | 201 | | derivation | integer | | | 202 | | [config] | \* | CONFIG | | 203 | 204 | 205 | 206 | ## GenericWallet 207 |

Don't use the generic wallet, for a new coin write an implementation

208 | 209 | **Kind**: global class 210 | 211 | 212 | ## Chains : enum 213 |

Enum for supported blockchains types

214 | 215 | **Kind**: global enum 216 | **Read only**: true 217 | **Properties** 218 | 219 | | Name | Type | Description | 220 | | --- | --- | --- | 221 | | BTC | string |

"BTC"

| 222 | | ETH | string |

"ETH"

| 223 | | MATIC | string |

"MATIC"

| 224 | | BSC | string |

"BSC"

| 225 | 226 | 227 | * * * 228 | 229 | ## Code of Conduct 230 | 231 | This library has adopted a Code of Conduct that we expect project participants to adhere to. Please read the [full text](CODE_OF_CONDUCT.md) so that you can understand what actions will and will not be tolerated. 232 | 233 | ## License 234 | 235 | The Coingrig Core Library is licensed under the [MIT License](LICENSE). 236 | -------------------------------------------------------------------------------- /jsdoc2md.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "includePattern": ".+\\.ts(doc|x)?$", 4 | "excludePattern": ".+\\.(test|spec).ts" 5 | }, 6 | "plugins": [ 7 | "plugins/markdown", 8 | "node_modules/jsdoc-babel" 9 | ], 10 | "babel": { 11 | "extensions": ["ts", "tsx"], 12 | "ignore": ["**/*.(test|spec).ts"], 13 | "babelrc": false, 14 | "presets": [["@babel/preset-env", { "targets": { "node": true } }], "@babel/preset-typescript"], 15 | "plugins": ["@babel/proposal-class-properties", "@babel/proposal-object-rest-spread"] 16 | } 17 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@coingrig/core", 3 | "title": "The Coingrig Core library", 4 | "description": "The Coingrig Core library handling the crypto wallet interactions", 5 | "author": "Coingrig", 6 | "version": "1.3.2", 7 | "license": "MIT", 8 | "main": "dist/index.js", 9 | "typings": "dist/index.d.ts", 10 | "files": [ 11 | "dist", 12 | "src" 13 | ], 14 | "engines": { 15 | "node": ">=10" 16 | }, 17 | "scripts": { 18 | "start": "tsdx watch", 19 | "build": "tsdx build", 20 | "test": "tsdx test", 21 | "lint": "tsdx lint src test", 22 | "lint-fix": "tsdx lint --fix src test", 23 | "prepare": "tsdx build", 24 | "size": "size-limit", 25 | "analyze": "size-limit --why", 26 | "docs": "jsdoc2md \"./src/**/*.ts\" --configure ./jsdoc2md.json --template README.hbs > ./README.md" 27 | }, 28 | "husky": { 29 | "hooks": { 30 | "pre-commit": "tsdx lint" 31 | } 32 | }, 33 | "prettier": { 34 | "printWidth": 80, 35 | "semi": true, 36 | "singleQuote": true, 37 | "trailingComma": "es5" 38 | }, 39 | "module": "dist/core.esm.js", 40 | "size-limit": [ 41 | { 42 | "path": "dist/core.cjs.production.min.js", 43 | "limit": "10 KB" 44 | }, 45 | { 46 | "path": "dist/core.esm.js", 47 | "limit": "10 KB" 48 | } 49 | ], 50 | "devDependencies": { 51 | "@babel/cli": "^7.15.7", 52 | "@babel/core": "^7.15.8", 53 | "@babel/preset-env": "^7.15.8", 54 | "@babel/preset-typescript": "^7.15.0", 55 | "@size-limit/preset-small-lib": "5.0.3", 56 | "@types/bitcore-lib": "0.15.3", 57 | "husky": "7.0.2", 58 | "jsdoc-babel": "^0.5.0", 59 | "jsdoc-to-markdown": "^7.1.0", 60 | "size-limit": "5.0.3", 61 | "tsdx": "0.14.1", 62 | "tslib": "2.3.1", 63 | "typescript": "^4.4.2" 64 | }, 65 | "keywords": [ 66 | "crypto", 67 | "bitcoin", 68 | "wallet", 69 | "typescript" 70 | ], 71 | "homepage": "https://coingrig.com", 72 | "repository": { 73 | "type": "git", 74 | "url": "git+https://github.com/coingrig/core.git" 75 | }, 76 | "dependencies": { 77 | "@metamask/eth-sig-util": "^4.0.0", 78 | "axios": "0.21.1", 79 | "bignumber.js": "9.0.1", 80 | "bip32": "2.0.6", 81 | "bip39": "3.0.4", 82 | "bitcoinjs-lib": "5.2.0", 83 | "bitcore-lib": "8.25.10", 84 | "coinselect": "3.1.12", 85 | "decimal.js": "10.3.1", 86 | "dotenv": "10.0.0", 87 | "ethereumjs-wallet": "1.0.1", 88 | "hdkey": "2.0.1", 89 | "web3": "1.5.2" 90 | }, 91 | "jest": { 92 | "moduleFileExtensions": [ 93 | "js", 94 | "json", 95 | "ts" 96 | ], 97 | "rootDir": ".", 98 | "coverageDirectory": "../coverage", 99 | "testEnvironment": "node", 100 | "testTimeout": 30000 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/balances/GenericBalance.ts: -------------------------------------------------------------------------------- 1 | import { IBalance } from './IBalance'; 2 | import BigNumber from 'bignumber.js'; 3 | 4 | export class GenericBalance implements IBalance { 5 | currency: string = ''; 6 | value = 0; 7 | unconfirmedBalance = 0; 8 | confirmedBalance = 0; 9 | 10 | constructor( 11 | currency: string, 12 | confirmedBalance: number, 13 | unconfirmedBalance: number 14 | ) { 15 | this.currency = currency; 16 | this.value = Number( 17 | new BigNumber(confirmedBalance).plus(new BigNumber(unconfirmedBalance)) 18 | ); 19 | this.confirmedBalance = confirmedBalance; 20 | this.unconfirmedBalance = unconfirmedBalance; 21 | } 22 | getValue() { 23 | return this.value; 24 | } 25 | getConfirmedBalance() { 26 | return this.confirmedBalance; 27 | } 28 | getUnconfirmedBalance() { 29 | return this.unconfirmedBalance; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/balances/GenericBalanceDriver.ts: -------------------------------------------------------------------------------- 1 | import { IBalanceDriver } from './IBalance'; 2 | import { GenericBalance } from './GenericBalance'; 3 | 4 | export class GenericBalanceDriver implements IBalanceDriver { 5 | currency: string; 6 | assetConfig: any; 7 | config: any; 8 | constructor(assetConfig: any, config?: any) { 9 | this.config = config; 10 | this.assetConfig = assetConfig; 11 | this.currency = assetConfig.symbol; 12 | } 13 | getBalance = async (_address: string) => { 14 | return new GenericBalance(this.currency, 0, 0); 15 | }; 16 | getBalanceEndpoint() { 17 | const endpoint = this.config.endpoint; 18 | if (endpoint) { 19 | return endpoint; 20 | } 21 | throw new Error( 22 | this.currency + ' Balance currency endpoint is required in config' 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/balances/IBalance.ts: -------------------------------------------------------------------------------- 1 | export interface IBalance { 2 | currency: string; 3 | getValue(): number; 4 | getUnconfirmedBalance(): number; 5 | } 6 | 7 | export interface IBalanceDriver { 8 | currency: string; 9 | getBalance(address: string): Promise; 10 | } 11 | -------------------------------------------------------------------------------- /src/balances/drivers/BSC_Driver.ts: -------------------------------------------------------------------------------- 1 | import { WEB3_Driver } from './WEB3_Driver'; 2 | 3 | export class BSC_Driver extends WEB3_Driver { 4 | config: any; 5 | nativeCurrencySymbol: string = 'BNB'; 6 | getTokenBalanceEndpoint() { 7 | return this.getBalanceEndpoint(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/balances/drivers/BTC_Driver.ts: -------------------------------------------------------------------------------- 1 | import { GenericBalanceDriver } from '../GenericBalanceDriver'; 2 | import { GenericBalance } from '../GenericBalance'; 3 | import axios from 'axios'; 4 | import { GENERIC_REQUEST_THROTTLE_DELAY, UA } from '../../constants'; 5 | import { satoshi_to_btc } from '../../currencyFunctions'; 6 | import BigNumber from 'bignumber.js'; 7 | 8 | export class BTC_Driver extends GenericBalanceDriver { 9 | config: any; 10 | getBalance = async (address: string) => { 11 | let endpoints = this.getBalanceEndpoint(); 12 | for (let i = 0; i < endpoints.length; i++) { 13 | let endpoint = endpoints[i]; 14 | const url = endpoint + address + '?details=basic'; 15 | const param: object = { 16 | method: 'get', 17 | url: url, 18 | headers: { 19 | 'User-Agent': UA, 20 | }, 21 | timeout: 1000, 22 | }; 23 | try { 24 | const response = await axios(param); 25 | if (response.data.balance && response.data.unconfirmedBalance) { 26 | let balanceSet = { 27 | balance: response.data.balance, 28 | unconfirmedBalance: response.data.unconfirmedBalance, 29 | }; 30 | const confirmedBalance: number = Number( 31 | new BigNumber(balanceSet.balance) 32 | ); 33 | const unconfirmedBalance: number = Number( 34 | new BigNumber(balanceSet.unconfirmedBalance) 35 | ); 36 | 37 | return new GenericBalance( 38 | this.currency, 39 | satoshi_to_btc(confirmedBalance), 40 | satoshi_to_btc(unconfirmedBalance) 41 | ); 42 | } 43 | } catch (e) {} 44 | await new Promise(resolve => 45 | setTimeout(resolve, GENERIC_REQUEST_THROTTLE_DELAY) 46 | ); 47 | } 48 | throw new Error('Unable to retrieve balance!'); 49 | }; 50 | 51 | getBalanceEndpoint() { 52 | let endpoints = []; 53 | if (this.config.endpoint) { 54 | if (!Array.isArray(this.config.endpoint)) { 55 | endpoints = [this.config.endpoint]; 56 | } else { 57 | endpoints = this.config.endpoint; 58 | } 59 | return endpoints; 60 | } 61 | throw new Error( 62 | this.currency + ' Balance currency endpoint is required in config' 63 | ); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/balances/drivers/ETH_Driver.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { UA } from '../../constants'; 3 | import { weiToETH } from '../../currencyFunctions'; 4 | import { GenericBalance } from '../GenericBalance'; 5 | import { WEB3_Driver } from './WEB3_Driver'; 6 | import BigNumber from 'bignumber.js'; 7 | 8 | export class ETH_Driver extends WEB3_Driver { 9 | config: any; 10 | nativeCurrencySymbol: string = 'ETH'; 11 | getNativeAssetBalance = async (address: string) => { 12 | const url = this.getBalanceEndpoint() + address + '?details=basic'; 13 | const param: object = { 14 | method: 'get', 15 | url: url, 16 | headers: { 17 | 'User-Agent': UA, 18 | }, 19 | }; 20 | const response = await axios(param); 21 | 22 | const confirmedBalance: number = Number( 23 | new BigNumber(response.data.balance) 24 | ); 25 | const unconfirmedBalance: number = Number( 26 | new BigNumber(response.data.unconfirmedBalance) 27 | ); 28 | return new GenericBalance( 29 | this.currency, 30 | Number(weiToETH(confirmedBalance.toString())), 31 | Number(weiToETH(unconfirmedBalance.toString())) 32 | ); 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /src/balances/drivers/POLYGON_Driver.ts: -------------------------------------------------------------------------------- 1 | import { WEB3_Driver } from './WEB3_Driver'; 2 | 3 | export class POLYGON_Driver extends WEB3_Driver { 4 | config: any; 5 | nativeCurrencySymbol: string = 'MATIC'; 6 | getTokenBalanceEndpoint() { 7 | return this.getBalanceEndpoint(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/balances/drivers/WEB3_Driver.ts: -------------------------------------------------------------------------------- 1 | import { ERC20_ABI } from '../../constants'; 2 | import { weiToETH } from '../../currencyFunctions'; 3 | import { GenericBalance } from '../GenericBalance'; 4 | import { GenericBalanceDriver } from '../GenericBalanceDriver'; 5 | import BigNumber from 'bignumber.js'; 6 | import Web3 from 'web3'; 7 | 8 | export class WEB3_Driver extends GenericBalanceDriver { 9 | config: any; 10 | nativeCurrencySymbol: string = 'ETH'; 11 | getBalance = async (address: string) => { 12 | if (this.currency === this.nativeCurrencySymbol) { 13 | return this.getNativeAssetBalance(address); 14 | } else { 15 | return this.getTokenBalance(address); 16 | } 17 | }; 18 | getNativeAssetBalance = async (address: string) => { 19 | const provider = new Web3.providers.HttpProvider(this.getBalanceEndpoint()); 20 | const client = new Web3(provider); 21 | let bnbBalance = await client.eth.getBalance(address); 22 | const confirmedBalance: number = Number(new BigNumber(bnbBalance)); 23 | 24 | const value = Number(weiToETH(confirmedBalance.toString())); 25 | // console.log('value', value); 26 | return new GenericBalance(this.currency, value, 0); 27 | }; 28 | getTokenBalance = async (address: string) => { 29 | if (this.assetConfig.decimals === null) { 30 | throw new Error( 31 | 'Wallet decimals not set, can not retrieve balance without decimals!' 32 | ); 33 | } 34 | const provider = new Web3.providers.HttpProvider( 35 | this.getTokenBalanceEndpoint() 36 | ); 37 | const client = new Web3(provider); 38 | 39 | // The minimum ABI required to get the ERC20 Token balance 40 | const minABI: any = ERC20_ABI; 41 | 42 | const contract = new client.eth.Contract( 43 | minABI, 44 | this.assetConfig.contract! 45 | ); 46 | 47 | const result = await contract.methods 48 | .balanceOf(address) 49 | .call({ from: address }); 50 | 51 | const format = result; 52 | const value = Number( 53 | new BigNumber(format).div(10 ** this.assetConfig.decimals!) 54 | ); 55 | 56 | return new GenericBalance(this.currency, value, 0); 57 | }; 58 | getTokenBalanceEndpoint() { 59 | const endpoint = this.config.token_endpoint; 60 | if (endpoint) { 61 | return endpoint; 62 | } 63 | throw new Error( 64 | this.currency + ' Balance token endpoint is required in config' 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/balances/index.ts: -------------------------------------------------------------------------------- 1 | export { BTC_Driver } from './drivers/BTC_Driver'; 2 | export { ETH_Driver } from './drivers/ETH_Driver'; 3 | export { BSC_Driver } from './drivers/BSC_Driver'; 4 | export { POLYGON_Driver } from './drivers/POLYGON_Driver'; 5 | // 6 | export { GenericBalance } from './GenericBalance'; 7 | -------------------------------------------------------------------------------- /src/chains.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enum for supported blockchains types 3 | * @readonly 4 | * @enum {string} 5 | * @property {string} BTC "BTC" 6 | * @property {string} ETH "ETH" 7 | * @property {string} POLYGON "POLYGON" 8 | * @property {string} BSC "BSC" 9 | */ 10 | export enum Chains { 11 | BTC = 'BTC', 12 | ETH = 'ETH', 13 | POLYGON = 'POLYGON', 14 | BSC = 'BSC', 15 | } 16 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | import { Currency } from './currencies'; 2 | 3 | export const GENERIC_REQUEST_THROTTLE_DELAY = 250; 4 | 5 | export const SATOSHI = 100000000; 6 | export const UA = 7 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_5_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'; 8 | 9 | export const ETH_DERIVATION_PATH = "m/44'/60'/0'/0"; 10 | export const MATIC_DERIVATION_PATH = "m/44'/966'/0'/0"; 11 | export const ONE_DERIVATION_PATH = "m/44'/1023'/0'/0"; 12 | export const FLOW_DERIVATION_PATH = "m/44'/539'/0'/0"; 13 | export const CELO_DERIVATION_PATH = "m/44'/52752'/0'/0"; 14 | export const VET_DERIVATION_PATH = "m/44'/818'/0'/0"; 15 | export const BTC_DERIVATION_PATH = "m/84'/0'/0'/0"; 16 | export const QTUM_DERIVATION_PATH = "m/44'/2301'/0'/0"; 17 | export const TRON_DERIVATION_PATH = "m/44'/195'/0'/0"; 18 | export const LTC_DERIVATION_PATH = "m/44'/2'/0'/0"; 19 | export const DOGE_DERIVATION_PATH = "m/44'/3'/0'/0"; 20 | export const BCH_DERIVATION_PATH = "m/44'/145'/0'/0"; 21 | export const LYRA_DERIVATION_PATH = "m/44'/497'/0'/0"; 22 | export const ADA_DERIVATION_PATH = "m/1852'/1815'/0'"; 23 | export const XDC_DERIVATION_PATH = "m/44'/550'/0'/0"; 24 | export const EGLD_DERIVATION_PATH = "m/44'/508'/0'/0'"; 25 | export const TESTNET_DERIVATION_PATH = "m/44'/1'/0'/0"; 26 | 27 | export const ADA_DERIVATION_SCHEME = 2; 28 | 29 | export const LTC_TEST_NETWORK = { 30 | messagePrefix: '\x18Litecoin Signed Message:\n', 31 | bech32: '', 32 | bip32: { 33 | public: 0x0436f6e1, 34 | private: 0x0436ef7d, 35 | }, 36 | pubKeyHash: 0x6f, 37 | scriptHash: 0x3a, 38 | wif: 0xef, 39 | }; 40 | export const LTC_NETWORK = { 41 | messagePrefix: '\x18Litecoin Signed Message:\n', 42 | bech32: '', 43 | bip32: { 44 | public: 0x019da462, 45 | private: 0x019d9cfe, 46 | }, 47 | pubKeyHash: 0x30, 48 | scriptHash: 0x32, 49 | wif: 0xb0, 50 | }; 51 | export const QTUM_NETWORK_MAINNET = { 52 | messagePrefix: '\x15Qtum Signed Message:\n', 53 | bech32: 'qc', 54 | bip32: { 55 | public: 0x0488b21e, 56 | private: 0x0488ade4, 57 | }, 58 | pubKeyHash: 0x3a, 59 | scriptHash: 0x32, 60 | wif: 0x80, 61 | }; 62 | export const QTUM_NETWORK_TESTNET = { 63 | messagePrefix: '\x15Qtum Signed Message:\n', 64 | bech32: 'tq', 65 | bip32: { 66 | public: 0x043587cf, 67 | private: 0x04358394, 68 | }, 69 | pubKeyHash: 0x78, 70 | scriptHash: 0x6e, 71 | wif: 0xef, 72 | }; 73 | 74 | export const DOGE_TEST_NETWORK = { 75 | messagePrefix: '\x18Dogecoin Signed Message:\n', 76 | bech32: '', 77 | bip32: { 78 | public: 0x043587cf, 79 | private: 0x04358394, 80 | }, 81 | pubKeyHash: 0x71, 82 | scriptHash: 0xc4, 83 | wif: 0xf1, 84 | }; 85 | export const DOGE_NETWORK = { 86 | messagePrefix: '\x18Dogecoin Signed Message:\n', 87 | bech32: '', 88 | bip32: { 89 | public: 0x0488b21e, 90 | private: 0x0488ade4, 91 | }, 92 | pubKeyHash: 0x1e, 93 | scriptHash: 0x16, 94 | wif: 0x9e, 95 | }; 96 | 97 | export const LYRA_TEST_NETWORK = { 98 | messagePrefix: '\x18DarkNet Signed Message:\n', 99 | bech32: '', 100 | bip32: { 101 | public: 0x043587cf, 102 | private: 0x04358394, 103 | }, 104 | pubKeyHash: 0x7f, 105 | scriptHash: 0x13, 106 | wif: 0xae, 107 | }; 108 | export const LYRA_NETWORK = { 109 | messagePrefix: '\x18DarkNet Signed Message:\n', 110 | bech32: '', 111 | bip32: { 112 | public: 0x0488b21e, 113 | private: 0x0488ade4, 114 | }, 115 | pubKeyHash: 0x30, 116 | scriptHash: 0x0d, 117 | wif: 0xae, 118 | }; 119 | 120 | export const RIPPLE_EPOCH = 946684800; 121 | 122 | export const CUSD_ADDRESS_MAINNET = 123 | '0x765de816845861e75a25fca122bb6898b8b1282a'; 124 | export const CUSD_ADDRESS_TESTNET = 125 | '0x874069fa1eb16d44d622f2e0ca25eea172369bc1'; 126 | export const CEUR_ADDRESS_MAINNET = 127 | '0xd8763cba276a3738e6de85b4b3bf5fded6d6ca73'; 128 | export const CEUR_ADDRESS_TESTNET = 129 | '0x10c892a6ec43a53e45d0b916b4b7d383b1b78c0f'; 130 | 131 | export const FLOW_TESTNET_ADDRESSES = { 132 | FlowToken: '0x7e60df042a9c0868', 133 | FungibleToken: '0x9a0766d93b6608b7', 134 | FUSD: '0xe223d8a629e49c68', 135 | TatumMultiNFT: '0x87fe4ebd0cddde06', 136 | }; 137 | 138 | export const FLOW_MAINNET_ADDRESSES = { 139 | FlowToken: '0x1654653399040a61', 140 | FungibleToken: '0xf233dcee88fe0abe', 141 | FUSD: '0x3c5959b568896393', 142 | TatumMultiNFT: '0x354e6721564ccd2c', 143 | }; 144 | 145 | export const CONTRACT_ADDRESSES = { 146 | [Currency.USDT.toString()]: '0xdac17f958d2ee523a2206206994597c13d831ec7', 147 | [Currency.LEO.toString()]: '0x2af5d2ad76741191d15dfe7bf6ac92d4bd912ca3', 148 | [Currency.UNI.toString()]: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', 149 | [Currency.LINK.toString()]: '0x514910771af9ca656af840dff83e8264ecf986ca', 150 | [Currency.WBTC.toString()]: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', 151 | [Currency.FREE.toString()]: '0x2f141ce366a2462f02cea3d12cf93e4dca49e4fd', 152 | [Currency.MKR.toString()]: '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2', 153 | [Currency.USDC.toString()]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', 154 | [Currency.BAT.toString()]: '0x0d8775f648430679a709e98d2b0cb6250d2887ef', 155 | [Currency.USDT_MATIC.toString()]: '0xc2132d05d31c914a87c6611c10748aeb04b58e8f', 156 | [Currency.LATOKEN.toString()]: '0xe50365f5d679cb98a1dd62d6f6e58e59321bcddf', 157 | [Currency.TUSD.toString()]: '0x0000000000085d4780B73119b644AE5ecd22b376', 158 | [Currency.PAX.toString()]: '0x8e870d67f660d95d5be530380d0ec0bd388289e1', 159 | [Currency.GMC.toString()]: '0xa6272359bc37f61af398071b65c8934aca744d53', 160 | [Currency.PAXG.toString()]: '0x45804880de22913dafe09f4980848ece6ecbaf78', 161 | [Currency.HAG.toString()]: '0x44e133e71bf90cb67de4c0f31c391ade021def4a', 162 | [Currency.PLTC.toString()]: '0x429d83bb0dcb8cdd5311e34680adc8b12070a07f', 163 | [Currency.MMY.toString()]: '0x385ddf50c3de724f6b8ecb41745c29f9dd3c6d75', 164 | [Currency.XCON.toString()]: '0x0f237d5ea7876e0e2906034d98fdb20d43666ad4', 165 | [Currency.REVV.toString()]: '0x557b933a7c2c45672b610f8954a3deb39a51a8ca', 166 | [Currency.MATIC_ETH.toString()]: '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0', 167 | [Currency.SAND.toString()]: '0x3845badade8e6dff049820680d1f14bd3903a5d0', 168 | [Currency.USDT_TRON.toString()]: 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t', 169 | [Currency.INRT_TRON.toString()]: 'TX66VmiV1txm45vVLvcHYEqPXXLoREyAXm', 170 | [Currency.USDC_MATIC.toString()]: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', 171 | [Currency.USDC_BSC.toString()]: '0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', 172 | [Currency.B2U_BSC.toString()]: '0x02926e6e2898e9235fdddde3f51c3b644af8c403', 173 | [Currency.BUSD.toString()]: '0x4fabb145d64652a948d72533023f6e7a623c7c53', 174 | [Currency.BETH.toString()]: '0x2170ed0880ac9a755fd29b2688956bd959f933f8', 175 | [Currency.BBTC.toString()]: '0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c', 176 | [Currency.BADA.toString()]: '0x3ee2200efb3400fabb9aacf31297cbdd1d435d47', 177 | [Currency.RMD.toString()]: '0x02888e65324a98219c26f292e7cd3e52ef39c5c2', 178 | [Currency.WBNB.toString()]: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c', 179 | [Currency.BDOT.toString()]: '0x7083609fce4d1d8dc0c979aab8c869ea2c873402', 180 | [Currency.BXRP.toString()]: '0x1d2f0da169ceb9fc7b3144628db156f3f6c60dbe', 181 | [Currency.BLTC.toString()]: '0x4338665cbb7b2485a8855a139b75d5e34ab0db94', 182 | [Currency.BBCH.toString()]: '0x8ff795a6f4d97e7887c79bea79aba5cc76444adf', 183 | [Currency.CAKE.toString()]: '0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82', 184 | [Currency.BUSD_BSC.toString()]: '0xe9e7cea3dedca5984780bafc599bd69add087d56', 185 | [Currency.GMC_BSC.toString()]: '0xa6272359bc37f61af398071b65c8934aca744d53', 186 | }; 187 | 188 | export const CONTRACT_DECIMALS = { 189 | [Currency.USDT.toString()]: 6, 190 | [Currency.USDT_TRON.toString()]: 6, 191 | [Currency.INRT_TRON.toString()]: 2, 192 | [Currency.USDT_MATIC.toString()]: 6, 193 | [Currency.WBTC.toString()]: 8, 194 | [Currency.LEO.toString()]: 18, 195 | [Currency.LATOKEN.toString()]: 18, 196 | [Currency.RMD.toString()]: 18, 197 | [Currency.MATIC_ETH.toString()]: 18, 198 | [Currency.GMC.toString()]: 18, 199 | [Currency.GMC_BSC.toString()]: 18, 200 | [Currency.BUSD.toString()]: 18, 201 | [Currency.CAKE.toString()]: 18, 202 | [Currency.BUSD_BSC.toString()]: 18, 203 | [Currency.LINK.toString()]: 18, 204 | [Currency.UNI.toString()]: 18, 205 | [Currency.FREE.toString()]: 18, 206 | [Currency.MKR.toString()]: 18, 207 | [Currency.USDC.toString()]: 6, 208 | [Currency.HAG.toString()]: 8, 209 | [Currency.BAT.toString()]: 18, 210 | [Currency.TUSD.toString()]: 18, 211 | [Currency.PAX.toString()]: 18, 212 | [Currency.PAXG.toString()]: 18, 213 | [Currency.PLTC.toString()]: 18, 214 | [Currency.MMY.toString()]: 18, 215 | [Currency.XCON.toString()]: 18, 216 | [Currency.REVV.toString()]: 18, 217 | [Currency.SAND.toString()]: 18, 218 | [Currency.USDC_MATIC.toString()]: 6, 219 | [Currency.USDC_BSC.toString()]: 18, 220 | [Currency.B2U_BSC.toString()]: 18, 221 | [Currency.BETH.toString()]: 18, 222 | [Currency.BBTC.toString()]: 18, 223 | [Currency.BADA.toString()]: 18, 224 | [Currency.WBNB.toString()]: 18, 225 | [Currency.BDOT.toString()]: 18, 226 | [Currency.BXRP.toString()]: 18, 227 | [Currency.BLTC.toString()]: 18, 228 | [Currency.BBCH.toString()]: 18, 229 | }; 230 | 231 | export const CELO_BASED_CURRENCIES = [ 232 | Currency.CELO.toString(), 233 | Currency.CEUR.toString(), 234 | Currency.CUSD.toString(), 235 | ]; 236 | 237 | export const ERC20_ABI = [ 238 | { 239 | constant: true, 240 | inputs: [], 241 | name: 'name', 242 | outputs: [ 243 | { 244 | name: '', 245 | type: 'string', 246 | }, 247 | ], 248 | payable: false, 249 | stateMutability: 'view', 250 | type: 'function', 251 | }, 252 | { 253 | constant: false, 254 | inputs: [ 255 | { 256 | name: 'spender', 257 | type: 'address', 258 | }, 259 | { 260 | name: 'value', 261 | type: 'uint256', 262 | }, 263 | ], 264 | name: 'approve', 265 | outputs: [ 266 | { 267 | name: '', 268 | type: 'bool', 269 | }, 270 | ], 271 | payable: false, 272 | stateMutability: 'nonpayable', 273 | type: 'function', 274 | }, 275 | { 276 | constant: true, 277 | inputs: [], 278 | name: 'totalSupply', 279 | outputs: [ 280 | { 281 | name: '', 282 | type: 'uint256', 283 | }, 284 | ], 285 | payable: false, 286 | stateMutability: 'view', 287 | type: 'function', 288 | }, 289 | { 290 | constant: false, 291 | inputs: [ 292 | { 293 | name: 'from', 294 | type: 'address', 295 | }, 296 | { 297 | name: 'to', 298 | type: 'address', 299 | }, 300 | { 301 | name: 'value', 302 | type: 'uint256', 303 | }, 304 | ], 305 | name: 'transferFrom', 306 | outputs: [ 307 | { 308 | name: '', 309 | type: 'bool', 310 | }, 311 | ], 312 | payable: false, 313 | stateMutability: 'nonpayable', 314 | type: 'function', 315 | }, 316 | { 317 | constant: true, 318 | inputs: [], 319 | name: 'decimals', 320 | outputs: [ 321 | { 322 | name: '', 323 | type: 'uint8', 324 | }, 325 | ], 326 | payable: false, 327 | stateMutability: 'view', 328 | type: 'function', 329 | }, 330 | { 331 | constant: true, 332 | inputs: [], 333 | name: 'cap', 334 | outputs: [ 335 | { 336 | name: '', 337 | type: 'uint256', 338 | }, 339 | ], 340 | payable: false, 341 | stateMutability: 'view', 342 | type: 'function', 343 | }, 344 | { 345 | constant: false, 346 | inputs: [ 347 | { 348 | name: 'spender', 349 | type: 'address', 350 | }, 351 | { 352 | name: 'addedValue', 353 | type: 'uint256', 354 | }, 355 | ], 356 | name: 'increaseAllowance', 357 | outputs: [ 358 | { 359 | name: '', 360 | type: 'bool', 361 | }, 362 | ], 363 | payable: false, 364 | stateMutability: 'nonpayable', 365 | type: 'function', 366 | }, 367 | { 368 | constant: false, 369 | inputs: [ 370 | { 371 | name: 'to', 372 | type: 'address', 373 | }, 374 | { 375 | name: 'value', 376 | type: 'uint256', 377 | }, 378 | ], 379 | name: 'mint', 380 | outputs: [ 381 | { 382 | name: '', 383 | type: 'bool', 384 | }, 385 | ], 386 | payable: false, 387 | stateMutability: 'nonpayable', 388 | type: 'function', 389 | }, 390 | { 391 | constant: false, 392 | inputs: [ 393 | { 394 | name: 'value', 395 | type: 'uint256', 396 | }, 397 | ], 398 | name: 'burn', 399 | outputs: [], 400 | payable: false, 401 | stateMutability: 'nonpayable', 402 | type: 'function', 403 | }, 404 | { 405 | constant: true, 406 | inputs: [ 407 | { 408 | name: 'owner', 409 | type: 'address', 410 | }, 411 | ], 412 | name: 'balanceOf', 413 | outputs: [ 414 | { 415 | name: '', 416 | type: 'uint256', 417 | }, 418 | ], 419 | payable: false, 420 | stateMutability: 'view', 421 | type: 'function', 422 | }, 423 | { 424 | constant: false, 425 | inputs: [ 426 | { 427 | name: 'from', 428 | type: 'address', 429 | }, 430 | { 431 | name: 'value', 432 | type: 'uint256', 433 | }, 434 | ], 435 | name: 'burnFrom', 436 | outputs: [], 437 | payable: false, 438 | stateMutability: 'nonpayable', 439 | type: 'function', 440 | }, 441 | { 442 | constant: true, 443 | inputs: [], 444 | name: 'symbol', 445 | outputs: [ 446 | { 447 | name: '', 448 | type: 'string', 449 | }, 450 | ], 451 | payable: false, 452 | stateMutability: 'view', 453 | type: 'function', 454 | }, 455 | { 456 | constant: false, 457 | inputs: [ 458 | { 459 | name: 'account', 460 | type: 'address', 461 | }, 462 | ], 463 | name: 'addMinter', 464 | outputs: [], 465 | payable: false, 466 | stateMutability: 'nonpayable', 467 | type: 'function', 468 | }, 469 | { 470 | constant: false, 471 | inputs: [], 472 | name: 'renounceMinter', 473 | outputs: [], 474 | payable: false, 475 | stateMutability: 'nonpayable', 476 | type: 'function', 477 | }, 478 | { 479 | constant: false, 480 | inputs: [ 481 | { 482 | name: 'spender', 483 | type: 'address', 484 | }, 485 | { 486 | name: 'subtractedValue', 487 | type: 'uint256', 488 | }, 489 | ], 490 | name: 'decreaseAllowance', 491 | outputs: [ 492 | { 493 | name: '', 494 | type: 'bool', 495 | }, 496 | ], 497 | payable: false, 498 | stateMutability: 'nonpayable', 499 | type: 'function', 500 | }, 501 | { 502 | constant: false, 503 | inputs: [ 504 | { 505 | name: 'to', 506 | type: 'address', 507 | }, 508 | { 509 | name: 'value', 510 | type: 'uint256', 511 | }, 512 | ], 513 | name: 'transfer', 514 | outputs: [ 515 | { 516 | name: '', 517 | type: 'bool', 518 | }, 519 | ], 520 | payable: false, 521 | stateMutability: 'nonpayable', 522 | type: 'function', 523 | }, 524 | { 525 | constant: true, 526 | inputs: [ 527 | { 528 | name: 'account', 529 | type: 'address', 530 | }, 531 | ], 532 | name: 'isMinter', 533 | outputs: [ 534 | { 535 | name: '', 536 | type: 'bool', 537 | }, 538 | ], 539 | payable: false, 540 | stateMutability: 'view', 541 | type: 'function', 542 | }, 543 | { 544 | constant: true, 545 | inputs: [], 546 | name: 'builtOn', 547 | outputs: [ 548 | { 549 | name: '', 550 | type: 'string', 551 | }, 552 | ], 553 | payable: false, 554 | stateMutability: 'view', 555 | type: 'function', 556 | }, 557 | { 558 | constant: true, 559 | inputs: [ 560 | { 561 | name: 'owner', 562 | type: 'address', 563 | }, 564 | { 565 | name: 'spender', 566 | type: 'address', 567 | }, 568 | ], 569 | name: 'allowance', 570 | outputs: [ 571 | { 572 | name: '', 573 | type: 'uint256', 574 | }, 575 | ], 576 | payable: false, 577 | stateMutability: 'view', 578 | type: 'function', 579 | }, 580 | { 581 | inputs: [ 582 | { 583 | name: 'name', 584 | type: 'string', 585 | }, 586 | { 587 | name: 'symbol', 588 | type: 'string', 589 | }, 590 | { 591 | name: 'receiver', 592 | type: 'address', 593 | }, 594 | { 595 | name: 'decimals', 596 | type: 'uint8', 597 | }, 598 | { 599 | name: 'cap', 600 | type: 'uint256', 601 | }, 602 | { 603 | name: 'initialBalance', 604 | type: 'uint256', 605 | }, 606 | ], 607 | payable: false, 608 | stateMutability: 'nonpayable', 609 | type: 'constructor', 610 | }, 611 | { 612 | anonymous: false, 613 | inputs: [ 614 | { 615 | indexed: true, 616 | name: 'account', 617 | type: 'address', 618 | }, 619 | ], 620 | name: 'MinterAdded', 621 | type: 'event', 622 | }, 623 | { 624 | anonymous: false, 625 | inputs: [ 626 | { 627 | indexed: true, 628 | name: 'account', 629 | type: 'address', 630 | }, 631 | ], 632 | name: 'MinterRemoved', 633 | type: 'event', 634 | }, 635 | { 636 | anonymous: false, 637 | inputs: [ 638 | { 639 | indexed: true, 640 | name: 'from', 641 | type: 'address', 642 | }, 643 | { 644 | indexed: true, 645 | name: 'to', 646 | type: 'address', 647 | }, 648 | { 649 | indexed: false, 650 | name: 'value', 651 | type: 'uint256', 652 | }, 653 | ], 654 | name: 'Transfer', 655 | type: 'event', 656 | }, 657 | { 658 | anonymous: false, 659 | inputs: [ 660 | { 661 | indexed: true, 662 | name: 'owner', 663 | type: 'address', 664 | }, 665 | { 666 | indexed: true, 667 | name: 'spender', 668 | type: 'address', 669 | }, 670 | { 671 | indexed: false, 672 | name: 'value', 673 | type: 'uint256', 674 | }, 675 | ], 676 | name: 'Approval', 677 | type: 'event', 678 | }, 679 | ]; 680 | 681 | export const TRANSFER_METHOD_ABI = { 682 | constant: false, 683 | inputs: [ 684 | { 685 | name: 'to', 686 | type: 'address', 687 | }, 688 | { 689 | name: 'value', 690 | type: 'uint256', 691 | }, 692 | ], 693 | name: 'transfer', 694 | outputs: [ 695 | { 696 | name: '', 697 | type: 'bool', 698 | }, 699 | ], 700 | payable: false, 701 | stateMutability: 'nonpayable', 702 | type: 'function', 703 | }; 704 | 705 | export const ESDT_SYSTEM_SMART_CONTRACT_ADDRESS = 706 | 'erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u'; 707 | -------------------------------------------------------------------------------- /src/currencies.ts: -------------------------------------------------------------------------------- 1 | export enum Currency { 2 | BTC = 'BTC', 3 | BCH = 'BCH', 4 | LTC = 'LTC', 5 | CELO = 'CELO', 6 | ONE = 'ONE', 7 | CUSD = 'CUSD', 8 | CEUR = 'CEUR', 9 | ETH = 'ETH', 10 | FABRIC = 'FABRIC', 11 | QUORUM = 'QUORUM', 12 | XRP = 'XRP', 13 | XLM = 'XLM', 14 | DOGE = 'DOGE', 15 | VET = 'VET', 16 | NEO = 'NEO', 17 | BNB = 'BNB', 18 | BSC = 'BSC', 19 | CAKE = 'CAKE', 20 | BUSD_BSC = 'BUSD_BSC', 21 | B2U_BSC = 'B2U_BSC', 22 | BETH = 'BETH', 23 | BBTC = 'BBTC', 24 | BADA = 'BADA', 25 | RMD = 'RMD', 26 | WBNB = 'WBNB', 27 | BDOT = 'BDOT', 28 | BXRP = 'BXRP', 29 | BLTC = 'BLTC', 30 | BBCH = 'BBCH', 31 | MATIC = 'MATIC', 32 | USDC_MATIC = 'USDC_MATIC', 33 | USDC_BSC = 'USDC_BSC', 34 | USDT = 'USDT', 35 | GMC = 'GMC', 36 | GMC_BSC = 'GMC_BSC', 37 | FLOW = 'FLOW', 38 | FUSD = 'FUSD', 39 | USDT_TRON = 'USDT_TRON', 40 | INRT_TRON = 'INRT_TRON', 41 | TRON = 'TRON', 42 | LEO = 'LEO', 43 | LINK = 'LINK', 44 | WBTC = 'WBTC', 45 | UNI = 'UNI', 46 | FREE = 'FREE', 47 | MKR = 'MKR', 48 | USDC = 'USDC', 49 | MATIC_ETH = 'MATIC_ETH', 50 | BAT = 'BAT', 51 | TUSD = 'TUSD', 52 | BUSD = 'BUSD', 53 | PAX = 'PAX', 54 | PLTC = 'PLTC', 55 | XCON = 'XCON', 56 | REVV = 'REVV', 57 | SAND = 'SAND', 58 | MMY = 'MMY', 59 | PAXG = 'PAXG', 60 | HAG = 'HAG', 61 | LYRA = 'LYRA', 62 | ADA = 'ADA', 63 | XDC = 'XDC', 64 | LATOKEN = 'LATOKEN', 65 | USDT_MATIC = 'USDT_MATIC', 66 | QTUM = 'QTUM', 67 | EGLD = 'EGLD', 68 | ALGO = 'ALGO', 69 | } 70 | 71 | export const ERC20_CURRENCIES = [ 72 | Currency.USDT.toString(), 73 | Currency.LATOKEN.toString(), 74 | Currency.LEO.toString(), 75 | Currency.LINK.toString(), 76 | Currency.UNI.toString(), 77 | Currency.FREE.toString(), 78 | Currency.MKR.toString(), 79 | Currency.BUSD.toString(), 80 | Currency.USDC.toString(), 81 | Currency.MATIC_ETH.toString(), 82 | Currency.BAT.toString(), 83 | Currency.WBTC.toString(), 84 | Currency.TUSD.toString(), 85 | Currency.PAX.toString(), 86 | Currency.PAXG.toString(), 87 | Currency.PLTC.toString(), 88 | Currency.XCON.toString(), 89 | Currency.MMY.toString(), 90 | Currency.REVV.toString(), 91 | Currency.SAND.toString(), 92 | Currency.GMC.toString(), 93 | ]; 94 | 95 | export const BEP20_CURRENCIES = [ 96 | Currency.BETH.toString(), 97 | Currency.BBTC.toString(), 98 | Currency.RMD.toString(), 99 | Currency.USDC_BSC.toString(), 100 | Currency.B2U_BSC.toString(), 101 | Currency.BADA.toString(), 102 | Currency.WBNB.toString(), 103 | Currency.GMC_BSC.toString(), 104 | Currency.BDOT.toString(), 105 | Currency.BXRP.toString(), 106 | Currency.BLTC.toString(), 107 | Currency.BBCH.toString(), 108 | Currency.HAG.toString(), 109 | Currency.CAKE.toString(), 110 | Currency.BUSD_BSC.toString(), 111 | ]; 112 | 113 | export const MATIC20_CURRENCIES = [ 114 | Currency.USDC_MATIC.toString(), 115 | Currency.USDT_MATIC.toString(), 116 | ]; 117 | 118 | export const ETH_BASED_CURRENCIES = [ 119 | Currency.ETH.toString(), 120 | ...ERC20_CURRENCIES, 121 | ]; 122 | 123 | export const MATIC_BASED_CURRENCIES = [ 124 | Currency.MATIC.toString(), 125 | ...MATIC20_CURRENCIES, 126 | ]; 127 | 128 | export const BSC_BASED_CURRENCIES = [ 129 | Currency.BSC.toString(), 130 | ...BEP20_CURRENCIES, 131 | ]; 132 | -------------------------------------------------------------------------------- /src/currencyFunctions.ts: -------------------------------------------------------------------------------- 1 | import { SATOSHI } from './constants'; 2 | import BigNumber from 'bignumber.js'; 3 | import { fromWei, isAddress } from 'web3-utils'; 4 | 5 | export const btc_to_satoshi = (btcValue: any) => { 6 | return Number( 7 | new BigNumber(btcValue) 8 | .multipliedBy(SATOSHI) 9 | .toFixed(8, BigNumber.ROUND_FLOOR) 10 | ); 11 | }; 12 | 13 | export const satoshi_to_btc = (satoshiValue: any) => { 14 | return Number(new BigNumber(satoshiValue).dividedBy(SATOSHI)); 15 | }; 16 | 17 | export const weiToETH = (amount: string) => { 18 | return fromWei(amount, 'ether'); 19 | }; 20 | 21 | export const isETHAddress = (address: string) => { 22 | return isAddress(address); 23 | }; 24 | -------------------------------------------------------------------------------- /src/fees/GenericDriver.ts: -------------------------------------------------------------------------------- 1 | import { IFeeDriver } from './IFee'; 2 | import { IWalletConfig } from '..'; 3 | 4 | export class GenericDriver implements IFeeDriver { 5 | assetConfig: IWalletConfig; 6 | currency: string; 7 | config: any; 8 | constructor(assetConfig: any, config?: any) { 9 | this.config = config; 10 | this.assetConfig = assetConfig; 11 | this.currency = assetConfig.symbol; 12 | } 13 | getTxSendProposals = async (_destination: string, _valueToSend: number) => { 14 | return {}; 15 | }; 16 | getFeeEndpoint() { 17 | const endpoint = this.config.endpoint; 18 | if (endpoint) { 19 | return endpoint; 20 | } 21 | throw new Error(this.currency + ' Balance currency is required in config'); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/fees/GenericTxProposal.ts: -------------------------------------------------------------------------------- 1 | import { IFee } from './IFee'; 2 | import { Currency } from '../currencies'; 3 | 4 | export class GenericTxProposal implements IFee { 5 | currency = Currency.BTC; 6 | settings = {}; 7 | getFeeValue() { 8 | return 0; 9 | } 10 | getData() { 11 | return {}; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/fees/IFee.ts: -------------------------------------------------------------------------------- 1 | import { Currency } from '../currencies'; 2 | 3 | export const FEE_TYPES = { 4 | REGULAR: 'regular', 5 | PRIORITY: 'priority', 6 | }; 7 | 8 | export interface IFee { 9 | currency: Currency; 10 | settings: any; 11 | getFeeValue(): number; 12 | getData(): any; 13 | } 14 | 15 | export interface IFeeMap { 16 | [key: string]: IFee; 17 | } 18 | 19 | export interface IFeeDriver { 20 | currency: string; 21 | getTxSendProposals( 22 | destination: string, 23 | valueToSend: number 24 | ): Promise; 25 | } 26 | -------------------------------------------------------------------------------- /src/fees/drivers/BSC_Driver.ts: -------------------------------------------------------------------------------- 1 | import { FEE_TYPES } from '../IFee'; 2 | import { WEB3_Driver } from './WEB3_Driver'; 3 | import { BnbFee } from '../types/BnbFee'; 4 | import axios from 'axios'; 5 | 6 | export class BSC_Driver extends WEB3_Driver { 7 | nativeAssetSymbol: string = 'BNB'; 8 | 9 | getGasFeePrices = async () => { 10 | const config: object = { 11 | method: 'get', 12 | url: this.getFeeEndpoint(), 13 | }; 14 | const response = await axios(config); 15 | const data = response.data; 16 | 17 | let prices: any = {}; 18 | prices[FEE_TYPES.REGULAR] = data.standard; 19 | prices[FEE_TYPES.PRIORITY] = data.fast; 20 | return prices; 21 | }; 22 | 23 | buildFee = (proposal: any) => { 24 | return new BnbFee(proposal); 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /src/fees/drivers/BTC_Driver.ts: -------------------------------------------------------------------------------- 1 | import { IFeeMap, FEE_TYPES } from '../IFee'; 2 | import { GenericDriver } from '../GenericDriver'; 3 | import { BitcoinFee } from '../types/BitcoinFee'; 4 | import axios from 'axios'; 5 | 6 | import { GENERIC_REQUEST_THROTTLE_DELAY, UA } from '../../constants'; 7 | import { btc_to_satoshi, satoshi_to_btc } from '../../currencyFunctions'; 8 | 9 | let coinSelect = require('coinselect'); 10 | 11 | export class BTC_Driver extends GenericDriver { 12 | getUTXOEndpoint() { 13 | let endpoints = []; 14 | if (this.config.utxo_endpoint) { 15 | if (!Array.isArray(this.config.utxo_endpoint)) { 16 | endpoints = [this.config.utxo_endpoint]; 17 | } else { 18 | endpoints = this.config.utxo_endpoint; 19 | } 20 | return endpoints; 21 | } 22 | throw new Error('BTC UTXO endpoint is required in config section'); 23 | } 24 | getUTXO = async (address: string) => { 25 | let endpoints = this.getUTXOEndpoint(); 26 | for (let i = 0; i < endpoints.length; i++) { 27 | let endpoint = endpoints[i]; 28 | const url = endpoint + address + '?confirmed=false'; 29 | const param: object = { 30 | method: 'get', 31 | url: url, 32 | headers: { 33 | 'User-Agent': UA, 34 | }, 35 | }; 36 | try { 37 | const response = await axios(param); 38 | return response.data; 39 | } catch (e) {} 40 | await new Promise(resolve => 41 | setTimeout(resolve, GENERIC_REQUEST_THROTTLE_DELAY) 42 | ); 43 | } 44 | throw new Error('Unable to retrieve UTXO information!'); 45 | }; 46 | getTxSendProposals = async (destination: string, valueToSend: number) => { 47 | const fromAddress = this.assetConfig.walletAddress!; 48 | const privKey = this.assetConfig.privKey; 49 | // const currency = this.assetConfig.symbol; 50 | 51 | const config: object = { 52 | method: 'get', 53 | url: this.getFeeEndpoint(), 54 | }; 55 | const response = await axios(config); 56 | const data = response.data; 57 | // { 58 | // "limits": { 59 | // "min": 2, 60 | // "max": 16 61 | // }, 62 | // "regular": 4, 63 | // "priority": 11 64 | // } 65 | // TODO: Check valid reply 66 | 67 | let utxosQueryResults = await this.getUTXO(fromAddress); 68 | let utxos: any[] = []; 69 | 70 | utxosQueryResults.forEach((t: any) => { 71 | utxos.push({ 72 | txid: t.txid, 73 | vout: t.vout, 74 | value: parseInt(t.value, 10), 75 | amount: satoshi_to_btc(t.value), 76 | }); 77 | }); 78 | let targets = [ 79 | { 80 | address: destination, 81 | value: btc_to_satoshi(valueToSend), 82 | }, 83 | ]; 84 | let fees: IFeeMap = {}; 85 | // 86 | let feeSet = [FEE_TYPES.REGULAR, FEE_TYPES.PRIORITY]; 87 | let inputs: any = []; 88 | let outputs: any = []; 89 | let fee = 0; 90 | let result: any = {}; 91 | let adjustedOutputs: any = []; 92 | let adjustedInputs: any = []; 93 | 94 | let privateKey = privKey; 95 | 96 | for (let i = 0; i < feeSet.length; i++) { 97 | const feeType = feeSet[i]; 98 | result = coinSelect(utxos.slice(), targets.slice(), data[feeType]); 99 | inputs = result.inputs; 100 | outputs = result.outputs; 101 | if (!inputs || !outputs) { 102 | throw new Error('Can not compute fees for the passed value'); 103 | } 104 | fee = result.fee; 105 | adjustedOutputs = []; 106 | adjustedInputs = []; 107 | for (let z = 0; z < inputs.length; z++) { 108 | const o = inputs[z]; 109 | adjustedInputs.push({ 110 | txHash: o.txid, 111 | index: o.vout, 112 | privateKey: privateKey, 113 | value: o.value, //SATOSHI 114 | amount: o.amount, //BTC 115 | }); 116 | } 117 | // Convert from satoshi back to BTC []; 118 | for (let z = 0; z < outputs.length; z++) { 119 | const o = outputs[z]; 120 | adjustedOutputs.push( 121 | Object.assign({}, o, { 122 | address: !o.address ? fromAddress : o.address, 123 | value: o.value, //SATOSHI 124 | amount: satoshi_to_btc(o.value), //BTC 125 | }) 126 | ); 127 | } 128 | fees[feeType] = new BitcoinFee(fee, { 129 | fromUTXO: adjustedInputs, 130 | to: adjustedOutputs, 131 | }); 132 | } 133 | // 134 | return fees; 135 | }; 136 | } 137 | -------------------------------------------------------------------------------- /src/fees/drivers/ETH_Driver.ts: -------------------------------------------------------------------------------- 1 | import { FEE_TYPES } from '../IFee'; 2 | import { WEB3_Driver } from './WEB3_Driver'; 3 | import axios from 'axios'; 4 | 5 | export class ETH_Driver extends WEB3_Driver { 6 | nativeAssetSymbol: string = 'ETH'; 7 | getGasFeePrices = async () => { 8 | const config: object = { 9 | method: 'get', 10 | url: this.getFeeEndpoint(), 11 | }; 12 | const response = await axios(config); 13 | const data = response.data; 14 | 15 | let prices: any = {}; 16 | prices[FEE_TYPES.REGULAR] = data.standard; 17 | prices[FEE_TYPES.PRIORITY] = data.fast; 18 | return prices; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/fees/drivers/POLYGON_Driver.ts: -------------------------------------------------------------------------------- 1 | import { FEE_TYPES } from '../IFee'; 2 | import { WEB3_Driver } from './WEB3_Driver'; 3 | import { PolygonFee } from '../types/PolygonFee'; 4 | import axios from 'axios'; 5 | 6 | export class POLYGON_Driver extends WEB3_Driver { 7 | nativeAssetSymbol: string = 'MATIC'; 8 | 9 | getGasFeePrices = async () => { 10 | const config: object = { 11 | method: 'get', 12 | url: this.getFeeEndpoint(), 13 | }; 14 | const response = await axios(config); 15 | const data = response.data; 16 | 17 | let prices: any = {}; 18 | prices[FEE_TYPES.REGULAR] = data.standard; 19 | prices[FEE_TYPES.PRIORITY] = data.fast; 20 | return prices; 21 | }; 22 | 23 | buildFee = (proposal: any) => { 24 | return new PolygonFee(proposal); 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /src/fees/drivers/WEB3_Driver.ts: -------------------------------------------------------------------------------- 1 | import { IFeeMap, FEE_TYPES } from '../IFee'; 2 | import { GenericDriver } from '../GenericDriver'; 3 | import { EthereumFee } from '../types/EthereumFee'; 4 | import { TransactionConfig } from 'web3-core'; 5 | import Web3 from 'web3'; 6 | import BigNumber from 'bignumber.js'; 7 | import { TRANSFER_METHOD_ABI } from '../../constants'; 8 | 9 | export class WEB3_Driver extends GenericDriver { 10 | nativeAssetSymbol: string = 'ETH'; 11 | 12 | getGasFeePrices = async () => { 13 | let prices: any = {}; 14 | prices[FEE_TYPES.REGULAR] = 0; 15 | prices[FEE_TYPES.PRIORITY] = 0; 16 | return prices; 17 | }; 18 | 19 | buildFee = (proposal: any) => { 20 | return new EthereumFee(proposal); 21 | }; 22 | 23 | getTxSendProposals = async (destination: string, valueToSend: number) => { 24 | const currency = this.assetConfig.symbol!; 25 | const privateKey = this.assetConfig.privKey!; 26 | 27 | let prices = await this.getGasFeePrices(); 28 | 29 | let fees: IFeeMap = {}; 30 | 31 | let body = { 32 | to: destination, 33 | amount: valueToSend, 34 | currency: currency, 35 | fee: { 36 | gasLimit: currency === this.nativeAssetSymbol ? 40000 : null, 37 | gasPrice: prices[FEE_TYPES.REGULAR].toString(), 38 | }, 39 | fromPrivateKey: privateKey, 40 | }; 41 | let proposal = await this.buildProposal(body); 42 | 43 | fees[FEE_TYPES.REGULAR] = this.buildFee(proposal); 44 | 45 | body = { 46 | to: destination, 47 | amount: valueToSend, 48 | currency: currency, 49 | fee: { 50 | gasLimit: currency === this.nativeAssetSymbol ? 40000 : null, 51 | gasPrice: prices[FEE_TYPES.PRIORITY].toString(), 52 | }, 53 | fromPrivateKey: privateKey, 54 | }; 55 | 56 | proposal = await this.buildProposal(body); 57 | 58 | fees[FEE_TYPES.PRIORITY] = this.buildFee(proposal); 59 | 60 | return fees; 61 | }; 62 | 63 | buildProposal = async (body: any) => { 64 | const provider = new Web3.providers.HttpProvider( 65 | this.getProposalEndpoint() 66 | ); 67 | 68 | const { 69 | fromPrivateKey, 70 | to, 71 | amount, 72 | currency, 73 | fee, 74 | data, 75 | nonce, 76 | signatureId, 77 | } = body; 78 | 79 | const client = new Web3(provider); 80 | client.eth.accounts.wallet.add(fromPrivateKey); 81 | client.eth.defaultAccount = client.eth.accounts.wallet[0].address; 82 | 83 | let tx: TransactionConfig; 84 | if (currency === this.nativeAssetSymbol) { 85 | tx = { 86 | from: 0, 87 | to: to.trim(), 88 | value: client.utils.toWei(`${amount}`, 'ether'), 89 | data: data 90 | ? client.utils.isHex(data) 91 | ? client.utils.stringToHex(data) 92 | : client.utils.toHex(data) 93 | : undefined, 94 | nonce, 95 | }; 96 | } else { 97 | const contract = new client.eth.Contract( 98 | // @ts-ignore 99 | [TRANSFER_METHOD_ABI], 100 | this.assetConfig.contract 101 | ); 102 | const digits = new BigNumber(10).pow(this.assetConfig.decimals!); 103 | tx = { 104 | from: 0, 105 | to: this.assetConfig.contract!, 106 | data: contract.methods 107 | .transfer( 108 | to.trim(), 109 | `0x${new BigNumber(amount).multipliedBy(digits).toString(16)}` 110 | ) 111 | .encodeABI(), 112 | nonce, 113 | }; 114 | } 115 | 116 | const gasPrice = client.utils.toWei(fee.gasPrice, 'gwei'); 117 | tx = { 118 | ...tx, 119 | gasPrice, 120 | }; 121 | 122 | if (!signatureId) { 123 | tx.gas = fee?.gasLimit ?? (await client.eth.estimateGas(tx)); 124 | } 125 | 126 | return { 127 | signatureId: signatureId, 128 | fromPrivateKey: fromPrivateKey, 129 | fee: { 130 | gasLimit: tx.gas, 131 | gasPrice: fee.gasPrice, 132 | }, 133 | proposal: signatureId ? JSON.stringify(tx) : tx, 134 | }; 135 | }; 136 | 137 | getProposalEndpoint() { 138 | const endpoint = this.config.proposal_endpoint; 139 | if (endpoint) { 140 | return endpoint; 141 | } 142 | throw new Error(this.currency + ' Balance currency is required in config'); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/fees/index.ts: -------------------------------------------------------------------------------- 1 | export { ETH_Driver } from './drivers/ETH_Driver'; 2 | export { BTC_Driver } from './drivers/BTC_Driver'; 3 | export { BSC_Driver } from './drivers/BSC_Driver'; 4 | export { POLYGON_Driver } from './drivers/POLYGON_Driver'; 5 | 6 | // 7 | export { BitcoinFee } from './types/BitcoinFee'; 8 | export { EthereumFee } from './types/EthereumFee'; 9 | export { BnbFee } from './types/BnbFee'; 10 | export { PolygonFee } from './types/PolygonFee'; 11 | -------------------------------------------------------------------------------- /src/fees/types/BitcoinFee.ts: -------------------------------------------------------------------------------- 1 | import { GenericTxProposal } from '../GenericTxProposal'; 2 | import { Currency } from '../../currencies'; 3 | import { SATOSHI } from '../../constants'; 4 | import BigNumber from 'bignumber.js'; 5 | 6 | export class BitcoinFee extends GenericTxProposal { 7 | currency = Currency.BTC; 8 | settings: { 9 | value: number; 10 | proposal: any; 11 | } = { 12 | value: 0, 13 | proposal: null, 14 | }; 15 | constructor(value: number, settings: any) { 16 | super(); 17 | this.settings = { 18 | value: value, 19 | proposal: settings, 20 | }; 21 | } 22 | getFeeValue() { 23 | return new BigNumber(this.settings.value) 24 | .dividedBy(new BigNumber(SATOSHI)) 25 | .toNumber(); 26 | } 27 | getData() { 28 | return this.settings.proposal; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/fees/types/BnbFee.ts: -------------------------------------------------------------------------------- 1 | import { Currency } from '../../currencies'; 2 | import { EthereumFee } from './EthereumFee'; 3 | 4 | export class BnbFee extends EthereumFee { 5 | currency = Currency.BNB; 6 | } 7 | -------------------------------------------------------------------------------- /src/fees/types/EthereumFee.ts: -------------------------------------------------------------------------------- 1 | import { GenericTxProposal } from '../GenericTxProposal'; 2 | import { Currency } from '../../currencies'; 3 | import BigNumber from 'bignumber.js'; 4 | import Web3 from 'web3'; 5 | import { weiToETH } from '../../currencyFunctions'; 6 | 7 | export class EthereumFee extends GenericTxProposal { 8 | currency = Currency.ETH; 9 | settings: { 10 | signatureId: string | undefined; 11 | fromPrivateKey: string; 12 | fee: { 13 | gasLimit: number; 14 | gasPrice: number; 15 | }; 16 | proposal: any; 17 | } = { 18 | signatureId: undefined, 19 | fromPrivateKey: '', 20 | fee: { 21 | gasLimit: 0, 22 | gasPrice: 0, 23 | }, 24 | proposal: '', 25 | }; 26 | constructor(settings: any) { 27 | super(); 28 | this.settings = settings; 29 | } 30 | getFeeValue() { 31 | const gasToWei = Web3.utils.toWei( 32 | this.settings.fee.gasPrice.toString(), 33 | 'Gwei' 34 | ); 35 | const feeValue = new BigNumber(this.settings.fee.gasLimit) 36 | .multipliedBy(gasToWei) 37 | .toString(); 38 | return Number(weiToETH(feeValue)); 39 | // 40 | } 41 | getData() { 42 | return this.settings; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/fees/types/PolygonFee.ts: -------------------------------------------------------------------------------- 1 | import { Currency } from '../../currencies'; 2 | import { EthereumFee } from './EthereumFee'; 3 | 4 | export class PolygonFee extends EthereumFee { 5 | currency = Currency.MATIC; 6 | } 7 | -------------------------------------------------------------------------------- /src/generators/GenericGenerator.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * 4 | * @export 5 | * @class GenericGenerator 6 | */ 7 | export class GenericGenerator { 8 | /** 9 | * Generate the wallet's XPUB 10 | * 11 | * @static 12 | * @param {string} mnemonic 13 | * @param {*} config 14 | * @memberof GenericGenerator 15 | * @returns {string} The XPUB value 16 | */ 17 | static generateWalletXpub(_mnemonic: any, _config: any) {} 18 | /** 19 | * Generate the wallet's Private Key 20 | * 21 | * @static 22 | * @param {string} mnemonic 23 | * @param {integer} derivation 24 | * @param {*} config 25 | * @memberof GenericGenerator 26 | * @returns {string} The Private Key 27 | */ 28 | static generatePrivateKeyFromMnemonic( 29 | _mnemonic: any, 30 | _derivation: any, 31 | _config: any 32 | ) {} 33 | /** 34 | * Generate teh wallet's Public Address 35 | * 36 | * @static 37 | * @param {string} xpub 38 | * @param {integer} derivation 39 | * @param {*} config 40 | * @memberof GenericGenerator 41 | * @returns {string} The Public Key 42 | */ 43 | static generateAddressFromXPub(_xpub: any, _derivation: any, _config: any) {} 44 | } 45 | -------------------------------------------------------------------------------- /src/generators/drivers/bitcoin.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import hdkey from 'hdkey'; 3 | import { fromBase58, fromSeed } from 'bip32'; 4 | import { networks, payments } from 'bitcoinjs-lib'; 5 | import { mnemonicToSeed } from 'bip39'; 6 | 7 | import { BTC_DERIVATION_PATH, TESTNET_DERIVATION_PATH } from '../../constants'; 8 | import { CONFIG } from '../../utils/config'; 9 | import { GenericGenerator } from '../GenericGenerator'; 10 | 11 | /** 12 | * 13 | * 14 | * @export 15 | * @class BitcoinGenerator 16 | * @extends {GenericGenerator} 17 | */ 18 | export class BitcoinGenerator extends GenericGenerator { 19 | static async generateWalletXpub(mnemonic: any, config: any = CONFIG) { 20 | const hdwallet = hdkey.fromMasterSeed( 21 | await mnemonicToSeed(mnemonic), 22 | config.TESTNET ? networks.testnet.bip32 : networks.bitcoin.bip32 23 | ); 24 | return hdwallet 25 | .derive(config.TESTNET ? TESTNET_DERIVATION_PATH : BTC_DERIVATION_PATH) 26 | .toJSON().xpub; 27 | } 28 | static async generatePrivateKeyFromMnemonic( 29 | mnemonic: any, 30 | derivation: any, 31 | config: any = CONFIG 32 | ) { 33 | const network = config.TESTNET ? networks.testnet : networks.bitcoin; 34 | return fromSeed(await mnemonicToSeed(mnemonic), network) 35 | .derivePath( 36 | config.TESTNET ? TESTNET_DERIVATION_PATH : BTC_DERIVATION_PATH 37 | ) 38 | .derive(derivation) 39 | .toWIF(); 40 | } 41 | static async generateAddressFromXPub( 42 | xpub: any, 43 | derivation: any, 44 | config: any = CONFIG 45 | ) { 46 | const network = config.TESTNET ? networks.testnet : networks.bitcoin; 47 | const w = fromBase58(xpub, network).derivePath(String(derivation)); 48 | // p2wpkh | p2pkh 49 | const address = payments.p2wpkh({ pubkey: w.publicKey, network }) 50 | .address as string; 51 | return address; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/generators/drivers/bsc.ts: -------------------------------------------------------------------------------- 1 | import { EthereumGenerator } from './ethereum'; 2 | /** 3 | * 4 | * 5 | * @export 6 | * @class BscGenerator 7 | * @extends {EthereumGenerator} 8 | */ 9 | export class BscGenerator extends EthereumGenerator {} 10 | -------------------------------------------------------------------------------- /src/generators/drivers/ethereum.ts: -------------------------------------------------------------------------------- 1 | import { hdkey as ethHdKey } from 'ethereumjs-wallet'; 2 | import { mnemonicToSeed } from 'bip39'; 3 | 4 | import { ETH_DERIVATION_PATH, TESTNET_DERIVATION_PATH } from '../../constants'; 5 | import { CONFIG } from '../../utils/config'; 6 | import { GenericGenerator } from '../GenericGenerator'; 7 | /** 8 | * 9 | * 10 | * @export 11 | * @class EthereumGenerator 12 | * @extends {GenericGenerator} 13 | */ 14 | export class EthereumGenerator extends GenericGenerator { 15 | static async generateWalletXpub(mnemonic: any, config: any = CONFIG) { 16 | const path = config.TESTNET ? TESTNET_DERIVATION_PATH : ETH_DERIVATION_PATH; 17 | const hdwallet = ethHdKey.fromMasterSeed(await mnemonicToSeed(mnemonic)); 18 | const derivePath = hdwallet.derivePath(path); 19 | return derivePath.publicExtendedKey().toString(); 20 | } 21 | static async generatePrivateKeyFromMnemonic( 22 | mnemonic: any, 23 | derivation: any, 24 | config: any = CONFIG 25 | ) { 26 | const path = config.TESTNET ? TESTNET_DERIVATION_PATH : ETH_DERIVATION_PATH; 27 | const hdwallet = ethHdKey.fromMasterSeed(await mnemonicToSeed(mnemonic)); 28 | const derivePath = hdwallet.derivePath(path).deriveChild(derivation); 29 | return derivePath.getWallet().getPrivateKeyString(); 30 | } 31 | static async generateAddressFromXPub( 32 | xpub: any, 33 | derivation: any, 34 | _config: any 35 | ) { 36 | const w = ethHdKey.fromExtendedKey(xpub); 37 | const wallet = w.deriveChild(derivation).getWallet(); 38 | return ( 39 | '0x' + 40 | wallet 41 | .getAddress() 42 | .toString('hex') 43 | .toLowerCase() 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/generators/drivers/polygon.ts: -------------------------------------------------------------------------------- 1 | import { EthereumGenerator } from './ethereum'; 2 | /** 3 | * 4 | * 5 | * @export 6 | * @class PolygonGenerator 7 | * @extends {EthereumGenerator} 8 | */ 9 | export class PolygonGenerator extends EthereumGenerator {} 10 | -------------------------------------------------------------------------------- /src/generators/index.ts: -------------------------------------------------------------------------------- 1 | export { BitcoinGenerator } from './drivers/bitcoin'; 2 | export { BscGenerator } from './drivers/bsc'; 3 | export { EthereumGenerator } from './drivers/ethereum'; 4 | export { PolygonGenerator } from './drivers/polygon'; 5 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as Generators from './generators'; 2 | 3 | import * as Balances from './balances'; 4 | 5 | import * as Fees from './fees'; 6 | 7 | import * as Transactions from './transactions'; 8 | 9 | import * as CurrencyFunctionsfrom from './currencyFunctions'; 10 | 11 | require('dotenv').config(); 12 | export { Currency } from './currencies'; 13 | export { Chains } from './chains'; 14 | export { WalletFactory } from './walletFactory'; 15 | export { IWalletConfig } from './wallets/IWalletConfig'; 16 | export { WalletGenerator } from './walletGenerator'; 17 | export { IConfig, CONFIG } from './utils/config'; 18 | export { Generators }; 19 | export { Balances }; 20 | export { Fees }; 21 | export { Transactions }; 22 | export { CurrencyFunctionsfrom }; 23 | 24 | export { getAllCoins, getCoins } from './market/getCoins'; 25 | -------------------------------------------------------------------------------- /src/market/getCoins.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { CONFIG } from '../utils/config'; 3 | 4 | export const getAllCoins = async ( 5 | limit: number = 10, 6 | sparkline: boolean = false 7 | ) => { 8 | const url = 9 | CONFIG.SERVICES_ENDPOINTS.CoinGecko + 10 | 'coins/markets?vs_currency=usd&order=market_cap_desc&per_page=' + 11 | limit + 12 | '&page=1&sparkline=' + 13 | sparkline; 14 | 15 | const params: object = { 16 | method: 'get', 17 | url: url, 18 | }; 19 | try { 20 | const response = await axios(params); 21 | return response.data; 22 | } catch (error) { 23 | return false; 24 | } 25 | }; 26 | 27 | export const getCoins = async (list: string[]) => { 28 | const url = 29 | CONFIG.SERVICES_ENDPOINTS.CoinGecko + 30 | 'simple/price?ids=' + 31 | list.join(',') + 32 | '&vs_currencies=usd'; 33 | 34 | const params: object = { 35 | method: 'get', 36 | url: url, 37 | }; 38 | const response = await axios(params); 39 | return response.data; 40 | }; 41 | -------------------------------------------------------------------------------- /src/transactions/GenericTransactionDriver.ts: -------------------------------------------------------------------------------- 1 | import { IWalletConfig } from '..'; 2 | import { GenericTxProposal } from '../fees/GenericTxProposal'; 3 | 4 | export class GenericTransactionDriver { 5 | currency: string; 6 | assetConfig: IWalletConfig; 7 | config: any; 8 | constructor(assetConfig: any, config?: any) { 9 | this.config = config; 10 | this.assetConfig = assetConfig; 11 | this.currency = assetConfig.symbol; 12 | } 13 | send = async (_transaction: GenericTxProposal): Promise => { 14 | return null; 15 | }; 16 | sendRaw = async (_transaction: any): Promise => { 17 | return null; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /src/transactions/drivers/BSC_Driver.ts: -------------------------------------------------------------------------------- 1 | import { WEB3_Driver } from './WEB3_Driver'; 2 | 3 | export class BSC_Driver extends WEB3_Driver {} 4 | -------------------------------------------------------------------------------- /src/transactions/drivers/BTC_Driver.ts: -------------------------------------------------------------------------------- 1 | import { GenericTransactionDriver } from '../GenericTransactionDriver'; 2 | import { GenericTxProposal } from '../../fees/GenericTxProposal'; 3 | import axios from 'axios'; 4 | import { GENERIC_REQUEST_THROTTLE_DELAY, UA } from '../../constants'; 5 | import { ECPair, networks, Psbt } from 'bitcoinjs-lib'; 6 | import { CONFIG } from '../../utils/config'; 7 | 8 | export class BTC_Driver extends GenericTransactionDriver { 9 | send = async (transaction: GenericTxProposal) => { 10 | let txData = await this.prepareSignedTransaction(transaction.getData()); 11 | return await this.sendRaw(txData); 12 | }; 13 | 14 | prepareSignedTransaction = async (body: any) => { 15 | const { fromUTXO, to } = body; 16 | const net = CONFIG.TESTNET ? networks.testnet : networks.bitcoin; 17 | const psbt = new Psbt({ network: net }); 18 | const privateKeysToSign = []; 19 | for (const item of fromUTXO) { 20 | const t = await this.getTxs(item.txHash); 21 | // const txHex = t.hex; 22 | psbt.addInput({ 23 | // @ts-ignore 24 | hash: item.txHash, 25 | index: item.index, 26 | // nonWitnessUtxo: Buffer.from(txHex, 'hex'), 27 | witnessUtxo: { 28 | script: Buffer.from(t.vout?.[item.index].hex, 'hex'), 29 | value: item.value, 30 | }, 31 | }); 32 | privateKeysToSign.push(item.signatureId || item.privateKey); 33 | } 34 | for (const item of to) { 35 | psbt.addOutput({ 36 | address: item.address, 37 | value: item.value, 38 | }); 39 | } 40 | 41 | if (fromUTXO && fromUTXO[0].signatureId) { 42 | return JSON.stringify({ 43 | txData: JSON.stringify(psbt), 44 | privateKeysToSign, 45 | }); 46 | } 47 | for (let index = 0; index < privateKeysToSign.length; index++) { 48 | const item = privateKeysToSign[index]; 49 | const kp = ECPair.fromWIF(item, net); 50 | psbt.signInput(index, kp); 51 | } 52 | let x = psbt.finalizeAllInputs().extractTransaction(); 53 | return x.toHex(); 54 | }; 55 | 56 | getTxs = async (tx: string) => { 57 | let endpoints = this.getTransactionInfoEndpoint(); 58 | for (let i = 0; i < endpoints.length; i++) { 59 | let endpoint = endpoints[i]; 60 | const url = endpoint + tx; 61 | const params: object = { 62 | method: 'get', 63 | url: url, 64 | headers: { 65 | 'User-Agent': UA, 66 | }, 67 | }; 68 | try { 69 | const response = await axios(params); 70 | return response.data; 71 | } catch (error) { 72 | if (process.env.NODE_ENV !== 'production') { 73 | console.log(error); 74 | } 75 | } 76 | await new Promise(resolve => 77 | setTimeout(resolve, GENERIC_REQUEST_THROTTLE_DELAY) 78 | ); 79 | } 80 | return false; 81 | }; 82 | 83 | sendRaw = async (transaction: any): Promise => { 84 | let endpoints = this.getTransactionSendEndpoint(); 85 | for (let i = 0; i < endpoints.length; i++) { 86 | let endpoint = endpoints[i]; 87 | const url = endpoint + transaction; 88 | const params: object = { 89 | method: 'get', 90 | url: url, 91 | headers: { 92 | 'User-Agent': UA, 93 | }, 94 | }; 95 | try { 96 | const response = await axios(params); 97 | return response.data.result; 98 | } catch (error) { 99 | if (process.env.NODE_ENV !== 'production') { 100 | console.log('response.data', error); 101 | } 102 | } 103 | await new Promise(resolve => 104 | setTimeout(resolve, GENERIC_REQUEST_THROTTLE_DELAY) 105 | ); 106 | } 107 | return false; 108 | }; 109 | 110 | getTransactionSendEndpoint() { 111 | let endpoints = []; 112 | if (this.config.send_endpoint) { 113 | if (!Array.isArray(this.config.send_endpoint)) { 114 | endpoints = [this.config.send_endpoint]; 115 | } else { 116 | endpoints = this.config.send_endpoint; 117 | } 118 | return endpoints; 119 | } 120 | throw new Error( 121 | this.currency + ' Transaction endpoint is required in config' 122 | ); 123 | } 124 | getTransactionInfoEndpoint() { 125 | let endpoints = []; 126 | if (this.config.send_endpoint) { 127 | if (!Array.isArray(this.config.get_endpoint)) { 128 | endpoints = [this.config.get_endpoint]; 129 | } else { 130 | endpoints = this.config.get_endpoint; 131 | } 132 | return endpoints; 133 | } 134 | throw new Error( 135 | this.currency + ' Transaction endpoint is required in config' 136 | ); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/transactions/drivers/ETH_Driver.ts: -------------------------------------------------------------------------------- 1 | import { WEB3_Driver } from './WEB3_Driver'; 2 | 3 | export class ETH_Driver extends WEB3_Driver {} 4 | -------------------------------------------------------------------------------- /src/transactions/drivers/POLYGON_Driver.ts: -------------------------------------------------------------------------------- 1 | import { WEB3_Driver } from './WEB3_Driver'; 2 | 3 | export class POLYGON_Driver extends WEB3_Driver {} 4 | -------------------------------------------------------------------------------- /src/transactions/drivers/WEB3_Driver.ts: -------------------------------------------------------------------------------- 1 | import Web3 from 'web3'; 2 | import { GenericTxProposal } from '../../fees/GenericTxProposal'; 3 | import { GenericTransactionDriver } from '../GenericTransactionDriver'; 4 | 5 | export class WEB3_Driver extends GenericTransactionDriver { 6 | send = async (transaction: GenericTxProposal): Promise => { 7 | const data: any = transaction.getData(); 8 | let txRaw = await this.prepareSignedTransaction(data); 9 | return this.sendRaw(txRaw); 10 | }; 11 | 12 | sendRaw = async (transaction: any): Promise => { 13 | const provider = new Web3.providers.HttpProvider(this.getEndpoint()); 14 | const client = new Web3(provider); 15 | 16 | let p = new Promise((resolve, reject) => { 17 | client.eth 18 | .sendSignedTransaction(transaction) 19 | .on('transactionHash', function(hash) { 20 | resolve(hash); 21 | }) 22 | .on('receipt', function(_receipt) { 23 | // resolve(receipt.transactionHash); 24 | }) 25 | // Fired for every confirmation up to the 12th confirmation. 26 | // .on('confirmation', function(_confirmationNumber, _receipt){ 27 | // console.log('_confirmationNumber', _confirmationNumber) 28 | // resolve(_receipt); 29 | // }) 30 | .on('error', function(error) { 31 | reject(error); 32 | }); 33 | }); 34 | return p; 35 | }; 36 | 37 | prepareSignedTransaction = async (data: any) => { 38 | const provider = new Web3.providers.HttpProvider(this.getEndpoint()); 39 | const fromPrivateKey = data.fromPrivateKey; 40 | const client = new Web3(provider); 41 | client.eth.accounts.wallet.add(fromPrivateKey); 42 | client.eth.defaultAccount = client.eth.accounts.wallet[0].address; 43 | 44 | let txRaw; 45 | 46 | if (data.signatureId) { 47 | txRaw = data.proposal; 48 | } else { 49 | txRaw = ( 50 | await client.eth.accounts.signTransaction( 51 | data.proposal, 52 | fromPrivateKey as string 53 | ) 54 | ).rawTransaction as string; 55 | } 56 | 57 | return txRaw; 58 | }; 59 | 60 | getEndpoint() { 61 | const endpoint = this.config.endpoint; 62 | if (endpoint) { 63 | return endpoint; 64 | } 65 | throw new Error( 66 | this.currency + ' Transaction endpoint is required in config' 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/transactions/index.ts: -------------------------------------------------------------------------------- 1 | export { BTC_Driver } from './drivers/BTC_Driver'; 2 | export { ETH_Driver } from './drivers/ETH_Driver'; 3 | export { BSC_Driver } from './drivers/BSC_Driver'; 4 | export { POLYGON_Driver } from './drivers/POLYGON_Driver'; 5 | -------------------------------------------------------------------------------- /src/utils/coins.ts: -------------------------------------------------------------------------------- 1 | export const COINS = require('./registry.json'); 2 | -------------------------------------------------------------------------------- /src/utils/config.mainnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "TESTNET": false, 3 | "DEFAULT_DERIVATION_KEY": 0, 4 | "CHAIN_ENDPOINTS": { 5 | "BSC": { 6 | "balance": [ 7 | { 8 | "driver": "BSC_Driver", 9 | "config": { 10 | "endpoint": "https://bsc-dataseed.binance.org/" 11 | } 12 | } 13 | ], 14 | "fee": [ 15 | { 16 | "driver": "BSC_Driver", 17 | "config": { 18 | "endpoint": "https://api.coingrig.com/gas/bsc/", 19 | "proposal_endpoint": "https://bsc-dataseed.binance.org/" 20 | } 21 | } 22 | ], 23 | "transaction": [ 24 | { 25 | "driver": "BSC_Driver", 26 | "config": { 27 | "endpoint": "https://bsc-dataseed.binance.org/" 28 | } 29 | } 30 | ] 31 | }, 32 | "BTC": { 33 | "balance": [ 34 | { 35 | "driver": "BTC_Driver", 36 | "config": { 37 | "endpoint": [ 38 | "https://btc1.trezor.io/api/v2/address/", 39 | "https://btc2.trezor.io/api/v2/address/", 40 | "https://btc3.trezor.io/api/v2/address/", 41 | "https://btc4.trezor.io/api/v2/address/", 42 | "https://btc5.trezor.io/api/v2/address/", 43 | "https://api.coingrig.com/btc/address/" 44 | ] 45 | } 46 | } 47 | ], 48 | "fee": [ 49 | { 50 | "driver": "BTC_Driver", 51 | "config": { 52 | "endpoint": "https://api.blockchain.info/mempool/fees", 53 | "utxo_endpoint": [ 54 | "https://btc1.trezor.io/api/v2/utxo/", 55 | "https://btc2.trezor.io/api/v2/utxo/", 56 | "https://btc3.trezor.io/api/v2/utxo/", 57 | "https://btc4.trezor.io/api/v2/utxo/", 58 | "https://btc5.trezor.io/api/v2/utxo/", 59 | "https://api.coingrig.com/btc/utxo/" 60 | ] 61 | } 62 | } 63 | ], 64 | "transaction": [ 65 | { 66 | "driver": "BTC_Driver", 67 | "config": { 68 | "get_endpoint": [ 69 | "https://btc1.trezor.io/api/v2/tx/", 70 | "https://btc2.trezor.io/api/v2/tx/", 71 | "https://btc3.trezor.io/api/v2/tx/", 72 | "https://btc4.trezor.io/api/v2/tx/", 73 | "https://btc5.trezor.io/api/v2/tx/", 74 | "https://api.coingrig.com/btc/tx/" 75 | ], 76 | "send_endpoint": [ 77 | "https://btc1.trezor.io/api/v2/sendtx/", 78 | "https://btc2.trezor.io/api/v2/sendtx/", 79 | "https://btc3.trezor.io/api/v2/sendtx/", 80 | "https://btc4.trezor.io/api/v2/sendtx/", 81 | "https://btc5.trezor.io/api/v2/sendtx/", 82 | "https://api.coingrig.com/btc/sendtx/" 83 | ], 84 | "TESTNET": false 85 | } 86 | } 87 | ] 88 | }, 89 | "ETH": { 90 | "balance": [ 91 | { 92 | "driver": "ETH_Driver", 93 | "config": { 94 | "endpoint": "https://eth1.trezor.io/api/v2/address/", 95 | "token_endpoint": "https://api.coingrig.com/web3/eth/" 96 | } 97 | } 98 | ], 99 | "fee": [ 100 | { 101 | "driver": "ETH_Driver", 102 | "config": { 103 | "endpoint": "https://api.coingrig.com/gas/eth/", 104 | "proposal_endpoint": "https://api.coingrig.com/web3/eth/" 105 | } 106 | } 107 | ], 108 | "transaction": [ 109 | { 110 | "driver": "ETH_Driver", 111 | "config": { 112 | "endpoint": "https://api.coingrig.com/web3/eth/" 113 | } 114 | } 115 | ] 116 | }, 117 | "POLYGON": { 118 | "balance": [ 119 | { 120 | "driver": "POLYGON_Driver", 121 | "config": { 122 | "endpoint": "https://polygon-rpc.com/" 123 | } 124 | } 125 | ], 126 | "fee": [ 127 | { 128 | "driver": "POLYGON_Driver", 129 | "config": { 130 | "endpoint": "https://api.coingrig.com/gas/polygon/", 131 | "proposal_endpoint": "https://polygon-rpc.com/" 132 | } 133 | } 134 | ], 135 | "transaction": [ 136 | { 137 | "driver": "POLYGON_Driver", 138 | "config": { 139 | "endpoint": "https://polygon-rpc.com/" 140 | } 141 | } 142 | ] 143 | } 144 | }, 145 | "SERVICES_ENDPOINTS": { 146 | "CoinGecko": "https://api.coingecko.com/api/v3/" 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/utils/config.testnet.json: -------------------------------------------------------------------------------- 1 | { 2 | "TESTNET": true, 3 | "DEFAULT_DERIVATION_KEY": 0, 4 | "CHAIN_ENDPOINTS": { 5 | "BSC": { 6 | "balance": [ 7 | { 8 | "driver": "BSC_Driver", 9 | "config": { 10 | "endpoint": "https://data-seed-prebsc-1-s1.binance.org:8545/" 11 | } 12 | } 13 | ], 14 | "fee": [ 15 | { 16 | "driver": "BSC_Driver", 17 | "config": { 18 | "endpoint": "https://api.coingrig.com/gas/bsc/", 19 | "proposal_endpoint": "https://data-seed-prebsc-1-s1.binance.org:8545/" 20 | } 21 | } 22 | ], 23 | "transaction": [ 24 | { 25 | "driver": "BSC_Driver", 26 | "config": { 27 | "endpoint": "https://data-seed-prebsc-1-s1.binance.org:8545/" 28 | } 29 | } 30 | ] 31 | }, 32 | "BTC": { 33 | "balance": [ 34 | { 35 | "driver": "BTC_Driver", 36 | "config": { 37 | "endpoint": [ 38 | "https://tbtc1.trezorzz.io/api/v2/address/", 39 | "https://tbtc2.trezor.io/api/v2/address/", 40 | "https://api.coingrig.com/tbtc/address/" 41 | ] 42 | } 43 | } 44 | ], 45 | "fee": [ 46 | { 47 | "driver": "BTC_Driver", 48 | "config": { 49 | "endpoint": "https://api.blockchain.info/mempool/fees", 50 | "utxo_endpoint": [ 51 | "https://tbtc1.trezorzz.io/api/v2/utxo/", 52 | "https://tbtc2.trezor.io/api/v2/utxo/", 53 | "https://api.coingrig.com/tbtc/utxo/" 54 | ] 55 | } 56 | } 57 | ], 58 | "transaction": [ 59 | { 60 | "driver": "BTC_Driver", 61 | "config": { 62 | "get_endpoint": [ 63 | "https://tbtc1.trezorzz.io/api/v2/tx/", 64 | "https://tbtc2.trezor.io/api/v2/tx/", 65 | "https://api.coingrig.com/tbtc/tx/" 66 | ], 67 | "send_endpoint": [ 68 | "https://tbtc1.trezorzz.io/api/v2/sendtx/", 69 | "https://tbtc2.trezor.io/api/v2/sendtx/", 70 | "https://api.coingrig.com/tbtc/sendtx/" 71 | ], 72 | "TESTNET": true 73 | } 74 | } 75 | ] 76 | }, 77 | "ETH": { 78 | "balance": [ 79 | { 80 | "driver": "ETH_Driver", 81 | "config": { 82 | "endpoint": "https://api.coingrig.com/teth/address/", 83 | "token_endpoint": "https://api.coingrig.com/web3test/eth/" 84 | } 85 | } 86 | ], 87 | "fee": [ 88 | { 89 | "driver": "ETH_Driver", 90 | "config": { 91 | "endpoint": "https://api.coingrig.com/gas/eth/", 92 | "proposal_endpoint": "https://api.coingrig.com/web3test/eth/" 93 | } 94 | } 95 | ], 96 | "transaction": [ 97 | { 98 | "driver": "ETH_Driver", 99 | "config": { 100 | "endpoint": "https://api.coingrig.com/web3test/eth/" 101 | } 102 | } 103 | ] 104 | }, 105 | "POLYGON": { 106 | "balance": [ 107 | { 108 | "driver": "POLYGON_Driver", 109 | "config": { 110 | "endpoint": "https://rpc-mumbai.maticvigil.com/" 111 | } 112 | } 113 | ], 114 | "fee": [ 115 | { 116 | "driver": "POLYGON_Driver", 117 | "config": { 118 | "endpoint": "https://api.coingrig.com/gas/polygon/", 119 | "proposal_endpoint": "https://rpc-mumbai.maticvigil.com/" 120 | } 121 | } 122 | ], 123 | "transaction": [ 124 | { 125 | "driver": "POLYGON_Driver", 126 | "config": { 127 | "endpoint": "https://rpc-mumbai.maticvigil.com/" 128 | } 129 | } 130 | ] 131 | } 132 | }, 133 | "SERVICES_ENDPOINTS": { 134 | "CoinGecko": "https://api.coingecko.com/api/v3/" 135 | } 136 | } -------------------------------------------------------------------------------- /src/utils/config.ts: -------------------------------------------------------------------------------- 1 | import * as MAINNET_CONFIG_DATA from './config.mainnet.json'; 2 | import * as TESTNET_CONFIG_DATA from './config.testnet.json'; 3 | 4 | interface IGENERIC_ENDPOINTS_MAP { 5 | [key: string]: string[]; 6 | } 7 | 8 | export interface IGENERIC_ENDPOINTS { 9 | balance: any; 10 | fee: any; 11 | transaction: any; 12 | other?: IGENERIC_ENDPOINTS_MAP; 13 | } 14 | 15 | export interface CHAIN_ENDPOINTS_MAP { 16 | [key: string]: IGENERIC_ENDPOINTS; 17 | } 18 | 19 | export interface SERVICES_ENDPOINTS_MAP { 20 | [key: string]: string; 21 | } 22 | 23 | export interface IConfig { 24 | TESTNET: boolean; 25 | DEFAULT_DERIVATION_KEY: number; 26 | CHAIN_ENDPOINTS: CHAIN_ENDPOINTS_MAP; 27 | SERVICES_ENDPOINTS: SERVICES_ENDPOINTS_MAP; 28 | } 29 | 30 | const TESTNET = String(process.env.TESTNET) === 'true'; 31 | console.log( 32 | 'TESTNET: ', 33 | process.env.TESTNET, 34 | TESTNET, 35 | typeof process.env.TESTNET, 36 | typeof TESTNET 37 | ); 38 | 39 | const MAINNET_CONFIG: IConfig = MAINNET_CONFIG_DATA; 40 | const TESTNET_CONFIG: IConfig = TESTNET_CONFIG_DATA; 41 | 42 | export const CONFIG: IConfig = TESTNET ? TESTNET_CONFIG : MAINNET_CONFIG; 43 | -------------------------------------------------------------------------------- /src/utils/registry.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "bitcoin", 4 | "name": "Bitcoin", 5 | "coinId": 0, 6 | "symbol": "BTC", 7 | "decimals": 8, 8 | "blockchain": "Bitcoin", 9 | "derivationPath": "m/84'/0'/0'/0/0", 10 | "curve": "secp256k1", 11 | "publicKeyType": "secp256k1", 12 | "p2pkhPrefix": 0, 13 | "p2shPrefix": 5, 14 | "hrp": "bc", 15 | "publicKeyHasher": "sha256ripemd", 16 | "base58Hasher": "sha256d", 17 | "xpub": "zpub", 18 | "xprv": "zprv", 19 | "explorer": { 20 | "url": "https://blockchair.com", 21 | "txPath": "/bitcoin/transaction/", 22 | "accountPath": "/bitcoin/address/", 23 | "sampleTx": "0607f62530b68cfcc91c57a1702841dd399a899d0eecda8e31ecca3f52f01df2", 24 | "sampleAccount": "17A16QmavnUfCW11DAApiJxp7ARnxN5pGX" 25 | }, 26 | "info": { 27 | "url": "https://bitcoin.org", 28 | "source": "https://github.com/trezor/blockbook", 29 | "rpc": "", 30 | "documentation": "https://github.com/trezor/blockbook/blob/master/docs/api.md" 31 | } 32 | }, 33 | { 34 | "id": "litecoin", 35 | "name": "Litecoin", 36 | "coinId": 2, 37 | "symbol": "LTC", 38 | "decimals": 8, 39 | "blockchain": "Bitcoin", 40 | "derivationPath": "m/84'/2'/0'/0/0", 41 | "curve": "secp256k1", 42 | "publicKeyType": "secp256k1", 43 | "p2pkhPrefix": 48, 44 | "p2shPrefix": 50, 45 | "hrp": "ltc", 46 | "publicKeyHasher": "sha256ripemd", 47 | "base58Hasher": "sha256d", 48 | "xpub": "zpub", 49 | "xprv": "zprv", 50 | "explorer": { 51 | "url": "https://blockchair.com", 52 | "txPath": "/litecoin/transaction/", 53 | "accountPath": "/litecoin/address/" 54 | }, 55 | "info": { 56 | "url": "https://litecoin.org", 57 | "source": "https://github.com/trezor/blockbook", 58 | "rpc": "", 59 | "documentation": "https://github.com/trezor/blockbook/blob/master/docs/api.md" 60 | } 61 | }, 62 | { 63 | "id": "doge", 64 | "name": "Dogecoin", 65 | "coinId": 3, 66 | "symbol": "DOGE", 67 | "decimals": 8, 68 | "blockchain": "Bitcoin", 69 | "derivationPath": "m/44'/3'/0'/0/0", 70 | "curve": "secp256k1", 71 | "publicKeyType": "secp256k1", 72 | "p2pkhPrefix": 30, 73 | "p2shPrefix": 22, 74 | "publicKeyHasher": "sha256ripemd", 75 | "base58Hasher": "sha256d", 76 | "xpub": "dgub", 77 | "xprv": "dgpv", 78 | "explorer": { 79 | "url": "https://blockchair.com", 80 | "txPath": "/dogecoin/transaction/", 81 | "accountPath": "/dogecoin/address/" 82 | }, 83 | "info": { 84 | "url": "https://dogecoin.com", 85 | "source": "https://github.com/trezor/blockbook", 86 | "rpc": "", 87 | "documentation": "https://github.com/trezor/blockbook/blob/master/docs/api.md" 88 | } 89 | }, 90 | { 91 | "id": "dash", 92 | "name": "Dash", 93 | "coinId": 5, 94 | "symbol": "DASH", 95 | "decimals": 8, 96 | "blockchain": "Bitcoin", 97 | "derivationPath": "m/44'/5'/0'/0/0", 98 | "curve": "secp256k1", 99 | "publicKeyType": "secp256k1", 100 | "p2pkhPrefix": 76, 101 | "p2shPrefix": 16, 102 | "publicKeyHasher": "sha256ripemd", 103 | "base58Hasher": "sha256d", 104 | "xpub": "xpub", 105 | "xprv": "xprv", 106 | "explorer": { 107 | "url": "https://blockchair.com", 108 | "txPath": "/dash/transaction/", 109 | "accountPath": "/dash/address/" 110 | }, 111 | "info": { 112 | "url": "https://dash.org", 113 | "source": "https://github.com/trezor/blockbook", 114 | "rpc": "", 115 | "documentation": "https://github.com/trezor/blockbook/blob/master/docs/api.md" 116 | } 117 | }, 118 | { 119 | "id": "ethereum", 120 | "name": "Ethereum", 121 | "coinId": 60, 122 | "symbol": "ETH", 123 | "decimals": 18, 124 | "blockchain": "Ethereum", 125 | "derivationPath": "m/44'/60'/0'/0/0", 126 | "curve": "secp256k1", 127 | "publicKeyType": "secp256k1Extended", 128 | "explorer": { 129 | "url": "https://etherscan.io", 130 | "txPath": "/tx/", 131 | "accountPath": "/address/", 132 | "sampleTx": "0x9edaf0f7d9c6629c31bbf0471fc07d696c73b566b93783f7e25d8d5d2b62fa4f", 133 | "sampleAccount": "0x5bb497e8d9fe26e92dd1be01e32076c8e024d167" 134 | }, 135 | "info": { 136 | "url": "https://ethereum.org", 137 | "source": "https://github.com/ethereum/go-ethereum", 138 | "rpc": "https://mainnet.infura.io", 139 | "documentation": "https://eth.wiki/json-rpc/API" 140 | } 141 | }, 142 | { 143 | "id": "classic", 144 | "name": "Ethereum Classic", 145 | "coinId": 61, 146 | "symbol": "ETC", 147 | "decimals": 18, 148 | "blockchain": "Ethereum", 149 | "derivationPath": "m/44'/61'/0'/0/0", 150 | "curve": "secp256k1", 151 | "publicKeyType": "secp256k1Extended", 152 | "explorer": { 153 | "url": "https://blockscout.com/etc/mainnet", 154 | "txPath": "/tx/", 155 | "accountPath": "/address/" 156 | }, 157 | "info": { 158 | "url": "https://ethereumclassic.org", 159 | "source": "https://github.com/ethereumclassic/go-ethereum", 160 | "rpc": "https://www.ethercluster.com/etc", 161 | "documentation": "https://eth.wiki/json-rpc/API" 162 | } 163 | }, 164 | { 165 | "id": "ripple", 166 | "name": "XRP", 167 | "coinId": 144, 168 | "symbol": "XRP", 169 | "decimals": 6, 170 | "blockchain": "Ripple", 171 | "derivationPath": "m/44'/144'/0'/0/0", 172 | "curve": "secp256k1", 173 | "publicKeyType": "secp256k1", 174 | "explorer": { 175 | "url": "https://bithomp.com", 176 | "txPath": "/explorer/", 177 | "accountPath": "/explorer/", 178 | "sampleTx": "E26AB8F3372D2FC02DEC1FD5674ADAB762D684BFFDBBDF5D674E9D7CF4A47054", 179 | "sampleAccount": "rfkH7EuS1XcSkB9pocy1R6T8F4CsNYixYU" 180 | }, 181 | "info": { 182 | "url": "https://ripple.com/xrp", 183 | "source": "https://github.com/ripple/rippled", 184 | "rpc": "https://s2.ripple.com:51234", 185 | "documentation": "https://xrpl.org/rippled-api.html" 186 | } 187 | }, 188 | { 189 | "id": "bitcoincash", 190 | "name": "Bitcoin Cash", 191 | "coinId": 145, 192 | "symbol": "BCH", 193 | "decimals": 8, 194 | "blockchain": "Bitcoin", 195 | "derivationPath": "m/44'/145'/0'/0/0", 196 | "curve": "secp256k1", 197 | "publicKeyType": "secp256k1", 198 | "p2pkhPrefix": 0, 199 | "p2shPrefix": 5, 200 | "hrp": "bitcoincash", 201 | "publicKeyHasher": "sha256ripemd", 202 | "base58Hasher": "sha256d", 203 | "xpub": "xpub", 204 | "xprv": "xprv", 205 | "explorer": { 206 | "url": "https://blockchair.com", 207 | "txPath": "/bitcoin-cash/transaction/", 208 | "accountPath": "/bitcoin-cash/address/" 209 | }, 210 | "info": { 211 | "url": "https://bitcoincash.org", 212 | "source": "https://github.com/trezor/blockbook", 213 | "rpc": "", 214 | "documentation": "https://github.com/trezor/blockbook/blob/master/docs/api.md" 215 | } 216 | }, 217 | { 218 | "id": "stellar", 219 | "name": "Stellar", 220 | "coinId": 148, 221 | "symbol": "XLM", 222 | "decimals": 7, 223 | "blockchain": "Stellar", 224 | "derivationPath": "m/44'/148'/0'", 225 | "curve": "ed25519", 226 | "publicKeyType": "ed25519", 227 | "explorer": { 228 | "url": "https://blockchair.com/stellar", 229 | "txPath": "/transaction/", 230 | "accountPath": "/account/" 231 | }, 232 | "info": { 233 | "url": "https://stellar.org", 234 | "source": "https://github.com/stellar/go", 235 | "rpc": "https://horizon.stellar.org", 236 | "documentation": "https://www.stellar.org/developers/horizon/reference" 237 | } 238 | }, 239 | { 240 | "id": "eos", 241 | "name": "EOS", 242 | "coinId": 194, 243 | "symbol": "EOS", 244 | "decimals": 4, 245 | "blockchain": "EOS", 246 | "derivationPath": "m/44'/194'/0'/0/0", 247 | "curve": "secp256k1", 248 | "publicKeyType": "secp256k1", 249 | "explorer": { 250 | "url": "https://bloks.io", 251 | "txPath": "/transaction/", 252 | "accountPath": "/account/" 253 | }, 254 | "info": { 255 | "url": "http://eos.io", 256 | "source": "https://github.com/eosio/eos", 257 | "rpc": "", 258 | "documentation": "https://developers.eos.io/eosio-nodeos/reference" 259 | } 260 | }, 261 | { 262 | "id": "tron", 263 | "name": "Tron", 264 | "coinId": 195, 265 | "symbol": "TRX", 266 | "decimals": 6, 267 | "blockchain": "Tron", 268 | "derivationPath": "m/44'/195'/0'/0/0", 269 | "curve": "secp256k1", 270 | "publicKeyType": "secp256k1Extended", 271 | "explorer": { 272 | "url": "https://tronscan.org", 273 | "txPath": "/#/transaction/", 274 | "accountPath": "/#/address/" 275 | }, 276 | "info": { 277 | "url": "https://tron.network", 278 | "source": "https://github.com/tronprotocol/java-tron", 279 | "rpc": "https://api.trongrid.io", 280 | "documentation": "https://developers.tron.network/docs/tron-wallet-rpc-api" 281 | } 282 | }, 283 | { 284 | "id": "polkadot", 285 | "name": "Polkadot", 286 | "coinId": 354, 287 | "symbol": "DOT", 288 | "decimals": 10, 289 | "blockchain": "Polkadot", 290 | "derivationPath": "m/44'/354'/0'/0'/0'", 291 | "curve": "ed25519", 292 | "publicKeyType": "ed25519", 293 | "explorer": { 294 | "url": "https://polkadot.subscan.io", 295 | "txPath": "/extrinsic/", 296 | "accountPath": "/account/" 297 | }, 298 | "info": { 299 | "url": "https://polkadot.network/", 300 | "source": "https://github.com/paritytech/polkadot", 301 | "rpc": "", 302 | "documentation": "https://polkadot.js.org/api/substrate/rpc.html" 303 | } 304 | }, 305 | { 306 | "id": "filecoin", 307 | "name": "Filecoin", 308 | "coinId": 461, 309 | "symbol": "FIL", 310 | "decimals": 18, 311 | "blockchain": "Filecoin", 312 | "derivationPath": "m/44'/461'/0'/0/0", 313 | "curve": "secp256k1", 314 | "publicKeyType": "secp256k1Extended", 315 | "explorer": { 316 | "url": "https://filfox.info/en", 317 | "txPath": "/message/", 318 | "accountPath": "/address/", 319 | "sampleTx": "bafy2bzacedsgjcd6xfhrrymmfrqubb44otlyhvgqkgsh533d5j5hwniiqespm", 320 | "sampleAccount": "f1abjxfbp274xpdqcpuaykwkfb43omjotacm2p3za" 321 | }, 322 | "info": { 323 | "url": "https://filecoin.io/", 324 | "source": "https://github.com/filecoin-project/lotus", 325 | "rpc": "", 326 | "documentation": "https://docs.lotu.sh" 327 | } 328 | }, 329 | { 330 | "id": "solana", 331 | "name": "Solana", 332 | "coinId": 501, 333 | "symbol": "SOL", 334 | "decimals": 9, 335 | "blockchain": "Solana", 336 | "derivationPath": "m/44'/501'/0'", 337 | "curve": "ed25519", 338 | "publicKeyType": "ed25519", 339 | "explorer": { 340 | "url": "https://solscan.io", 341 | "txPath": "/tx/", 342 | "accountPath": "/account/", 343 | "sampleTx": "5LmxrEKGchhMuYfw6Qut6CbsvE9pVfb8YvwZKvWssSesDVjHioBCmWKSJQh1WhvcM6CpemhpHNmEMA2a36rzwTa8", 344 | "sampleAccount": "Bxp8yhH9zNwxyE4UqxP7a7hgJ5xTZfxNNft7YJJ2VRjT" 345 | }, 346 | "info": { 347 | "url": "https://solana.com", 348 | "source": "https://github.com/solana-labs/solana", 349 | "rpc": "https://api.mainnet-beta.solana.com", 350 | "documentation": "https://docs.solana.com" 351 | } 352 | }, 353 | { 354 | "id": "elrond", 355 | "name": "Elrond", 356 | "coinId": 508, 357 | "symbol": "eGLD", 358 | "decimals": 18, 359 | "blockchain": "ElrondNetwork", 360 | "derivationPath": "m/44'/508'/0'/0'/0'", 361 | "curve": "ed25519", 362 | "publicKeyType": "ed25519", 363 | "hrp": "erd", 364 | "explorer": { 365 | "url": "https://explorer.elrond.com", 366 | "txPath": "/transactions/", 367 | "accountPath": "/address/" 368 | }, 369 | "info": { 370 | "url": "https://elrond.com/", 371 | "source": "https://github.com/ElrondNetwork/elrond-go", 372 | "rpc": "https://api.elrond.com", 373 | "documentation": "https://docs.elrond.com" 374 | } 375 | }, 376 | { 377 | "id": "binance", 378 | "name": "Binance", 379 | "displayName": "BNB", 380 | "coinId": 714, 381 | "symbol": "BNB", 382 | "decimals": 8, 383 | "blockchain": "Binance", 384 | "derivationPath": "m/44'/714'/0'/0/0", 385 | "curve": "secp256k1", 386 | "publicKeyType": "secp256k1", 387 | "hrp": "bnb", 388 | "explorer": { 389 | "url": "https://explorer.binance.org", 390 | "txPath": "/tx/", 391 | "accountPath": "/address/", 392 | "sampleTx": "A93625C9F9ABEA1A8E31585B30BBB16C34FAE0D172EB5B6B2F834AF077BF06BB", 393 | "sampleAccount": "bnb1u7jm0cll5h3224y0tapwn6gf6pr49ytewx4gsz" 394 | }, 395 | "info": { 396 | "url": "https://binance.org", 397 | "source": "https://github.com/binance-chain/node-binary", 398 | "rpc": "https://dex.binance.org", 399 | "documentation": "https://docs.binance.org/api-reference/dex-api/paths.html" 400 | } 401 | }, 402 | { 403 | "id": "vechain", 404 | "name": "VeChain", 405 | "coinId": 818, 406 | "symbol": "VET", 407 | "decimals": 18, 408 | "blockchain": "Vechain", 409 | "derivationPath": "m/44'/818'/0'/0/0", 410 | "curve": "secp256k1", 411 | "publicKeyType": "secp256k1Extended", 412 | "explorer": { 413 | "url": "https://explore.vechain.org", 414 | "txPath": "/transactions/", 415 | "accountPath": "/accounts/" 416 | }, 417 | "info": { 418 | "url": "https://vechain.org", 419 | "source": "https://github.com/vechain/thor", 420 | "rpc": "", 421 | "documentation": "https://doc.vechainworld.io/docs" 422 | } 423 | }, 424 | { 425 | "id": "neo", 426 | "name": "NEO", 427 | "coinId": 888, 428 | "symbol": "NEO", 429 | "decimals": 8, 430 | "blockchain": "NEO", 431 | "derivationPath": "m/44'/888'/0'/0/0", 432 | "curve": "nist256p1", 433 | "publicKeyType": "nist256p1", 434 | "explorer": { 435 | "url": "https://neoscan.io", 436 | "txPath": "/transaction/", 437 | "accountPath": "/address/", 438 | "sampleTx": "e0ddf7c81c732df26180aca0c36d5868ad009fdbbe6e7a56ebafc14bba41cd53", 439 | "sampleAccount": "AcxuqWhTureEQGeJgbmtSWNAtssjMLU7pb" 440 | }, 441 | "info": { 442 | "url": "https://neo.org", 443 | "source": "https://github.com/neo-project/neo", 444 | "rpc": "http://seed1.ngd.network:10332", 445 | "documentation": "https://neo.org/eco" 446 | } 447 | }, 448 | { 449 | "id": "harmony", 450 | "name": "Harmony", 451 | "coinId": 1023, 452 | "symbol": "ONE", 453 | "decimals": 18, 454 | "blockchain": "Harmony", 455 | "derivationPath": "m/44'/1023'/0'/0/0", 456 | "curve": "secp256k1", 457 | "publicKeyType": "secp256k1Extended", 458 | "hrp": "one", 459 | "explorer": { 460 | "url": "https://explorer.harmony.one", 461 | "txPath": "/#/tx/", 462 | "accountPath": "/#/address/" 463 | }, 464 | "info": { 465 | "url": "https://harmony.one", 466 | "source": "https://github.com/harmony-one/go-sdk", 467 | "rpc": "", 468 | "documentation": "https://docs.harmony.one/home/harmony-networks/harmony-network-overview/mainnet" 469 | } 470 | }, 471 | { 472 | "id": "tezos", 473 | "name": "Tezos", 474 | "coinId": 1729, 475 | "symbol": "XTZ", 476 | "decimals": 6, 477 | "blockchain": "Tezos", 478 | "derivationPath": "m/44'/1729'/0'/0'", 479 | "curve": "ed25519", 480 | "publicKeyType": "ed25519", 481 | "explorer": { 482 | "url": "https://tzstats.com", 483 | "txPath": "/", 484 | "accountPath": "/" 485 | }, 486 | "info": { 487 | "url": "https://tezos.com", 488 | "source": "https://gitlab.com/tezos/tezos", 489 | "rpc": "https://rpc.tulip.tools/mainnet", 490 | "documentation": "https://tezos.gitlab.io/tezos/api/rpc.html" 491 | } 492 | }, 493 | { 494 | "id": "cardano", 495 | "name": "Cardano", 496 | "coinId": 1815, 497 | "symbol": "ADA", 498 | "decimals": 6, 499 | "blockchain": "Cardano", 500 | "derivationPath": "m/1852'/1815'/0'/0/0", 501 | "curve": "ed25519Extended", 502 | "publicKeyType": "ed25519Extended", 503 | "hrp": "addr", 504 | "explorer": { 505 | "url": "https://shelleyexplorer.cardano.org", 506 | "txPath": "/tx/", 507 | "accountPath": "/address/", 508 | "sampleTx": "b7a6c5cadab0f64bdc89c77ee4a351463aba5c33f2cef6bbd6542a74a90a3af3", 509 | "sampleAccount": "addr1s3xuxwfetyfe7q9u3rfn6je9stlvcgmj8rezd87qjjegdtxm3y3f2mgtn87mrny9r77gm09h6ecslh3gmarrvrp9n4yzmdnecfxyu59jz29g8j" 510 | }, 511 | "info": { 512 | "url": "https://www.cardano.org", 513 | "source": "https://github.com/input-output-hk/cardano-sl", 514 | "rpc": "", 515 | "documentation": "https://cardanodocs.com/introduction/" 516 | } 517 | }, 518 | { 519 | "id": "smartchain", 520 | "name": "Smart Chain", 521 | "coinId": 20000714, 522 | "slip44": 714, 523 | "symbol": "BNB", 524 | "decimals": 18, 525 | "blockchain": "Ethereum", 526 | "derivationPath": "m/44'/60'/0'/0/0", 527 | "curve": "secp256k1", 528 | "publicKeyType": "secp256k1Extended", 529 | "explorer": { 530 | "url": "https://bscscan.com", 531 | "txPath": "/tx/", 532 | "accountPath": "/address/", 533 | "sampleTx": "0xb9ae2e808fe8e57171f303ad8f6e3fd17d949b0bfc7b4db6e8e30a71cc517d7e", 534 | "sampleAccount": "0x35552c16704d214347f29Fa77f77DA6d75d7C752" 535 | }, 536 | "info": { 537 | "url": "https://www.binance.org/en/smartChain", 538 | "source": "https://github.com/binance-chain/bsc", 539 | "rpc": "https://bsc-dataseed1.binance.org", 540 | "documentation": "https://eth.wiki/json-rpc/API" 541 | } 542 | }, 543 | { 544 | "id": "polygon", 545 | "name": "Polygon", 546 | "coinId": 966, 547 | "symbol": "MATIC", 548 | "decimals": 18, 549 | "blockchain": "Ethereum", 550 | "derivationPath": "m/44'/60'/0'/0/0", 551 | "curve": "secp256k1", 552 | "publicKeyType": "secp256k1Extended", 553 | "explorer": { 554 | "url": "https://polygonscan.com", 555 | "txPath": "/tx/", 556 | "accountPath": "/address/", 557 | "sampleTx": "0xe26ed1470d5bf99a53d687843e7acdf7e4ba6620af93b4d672e714de90476e8e", 558 | "sampleAccount": "0x720E1fa107A1Df39Db4E78A3633121ac36Bec132" 559 | }, 560 | "info": { 561 | "url": "https://polygon.technology", 562 | "source": "https://github.com/maticnetwork/contracts", 563 | "rpc": "https://rpc-mainnet.matic.network", 564 | "documentation": "https://eth.wiki/json-rpc/API" 565 | } 566 | }, 567 | { 568 | "id": "xdai", 569 | "name": "xDai", 570 | "coinId": 10000100, 571 | "symbol": "xDAI", 572 | "decimals": 18, 573 | "blockchain": "Ethereum", 574 | "derivationPath": "m/44'/60'/0'/0/0", 575 | "curve": "secp256k1", 576 | "publicKeyType": "secp256k1Extended", 577 | "explorer": { 578 | "url": "https://blockscout.com/xdai/mainnet", 579 | "txPath": "/tx/", 580 | "accountPath": "/address/", 581 | "sampleTx": "0x936798a1ef607c9e856d7861b15999c770c06f0887c4fc1f6acbf3bef09899c1", 582 | "sampleAccount": "0x12d61a95CF55e18D267C2F1AA67d8e42ae1368f8" 583 | }, 584 | "info": { 585 | "url": "https://www.xdaichain.com", 586 | "client": "https://github.com/openethereum/openethereum", 587 | "clientPublic": "https://rpc.xdaichain.com", 588 | "clientDocs": "https://eth.wiki/json-rpc/API" 589 | } 590 | } 591 | ] 592 | -------------------------------------------------------------------------------- /src/walletFactory.ts: -------------------------------------------------------------------------------- 1 | import { Chains } from './chains'; 2 | import { IWalletConfig } from './wallets/IWalletConfig'; 3 | import { BitcoinWallet } from './wallets/types/BitcoinWallet'; 4 | import { EthereumWallet } from './wallets/types/EthereumWallet'; 5 | import { BscWallet } from './wallets/types/BscWallet'; 6 | import { PolygonWallet } from './wallets/types/PolygonWallet'; 7 | 8 | /** 9 | * Implements the Factory pattern to help generate easily wallets 10 | * for the supported blockchains. 11 | * 12 | * @export 13 | * @class WalletFactory 14 | */ 15 | export class WalletFactory { 16 | /** 17 | * Instantiates a wallet for the specified blockchain configuration options 18 | * Currently supports only BTC and ETH. 19 | * 20 | * @static 21 | * @param {IWalletConfig} config 22 | * @throws {Error} If config specifies an unsupported blockchain 23 | * @memberof WalletFactory 24 | */ 25 | static getWallet = (config: IWalletConfig) => { 26 | let chain = config.chain; 27 | let wallet = null; 28 | switch (chain) { 29 | case Chains.BTC: 30 | wallet = new BitcoinWallet(config); 31 | break; 32 | case Chains.ETH: 33 | wallet = new EthereumWallet(config); 34 | break; 35 | case Chains.BSC: 36 | wallet = new BscWallet(config); 37 | break; 38 | case Chains.POLYGON: 39 | wallet = new PolygonWallet(config); 40 | break; 41 | default: 42 | throw new Error('Unsupported wallet blockchain'); 43 | } 44 | return wallet; 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /src/walletGenerator.ts: -------------------------------------------------------------------------------- 1 | import { Chains } from './chains'; 2 | import { CONFIG } from './utils/config'; 3 | import { generateMnemonic } from 'bip39'; 4 | import { 5 | BitcoinGenerator, 6 | BscGenerator, 7 | EthereumGenerator, 8 | PolygonGenerator, 9 | } from './generators'; 10 | 11 | const DRIVER_NAMESPACE: { 12 | [key: string]: any; 13 | } = { 14 | [Chains.BTC]: BitcoinGenerator, 15 | [Chains.ETH]: EthereumGenerator, 16 | [Chains.POLYGON]: PolygonGenerator, 17 | [Chains.BSC]: BscGenerator, 18 | }; 19 | 20 | /** 21 | * 22 | * 23 | * @export 24 | * @class WalletGenerator 25 | */ 26 | export class WalletGenerator { 27 | /** 28 | * Generates a string containing the 12 words used as a mnemonic 29 | * to create the private and public wallet keys. 30 | * 31 | * @static 32 | * @param {number} [size=128] Or use 256 for 24 words 33 | * @return {string} The mnemonic 34 | * @memberof WalletGenerator 35 | */ 36 | static generateMnemonic(size = 128): string { 37 | return generateMnemonic(size); 38 | } 39 | 40 | /** 41 | * Offers direct access to the drivers that offer the key generation. 42 | * 43 | * @static 44 | * @param {Chains} chain 45 | * @return {GenericGenerator} 46 | * @memberof WalletGenerator 47 | */ 48 | static getDriver(chain: Chains) { 49 | let driver = DRIVER_NAMESPACE[chain]; 50 | if (!driver) { 51 | throw new Error('Unsupported wallet chain'); 52 | } 53 | return driver; 54 | } 55 | 56 | /** 57 | * Generate the wallet's XPUB address. 58 | * The source of all addresses to be generated for the public. 59 | * 60 | * @static 61 | * @param {Chains} chain The type of chain 62 | * @param {string} mnemonic 63 | * @param {*} [config=CONFIG] 64 | * @return {string} The wallet's XPUB address 65 | * @memberof WalletGenerator 66 | */ 67 | static async generateWalletXpub( 68 | chain: Chains, 69 | mnemonic: any, 70 | config: any = CONFIG 71 | ) { 72 | let driver = WalletGenerator.getDriver(chain); 73 | return driver.generateWalletXpub(mnemonic, config); 74 | } 75 | 76 | /** 77 | * Generate the wallet's private key. 78 | * 79 | * @static 80 | * @param {Chains} chain The type of chain 81 | * @param {string} mnemonic 82 | * @param {integer} derivation The derivation key to allow generation of more private keys for the same chain 83 | * @param {*} [config=CONFIG] 84 | * @return {string} The wallet's private key 85 | * @memberof WalletGenerator 86 | */ 87 | static async generatePrivateKeyFromMnemonic( 88 | chain: Chains, 89 | mnemonic: any, 90 | derivation: any, 91 | config: any = CONFIG 92 | ) { 93 | let driver = WalletGenerator.getDriver(chain); 94 | return driver.generatePrivateKeyFromMnemonic(mnemonic, derivation, config); 95 | } 96 | 97 | /** 98 | * Generate the public wallet address for the specified chain 99 | * 100 | * @static 101 | * @param {Chains} chain The type of chain 102 | * @param {string} xpub 103 | * @param {integer} derivation 104 | * @param {*} [config=CONFIG] 105 | * @return {string} The wallet's public address 106 | * @memberof WalletGenerator 107 | */ 108 | static async generateAddressFromXPub( 109 | chain: Chains, 110 | xpub: any, 111 | derivation: any, 112 | config: any = CONFIG 113 | ) { 114 | let driver = WalletGenerator.getDriver(chain); 115 | return driver.generateAddressFromXPub(xpub, derivation, config); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/wallets/GenericWallet.ts: -------------------------------------------------------------------------------- 1 | import { IWallet } from './IWallet'; 2 | import { GenericTxProposal } from '../fees/GenericTxProposal'; 3 | import { IWalletConfig } from './IWalletConfig'; 4 | import { CONFIG } from '../utils/config'; 5 | import { GenericBalance } from '../balances/GenericBalance'; 6 | import { Web3SigningManager } from './signing/web3'; 7 | 8 | /** 9 | * Don't use the generic wallet, for a new coin write an implementation 10 | */ 11 | export class GenericWallet implements IWallet { 12 | config: IWalletConfig; 13 | address: any = null; 14 | currency: string | null; 15 | signingManager: Web3SigningManager | null = null; 16 | 17 | TRANSACTION_DRIVER_NAMESPACE: { 18 | [key: string]: any; 19 | } = {}; 20 | 21 | FEES_DRIVER_NAMESPACE: { 22 | [key: string]: any; 23 | } = {}; 24 | 25 | BALANCE_DRIVER_NAMESPACE: { 26 | [key: string]: any; 27 | } = {}; 28 | 29 | // 30 | constructor(config: IWalletConfig) { 31 | this.address = config.walletAddress; 32 | this.config = config; 33 | this.currency = this.config.symbol; 34 | this.signingManager = null; 35 | } 36 | // 37 | getDecimals = async (): Promise => { 38 | if (this.config.decimals === null) { 39 | throw new Error('Wallet decimals not set!'); 40 | } 41 | return this.config.decimals; 42 | }; 43 | getAddress = () => { 44 | if (!this.address) { 45 | throw new Error('Wallet address not set!'); 46 | } 47 | return this.address; 48 | }; 49 | getPrivateKey = () => { 50 | if (!this.config.privKey) { 51 | throw new Error('Wallet private key not set!'); 52 | } 53 | return this.config.privKey; 54 | }; 55 | getCurrencyName = async (): Promise => { 56 | if (!this.config.symbol) { 57 | throw new Error('Wallet currency not set!'); 58 | } 59 | return this.config.symbol; 60 | }; 61 | getCurrencySymbol = async (): Promise => { 62 | if (!this.config.symbol) { 63 | throw new Error('Wallet currency not set!'); 64 | } 65 | return this.config.symbol; 66 | }; 67 | getBlockchainSymbol = () => { 68 | if (!this.config.chain) { 69 | throw new Error('Wallet blockchain not set!'); 70 | } 71 | return this.config.chain; 72 | }; 73 | getSigningManager() { 74 | return this.signingManager; 75 | } 76 | // End of common functions 77 | getBalance = async () => { 78 | // Loop through the drivers to get the balance 79 | let drivers = 80 | CONFIG.CHAIN_ENDPOINTS[this.getBlockchainSymbol()]?.balance ?? []; 81 | for (let i = 0; i < drivers.length; i++) { 82 | // Try all drivers in case one of them fails 83 | const driverDescription: any = drivers[i]; 84 | try { 85 | var driver = new this.BALANCE_DRIVER_NAMESPACE[ 86 | driverDescription.driver 87 | ](this.config, driverDescription.config); 88 | let balance = await driver.getBalance(this.getAddress()); 89 | if (balance) { 90 | return balance; 91 | } 92 | } catch (e) { 93 | if (process.env.NODE_ENV !== 'production') { 94 | console.log(e); 95 | } 96 | continue; 97 | } 98 | } 99 | let currencySymbol = await this.getCurrencySymbol(); 100 | if (!currencySymbol) { 101 | throw new Error( 102 | 'Unable to retrieve balance for a contract without a currency symbol!' 103 | ); 104 | } 105 | return new GenericBalance(currencySymbol, 0, 0); 106 | }; 107 | // This is a send currency transaction 108 | getTxSendProposals = async (destination: string, valueToSend: any) => { 109 | // Loop through the drivers to get the fees 110 | let drivers = CONFIG.CHAIN_ENDPOINTS[this.getBlockchainSymbol()]?.fee ?? []; 111 | for (let i = 0; i < drivers.length; i++) { 112 | // Try all drivers in case one of them fails 113 | const driverDescription: any = drivers[i]; 114 | try { 115 | var driver = new this.FEES_DRIVER_NAMESPACE[driverDescription.driver]( 116 | this.config, 117 | driverDescription.config 118 | ); 119 | if (typeof driver.getTxSendProposals !== 'function') { 120 | continue; 121 | } 122 | let fees = await driver.getTxSendProposals(destination, valueToSend); 123 | if (fees) { 124 | return fees; 125 | } 126 | } catch (e) { 127 | if (process.env.NODE_ENV !== 'production') { 128 | console.log(e); 129 | } 130 | continue; 131 | } 132 | } 133 | return null; 134 | }; 135 | 136 | postTxSend = async (transactionProposal: GenericTxProposal): Promise => { 137 | // Loop through the drivers to get the fees 138 | let drivers = 139 | CONFIG.CHAIN_ENDPOINTS[this.getBlockchainSymbol()]?.transaction ?? []; 140 | for (let i = 0; i < drivers.length; i++) { 141 | // Try all drivers in case one of them fails 142 | const driverDescription: any = drivers[i]; 143 | try { 144 | var driver = new this.TRANSACTION_DRIVER_NAMESPACE[ 145 | driverDescription.driver 146 | ](this.config, driverDescription.config); 147 | let tx = await driver.send(transactionProposal); 148 | return tx; 149 | } catch (e) { 150 | if (process.env.NODE_ENV !== 'production') { 151 | console.log(e); 152 | } 153 | continue; 154 | } 155 | } 156 | return null; 157 | }; 158 | 159 | postRawTxSend = async (transaction: any): Promise => { 160 | // Loop through the drivers to get the fees 161 | let drivers = 162 | CONFIG.CHAIN_ENDPOINTS[this.getBlockchainSymbol()]?.transaction ?? []; 163 | for (let i = 0; i < drivers.length; i++) { 164 | // Try all drivers in case one of them fails 165 | const driverDescription: any = drivers[i]; 166 | try { 167 | var driver = new this.TRANSACTION_DRIVER_NAMESPACE[ 168 | driverDescription.driver 169 | ](this.config, driverDescription.config); 170 | let tx = await driver.sendRaw(transaction); 171 | return tx; 172 | } catch (e) { 173 | if (process.env.NODE_ENV !== 'production') { 174 | console.log(e); 175 | } 176 | continue; 177 | } 178 | } 179 | return null; 180 | }; 181 | } 182 | -------------------------------------------------------------------------------- /src/wallets/IWallet.ts: -------------------------------------------------------------------------------- 1 | import { GenericTxProposal } from '../fees/GenericTxProposal'; 2 | 3 | export interface IWallet { 4 | getBalance(): Promise; 5 | getDecimals(): Promise; 6 | getTxSendProposals(destination: string, valueToSend: any): Promise; 7 | getAddress(): any; 8 | postTxSend(transactionProposal: GenericTxProposal): Promise; 9 | } 10 | -------------------------------------------------------------------------------- /src/wallets/IWalletConfig.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The configuration of a wallet 3 | * 4 | * @export 5 | * @interface IWalletConfig 6 | * @property {null|string} symbol Official symbol 7 | * @property {null|string} name Display name 8 | * @property {string} chain Blockchain type 9 | * @property {string} type 10 | * @property {null|number} decimals 11 | * @property {null|string} contract Contract address if it is a token 12 | * @property {*} options 13 | * @property {null|string} walletAddress The wallet address for this chain 14 | * @property {null|string} privKey The private key used for transaction signing 15 | */ 16 | export interface IWalletConfig { 17 | symbol: null | string; 18 | name: null | string; 19 | chain: string; 20 | type: string; 21 | decimals: null | number; 22 | contract: null | string; 23 | options?: { 24 | testnet?: boolean; 25 | }; 26 | walletAddress: null | string; 27 | privKey: null | string; 28 | } 29 | -------------------------------------------------------------------------------- /src/wallets/index.ts: -------------------------------------------------------------------------------- 1 | export { EthereumWallet } from './types/EthereumWallet'; 2 | export { BitcoinWallet } from './types/BitcoinWallet'; 3 | export { BscWallet } from './types/BscWallet'; 4 | export { PolygonWallet } from './types/PolygonWallet'; 5 | -------------------------------------------------------------------------------- /src/wallets/signing/web3.ts: -------------------------------------------------------------------------------- 1 | import Web3 from 'web3'; 2 | import { 3 | signTypedData as web3SignTypeData, 4 | SignTypedDataVersion, 5 | } from '@metamask/eth-sig-util'; 6 | import { toBuffer } from 'ethereumjs-util'; 7 | export class Web3SigningManager { 8 | client: Web3; 9 | privateKey: string; 10 | 11 | constructor(client: any, privateKey: any) { 12 | this.client = client; 13 | this.privateKey = privateKey; 14 | this.client.eth.accounts.wallet.add(privateKey); 15 | this.client.eth.defaultAccount = client.eth.accounts.wallet[0].address; 16 | } 17 | 18 | async personalSign( 19 | dataToSign: any, 20 | password: string, 21 | address: string | null = null 22 | ) { 23 | if (!address) { 24 | address = this.client.eth.defaultAccount!; 25 | } 26 | return await this.client.eth.personal.sign(dataToSign, address, password); 27 | } 28 | 29 | async sign(dataToSign: any) { 30 | return this.client.eth.accounts.sign(dataToSign, this.privateKey).signature; 31 | } 32 | 33 | async signTypedData(dataToSign: any) { 34 | // console.log('private key', this.privateKey); 35 | let privateKeyBuffer = toBuffer(this.privateKey); 36 | // console.log('privateKeyBuffer', privateKeyBuffer); 37 | // console.log('dataToSign', dataToSign); 38 | let sig = web3SignTypeData({ 39 | privateKey: privateKeyBuffer, 40 | data: dataToSign, 41 | version: SignTypedDataVersion.V3, 42 | }); 43 | // console.log('sig', sig); 44 | return sig; 45 | // return (this.client.eth.accounts.sign(dataToSign, this.privateKey)).signature; 46 | } 47 | 48 | async signTransaction(transactionObject: any) { 49 | return ( 50 | await this.client.eth.accounts.signTransaction( 51 | transactionObject, 52 | this.privateKey 53 | ) 54 | ).rawTransaction as string; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/wallets/types/BitcoinWallet.ts: -------------------------------------------------------------------------------- 1 | import { GenericWallet } from '../GenericWallet'; 2 | 3 | import { BTC_Driver } from '../../fees/drivers/BTC_Driver'; 4 | import { BTC_Driver as BTC_Transaction_Driver } from '../../transactions/drivers/BTC_Driver'; 5 | import { BTC_Driver as BTC_Balance_Driver } from '../../balances/drivers/BTC_Driver'; 6 | 7 | export class BitcoinWallet extends GenericWallet { 8 | TRANSACTION_DRIVER_NAMESPACE: { 9 | [key: string]: any; 10 | } = { 11 | BTC_Driver: BTC_Transaction_Driver, 12 | }; 13 | 14 | FEES_DRIVER_NAMESPACE: { 15 | [key: string]: any; 16 | } = { 17 | BTC_Driver: BTC_Driver, 18 | }; 19 | 20 | BALANCE_DRIVER_NAMESPACE: { 21 | [key: string]: any; 22 | } = { 23 | BTC_Driver: BTC_Balance_Driver, 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /src/wallets/types/BscWallet.ts: -------------------------------------------------------------------------------- 1 | import { BSC_Driver } from '../../fees/drivers/BSC_Driver'; 2 | import { BSC_Driver as BSC_Transaction_Driver } from '../../transactions/drivers/BSC_Driver'; 3 | import { BSC_Driver as BSC_Balance_Driver } from '../../balances/drivers/BSC_Driver'; 4 | 5 | import { EthereumWallet } from './EthereumWallet'; 6 | 7 | export class BscWallet extends EthereumWallet { 8 | TRANSACTION_DRIVER_NAMESPACE: { 9 | [key: string]: any; 10 | } = { 11 | BSC_Driver: BSC_Transaction_Driver, 12 | }; 13 | 14 | FEES_DRIVER_NAMESPACE: { 15 | [key: string]: any; 16 | } = { 17 | BSC_Driver: BSC_Driver, 18 | }; 19 | 20 | BALANCE_DRIVER_NAMESPACE: { 21 | [key: string]: any; 22 | } = { 23 | BSC_Driver: BSC_Balance_Driver, 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /src/wallets/types/EthereumWallet.ts: -------------------------------------------------------------------------------- 1 | import { GenericWallet } from '../GenericWallet'; 2 | 3 | import { ETH_Driver } from '../../fees/drivers/ETH_Driver'; 4 | import { ETH_Driver as ETH_Transaction_Driver } from '../../transactions/drivers/ETH_Driver'; 5 | import { ETH_Driver as ETH_Balance_Driver } from '../../balances/drivers/ETH_Driver'; 6 | import Web3 from 'web3'; 7 | import { ERC20_ABI } from '../../constants'; 8 | import { CONFIG } from '../../utils/config'; 9 | import BigNumber from 'bignumber.js'; 10 | import { Web3SigningManager } from '../signing/web3'; 11 | 12 | export class EthereumWallet extends GenericWallet { 13 | TRANSACTION_DRIVER_NAMESPACE: { 14 | [key: string]: any; 15 | } = { 16 | ETH_Driver: ETH_Transaction_Driver, 17 | }; 18 | 19 | FEES_DRIVER_NAMESPACE: { 20 | [key: string]: any; 21 | } = { 22 | ETH_Driver: ETH_Driver, 23 | }; 24 | 25 | BALANCE_DRIVER_NAMESPACE: { 26 | [key: string]: any; 27 | } = { 28 | ETH_Driver: ETH_Balance_Driver, 29 | }; 30 | 31 | getWeb3Client() { 32 | let drivers = 33 | CONFIG.CHAIN_ENDPOINTS[this.getBlockchainSymbol()]?.balance ?? []; 34 | if (drivers.length === 0) { 35 | throw new Error('Can not retrieve decimals without a balance driver!'); 36 | } 37 | let driverDescription = drivers[0]; 38 | let driver = new this.BALANCE_DRIVER_NAMESPACE[driverDescription.driver]( 39 | this.config, 40 | driverDescription.config 41 | ); 42 | const provider = new Web3.providers.HttpProvider( 43 | driver.getTokenBalanceEndpoint() 44 | ); 45 | const client = new Web3(provider); 46 | return client; 47 | } 48 | 49 | getSigningManager() { 50 | if (this.signingManager) { 51 | return this.signingManager; 52 | } 53 | // Create the signing manager 54 | this.signingManager = new Web3SigningManager( 55 | this.getWeb3Client(), 56 | this.getPrivateKey() 57 | ); 58 | return this.signingManager; 59 | } 60 | 61 | getDecimals = async (): Promise => { 62 | if (this.config.decimals === null) { 63 | // Retrieve decimals information 64 | if (!this.config.contract) { 65 | throw new Error( 66 | 'Wallet decimals not set, can not retrieve them without contract address!' 67 | ); 68 | } 69 | const client = this.getWeb3Client(); 70 | // The minimum ABI required to get the ERC20 Token balance 71 | const minABI: any = ERC20_ABI; 72 | const contract = new client.eth.Contract(minABI, this.config.contract!); 73 | const result = await contract.methods.decimals().call(); 74 | const decimals = Number(new BigNumber(result)); 75 | this.config.decimals = decimals; 76 | } 77 | return this.config.decimals; 78 | }; 79 | 80 | getCurrencySymbol = async (): Promise => { 81 | if (this.config.symbol === null) { 82 | // Retrieve decimals information 83 | if (!this.config.contract) { 84 | throw new Error( 85 | 'Wallet decimals not set, can not retrieve them without contract address!' 86 | ); 87 | } 88 | const client = this.getWeb3Client(); 89 | // The minimum ABI required to get the ERC20 Token balance 90 | const minABI: any = ERC20_ABI; 91 | const contract = new client.eth.Contract(minABI, this.config.contract!); 92 | const result = await contract.methods.symbol().call(); 93 | this.config.symbol = result; 94 | } 95 | return this.config.symbol; 96 | }; 97 | 98 | getCurrencyName = async (): Promise => { 99 | if (this.config.name === null) { 100 | // Retrieve decimals information 101 | if (!this.config.contract) { 102 | throw new Error( 103 | 'Wallet decimals not set, can not retrieve them without contract address!' 104 | ); 105 | } 106 | const client = this.getWeb3Client(); 107 | // The minimum ABI required to get the ERC20 Token balance 108 | const minABI: any = ERC20_ABI; 109 | const contract = new client.eth.Contract(minABI, this.config.contract!); 110 | const result = await contract.methods.name().call(); 111 | this.config.name = result; 112 | } 113 | return this.config.name; 114 | }; 115 | } 116 | -------------------------------------------------------------------------------- /src/wallets/types/PolygonWallet.ts: -------------------------------------------------------------------------------- 1 | import { POLYGON_Driver } from '../../fees/drivers/POLYGON_Driver'; 2 | import { POLYGON_Driver as POLYGON_Transaction_Driver } from '../../transactions/drivers/POLYGON_Driver'; 3 | import { POLYGON_Driver as POLYGON_Balance_Driver } from '../../balances/drivers/POLYGON_Driver'; 4 | 5 | import { EthereumWallet } from './EthereumWallet'; 6 | 7 | export class PolygonWallet extends EthereumWallet { 8 | TRANSACTION_DRIVER_NAMESPACE: { 9 | [key: string]: any; 10 | } = { 11 | POLYGON_Driver: POLYGON_Transaction_Driver, 12 | }; 13 | 14 | FEES_DRIVER_NAMESPACE: { 15 | [key: string]: any; 16 | } = { 17 | POLYGON_Driver: POLYGON_Driver, 18 | }; 19 | 20 | BALANCE_DRIVER_NAMESPACE: { 21 | [key: string]: any; 22 | } = { 23 | POLYGON_Driver: POLYGON_Balance_Driver, 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /test/balances.test.ts: -------------------------------------------------------------------------------- 1 | import { Balances, IWalletConfig } from '../dist'; 2 | import { CONFIG } from '../dist'; 3 | import { BTC_ADDRESS_SENDER, ETH_ADDRESS_SENDER } from './fixtures'; 4 | 5 | const BTC_DESCRIPTOR: IWalletConfig = { 6 | symbol: 'BTC', 7 | name: 'Bitcoin', 8 | chain: 'BTC', 9 | type: 'coin', 10 | decimals: 8, 11 | contract: null, 12 | walletAddress: null, 13 | privKey: null, 14 | }; 15 | 16 | const ETH_DESCRIPTOR: IWalletConfig = { 17 | symbol: 'ETH', 18 | name: 'Ethereum', 19 | chain: 'BTC', 20 | type: 'coin', 21 | decimals: 18, 22 | contract: null, 23 | walletAddress: null, 24 | privKey: null, 25 | }; 26 | 27 | const BSC_DESCRIPTOR: IWalletConfig = { 28 | symbol: 'BNB', 29 | name: 'BNB', 30 | chain: 'BSC', 31 | type: 'coin', 32 | decimals: 18, 33 | contract: null, 34 | walletAddress: null, 35 | privKey: null, 36 | }; 37 | 38 | describe('Balances', () => { 39 | it('can_get_btc_balance', async () => { 40 | let from = BTC_ADDRESS_SENDER; 41 | let driver = new Balances.BTC_Driver( 42 | BTC_DESCRIPTOR, 43 | CONFIG.CHAIN_ENDPOINTS.BTC.balance[0].config 44 | ); 45 | let balance = await driver.getBalance(from); 46 | expect(typeof balance).toBe('object'); 47 | expect(balance.getValue()).toBeGreaterThan(0); 48 | }); 49 | 50 | it('can_get_eth_balance', async () => { 51 | let from = ETH_ADDRESS_SENDER; 52 | let driver = new Balances.ETH_Driver( 53 | ETH_DESCRIPTOR, 54 | CONFIG.CHAIN_ENDPOINTS.ETH.balance[0].config 55 | ); 56 | let balance = await driver.getBalance(from); 57 | expect(typeof balance).toBe('object'); 58 | expect(balance.getValue()).toBeGreaterThan(0); 59 | // console.log('ETH', balance.getValue()); 60 | }); 61 | 62 | it('can_get_bsc_balance', async () => { 63 | let from = ETH_ADDRESS_SENDER; 64 | let driver = new Balances.BSC_Driver( 65 | BSC_DESCRIPTOR, 66 | CONFIG.CHAIN_ENDPOINTS.BSC.balance[0].config 67 | ); 68 | let balance = await driver.getBalance(from); 69 | expect(typeof balance).toBe('object'); 70 | expect(balance.getValue()).toBeGreaterThan(0); 71 | console.log('BNB', balance.getValue()); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /test/bscWallet.test.ts: -------------------------------------------------------------------------------- 1 | import { IWalletConfig, WalletFactory } from '../dist'; 2 | import { WalletGenerator } from '../dist'; 3 | import { Chains } from '../dist'; 4 | import { ETH_ADDRESS_RECEIVER, MNEMONIC } from './fixtures'; 5 | 6 | let config: IWalletConfig = { 7 | symbol: 'BNB', 8 | name: 'Binance', 9 | chain: 'BSC', 10 | type: 'coin', 11 | decimals: 18, 12 | contract: null, 13 | options: { 14 | testnet: true, 15 | }, 16 | walletAddress: null, 17 | privKey: null, 18 | }; 19 | 20 | describe('BscWallet', () => { 21 | it('can_get_balance', async () => { 22 | let mnemonic = MNEMONIC; 23 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BSC, mnemonic); 24 | let address = await WalletGenerator.generateAddressFromXPub( 25 | Chains.BSC, 26 | xpub, 27 | 0 28 | ); 29 | let _config = Object.assign({}, config, { walletAddress: address }); 30 | let w = WalletFactory.getWallet(_config); 31 | let balance = await w.getBalance(); 32 | expect(balance.getValue()).toBeGreaterThan(0); 33 | }); 34 | 35 | it('can_get_fee', async () => { 36 | let mnemonic = MNEMONIC; 37 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BSC, mnemonic); 38 | let address = await WalletGenerator.generateAddressFromXPub( 39 | Chains.BSC, 40 | xpub, 41 | 0 42 | ); 43 | let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 44 | Chains.BSC, 45 | mnemonic, 46 | 0 47 | ); 48 | let to = ETH_ADDRESS_RECEIVER; 49 | let _config = Object.assign({}, config, { 50 | walletAddress: address, 51 | privKey: privKey, 52 | }); 53 | let w = WalletFactory.getWallet(_config); 54 | let fees = await w.getTxSendProposals(to, 0.0001); 55 | expect(typeof fees).toBe('object'); 56 | }); 57 | 58 | // it('can_send_bnb', async () => { 59 | // let mnemonic = MNEMONIC; 60 | // let xpub = await WalletGenerator.generateWalletXpub(Chains.BSC, mnemonic); 61 | // let address = await WalletGenerator.generateAddressFromXPub( 62 | // Chains.BSC, 63 | // xpub, 64 | // 0 65 | // ); 66 | // let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 67 | // Chains.BSC, 68 | // mnemonic, 69 | // 0 70 | // ); 71 | // let to = ETH_ADDRESS_RECEIVER; 72 | // let _config = Object.assign({}, config, { 73 | // walletAddress: address, 74 | // privKey: privKey, 75 | // }); 76 | // let w = WalletFactory.getWallet(_config); 77 | // let balance = await w.getBalance(); 78 | // expect(balance.getValue()).toBeGreaterThan(0); 79 | // let proposals = await w.getTxSendProposals(to, 0.0001); 80 | // expect(typeof proposals).toBe('object'); 81 | // let result = await w.postTxSend(proposals.regular); 82 | // console.log('result', result); 83 | // }); 84 | }); 85 | -------------------------------------------------------------------------------- /test/btcWallet.test.ts: -------------------------------------------------------------------------------- 1 | import { IWalletConfig, WalletFactory } from '../dist'; 2 | import { WalletGenerator } from '../dist'; 3 | import { Chains } from '../dist'; 4 | import { MNEMONIC } from './fixtures'; 5 | import { BTC_ADDRESS_SENDER } from './fixtures'; 6 | import { BTC_ADDRESS_RECEIVER } from './fixtures'; 7 | 8 | let config: IWalletConfig = { 9 | symbol: 'BTC', 10 | name: 'Bitcoin', 11 | chain: 'BTC', 12 | type: 'coin', 13 | decimals: 8, 14 | contract: null, 15 | options: { 16 | testnet: true, 17 | }, 18 | walletAddress: null, 19 | privKey: null, 20 | }; 21 | 22 | describe('BitcoinWallet', () => { 23 | it('can_get_balance', async () => { 24 | let mnemonic = MNEMONIC; 25 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BTC, mnemonic); 26 | let address = await WalletGenerator.generateAddressFromXPub( 27 | Chains.BTC, 28 | xpub, 29 | 0 30 | ); 31 | let _config = Object.assign({}, config, { walletAddress: address }); 32 | let w = WalletFactory.getWallet(_config); 33 | let balance = await w.getBalance(); 34 | expect(balance.getValue()).toBeGreaterThan(0); 35 | }); 36 | 37 | it('can_get_fee', async () => { 38 | let mnemonic = MNEMONIC; 39 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BTC, mnemonic); 40 | let address = await WalletGenerator.generateAddressFromXPub( 41 | Chains.BTC, 42 | xpub, 43 | 0 44 | ); 45 | let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 46 | Chains.BTC, 47 | mnemonic, 48 | 0 49 | ); 50 | let to = BTC_ADDRESS_SENDER; 51 | let _config = Object.assign({}, config, { 52 | walletAddress: address, 53 | privKey: privKey, 54 | }); 55 | let w = WalletFactory.getWallet(_config); 56 | let fees = await w.getTxSendProposals(to, 0.0001); 57 | expect(typeof fees).toBe('object'); 58 | }); 59 | 60 | it('can_not_get_fee_for_large_send', async () => { 61 | let mnemonic = MNEMONIC; 62 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BTC, mnemonic); 63 | let address = await WalletGenerator.generateAddressFromXPub( 64 | Chains.BTC, 65 | xpub, 66 | 0 67 | ); 68 | let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 69 | Chains.BTC, 70 | mnemonic, 71 | 0 72 | ); 73 | let to = BTC_ADDRESS_RECEIVER; 74 | let _config = Object.assign({}, config, { 75 | walletAddress: address, 76 | privKey: privKey, 77 | }); 78 | let w = WalletFactory.getWallet(_config); 79 | let fees = await w.getTxSendProposals(to, 1); 80 | expect(fees).toBe(null); 81 | }); 82 | 83 | it('can_send_bitcoin', async () => { 84 | let mnemonic = MNEMONIC; 85 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BTC, mnemonic); 86 | let address = await WalletGenerator.generateAddressFromXPub( 87 | Chains.BTC, 88 | xpub, 89 | 0 90 | ); 91 | let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 92 | Chains.BTC, 93 | mnemonic, 94 | 0 95 | ); 96 | let to = BTC_ADDRESS_RECEIVER; 97 | let _config = Object.assign({}, config, { 98 | walletAddress: address, 99 | privKey: privKey, 100 | }); 101 | let w = WalletFactory.getWallet(_config); 102 | let balance = await w.getBalance(); 103 | expect(balance.getValue()).toBeGreaterThan(0); 104 | let proposals = await w.getTxSendProposals(to, 0.00002); 105 | expect(typeof proposals).toBe('object'); 106 | let result = await w.postTxSend(proposals.regular); 107 | console.log('result', result); 108 | expect(result.length).toBeGreaterThan(0); 109 | }); 110 | }); 111 | -------------------------------------------------------------------------------- /test/ethWallet.test.ts: -------------------------------------------------------------------------------- 1 | import { IWalletConfig, WalletFactory } from '../dist'; 2 | import { WalletGenerator } from '../dist'; 3 | import { Chains } from '../dist'; 4 | import { ETH_ADDRESS_RECEIVER, MNEMONIC } from './fixtures'; 5 | 6 | let config: IWalletConfig = { 7 | symbol: 'ETH', 8 | name: 'Ethereum', 9 | chain: 'ETH', 10 | type: 'coin', 11 | decimals: 18, 12 | contract: null, 13 | options: { 14 | testnet: true, 15 | }, 16 | walletAddress: null, 17 | privKey: null, 18 | }; 19 | 20 | describe('EthereumWallet', () => { 21 | it('can_get_balance', async () => { 22 | let mnemonic = MNEMONIC; 23 | let xpub = await WalletGenerator.generateWalletXpub(Chains.ETH, mnemonic); 24 | let address = await WalletGenerator.generateAddressFromXPub( 25 | Chains.ETH, 26 | xpub, 27 | 0 28 | ); 29 | let _config = Object.assign({}, config, { walletAddress: address }); 30 | let w = WalletFactory.getWallet(_config); 31 | let balance = await w.getBalance(); 32 | expect(balance.getValue()).toBeGreaterThan(0); 33 | }); 34 | 35 | it('can_get_fee', async () => { 36 | let mnemonic = MNEMONIC; 37 | let xpub = await WalletGenerator.generateWalletXpub(Chains.ETH, mnemonic); 38 | let address = await WalletGenerator.generateAddressFromXPub( 39 | Chains.ETH, 40 | xpub, 41 | 0 42 | ); 43 | let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 44 | Chains.ETH, 45 | mnemonic, 46 | 0 47 | ); 48 | let to = ETH_ADDRESS_RECEIVER; 49 | let _config = Object.assign({}, config, { 50 | walletAddress: address, 51 | privKey: privKey, 52 | }); 53 | let w = WalletFactory.getWallet(_config); 54 | let fees = await w.getTxSendProposals(to, 0.0001); 55 | expect(typeof fees).toBe('object'); 56 | }); 57 | 58 | it('can_send_ethereum', async () => { 59 | let mnemonic = MNEMONIC; 60 | let xpub = await WalletGenerator.generateWalletXpub(Chains.ETH, mnemonic); 61 | let address = await WalletGenerator.generateAddressFromXPub( 62 | Chains.ETH, 63 | xpub, 64 | 0 65 | ); 66 | let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 67 | Chains.ETH, 68 | mnemonic, 69 | 0 70 | ); 71 | let to = ETH_ADDRESS_RECEIVER; 72 | let _config = Object.assign({}, config, { 73 | walletAddress: address, 74 | privKey: privKey, 75 | }); 76 | let w = WalletFactory.getWallet(_config); 77 | let balance = await w.getBalance(); 78 | expect(balance.getValue()).toBeGreaterThan(0); 79 | let proposals = await w.getTxSendProposals(to, 0.0001); 80 | expect(typeof proposals).toBe('object'); 81 | let result = await w.postTxSend(proposals.regular); 82 | console.log('result', result); 83 | }); 84 | }); 85 | -------------------------------------------------------------------------------- /test/factory.test.ts: -------------------------------------------------------------------------------- 1 | import { WalletFactory } from '../dist'; 2 | import { WalletGenerator } from '../dist'; 3 | import { Chains } from '../dist'; 4 | import { IWalletConfig } from '../dist'; 5 | import { MNEMONIC } from './fixtures'; 6 | 7 | let mnemonic = MNEMONIC; 8 | 9 | describe('WalletFactory', () => { 10 | it('can_get_btc_wallet', async () => { 11 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BTC, mnemonic); 12 | let address = await WalletGenerator.generateAddressFromXPub( 13 | Chains.BTC, 14 | xpub, 15 | 0 16 | ); 17 | 18 | let config: IWalletConfig = { 19 | symbol: 'BTC', 20 | name: 'Bitcoin', 21 | chain: 'BTC', 22 | type: 'coin', 23 | decimals: 8, 24 | contract: null, 25 | options: { 26 | testnet: true, 27 | }, 28 | walletAddress: address, 29 | privKey: null, 30 | }; 31 | 32 | let wallet = WalletFactory.getWallet(config); 33 | expect(typeof wallet).toBe('object'); 34 | expect(wallet.getAddress()).toBe(address); 35 | }); 36 | 37 | it('can_get_eth_wallet', async () => { 38 | let xpub = await WalletGenerator.generateWalletXpub(Chains.ETH, mnemonic); 39 | let address = await WalletGenerator.generateAddressFromXPub( 40 | Chains.ETH, 41 | xpub, 42 | 0 43 | ); 44 | 45 | let config: IWalletConfig = { 46 | symbol: 'ETH', 47 | name: 'Ethereum', 48 | chain: 'ETH', 49 | type: 'coin', 50 | decimals: 8, 51 | contract: null, 52 | options: { 53 | testnet: true, 54 | }, 55 | walletAddress: address, 56 | privKey: null, 57 | }; 58 | 59 | let wallet = WalletFactory.getWallet(config); 60 | expect(typeof wallet).toBe('object'); 61 | expect(wallet.getAddress()).toBe(address); 62 | }); 63 | 64 | it('throws_unhandled_chain', async () => { 65 | try { 66 | let config: IWalletConfig = { 67 | symbol: 'ETH', 68 | name: 'Ethereum', 69 | chain: 'MATIC', 70 | type: 'coin', 71 | decimals: 8, 72 | contract: null, 73 | options: { 74 | testnet: true, 75 | }, 76 | walletAddress: null, 77 | privKey: null, 78 | }; 79 | 80 | WalletFactory.getWallet(config); 81 | } catch (e) { 82 | expect(e.toString()).toEqual('Error: Unsupported wallet blockchain'); 83 | } 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /test/fees.test.ts: -------------------------------------------------------------------------------- 1 | import { Fees, IWalletConfig } from '../dist'; 2 | import { CONFIG } from '../dist'; 3 | import { BitcoinFee, BnbFee, EthereumFee } from '../dist/fees'; 4 | import { Generators } from '../dist'; 5 | import { 6 | BTC_ADDRESS_RECEIVER, 7 | BTC_ADDRESS_SENDER, 8 | ETH_ADDRESS_RECEIVER, 9 | ETH_ADDRESS_SENDER, 10 | MNEMONIC, 11 | } from './fixtures'; 12 | 13 | const BTC_DESCRIPTOR: IWalletConfig = { 14 | symbol: 'BTC', 15 | name: 'Bitcoin', 16 | chain: 'BTC', 17 | type: 'coin', 18 | decimals: 8, 19 | contract: null, 20 | walletAddress: null, 21 | privKey: null, 22 | }; 23 | 24 | const ETH_DESCRIPTOR: IWalletConfig = { 25 | symbol: 'ETH', 26 | name: 'Ethereum', 27 | chain: 'BTC', 28 | type: 'ETH', 29 | decimals: 18, 30 | contract: null, 31 | walletAddress: null, 32 | privKey: null, 33 | }; 34 | 35 | const BSC_DESCRIPTOR: IWalletConfig = { 36 | symbol: 'BNB', 37 | name: 'BNB', 38 | chain: 'BSC', 39 | type: 'coin', 40 | decimals: 18, 41 | contract: null, 42 | walletAddress: null, 43 | privKey: null, 44 | }; 45 | 46 | const POLYGON_DESCRIPTOR: IWalletConfig = { 47 | symbol: 'MATIC', 48 | name: 'MATIC', 49 | chain: 'POLYGON', 50 | type: 'coin', 51 | decimals: 18, 52 | contract: null, 53 | walletAddress: null, 54 | privKey: null, 55 | }; 56 | 57 | describe('Fees', () => { 58 | it('can_use_btc_driver', async () => { 59 | let mnemonic = MNEMONIC; 60 | 61 | let privKey = await Generators.BitcoinGenerator.generatePrivateKeyFromMnemonic( 62 | mnemonic, 63 | 0 64 | ); 65 | 66 | let from = BTC_ADDRESS_SENDER; 67 | let to = BTC_ADDRESS_RECEIVER; 68 | let config = Object.assign({}, BTC_DESCRIPTOR, { 69 | privKey: privKey, 70 | walletAddress: from, 71 | }); 72 | let d = new Fees.BTC_Driver( 73 | config, 74 | CONFIG.CHAIN_ENDPOINTS.BTC.fee[0].config 75 | ); 76 | let proposals = await d.getTxSendProposals(to, 0.00001); 77 | expect(typeof proposals).toBe('object'); 78 | ['regular', 'priority'].forEach(element => { 79 | expect(proposals).toHaveProperty(element); 80 | let fee: BitcoinFee = proposals[element]; 81 | expect(fee).toHaveProperty('currency'); 82 | expect(fee.currency).toBe('BTC'); 83 | expect(fee).toHaveProperty('settings'); 84 | expect(fee.settings).toEqual({ 85 | value: expect.anything(), 86 | proposal: expect.anything(), 87 | }); 88 | expect(fee.getData()).toEqual({ 89 | fromUTXO: expect.anything(), 90 | to: expect.anything(), 91 | }); 92 | expect(fee.getFeeValue()).toBeGreaterThan(0); 93 | }); 94 | }); 95 | 96 | it('can_use_eth_driver', async () => { 97 | let mnemonic = MNEMONIC; 98 | let from = ETH_ADDRESS_SENDER; 99 | let to = ETH_ADDRESS_RECEIVER; 100 | 101 | let privKey = await Generators.EthereumGenerator.generatePrivateKeyFromMnemonic( 102 | mnemonic, 103 | 0 104 | ); 105 | let config = Object.assign({}, ETH_DESCRIPTOR, { 106 | privKey: privKey, 107 | walletAddress: from, 108 | }); 109 | let d = new Fees.ETH_Driver( 110 | config, 111 | CONFIG.CHAIN_ENDPOINTS.ETH.fee[0].config 112 | ); 113 | let proposals = await d.getTxSendProposals(to, 0.00001); 114 | expect(typeof proposals).toBe('object'); 115 | ['regular', 'priority'].forEach(element => { 116 | expect(proposals).toHaveProperty(element); 117 | let fee: EthereumFee = proposals[element]; 118 | expect(fee).toHaveProperty('currency'); 119 | expect(fee.currency).toBe('ETH'); 120 | expect(fee).toHaveProperty('settings'); 121 | expect(fee.settings).toEqual({ 122 | fee: expect.anything(), 123 | proposal: expect.anything(), 124 | fromPrivateKey: expect.anything(), 125 | }); 126 | let proposal = fee.getData().proposal; 127 | expect(typeof proposal).toEqual('object'); 128 | expect(fee.getFeeValue()).toBeGreaterThan(0); 129 | }); 130 | }); 131 | 132 | it('can_use_bsc_driver', async () => { 133 | let mnemonic = MNEMONIC; 134 | let from = ETH_ADDRESS_SENDER; 135 | let to = ETH_ADDRESS_RECEIVER; 136 | 137 | let privKey = await Generators.EthereumGenerator.generatePrivateKeyFromMnemonic( 138 | mnemonic, 139 | 0 140 | ); 141 | let config = Object.assign({}, BSC_DESCRIPTOR, { 142 | privKey: privKey, 143 | walletAddress: from, 144 | }); 145 | let d = new Fees.BSC_Driver( 146 | config, 147 | CONFIG.CHAIN_ENDPOINTS.BSC.fee[0].config 148 | ); 149 | let proposals = await d.getTxSendProposals(to, 0.00001); 150 | expect(typeof proposals).toBe('object'); 151 | ['regular', 'priority'].forEach(element => { 152 | expect(proposals).toHaveProperty(element); 153 | let fee: BnbFee = proposals[element]; 154 | expect(fee).toHaveProperty('currency'); 155 | expect(fee.currency).toBe('BNB'); 156 | expect(fee).toHaveProperty('settings'); 157 | expect(fee.settings).toEqual({ 158 | fee: expect.anything(), 159 | proposal: expect.anything(), 160 | fromPrivateKey: expect.anything(), 161 | }); 162 | let proposal = fee.getData().proposal; 163 | console.log(fee.settings); 164 | console.log(proposal); 165 | expect(typeof proposal).toEqual('object'); 166 | expect(fee.getFeeValue()).toBeGreaterThan(0); 167 | }); 168 | }); 169 | 170 | it('can_use_polygon_driver', async () => { 171 | let mnemonic = MNEMONIC; 172 | let from = ETH_ADDRESS_SENDER; 173 | let to = ETH_ADDRESS_RECEIVER; 174 | 175 | let privKey = await Generators.EthereumGenerator.generatePrivateKeyFromMnemonic( 176 | mnemonic, 177 | 0 178 | ); 179 | let config = Object.assign({}, POLYGON_DESCRIPTOR, { 180 | privKey: privKey, 181 | walletAddress: from, 182 | }); 183 | let d = new Fees.POLYGON_Driver( 184 | config, 185 | CONFIG.CHAIN_ENDPOINTS.POLYGON.fee[0].config 186 | ); 187 | let proposals = await d.getTxSendProposals(to, 0.00001); 188 | expect(typeof proposals).toBe('object'); 189 | ['regular', 'priority'].forEach(element => { 190 | expect(proposals).toHaveProperty(element); 191 | let fee: BnbFee = proposals[element]; 192 | expect(fee).toHaveProperty('currency'); 193 | expect(fee.currency).toBe('MATIC'); 194 | expect(fee).toHaveProperty('settings'); 195 | expect(fee.settings).toEqual({ 196 | fee: expect.anything(), 197 | proposal: expect.anything(), 198 | fromPrivateKey: expect.anything(), 199 | }); 200 | let proposal = fee.getData().proposal; 201 | console.log(fee.settings); 202 | console.log(proposal); 203 | expect(typeof proposal).toEqual('object'); 204 | expect(fee.getFeeValue()).toBeGreaterThan(0); 205 | }); 206 | }); 207 | }); 208 | -------------------------------------------------------------------------------- /test/fixtures.sample.ts: -------------------------------------------------------------------------------- 1 | export const MNEMONIC = ''; 2 | 3 | export const BTC_ADDRESS_SENDER = ''; 4 | export const BTC_ADDRESS_RECEIVER = ''; 5 | 6 | export const ETH_ADDRESS_SENDER = ''; 7 | export const ETH_ADDRESS_RECEIVER = ''; 8 | -------------------------------------------------------------------------------- /test/generator.test.ts: -------------------------------------------------------------------------------- 1 | import { WalletGenerator, Chains } from '../dist'; 2 | import { MNEMONIC } from './fixtures'; 3 | 4 | let mnemonic = MNEMONIC; 5 | 6 | describe('WalletGenerator', () => { 7 | it('can_generate_mnemonic', async () => { 8 | let mnemonic = await WalletGenerator.generateMnemonic(); 9 | expect(typeof mnemonic).toBe('string'); 10 | }); 11 | 12 | it('can_generate_btc_wallet', async () => { 13 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BTC, mnemonic); 14 | expect(typeof xpub).toBe('string'); 15 | expect(xpub.length).not.toEqual(0); 16 | }); 17 | 18 | it('can_generate_pvk', async () => { 19 | let pvk = await WalletGenerator.generatePrivateKeyFromMnemonic( 20 | Chains.BTC, 21 | mnemonic, 22 | 0 23 | ); 24 | expect(typeof pvk).toBe('string'); 25 | expect(pvk.length).not.toEqual(0); 26 | }); 27 | 28 | it('can_generate_address_from_xpub', async () => { 29 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BTC, mnemonic); 30 | expect(typeof xpub).toBe('string'); 31 | expect(xpub.length).not.toEqual(0); 32 | let address = await WalletGenerator.generateAddressFromXPub( 33 | Chains.BTC, 34 | xpub, 35 | 0 36 | ); 37 | expect(typeof address).toBe('string'); 38 | expect(address.length).not.toEqual(0); 39 | 40 | xpub = await WalletGenerator.generateWalletXpub(Chains.ETH, mnemonic); 41 | expect(typeof xpub).toBe('string'); 42 | expect(xpub.length).not.toEqual(0); 43 | address = await WalletGenerator.generateAddressFromXPub( 44 | Chains.ETH, 45 | xpub, 46 | 0 47 | ); 48 | expect(typeof address).toBe('string'); 49 | expect(address.length).not.toEqual(0); 50 | 51 | xpub = await WalletGenerator.generateWalletXpub(Chains.BSC, mnemonic); 52 | expect(typeof xpub).toBe('string'); 53 | expect(xpub.length).not.toEqual(0); 54 | address = await WalletGenerator.generateAddressFromXPub( 55 | Chains.BSC, 56 | xpub, 57 | 0 58 | ); 59 | expect(typeof address).toBe('string'); 60 | expect(address.length).not.toEqual(0); 61 | 62 | xpub = await WalletGenerator.generateWalletXpub(Chains.MATIC, mnemonic); 63 | expect(typeof xpub).toBe('string'); 64 | expect(xpub.length).not.toEqual(0); 65 | address = await WalletGenerator.generateAddressFromXPub( 66 | Chains.MATIC, 67 | xpub, 68 | 0 69 | ); 70 | expect(typeof address).toBe('string'); 71 | expect(address.length).not.toEqual(0); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /test/market.test.ts: -------------------------------------------------------------------------------- 1 | import { getAllCoins, getCoins } from '../dist'; 2 | 3 | describe('market', () => { 4 | it('can_get_all_coins', async () => { 5 | let coins = await getAllCoins(); 6 | expect(Object.entries(coins).length).toBe(10); 7 | }); 8 | 9 | it('can_get_some_coins', async () => { 10 | let coins = await getCoins(['bitcoin', 'ethereum']); 11 | expect(Object.entries(coins).length).toBe(2); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/polygonWallet.test.ts: -------------------------------------------------------------------------------- 1 | import { IWalletConfig, WalletFactory } from '../dist'; 2 | import { WalletGenerator } from '../dist'; 3 | import { Chains } from '../dist'; 4 | import { MNEMONIC } from './fixtures'; 5 | import { ETH_ADDRESS_RECEIVER } from './fixtures'; 6 | 7 | let config: IWalletConfig = { 8 | symbol: 'MATIC', 9 | name: 'Polygon Matic', 10 | chain: 'POLYGON', 11 | type: 'coin', 12 | decimals: 18, 13 | contract: null, 14 | options: { 15 | testnet: true, 16 | }, 17 | walletAddress: null, 18 | privKey: null, 19 | }; 20 | 21 | describe('BscWallet', () => { 22 | it('can_get_balance', async () => { 23 | let mnemonic = MNEMONIC; 24 | let xpub = await WalletGenerator.generateWalletXpub( 25 | Chains.POLYGON, 26 | mnemonic 27 | ); 28 | let address = await WalletGenerator.generateAddressFromXPub( 29 | Chains.POLYGON, 30 | xpub, 31 | 0 32 | ); 33 | // console.log(address); 34 | let _config = Object.assign({}, config, { walletAddress: address }); 35 | let w = WalletFactory.getWallet(_config); 36 | let balance = await w.getBalance(); 37 | expect(balance.getValue()).toBeGreaterThan(0); 38 | // console.log(balance.getValue()) 39 | }); 40 | 41 | it('can_get_fee', async () => { 42 | let mnemonic = MNEMONIC; 43 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BSC, mnemonic); 44 | let address = await WalletGenerator.generateAddressFromXPub( 45 | Chains.BSC, 46 | xpub, 47 | 0 48 | ); 49 | let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 50 | Chains.BSC, 51 | mnemonic, 52 | 0 53 | ); 54 | let to = ETH_ADDRESS_RECEIVER; 55 | let _config = Object.assign({}, config, { 56 | walletAddress: address, 57 | privKey: privKey, 58 | }); 59 | let w = WalletFactory.getWallet(_config); 60 | let fees = await w.getTxSendProposals(to, 0.0001); 61 | expect(typeof fees).toBe('object'); 62 | }); 63 | 64 | it('can_send_matic', async () => { 65 | let mnemonic = MNEMONIC; 66 | let xpub = await WalletGenerator.generateWalletXpub( 67 | Chains.POLYGON, 68 | mnemonic 69 | ); 70 | let address = await WalletGenerator.generateAddressFromXPub( 71 | Chains.POLYGON, 72 | xpub, 73 | 0 74 | ); 75 | let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 76 | Chains.POLYGON, 77 | mnemonic, 78 | 0 79 | ); 80 | let to = ETH_ADDRESS_RECEIVER; 81 | let _config = Object.assign({}, config, { 82 | walletAddress: address, 83 | privKey: privKey, 84 | }); 85 | let w = WalletFactory.getWallet(_config); 86 | let balance = await w.getBalance(); 87 | expect(balance.getValue()).toBeGreaterThan(0); 88 | let proposals = await w.getTxSendProposals(to, 0.0001); 89 | expect(typeof proposals).toBe('object'); 90 | let result = await w.postTxSend(proposals.regular); 91 | console.log('result', result); 92 | }); 93 | }); 94 | -------------------------------------------------------------------------------- /test/transactionTokensBSC.test.ts: -------------------------------------------------------------------------------- 1 | import { IWalletConfig, WalletFactory } from '../dist'; 2 | import { WalletGenerator } from '../dist'; 3 | import { Chains } from '../dist'; 4 | import { MNEMONIC } from './fixtures'; 5 | // import { ETH_ADDRESS_RECEIVER } from './fixtures'; 6 | 7 | let config: IWalletConfig = { 8 | symbol: 'CGT', 9 | name: 'CGTest', 10 | chain: 'BSC', 11 | type: 'token', 12 | decimals: 18, 13 | contract: '0x9a7eC0322aD01d7Cb03D410faED912ed92AEa25C', 14 | walletAddress: null, 15 | privKey: null, 16 | }; 17 | 18 | describe('BSC Token Transactions', () => { 19 | it('can_get_name_token', async () => { 20 | let mnemonic = MNEMONIC; 21 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BSC, mnemonic); 22 | let address = await WalletGenerator.generateAddressFromXPub( 23 | Chains.BSC, 24 | xpub, 25 | 0 26 | ); 27 | let _config = Object.assign({}, config, { walletAddress: address }); 28 | _config.name = null; 29 | let w = WalletFactory.getWallet(_config); 30 | let result = await w.getCurrencyName(); 31 | expect(result).toBe(config.name); 32 | }); 33 | 34 | it('can_get_symbol_token', async () => { 35 | let mnemonic = MNEMONIC; 36 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BSC, mnemonic); 37 | let address = await WalletGenerator.generateAddressFromXPub( 38 | Chains.BSC, 39 | xpub, 40 | 0 41 | ); 42 | let _config = Object.assign({}, config, { walletAddress: address }); 43 | _config.symbol = null; 44 | let w = WalletFactory.getWallet(_config); 45 | let result = await w.getCurrencySymbol(); 46 | expect(result).toBe(config.symbol); 47 | }); 48 | 49 | it('can_get_decimals_token', async () => { 50 | let mnemonic = MNEMONIC; 51 | let xpub = await WalletGenerator.generateWalletXpub(Chains.BSC, mnemonic); 52 | let address = await WalletGenerator.generateAddressFromXPub( 53 | Chains.BSC, 54 | xpub, 55 | 0 56 | ); 57 | let _config = Object.assign({}, config, { walletAddress: address }); 58 | _config.decimals = null; 59 | let w = WalletFactory.getWallet(_config); 60 | let decimals = await w.getDecimals(); 61 | expect(decimals).toBeGreaterThan(0); 62 | }); 63 | 64 | // it('can_get_balance_for_token_without_decimals', async () => { 65 | // let mnemonic = MNEMONIC; 66 | // let xpub = await WalletGenerator.generateWalletXpub(Chains.BSC, mnemonic); 67 | // let address = await WalletGenerator.generateAddressFromXPub( 68 | // Chains.BSC, 69 | // xpub, 70 | // 0 71 | // ); 72 | // let _config = Object.assign({}, config, { walletAddress: address }); 73 | // _config.decimals = null; 74 | // let w = WalletFactory.getWallet(_config); 75 | // let decimals = await w.getDecimals(); 76 | // w.config.decimals = decimals; 77 | // let balance = await w.getBalance(); 78 | // expect(balance.getValue()).toBeGreaterThan(0); 79 | // console.log(balance.getValue().toString()); 80 | // }); 81 | 82 | // it('can_get_balance_for_token', async () => { 83 | // let mnemonic = MNEMONIC; 84 | // let xpub = await WalletGenerator.generateWalletXpub(Chains.BSC, mnemonic); 85 | // let address = await WalletGenerator.generateAddressFromXPub(Chains.BSC, xpub, 0); 86 | // let _config = Object.assign({}, config, {walletAddress: address}); 87 | // let w = WalletFactory.getWallet(_config); 88 | // let balance = await w.getBalance(); 89 | // expect(balance.getValue()).toBeGreaterThan(0); 90 | // console.log(balance.getValue().toString()); 91 | // }); 92 | 93 | // it('can_get_fee_for_token', async () => { 94 | // let mnemonic = MNEMONIC; 95 | // let xpub = await WalletGenerator.generateWalletXpub(Chains.BSC, mnemonic); 96 | // let address = await WalletGenerator.generateAddressFromXPub(Chains.BSC, xpub, 0); 97 | // let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic(Chains.BSC, mnemonic, 0); 98 | // let to = ETH_ADDRESS_RECEIVER; 99 | // let _config = Object.assign({}, config, {walletAddress: address, privKey: privKey}); 100 | // let w = WalletFactory.getWallet(_config); 101 | // let fees = await w.getTxSendProposals(to, 100); 102 | // expect(typeof fees).toBe('object'); 103 | // console.log(fees.regular.settings.fee); 104 | // }); 105 | 106 | // it('can_send_token', async () => { 107 | // let mnemonic = MNEMONIC; 108 | // let xpub = await WalletGenerator.generateWalletXpub(Chains.BSC, mnemonic); 109 | // let address = await WalletGenerator.generateAddressFromXPub(Chains.BSC, xpub, 0); 110 | // let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic(Chains.BSC, mnemonic, 0); 111 | // let to = ETH_ADDRESS_RECEIVER; 112 | // let _config = Object.assign({}, config, {walletAddress: address, privKey: privKey}); 113 | // let w = WalletFactory.getWallet(_config); 114 | // let balance = await w.getBalance(); 115 | // expect(balance.getValue()).toBeGreaterThan(0); 116 | // let proposals = await w.getTxSendProposals(to, 100); 117 | // expect(typeof proposals).toBe('object'); 118 | // let result = await w.postTxSend(proposals.regular); 119 | // console.log('result', result); 120 | // }); 121 | }); 122 | -------------------------------------------------------------------------------- /test/transactionTokensETH.test.ts: -------------------------------------------------------------------------------- 1 | import { IWalletConfig, WalletFactory } from '../dist'; 2 | import { WalletGenerator } from '../dist'; 3 | import { Chains } from '../dist'; 4 | import { MNEMONIC } from './fixtures'; 5 | // import { ETH_ADDRESS_RECEIVER } from './fixtures'; 6 | 7 | let config: IWalletConfig = { 8 | symbol: 'CGTEST', 9 | name: 'CGTEST', 10 | chain: 'ETH', 11 | type: 'token', 12 | decimals: 18, 13 | contract: '0xaf3acd9361fd975427761adfe1ca234c88137a06', 14 | walletAddress: null, 15 | privKey: null, 16 | }; 17 | 18 | describe('Ethereum Token Transactions', () => { 19 | it('can_get_decimals_token', async () => { 20 | let mnemonic = MNEMONIC; 21 | let xpub = await WalletGenerator.generateWalletXpub(Chains.ETH, mnemonic); 22 | let address = await WalletGenerator.generateAddressFromXPub( 23 | Chains.ETH, 24 | xpub, 25 | 0 26 | ); 27 | let _config = Object.assign({}, config, { walletAddress: address }); 28 | _config.decimals = null; 29 | let w = WalletFactory.getWallet(_config); 30 | console.log(w.currency); 31 | let decimals = await w.getDecimals(); 32 | expect(decimals).toBeGreaterThan(0); 33 | console.log('decimals', decimals); 34 | }); 35 | 36 | // it('can_get_balance_for_token_without_decimals', async () => { 37 | // let mnemonic = MNEMONIC; 38 | // let xpub = await WalletGenerator.generateWalletXpub(Chains.ETH, mnemonic); 39 | // let address = await WalletGenerator.generateAddressFromXPub( 40 | // Chains.ETH, 41 | // xpub, 42 | // 0 43 | // ); 44 | // let _config = Object.assign({}, config, { walletAddress: address }); 45 | // _config.decimals = null; 46 | // let w = WalletFactory.getWallet(_config); 47 | // let decimals = await w.getDecimals(); 48 | // w.config.decimals = decimals; 49 | // let balance = await w.getBalance(); 50 | // expect(balance.getValue()).toBeGreaterThan(0); 51 | // console.log(balance.getValue().toString()); 52 | // }); 53 | 54 | // it('can_get_balance_for_token', async () => { 55 | // let mnemonic = MNEMONIC; 56 | // let xpub = await WalletGenerator.generateWalletXpub(Chains.ETH, mnemonic); 57 | // let address = await WalletGenerator.generateAddressFromXPub( 58 | // Chains.ETH, 59 | // xpub, 60 | // 0 61 | // ); 62 | // let _config = Object.assign({}, config, { walletAddress: address }); 63 | // let w = WalletFactory.getWallet(_config); 64 | // let balance = await w.getBalance(); 65 | // expect(balance.getValue()).toBeGreaterThan(0); 66 | // console.log(balance.getValue().toString()); 67 | // }); 68 | 69 | // it('can_get_fee_for_token', async () => { 70 | // let mnemonic = MNEMONIC; 71 | // let xpub = await WalletGenerator.generateWalletXpub(Chains.ETH, mnemonic); 72 | // let address = await WalletGenerator.generateAddressFromXPub( 73 | // Chains.ETH, 74 | // xpub, 75 | // 0 76 | // ); 77 | // let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 78 | // Chains.ETH, 79 | // mnemonic, 80 | // 0 81 | // ); 82 | // let to = ETH_ADDRESS_RECEIVER; 83 | // let _config = Object.assign({}, config, { 84 | // walletAddress: address, 85 | // privKey: privKey, 86 | // }); 87 | // let w = WalletFactory.getWallet(_config); 88 | // let fees = await w.getTxSendProposals(to, 100); 89 | // expect(typeof fees).toBe('object'); 90 | // console.log(fees.regular.settings.fee); 91 | // }); 92 | 93 | // it('can_send_token', async () => { 94 | // let mnemonic = MNEMONIC; 95 | // let xpub = await WalletGenerator.generateWalletXpub(Chains.ETH, mnemonic); 96 | // let address = await WalletGenerator.generateAddressFromXPub( 97 | // Chains.ETH, 98 | // xpub, 99 | // 0 100 | // ); 101 | // let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 102 | // Chains.ETH, 103 | // mnemonic, 104 | // 0 105 | // ); 106 | // let to = ETH_ADDRESS_RECEIVER; 107 | // let _config = Object.assign({}, config, { 108 | // walletAddress: address, 109 | // privKey: privKey, 110 | // }); 111 | // let w = WalletFactory.getWallet(_config); 112 | // let balance = await w.getBalance(); 113 | // expect(balance.getValue()).toBeGreaterThan(0); 114 | // let proposals = await w.getTxSendProposals(to, 100); 115 | // expect(typeof proposals).toBe('object'); 116 | // let result = await w.postTxSend(proposals.regular); 117 | // console.log('result', result); 118 | // }); 119 | }); 120 | -------------------------------------------------------------------------------- /test/transactionTokensPOLYGON.test.ts: -------------------------------------------------------------------------------- 1 | import { IWalletConfig, WalletFactory } from '../dist'; 2 | import { WalletGenerator } from '../dist'; 3 | import { Chains } from '../dist'; 4 | import { MNEMONIC } from './fixtures'; 5 | import { ETH_ADDRESS_RECEIVER } from './fixtures'; 6 | 7 | let config: IWalletConfig = { 8 | symbol: 'TST', 9 | name: 'Polygon Test Token', 10 | chain: 'POLYGON', 11 | type: 'token', 12 | decimals: 18, 13 | contract: '0x2d7882bedcbfddce29ba99965dd3cdf7fcb10a1e', 14 | options: { 15 | testnet: true, 16 | }, 17 | walletAddress: null, 18 | privKey: null, 19 | }; 20 | 21 | describe('BSC Token Transactions', () => { 22 | it('can_get_decimals_token', async () => { 23 | let mnemonic = MNEMONIC; 24 | let xpub = await WalletGenerator.generateWalletXpub( 25 | Chains.POLYGON, 26 | mnemonic 27 | ); 28 | let address = await WalletGenerator.generateAddressFromXPub( 29 | Chains.POLYGON, 30 | xpub, 31 | 0 32 | ); 33 | let _config = Object.assign({}, config, { walletAddress: address }); 34 | _config.decimals = null; 35 | let w = WalletFactory.getWallet(_config); 36 | console.log(w.currency); 37 | let decimals = await w.getDecimals(); 38 | expect(decimals).toBeGreaterThan(0); 39 | console.log('decimals', decimals); 40 | }); 41 | 42 | it('can_get_balance_for_token_without_decimals', async () => { 43 | let mnemonic = MNEMONIC; 44 | let xpub = await WalletGenerator.generateWalletXpub( 45 | Chains.POLYGON, 46 | mnemonic 47 | ); 48 | let address = await WalletGenerator.generateAddressFromXPub( 49 | Chains.POLYGON, 50 | xpub, 51 | 0 52 | ); 53 | let _config = Object.assign({}, config, { walletAddress: address }); 54 | _config.decimals = null; 55 | let w = WalletFactory.getWallet(_config); 56 | let decimals = await w.getDecimals(); 57 | w.config.decimals = decimals; 58 | let balance = await w.getBalance(); 59 | expect(balance.getValue()).toBeGreaterThan(0); 60 | console.log(balance.getValue().toString()); 61 | }); 62 | 63 | it('can_get_balance_for_token', async () => { 64 | let mnemonic = MNEMONIC; 65 | let xpub = await WalletGenerator.generateWalletXpub( 66 | Chains.POLYGON, 67 | mnemonic 68 | ); 69 | let address = await WalletGenerator.generateAddressFromXPub( 70 | Chains.POLYGON, 71 | xpub, 72 | 0 73 | ); 74 | let _config = Object.assign({}, config, { walletAddress: address }); 75 | let w = WalletFactory.getWallet(_config); 76 | let balance = await w.getBalance(); 77 | expect(balance.getValue()).toBeGreaterThan(0); 78 | console.log(balance.getValue().toString()); 79 | }); 80 | 81 | it('can_get_fee_for_token', async () => { 82 | let mnemonic = MNEMONIC; 83 | let xpub = await WalletGenerator.generateWalletXpub( 84 | Chains.POLYGON, 85 | mnemonic 86 | ); 87 | let address = await WalletGenerator.generateAddressFromXPub( 88 | Chains.POLYGON, 89 | xpub, 90 | 0 91 | ); 92 | let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 93 | Chains.POLYGON, 94 | mnemonic, 95 | 0 96 | ); 97 | let to = ETH_ADDRESS_RECEIVER; 98 | let _config = Object.assign({}, config, { 99 | walletAddress: address, 100 | privKey: privKey, 101 | }); 102 | let w = WalletFactory.getWallet(_config); 103 | let fees = await w.getTxSendProposals(to, 0.00001); 104 | expect(typeof fees).toBe('object'); 105 | console.log(fees.regular.settings.fee); 106 | }); 107 | 108 | it('can_send_token', async () => { 109 | let mnemonic = MNEMONIC; 110 | let xpub = await WalletGenerator.generateWalletXpub( 111 | Chains.POLYGON, 112 | mnemonic 113 | ); 114 | let address = await WalletGenerator.generateAddressFromXPub( 115 | Chains.POLYGON, 116 | xpub, 117 | 0 118 | ); 119 | let privKey = await WalletGenerator.generatePrivateKeyFromMnemonic( 120 | Chains.POLYGON, 121 | mnemonic, 122 | 0 123 | ); 124 | let to = ETH_ADDRESS_RECEIVER; 125 | let _config = Object.assign({}, config, { 126 | walletAddress: address, 127 | privKey: privKey, 128 | }); 129 | let w = WalletFactory.getWallet(_config); 130 | let balance = await w.getBalance(); 131 | expect(balance.getValue()).toBeGreaterThan(0); 132 | let proposals = await w.getTxSendProposals(to, 0.00001); 133 | expect(typeof proposals).toBe('object'); 134 | let result = await w.postTxSend(proposals.regular); 135 | console.log('result', result); 136 | }); 137 | }); 138 | -------------------------------------------------------------------------------- /test/transactions.test.ts: -------------------------------------------------------------------------------- 1 | import { CONFIG, Fees, Transactions, Generators, IWalletConfig } from '../dist'; 2 | import { 3 | BTC_ADDRESS_RECEIVER, 4 | ETH_ADDRESS_RECEIVER, 5 | MNEMONIC, 6 | } from './fixtures'; 7 | 8 | const BTC_DESCRIPTOR: IWalletConfig = { 9 | symbol: 'BTC', 10 | name: 'Bitcoin', 11 | chain: 'BTC', 12 | type: 'coin', 13 | decimals: 8, 14 | contract: null, 15 | walletAddress: null, 16 | privKey: null, 17 | }; 18 | 19 | const ETH_DESCRIPTOR: IWalletConfig = { 20 | symbol: 'ETH', 21 | name: 'Ethereum', 22 | chain: 'BTC', 23 | type: 'ETH', 24 | decimals: 18, 25 | contract: null, 26 | walletAddress: null, 27 | privKey: null, 28 | }; 29 | 30 | const BSC_DESCRIPTOR: IWalletConfig = { 31 | symbol: 'BNB', 32 | name: 'BNB', 33 | chain: 'BSC', 34 | type: 'coin', 35 | decimals: 18, 36 | contract: null, 37 | walletAddress: null, 38 | privKey: null, 39 | }; 40 | 41 | const POLYGON_DESCRIPTOR: IWalletConfig = { 42 | symbol: 'MATIC', 43 | name: 'MATIC', 44 | chain: 'POLYGON', 45 | type: 'coin', 46 | decimals: 18, 47 | contract: null, 48 | walletAddress: null, 49 | privKey: null, 50 | }; 51 | 52 | describe('Transactions', () => { 53 | it('can_use_btc_driver', async () => { 54 | let mnemonic = MNEMONIC; 55 | let xpub = await Generators.BitcoinGenerator.generateWalletXpub( 56 | mnemonic, 57 | CONFIG 58 | ); 59 | let from = await Generators.BitcoinGenerator.generateAddressFromXPub( 60 | xpub, 61 | 0, 62 | CONFIG 63 | ); 64 | let privKey = await Generators.BitcoinGenerator.generatePrivateKeyFromMnemonic( 65 | mnemonic, 66 | 0 67 | ); 68 | let config = Object.assign({}, BTC_DESCRIPTOR, { 69 | privKey: privKey, 70 | walletAddress: from, 71 | }); 72 | let to = BTC_ADDRESS_RECEIVER; 73 | let d = new Fees.BTC_Driver( 74 | config, 75 | CONFIG.CHAIN_ENDPOINTS.BTC.fee[0].config 76 | ); 77 | let proposals = await d.getTxSendProposals(to, 0.00001); 78 | expect(typeof proposals).toBe('object'); 79 | let fee = proposals.regular; 80 | let txHandler = new Transactions.BTC_Driver( 81 | config, 82 | CONFIG.CHAIN_ENDPOINTS.BTC.transaction[0].config 83 | ); 84 | let signedTx = await txHandler.prepareSignedTransaction(fee.getData()); 85 | expect(typeof signedTx).toBe('string'); 86 | expect(signedTx.length).toBeGreaterThan(0); 87 | let sent = await txHandler.send(fee); 88 | expect(sent.length).toBeGreaterThan(0); 89 | // console.log(sent); 90 | }); 91 | 92 | it('can_use_eth_driver', async () => { 93 | let mnemonic = MNEMONIC; 94 | let xpub = await Generators.EthereumGenerator.generateWalletXpub( 95 | mnemonic, 96 | CONFIG 97 | ); 98 | let from = await Generators.EthereumGenerator.generateAddressFromXPub( 99 | xpub, 100 | 0, 101 | CONFIG 102 | ); 103 | let privKey = await Generators.EthereumGenerator.generatePrivateKeyFromMnemonic( 104 | mnemonic, 105 | 0 106 | ); 107 | let to = ETH_ADDRESS_RECEIVER; 108 | let config = Object.assign({}, ETH_DESCRIPTOR, { 109 | privKey: privKey, 110 | walletAddress: from, 111 | }); 112 | let d = new Fees.ETH_Driver( 113 | config, 114 | CONFIG.CHAIN_ENDPOINTS.ETH.fee[0].config 115 | ); 116 | let proposals = await d.getTxSendProposals(to, 0.00001); 117 | expect(typeof proposals).toBe('object'); 118 | let fee = proposals.regular; 119 | let txHandler = new Transactions.ETH_Driver( 120 | config, 121 | CONFIG.CHAIN_ENDPOINTS.ETH.transaction[0].config 122 | ); 123 | let signedTx = await txHandler.prepareSignedTransaction(fee.getData()); 124 | expect(typeof signedTx).toBe('string'); 125 | expect(signedTx.length).toBeGreaterThan(0); 126 | let sent = await txHandler.send(fee); 127 | expect(sent.length).toBeGreaterThan(0); 128 | // console.log(sent); 129 | }); 130 | 131 | it('can_use_bsc_driver', async () => { 132 | let mnemonic = MNEMONIC; 133 | let xpub = await Generators.EthereumGenerator.generateWalletXpub( 134 | mnemonic, 135 | CONFIG 136 | ); 137 | let from = await Generators.EthereumGenerator.generateAddressFromXPub( 138 | xpub, 139 | 0, 140 | CONFIG 141 | ); 142 | let privKey = await Generators.EthereumGenerator.generatePrivateKeyFromMnemonic( 143 | mnemonic, 144 | 0 145 | ); 146 | let to = ETH_ADDRESS_RECEIVER; 147 | let config = Object.assign({}, BSC_DESCRIPTOR, { 148 | privKey: privKey, 149 | walletAddress: from, 150 | }); 151 | let d = new Fees.BSC_Driver( 152 | config, 153 | CONFIG.CHAIN_ENDPOINTS.BSC.fee[0].config 154 | ); 155 | let proposals = await d.getTxSendProposals(to, 0.00001); 156 | expect(typeof proposals).toBe('object'); 157 | let fee = proposals.regular; 158 | let txHandler = new Transactions.BSC_Driver( 159 | config, 160 | CONFIG.CHAIN_ENDPOINTS.BSC.transaction[0].config 161 | ); 162 | let signedTx = await txHandler.prepareSignedTransaction(fee.getData()); 163 | expect(typeof signedTx).toBe('string'); 164 | expect(signedTx.length).toBeGreaterThan(0); 165 | let sent = await txHandler.send(fee); 166 | expect(sent.length).toBeGreaterThan(0); 167 | // console.log(sent); 168 | }); 169 | 170 | it('can_use_polygon_driver', async () => { 171 | let mnemonic = MNEMONIC; 172 | let xpub = await Generators.PolygonGenerator.generateWalletXpub( 173 | mnemonic, 174 | CONFIG 175 | ); 176 | let from = await Generators.PolygonGenerator.generateAddressFromXPub( 177 | xpub, 178 | 0, 179 | CONFIG 180 | ); 181 | let privKey = await Generators.PolygonGenerator.generatePrivateKeyFromMnemonic( 182 | mnemonic, 183 | 0 184 | ); 185 | let to = ETH_ADDRESS_RECEIVER; 186 | let config = Object.assign({}, POLYGON_DESCRIPTOR, { 187 | privKey: privKey, 188 | walletAddress: from, 189 | }); 190 | let d = new Fees.POLYGON_Driver( 191 | config, 192 | CONFIG.CHAIN_ENDPOINTS.POLYGON.fee[0].config 193 | ); 194 | let proposals = await d.getTxSendProposals(to, 0.00001); 195 | expect(typeof proposals).toBe('object'); 196 | let fee = proposals.regular; 197 | let txHandler = new Transactions.POLYGON_Driver( 198 | config, 199 | CONFIG.CHAIN_ENDPOINTS.POLYGON.transaction[0].config 200 | ); 201 | let signedTx = await txHandler.prepareSignedTransaction(fee.getData()); 202 | expect(typeof signedTx).toBe('string'); 203 | expect(signedTx.length).toBeGreaterThan(0); 204 | let sent = await txHandler.send(fee); 205 | expect(sent.length).toBeGreaterThan(0); 206 | // console.log(sent); 207 | }); 208 | }); 209 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs 3 | "include": ["src", "types"], 4 | "compilerOptions": { 5 | "module": "esnext", 6 | "lib": ["dom", "esnext"], 7 | "importHelpers": true, 8 | // output .d.ts declaration files for consumers 9 | "declaration": true, 10 | // output .js.map sourcemap files for consumers 11 | "sourceMap": true, 12 | // match output dir to input dir. e.g. dist/index instead of dist/src/index 13 | "rootDir": "./src", 14 | // stricter type-checking for stronger correctness. Recommended by TS 15 | "strict": true, 16 | // linter checks for common issues 17 | "noImplicitReturns": false, 18 | "noFallthroughCasesInSwitch": true, 19 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | // use Node's module resolution algorithm, instead of the legacy TS one 23 | "moduleResolution": "node", 24 | // transpile JSX to React.createElement 25 | "jsx": "react", 26 | // interop between ESM and CJS modules. Recommended by TS 27 | "esModuleInterop": true, 28 | "allowSyntheticDefaultImports": true, 29 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS 30 | "skipLibCheck": true, 31 | // error out if import and file system have a casing mismatch. Recommended by TS 32 | "forceConsistentCasingInFileNames": true, 33 | // `tsdx build` ignores this option, but it is commonly used when type-checking separately with `tsc` 34 | "noEmit": true, 35 | "resolveJsonModule": true 36 | } 37 | } 38 | --------------------------------------------------------------------------------