├── .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 | - BitcoinGenerator ⇐
GenericGenerator
25 |
26 | - BscGenerator ⇐
EthereumGenerator
27 |
28 | - EthereumGenerator ⇐
GenericGenerator
29 |
30 | - PolygonGenerator ⇐
EthereumGenerator
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 |
--------------------------------------------------------------------------------