├── .gitignore ├── LICENSE.md ├── README.md ├── package-lock.json ├── package.json └── src ├── dtos ├── addressDTO.js ├── baseDTO.js ├── broadcastSignedTxDTO.js ├── errorDTO.js ├── hdAddressesDTO.js ├── hdWalletDTO.js ├── index.js ├── listSyncedAddressesDTO.js ├── prepare │ ├── UTXOBasedTransaction.js │ ├── accountBasedTransactionDTO.js │ └── transactionDTO.js ├── signDTO.js ├── subscriptionForUnconfirmedCoinsTxsDTO.js ├── subscriptionForUnconfirmedInternalTxsDTO.js ├── subscriptionForUnconfirmedTokensTxsDTO.js └── walletDTO.js ├── enumerations ├── blockchainEnum.js ├── feePriorityEnum.js ├── index.js ├── networkEnum.js ├── prepareStrategyEnum.js └── tokenEnum.js ├── helpers ├── generateAddress │ ├── baseGeneratorHelper.js │ ├── bscGeneratorHelper.js │ ├── btcGeneratorHelper.js │ ├── etcGeneratorHelper.js │ ├── ethGeneratorHelper.js │ ├── generatorHelperFactory.js │ ├── zcash │ │ ├── base58.js │ │ └── hash.js │ └── zcashGeneratorHelper.js ├── prepare │ ├── UTXOBasedPrepareHelper.js │ ├── accountBasedHDWalletPrepareHelper.js │ ├── accountBasedSingleAddressPrepareHelper.js │ ├── basePrepareHelper.js │ └── tokenTransactions │ │ ├── erc20TokenPrepare.js │ │ ├── erc721TokenPrepare.js │ │ └── tokenPrepareFactory.js ├── sign │ ├── baseSignerHelper.js │ ├── bchSignerHelper.js │ ├── bscSignerHelper.js │ ├── btcSignerHelper.js │ ├── dashSignerHelper.js │ ├── dogecoinSignerHelper.js │ ├── etcSignerHelper.js │ ├── ethSignerHelper.js │ ├── ltcSignerHelper.js │ └── signerHelperFactory.js └── xpubFormatsHelper.js ├── index.js ├── kmsClient.js ├── models ├── feeOptionsModel.js ├── index.js └── recipientModel.js ├── services ├── addressService.js ├── baseServices.js ├── broadcastService.js ├── hdWalletsService.js ├── index.js ├── prepareService.js ├── signService.js ├── subscriptionsService.js └── walletService.js └── validators ├── blockchainValidator.js ├── configValidator.js └── customErrors.js /.gitignore: -------------------------------------------------------------------------------- 1 | # These are some examples of commonly ignored file patterns. 2 | # You should customize this list as applicable to your project. 3 | # Learn more about .gitignore: 4 | # https://www.atlassian.com/git/tutorials/saving-changes/gitignore 5 | 6 | # Node artifact files 7 | node_modules/ 8 | dist/ 9 | 10 | # Compiled Java class files 11 | *.class 12 | 13 | # Compiled Python bytecode 14 | *.py[cod] 15 | 16 | # Log files 17 | *.log 18 | 19 | # Package files 20 | *.jar 21 | 22 | # Maven 23 | target/ 24 | dist/ 25 | 26 | # JetBrains IDE 27 | .idea/ 28 | 29 | # Unit test reports 30 | TEST*.xml 31 | 32 | # Generated by MacOS 33 | .DS_Store 34 | 35 | # Generated by Windows 36 | Thumbs.db 37 | 38 | # Applications 39 | *.app 40 | *.exe 41 | *.war 42 | 43 | # Large media files 44 | *.mp4 45 | *.tiff 46 | *.avi 47 | *.flv 48 | *.mov 49 | *.wmv 50 | 51 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Crypto APIs 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ⚠️ SDK Deprecation Notice 2 | 3 | > **Status:** Archived & Deprecated 4 | > **Effective Date:** 1st April, 2025 5 | 6 | --- 7 | 8 | This SDK has been officially **deprecated** and is no longer actively maintained or updated. 9 | 10 | To give you more flexibility, we recommend generating your own SDK using our official **OpenAPI specification**, available for download from the Crypto APIs Developer Portal: 11 | 12 | 👉 [https://developers.cryptoapis.io/](https://developers.cryptoapis.io/) 13 | 14 | --- 15 | 16 | ## 💡 Recommended Approach 17 | 18 | You can easily generate SDKs in most major programming languages using tools such as: 19 | 20 | - [OpenAPI Generator](https://openapi-generator.tech/) 21 | - [Swagger Codegen](https://swagger.io/tools/swagger-codegen/) 22 | 23 | Simply use our OpenAPI JSON to create SDKs tailored to your specific needs. 24 | 25 | --- 26 | 27 | This repository will remain available for reference but is no longer supported. 28 | 29 | For questions, please contact us via our official support channels. 30 | 31 | --- 32 | 33 | _Thank you for your understanding and for building with Crypto APIs!_ 34 | 35 | 36 | # Crypto APIs - Key Management System Tool (KMS) 37 | 38 | Crypto APIs KMS (Key Management System) is an open-source Node.js library. It gives companies full custody of master private keys, master seeds, and mnemonics. The library allows businesses to create HD wallets (xPubs) and sign transactions locally without a network connection (offline). It can be used in combination with Crypto APIs product suite for syncing xPub, deriving wallet addresses, listing wallet addresses, getting fee recommendations, preparing the transaction with the right data, broadcasting locally signed transactions. 39 | The KMS is perfect for B2C companies, including hardware wallets and digital wallets, as well as custodial or non-custodial exchanges. By using Crypto API's open-source library, they can easily scale to satisfy the demand and create wallets for millions of users. The businesses can decide whether to hold custody of their clients' master keys, master seed, and mnemonic or give them to their customers instead. 40 | 41 | - Package version: 0.7.2 42 | - For more information, please visit [https://cryptoapis.io](https://cryptoapis.io) 43 | - minimum requirement NodeJS >= 14.0 44 | 45 | ## Installation 46 | 47 | ### For [Node.js](https://nodejs.org/) 48 | 49 | #### npm 50 | 51 | Then install it via: 52 | 53 | ```shell 54 | npm install cryptoapis-kms 55 | ``` 56 | 57 | ## Usage 58 | 59 | ## generateAddress 60 | This method generates and returns a new public and private key pair, and the associated address with it. 61 | 62 | ### Example 63 | 64 | ```javascript 65 | const { Enumerations, Services } = require('cryptoapis-kms'); 66 | const blockchain = Enumerations.Blockchains.BITCOIN; 67 | const network = Enumerations.Networks[blockchain].NETWORK_BITCOIN_MAINNET; 68 | 69 | const addressService = new Services.AddressService(blockchain, network) 70 | const address = addressService.generateAddress(); 71 | console.dir('New address generated successfully. Returned data:'); 72 | console.dir(address) 73 | console.dir(address.address) 74 | console.dir(address.privateKey) 75 | console.dir(address.publicKey) 76 | ``` 77 | 78 | ### Return type 79 | 80 | AddressDTO 81 | 82 | ## createHDWallet (xPub, yPub, zPub) 83 | This method generates a new HD Wallet for a specific blockchain and network. The response from the endpoint should be stored, 84 | otherwise the data is lost and cannot be recovered. 85 | 86 | `zPub`(bip84) is supported only by bitcoin and litecoin. 87 | 88 | ### Example 89 | 90 | ```javascript 91 | const { Enumerations, Services } = require('cryptoapis-kms'); 92 | const blockchain = Enumerations.Blockchains.BITCOIN; 93 | const network = Enumerations.Networks[blockchain].NETWORK_BITCOIN_MAINNET; 94 | 95 | (async () => { 96 | const walletService = new Services.WalletService(blockchain, network); 97 | const wallet = await walletService.createHDWallet().then((data) => { 98 | console.dir('HD Wallet created successfully. Returned data:'); 99 | console.dir(data); 100 | console.dir(data.xPub.accountXpriv); 101 | console.dir(data.xPub.accountXpub); 102 | }, (error) => { 103 | console.log(error) 104 | }); 105 | })(); 106 | ``` 107 | 108 | ### Parameters 109 | 110 | Name | Type | Description | Notes 111 | ------------- |------------|------------------------------------------------------------------| ------------- 112 | **mnemonicWordsCount** | **Number** | Mnemonic words count. Possible values are 12(default), 18 or 24. | [optional] 113 | 114 | 115 | ### Return type 116 | 117 | WalletDTO 118 | 119 | ## syncNewHDWallet (xPub, yPub, zPub) 120 | After initial sync we keep updating the synced xpub all the time. 121 | 122 | ### Example 123 | 124 | ```javascript 125 | const {Enumerations, Client, Services } = require('cryptoapis-kms'); 126 | const blockchain = Enumerations.Blockchains.BITCOIN; 127 | const network = Enumerations.Networks[blockchain].NETWORK_BITCOIN_MAINNET; 128 | const client = new Client('YOUR API KEY', blockchain, network); 129 | const xPub = 'xpub6BsFsonVJR5vPChKQamp55R7veBCMD2CL3LtL83B3FS5DiayYgmoHCGQodeLTukaa4anZRQD9kNtPFHuPnCzjCiT9nrXdf3voNLhXQryBRB'; 130 | 131 | client.syncNewHDWallet(xPub).then((data) => { 132 | console.dir('API called successfully. Returned data:'); 133 | console.dir(data); 134 | }, (error) => { 135 | console.log(error); 136 | }); 137 | ``` 138 | 139 | ### Parameters 140 | 141 | Name | Type | Description | Notes 142 | ------------- | ------------- | ------------- | ------------- 143 | **xPub** | **String**| Defines the account extended publicly known key which is used to derive all child public keys. | 144 | **context** | **String**| In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. | [optional] 145 | 146 | ### Return type 147 | 148 | HDWalletDTO 149 | 150 | ### Authorization 151 | 152 | [ApiKey](#ApiKey) 153 | 154 | ## deriveAndSyncNewChangeAddresses 155 | Through this endpoint users can derive 100 change addresses, starting from the last index we have data for, 156 | which are then added to the xPub, subscribed for syncing, and start recording data. If no data is available, 157 | it will start from index 0. 158 | ### Example 159 | 160 | ```javascript 161 | const {Enumerations, Client, Services } = require('cryptoapis-kms'); 162 | const blockchain = Enumerations.Blockchains.BITCOIN; 163 | const network = Enumerations.Networks[blockchain].NETWORK_BITCOIN_MAINNET; 164 | const client = new Client('YOUR API KEY', blockchain, network); 165 | const xPub = 'xpub6BsFsonVJR5vPChKQamp55R7veBCMD2CL3LtL83B3FS5DiayYgmoHCGQodeLTukaa4anZRQD9kNtPFHuPnCzjCiT9nrXdf3voNLhXQryBRB'; 166 | 167 | client.deriveAndSyncNewChangeAddresses(xPub).then((data) => { 168 | console.dir('API called successfully. Returned data:'); 169 | console.dir(data); 170 | }, (error) => { 171 | console.log(error); 172 | }); 173 | ``` 174 | 175 | ### Parameters 176 | 177 | Name | Type | Description | Notes 178 | ------------- | ------------- | ------------- | ------------- 179 | **xPub** | **String**| Defines the account extended publicly known key which is used to derive all child public keys. | 180 | **context** | **String**| In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. | [optional] 181 | 182 | ### Return type 183 | 184 | HDWalletDTO 185 | 186 | ### Authorization 187 | 188 | [ApiKey](#ApiKey) 189 | 190 | 191 | ## deriveAndSyncNewReceivingAddresses 192 | Through this endpoint users can derive 100 receiving addresses, starting from the last index we have data for, 193 | which are then added to the xPub, subscribed for syncing, and start recording data. If no data is available, it will 194 | start from index 0. 195 | ### Example 196 | 197 | ```javascript 198 | const {Enumerations, Client, Services } = require('cryptoapis-kms'); 199 | const blockchain = Enumerations.Blockchains.BITCOIN; 200 | const network = Enumerations.Networks[blockchain].NETWORK_BITCOIN_MAINNET; 201 | const client = new Client('YOUR API KEY', blockchain, network); 202 | const xPub = 'xpub6BsFsonVJR5vPChKQamp55R7veBCMD2CL3LtL83B3FS5DiayYgmoHCGQodeLTukaa4anZRQD9kNtPFHuPnCzjCiT9nrXdf3voNLhXQryBRB'; 203 | 204 | client.deriveAndSyncNewReceivingAddresses(xPub).then((data) => { 205 | console.dir('API called successfully. Returned data:'); 206 | console.dir(data); 207 | }, (error) => { 208 | console.log(error); 209 | }); 210 | ``` 211 | 212 | ### Parameters 213 | 214 | Name | Type | Description | Notes 215 | ------------- | ------------- | ------------- | ------------- 216 | **xPub** | **String**| Defines the account extended publicly known key which is used to derive all child public keys. | 217 | **context** | **String**| In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. | [optional] 218 | 219 | ### Return type 220 | 221 | HDWalletDTO 222 | 223 | ### Authorization 224 | 225 | [ApiKey](#ApiKey) 226 | 227 | 228 | ## listSyncedAddresses 229 | Through this endpoint users can list all addresses that Crypto APIs has synced for a specific xPub. This includes 230 | previous and current/new xPubs, what addresses we’ve synced for them, etc. 231 | ### Example 232 | 233 | ```javascript 234 | const {Enumerations, Client, Services } = require('cryptoapis-kms'); 235 | const blockchain = Enumerations.Blockchains.BITCOIN; 236 | const network = Enumerations.Networks[blockchain].NETWORK_BITCOIN_MAINNET; 237 | const client = new Client('YOUR API KEY', blockchain, network); 238 | const xPub = 'xpub6BsFsonVJR5vPChKQamp55R7veBCMD2CL3LtL83B3FS5DiayYgmoHCGQodeLTukaa4anZRQD9kNtPFHuPnCzjCiT9nrXdf3voNLhXQryBRB'; 239 | const opts = { 240 | context: 'yourExampleString', 241 | addressFormat: "P2WPKH", 242 | isChangeAddress: true, 243 | limit: 15, 244 | }; 245 | client.listSyncedAddresses(xPub, opts).then((data) => { 246 | console.dir('API called successfully. Returned data:'); 247 | console.dir(data); 248 | }, (error) => { 249 | console.log(error); 250 | }); 251 | ``` 252 | 253 | ### Parameters 254 | 255 | Name | Type | Description | Notes 256 | ------------- |------------| ------------ | ------------- 257 | **xPub** | **String** | Defines the account extended publicly known key which is used to derive all child public keys. | 258 | **opts** | **Object** | Optional parameters | [optional] 259 | **opts.context** | **String** | In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. | [optional] 260 | **opts.addressFormat** | **String** | Defines if the address is change addres or not. (default to true) | [optional] 261 | **opts.isChangeAddress** | **String** | Represents the format of the address | [optional] 262 | **opts.limit** | **String** | Defines how many items should be returned in the response per page basis. | [optional] 263 | **opts.offset** | **String** | The starting index of the response items, i.e. where the response should start listing the returned items | [optional] 264 | 265 | ### Return type 266 | 267 | ListSyncedAddressesDTO 268 | 269 | ### Authorization 270 | 271 | [ApiKey](#ApiKey) 272 | 273 | ## prepareUTXOBasedTransactionFromHDWallet (xPub, yPub, zPub) 274 | Through the “Prepare a UTXO-based transaction from HD Wallet” endpoint users can prepare a transaction for 275 | signing from all synced with Crypto APIs addresses for the specific xPub. This is based on the 276 | `selectionStrategy` and the addresses’ balances. In the case a user has an address not synced with Crypto APIs, 277 | it will not be included. This endpoint applies to all supported UTXO-based blockchain protocols, e.g. Bitcoin, 278 | Litecoin, etc. 279 | 280 | ### Example 281 | 282 | ```javascript 283 | const {Enumerations, Client, Services, Models } = require('cryptoapis-kms'); 284 | const blockchain = Enumerations.Blockchains.BITCOIN; 285 | const network = Enumerations.Networks[blockchain].NETWORK_BITCOIN_MAINNET; 286 | const client = new Client('YOUR API KEY', blockchain, network); 287 | const xPub = "xpub6BsFsonVJR5vPChKQamp55R7veBCMD2CL3LtL83B3FS5DiayYgmoHCGQodeLTukaa4anZRQD9kNtPFHuPnCzjCiT9nrXdf3voNLhXQryBRB" 288 | const feeOptions = new Models.UTXOBasedFeeOptionsModel({ 289 | prepareStrategy: Enumerations.PrepareStrategies.MINIMIZE_DUST, 290 | priority: Enumerations.FeePriorities.FAST, 291 | }); 292 | const recipients = [ 293 | new Models.RecipientModel("tb1q8qrk9pxkjcuk4a29ec7snskaxll55jzfhrcq24", '0.000031') 294 | ]; 295 | 296 | const preparedUTXOTransaction = await client.prepareUTXOBasedTransactionFromHDWallet({ 297 | xPub: xPub, 298 | recipients: recipients, 299 | feeOptions, 300 | }).then((data) => { 301 | console.dir('API called successfully. Returned data:'); 302 | console.dir(data); 303 | }, (error) => { 304 | console.log(error) 305 | }) 306 | ``` 307 | 308 | ### Parameters 309 | 310 | Name | Type | Description | Notes 311 | ------------- |--------------------------|----------------------------------------------------------------------| ------------- 312 | **xPub** | **String** | Account Extended Public Key | 313 | **recipients** | **Array<**RecipientModel**>** | Represents a list of recipient addresses with the respective amounts | 314 | **feeOptions** | **UTXOBasedFeeOptionsModel** | Represents the fee options | 315 | **feeOptions.address** | **string** | Represents the fee address | [optional] 316 | **feeOptions.priority** | **string** | Represents the fee priority | [optional] 317 | **feeOptions.feeAmount** | **string** | Represents the fee amount | [optional] 318 | **locktime** | **Number** | Represents the time at which a particular transaction can be added to the blockchain | [optional] 319 | **replaceable** | **Boolean** | Representation of whether the transaction is replaceable | [optional] 320 | **data** | **string** | Representation of the additional data | [optional] 321 | 322 | ### Return type 323 | 324 | UTXOBasedTransactionDTO 325 | 326 | ### Authorization 327 | 328 | [ApiKey](#ApiKey) 329 | 330 | ## prepareAccountBasedTransactionFromHDWallet (xPub, yPub, zPub) 331 | Through the “Prepare an account-based transaction from HD Wallet” endpoint users can prepare a transaction for 332 | signing from a synced with Crypto APIs address from the specific xPub. This endpoint applies to all supported 333 | account-based blockchain protocols, e.g. Ethereum, BSC, etc 334 | 335 | ### Example 336 | 337 | ```javascript 338 | const {Enumerations, Client, Services, Models } = require('cryptoapis-kms'); 339 | const blockchain = Enumerations.Blockchains.ETHEREUM; 340 | const network = Enumerations.Networks[blockchain].NETWORK_ETHEREUM_MAINNET; 341 | const client = new Client('YOUR API KEY', blockchain, network); 342 | const xPub = "xpub6BsFsonVJR5vPChKQamp55R7veBCMD2CL3LtL83B3FS5DiayYgmoHCGQodeLTukaa4anZRQD9kNtPFHuPnCzjCiT9nrXdf3voNLhXQryBRB 343 | const sender = '0x0b7155094947d785530f66d250b097b25c30a557'; 344 | const recipient = '0xd4e2a5949359e95c7c604050dd9d54af419689c0'; 345 | const amount = '1.2123'; 346 | const feeOptions = new Models.AccountBasedFeeOptionsModel({ 347 | priority: Enumerations.FeePriorities.FAST, 348 | }); 349 | const preparedAccountTransaction = await client.prepareAccountBasedTransactionFromHDWallet({ 350 | xPub, 351 | sender, 352 | recipient, 353 | amount, 354 | feeOptions 355 | }).then((data) => { 356 | console.dir('API called successfully. Returned data:'); 357 | console.dir(data); 358 | }, (error) => { 359 | console.log(error) 360 | }) 361 | ``` 362 | 363 | ### Parameters 364 | 365 | Name | Type | Description | Notes 366 | ------------- |-------------------------|----------------------------------------------------------------------| ------------- 367 | **xPub** | **string** | Account Extended Public Key | 368 | **sender** | **string** | Represents a sender address | 369 | **recipient** | **string** | Represents a recipient addresses | 370 | **amount** | **string** | Representation of the amount of the transaction | 371 | **feeOptions** | **AccountBasedFeeOptionsModel** | Represents the fee options | 372 | **feeOptions.priority** | **string** | Represents the fee priority | [optional] 373 | **feeOptions.feeAmount** | **string** | Represents the fee amount | [optional] 374 | **nonce** | **string** | Representation of the nonce value | [optional] 375 | **data** | **string** | Representation of the additional data | [optional] 376 | 377 | ### Return type 378 | 379 | AccountBasedTransactionDTO 380 | 381 | ### Authorization 382 | 383 | [ApiKey](#ApiKey) 384 | 385 | ## prepareAFungibleTokenTransferFromAddress (ERC-20, BEP-20) 386 | This endpoint is used to prepare a fungible token transfer from an address with private and public keys. 387 | The address does not have to belong to a wallet. The response will include the transaction fee in Wei 388 | 389 | ### Example 390 | 391 | ```javascript 392 | const {Enumerations, Client, Services, Models } = require('cryptoapis-kms'); 393 | const blockchain = Enumerations.Blockchains.ETHEREUM; 394 | const network = Enumerations.Networks[blockchain].NETWORK_ETHEREUM_MAINNET; 395 | const client = new Client('YOUR API KEY', blockchain, network); 396 | const sender = '0xc56c1baA10746268785018e9AAB081957b1B9F6f'; 397 | const contract = '0x5690B49D818c940A7E6B9FA26B717AdA00394fF4'; 398 | const recipient = '0xe9be409b2f52deb3dc24508895cb4ee8c468ac19'; 399 | const amount = '1.2123'; 400 | const feeOptions = new Models.AccountBasedFeeOptionsModel({ 401 | priority: Enumerations.FeePriorities.FAST, 402 | }); 403 | const tokenStandard = Enumerations.TokenStandards[blockchain].ERC_20; 404 | 405 | const preparedAccountTransaction = await client.prepareTokenTransaction({ 406 | tokenStandard, 407 | contract, 408 | sender, 409 | recipient, 410 | amount, 411 | feeOptions, 412 | }).then((data) => { 413 | console.dir('API called successfully. Returned data:'); 414 | console.dir(data); 415 | }, (error) => { 416 | console.log(error) 417 | }) 418 | ``` 419 | 420 | ### Parameters 421 | 422 | Name | Type | Description | Notes 423 | ------------- |-------------------------|-------------------------------------------------| ------------- 424 | **tokenStandard** | **enum** | Represents the token standard | 425 | **contract** | **string** | Represents a contract address | 426 | **sender** | **string** | Represents a sender address | 427 | **recipient** | **string** | Represents a recipient addresses | 428 | **amount** | **string** | Representation of the amount of the transaction | 429 | **feeOptions** | **AccountBasedFeeOptionsModel** | Represents the fee options | 430 | **feeOptions.priority** | **string** | Represents the fee priority | [optional] 431 | **feeOptions.feeAmount** | **string** | Represents the fee amount | [optional] 432 | **nonce** | **string** | Representation of the nonce value | [optional] 433 | **data** | **string** | Representation of the additional data | [optional] 434 | 435 | ### Return type 436 | 437 | AccountBasedTransactionDTO 438 | 439 | ### Authorization 440 | 441 | [ApiKey](#ApiKey) 442 | 443 | ## prepareANonFungibleTokenTransferFromAddress (ERC-721, BEP-721) 444 | This endpoint is used to prepare a non-fungible token transfer from an address with private and public keys. 445 | The address doesn’t have to belong to a wallet. The response will include the transaction fee in Wei. 446 | ### Example 447 | 448 | ```javascript 449 | const {Enumerations, Client, Services, Models } = require('cryptoapis-kms'); 450 | const blockchain = Enumerations.Blockchains.ETHEREUM; 451 | const network = Enumerations.Networks[blockchain].NETWORK_ETHEREUM_MAINNET; 452 | const client = new Client('YOUR API KEY', blockchain, network); 453 | const sender = '0xc56c1baA10746268785018e9AAB081957b1B9F6f'; 454 | const contract = '0x5690B49D818c940A7E6B9FA26B717AdA00394fF4'; 455 | const recipient = '0xe9be409b2f52deb3dc24508895cb4ee8c468ac19'; 456 | const tokenId = '3'; 457 | const feeOptions = new Models.AccountBasedFeeOptionsModel({ 458 | priority: Enumerations.FeePriorities.FAST, 459 | }); 460 | const tokenStandard = Enumerations.TokenStandards[blockchain].ERC_721; 461 | 462 | const preparedAccountTransaction = await client.prepareTokenTransaction({ 463 | tokenStandard, 464 | contract, 465 | sender, 466 | recipient, 467 | tokenId, 468 | feeOptions, 469 | }).then((data) => { 470 | console.dir('API called successfully. Returned data:'); 471 | console.dir(data); 472 | }, (error) => { 473 | console.log(error) 474 | }) 475 | ``` 476 | 477 | ### Parameters 478 | 479 | Name | Type | Description | Notes 480 | ------------- |-------------------------|---------------------------------------| ------------- 481 | **tokenStandard** | **enum** | Represents the token standard | 482 | **contract** | **string** | Represents a contract address | 483 | **sender** | **string** | Represents a sender address | 484 | **recipient** | **string** | Represents a recipient addresses | 485 | **tokenId** | **string** | Representation of the token id | 486 | **feeOptions** | **AccountBasedFeeOptionsModel** | Represents the fee options | 487 | **feeOptions.priority** | **string** | Represents the fee priority | [optional] 488 | **feeOptions.feeAmount** | **string** | Represents the fee amount | [optional] 489 | **nonce** | **string** | Representation of the nonce value | [optional] 490 | **data** | **string** | Representation of the additional data | [optional] 491 | 492 | ### Return type 493 | 494 | AccountBasedTransactionDTO 495 | 496 | ### Authorization 497 | 498 | [ApiKey](#ApiKey) 499 | 500 | 501 | ## prepareAccountBasedTransactionFromAddress 502 | Through this endpoint users can prepare a transaction from an address with private and public keys. 503 | The address does not have to belong to a wallet. The response will include the transaction fee in Wei. 504 | 505 | ### Example 506 | 507 | ```javascript 508 | const {Enumerations, Client, Services, Models } = require('cryptoapis-kms'); 509 | const blockchain = Enumerations.Blockchains.ETHEREUM; 510 | const network = Enumerations.Networks[blockchain].NETWORK_ETHEREUM_MAINNET; 511 | const client = new Client('YOUR API KEY', blockchain, network); 512 | const sender = '0x0b7155094947d785530f66d250b097b25c30a557'; 513 | const recipient = '0xd4e2a5949359e95c7c604050dd9d54af419689c0'; 514 | const amount = '1.00031246'; 515 | const feeOptions = new Models.AccountBasedFeeOptionsModel({ 516 | priority: Enumerations.FeePriorities.FAST, 517 | }); 518 | const preparedAccountTransaction = await client.prepareAccountBasedTransactionFromAddress({ 519 | sender, 520 | recipient, 521 | amount, 522 | feeOptions 523 | }).then((data) => { 524 | console.dir('API called successfully. Returned data:'); 525 | console.dir(data); 526 | }, (error) => { 527 | console.log(error) 528 | }) 529 | ``` 530 | 531 | ### Parameters 532 | 533 | Name | Type | Description | Notes 534 | ------------- |-------------------------|----------------------------------------------------------------------| ------------- 535 | **sender** | **string** | Represents a sender address | 536 | **recipient** | **string** | Represents a recipient addresses | 537 | **amount** | **string** | Representation of the amount of the transaction | 538 | **feeOptions** | **AccountBasedFeeOptionsModel** | Represents the fee options | 539 | **feeOptions.priority** | **string** | Represents the fee priority | [optional] 540 | **feeOptions.feeAmount** | **string** | Represents the fee amount | [optional] 541 | **nonce** | **string** | Representation of the nonce value | [optional] 542 | **data** | **string** | Representation of the additional data | [optional] 543 | 544 | ### Return type 545 | 546 | AccountBasedTransactionDTO 547 | 548 | ### Authorization 549 | 550 | [ApiKey](#ApiKey) 551 | 552 | ## signPreparedTransactionLocally 553 | Through this endpoint users sign their transactions locally(offline) using the transaction response from 554 | Prepare Transaction From HD Wallet endpoint, both for account-based and UTXO-based 555 | 556 | ### Example #1 557 | 558 | ```javascript 559 | const {Enumerations, Client, Services, Models} = require('cryptoapis-kms'); 560 | const blockchain = Enumerations.Blockchains.BITCOIN; 561 | const network = Enumerations.Networks[blockchain].NETWORK_BITCOIN_MAINNET; 562 | const client = new Client('YOUR API KEY', blockchain, network); 563 | const signService = new Services.SignService(blockchain, network) 564 | const accountXpriv = 'xprv8gdau6KURKnX7mcKNjLMWx3a3tEzHCMiJDBtFCJrvmXCsHNj3wvSuJ3T8g67WvN9hkFa4y1Mnr9ZbyUzs9fdhi8mhegLufkEuwSdmDeBXvz'; 565 | const xPub = 'xpub6BsFsonVJR5vPChKQamp55R7veBCMD2CL3LtL83B3FS5DiayYgmoHCGQodeLTukaa4anZRQD9kNtPFHuPnCzjCiT9nrXdf3voNLhXQryBRB'; 566 | 567 | const preparedUTXO = await client.prepareUTXOBasedTransactionFromHDWallet({ 568 | xPub: xPub, 569 | recipients: [ 570 | new Models.RecipientModel("tb1q8qrk9pxkjcuk4a29ec7snskaxll55jzfhrcq24", '0.000031') 571 | ], 572 | feeOptions: new Models.UTXOBasedFeeOptionsModel({ 573 | prepareStrategy: Enumerations.PrepareStrategies.MINIMIZE_DUST, 574 | priority: Enumerations.FeePriorities.FAST, 575 | }) 576 | }); 577 | 578 | const signedTx = signService.signPreparedTransactionLocally(accountXpriv, preparedUTXO); 579 | const callbackSecretKey = 'yourSecretString'; 580 | const callbackUrl = 'https://example.com'; // your URL for callback must be verifyed from dashboard 581 | 582 | client.broadcastSignedTx(signedTx.raw, callbackSecretKey, callbackUrl).then((data) => { 583 | console.dir('API called successfully. Returned data:'); 584 | console.dir(data); 585 | }, (error) => { 586 | console.log(error); 587 | }); 588 | ``` 589 | 590 | ### Example #2 591 | 592 | ```javascript 593 | const {Enumerations, Client, Services, Models} = require('cryptoapis-kms'); 594 | const blockchain = Enumerations.Blockchains.ETHEREUM; 595 | const network = Enumerations.Networks[blockchain].NETWORK_ETHEREUM_MAINNET; 596 | const client = new Client('YOUR API KEY', blockchain, network); 597 | const signService = new Services.SignService(blockchain, network) 598 | const privKey = '1f610a431f8d997484e6aab36cf7e185eb069aac65fdce81e82d39ba85848c12'; 599 | const sender = '0x0b7155094947d785530f66d250b097b25c30a557'; 600 | const recipient = '0xd4e2a5949359e95c7c604050dd9d54af419689c0'; 601 | const amount = '1.00031246'; 602 | const feeOptions = new Models.AccountBasedFeeOptionsModel({ 603 | priority: Enumerations.FeePriorities.FAST, 604 | }); 605 | 606 | const preparedAccountTransaction = await client.prepareAccountBasedTransactionFromAddress({ 607 | sender, 608 | recipient, 609 | amount, 610 | feeOptions 611 | }) 612 | 613 | const signedTx = signService.signPreparedTransactionLocally(privKey, preparedAccountTransaction); 614 | const callbackSecretKey = 'yourSecretString'; 615 | const callbackUrl = 'https://example.com'; // your URL for callback must be verifyed from dashboard 616 | 617 | client.broadcastSignedTx(signedTx.raw, callbackSecretKey, callbackUrl).then((data) => { 618 | console.dir('API called successfully. Returned data:'); 619 | console.dir(data); 620 | }, (error) => { 621 | console.log(error); 622 | }); 623 | ``` 624 | ### Parameters 625 | 626 | Name | Type | Description | Notes 627 | ------------- |--------------------|--------------------------------------------------------------| ------------- 628 | **accountXpriv** | **String** | Account Extended Private Key (for HDWallet Transactions) | 629 | **privKey** | **String** | Address Private Key (for Address Transactions) | 630 | **transaction** | **TransactionDTO** | Prepared Transaction (Account-based or UTXO-based) | 631 | 632 | ### Return type 633 | 634 | SignDTO 635 | 636 | ### Authorization 637 | 638 | [ApiKey](#ApiKey) 639 | 640 | ## broadcastSignedTx 641 | broadcast locally signed transaction 642 | 643 | ### Example 644 | 645 | ```javascript 646 | const {Enumerations, Client, Services, Models } = require('cryptoapis-kms'); 647 | const blockchain = Enumerations.Blockchains.BITCOIN; 648 | const network = Enumerations.Networks[blockchain].NETWORK_BITCOIN_MAINNET; 649 | const client = new Client('YOUR API KEY', blockchain, network); 650 | const signService = new Services.SignService(blockchain, network) 651 | const accountXpriv = 'xprv8gdau6KURKnX7mcKNjLMWx3a3tEzHCMiJDBtFCJrvmXCsHNj3wvSuJ3T8g67WvN9hkFa4y1Mnr9ZbyUzs9fdhi8mhegLufkEuwSdmDeBXvz'; 652 | const xPub = 'xpub6BsFsonVJR5vPChKQamp55R7veBCMD2CL3LtL83B3FS5DiayYgmoHCGQodeLTukaa4anZRQD9kNtPFHuPnCzjCiT9nrXdf3voNLhXQryBRB'; 653 | 654 | const preparedUTXO = await client.prepareUTXOBasedTransactionFromHDWallet({ 655 | xPub: xPub, 656 | recipients: [ 657 | new Models.RecipientModel("tb1q8qrk9pxkjcuk4a29ec7snskaxll55jzfhrcq24", '0.000031') 658 | ], 659 | feeOptions: new Models.UTXOBasedFeeOptionsModel({ 660 | prepareStrategy: Enumerations.PrepareStrategies.MINIMIZE_DUST, 661 | priority: Enumerations.FeePriorities.FAST, 662 | }) 663 | }); 664 | 665 | const signedTx = signService.signPreparedTransactionLocally(accountXpriv, preparedUTXO); 666 | const callbackSecretKey = 'yourSecretString'; 667 | const callbackUrl = 'https://example.com'; // your URL for callback must be verifyed from dashboard 668 | 669 | client.broadcastSignedTx(signedTx.raw, callbackSecretKey, callbackUrl).then((data) => { 670 | console.dir('API called successfully. Returned data:'); 671 | console.dir(data); 672 | }, (error) => { 673 | console.log(error); 674 | }); 675 | ``` 676 | 677 | ### Parameters 678 | 679 | Name | Type | Description | Notes 680 | ------------- | ------------- | ------------- | ------------- 681 | **signedTransactionHex** | **String**| String identifier of the transaction | 682 | **callbackSecretKey** | **String**| Represents the Secret Key value provided by the customer. This field is used for security purposes during the callback notification, in order to prove the sender of the callback as Crypto APIs | 683 | **callbackUrl** | **String**| Represents the URL that is set by the customer where the callback will be received at. The callback notification will be received only if and when the event occurs. | 684 | **context** | **String**| In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. | [optional] 685 | 686 | ### Return type 687 | 688 | BroadcastSignedTxDTO 689 | 690 | ### Authorization 691 | 692 | [ApiKey](#ApiKey) 693 | 694 | ## ApiKey 695 | 696 | - **Type**: API key 697 | - **API key parameter name**: x-api-key 698 | - **Location**: HTTP header 699 | 700 | ## Contributing 701 | 702 | Anyone who wants to contribute is welcome. Use the Issues as a way to make suggestions that you want to see or even want to create. 703 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cryptoapis-kms", 3 | "version": "0.7.2", 4 | "description": "Crypto APIs - Key Management System", 5 | "main": "src/index.js", 6 | "homepage": "https://github.com/Crypto-APIs/Crypto_APIs_Key_Management_System#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/Crypto-APIs/Crypto_APIs_Key_Management_System" 10 | }, 11 | "scripts": { 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "author": "Crypto APIs", 15 | "license": "MIT", 16 | "dependencies": { 17 | "@dashevo/dashcore-lib": "^0.19.44", 18 | "@ethereumjs/common": "^2.6.0", 19 | "@ethereumjs/tx": "^3.5.2", 20 | "bip39": "^3.0.4", 21 | "bitcoinjs-lib": "^5.2.0", 22 | "bitcore-lib": "^8.25.30", 23 | "bitcore-lib-cash": "^8.25.40", 24 | "bitcore-lib-doge": "^8.25.40", 25 | "bitcore-lib-ltc": "^8.25.40", 26 | "bs58": "^2.0.0", 27 | "cryptoapis": "^1.12.0", 28 | "decimal.js": "^10.3.1", 29 | "ecpair": "^2.1.0", 30 | "ethereumjs-util": "^7.1.5", 31 | "hdkey": "^2.0.1", 32 | "hex2dec": "^1.1.2", 33 | "tiny-secp256k1": "^2.2.1", 34 | "xrpl": "^2.5.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/dtos/addressDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | class AddressDTO { 5 | 6 | /** 7 | * @param {Object} object 8 | * 9 | * @returns {AddressDTO} 10 | */ 11 | constructor(object) { 12 | this._data = object; 13 | 14 | return this; 15 | } 16 | 17 | /** 18 | * @returns {string} 19 | */ 20 | get address() { 21 | return this._data.address; 22 | } 23 | 24 | /** 25 | * @returns {string} 26 | */ 27 | get privateKey() { 28 | return this._data.privateKey; 29 | } 30 | 31 | /** 32 | * @returns {string} 33 | */ 34 | get publicKey() { 35 | return this._data.publicKey; 36 | } 37 | } 38 | 39 | module.exports = AddressDTO; -------------------------------------------------------------------------------- /src/dtos/baseDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | class BaseDTO { 4 | /** 5 | * @param {Object} dataObj 6 | */ 7 | constructor(dataObj) { 8 | this._data = dataObj; 9 | 10 | return this; 11 | } 12 | 13 | /** 14 | * @returns {string} 15 | */ 16 | get apiVersion() { 17 | return this._data.apiVersion; 18 | } 19 | 20 | /** 21 | * @returns {string} 22 | */ 23 | get requestId() { 24 | return this._data.requestId; 25 | } 26 | 27 | /** 28 | * @returns {Object} 29 | */ 30 | get data() { 31 | return this._data.data; 32 | } 33 | 34 | /** 35 | * @returns {Object} 36 | */ 37 | get item() { 38 | return this.data.item; 39 | } 40 | 41 | /** 42 | * @returns {Object} 43 | */ 44 | serialize() { 45 | const result = {}; 46 | const mapping = { 47 | apiVersion: 'apiVersion', 48 | requestId: 'requestId', 49 | data: 'data', 50 | context: 'context', 51 | }; 52 | 53 | Object.keys(this.data).forEach((key) => { 54 | if (typeof this.data[key] === 'string' || key === 'data' && typeof this.data[key] === 'object') { 55 | if (mapping.hasOwnProperty(key)) { 56 | result[mapping[key]] = this.data[key]; 57 | } 58 | } 59 | }); 60 | 61 | return result; 62 | } 63 | } 64 | 65 | module.exports = BaseDTO; 66 | -------------------------------------------------------------------------------- /src/dtos/broadcastSignedTxDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseDTO = require('./baseDTO'); 4 | 5 | class BroadcastSignedTxDTO extends BaseDTO { 6 | 7 | /** 8 | * @param {Object} object 9 | * @returns {BroadcastSignedTxDTO} 10 | */ 11 | constructor(object) { 12 | super(object); 13 | 14 | return this; 15 | } 16 | } 17 | 18 | module.exports = BroadcastSignedTxDTO -------------------------------------------------------------------------------- /src/dtos/errorDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const errors = require('../validators/customErrors'); 4 | 5 | class ErrorDTO { 6 | error; 7 | 8 | /** 9 | * @param {string} code 10 | * @param {Object|null} placeholder 11 | */ 12 | constructor(code, placeholder = null) { 13 | this.error = errors.getErrorMessage(code, placeholder); 14 | 15 | return this; 16 | } 17 | } 18 | 19 | module.exports = ErrorDTO; -------------------------------------------------------------------------------- /src/dtos/hdAddressesDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseDTO = require('./baseDTO'); 4 | 5 | class HdAddressesDTO extends BaseDTO { 6 | 7 | /** 8 | * @param {Object} object 9 | * @returns {HdAddressesDTO} 10 | */ 11 | constructor(object) { 12 | super(object); 13 | 14 | return this; 15 | } 16 | 17 | /** 18 | * @returns {Array} 19 | */ 20 | get addresses() { 21 | return this.item.addresses; 22 | } 23 | } 24 | 25 | module.exports = HdAddressesDTO; -------------------------------------------------------------------------------- /src/dtos/hdWalletDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseDTO = require('./baseDTO'); 4 | 5 | class HDWalletDTO extends BaseDTO { 6 | 7 | /** 8 | * @param {Object} object 9 | * @returns {HDWalletDTO} 10 | */ 11 | constructor(object) { 12 | super(object); 13 | 14 | return this; 15 | } 16 | } 17 | 18 | module.exports = HDWalletDTO; -------------------------------------------------------------------------------- /src/dtos/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const WalletServiceDTO = require("./walletDTO") 4 | , HDWalletDTO = require("./hdWalletDTO") 5 | , SubscriptionForUnconfirmedCoinsTxsDTO = require("./subscriptionForUnconfirmedCoinsTxsDTO") 6 | , SubscriptionForUnconfirmedTokensTxsDTO = require("./subscriptionForUnconfirmedTokensTxsDTO") 7 | , SubscriptionForUnconfirmedInternalTxsDTO = require("./subscriptionForUnconfirmedInternalTxsDTO") 8 | , BroadcastSignedTxDTO = require("./broadcastSignedTxDTO") 9 | , HDAddressesDTO = require("./hdAddressesDTO") 10 | , ErrorDTO = require("./errorDTO") 11 | , ListSyncedAddressesDTO = require("./listSyncedAddressesDTO") 12 | , AccountBasedTransactionDTO = require("./prepare/accountBasedTransactionDTO") 13 | , UTXOBasedTransactionDTO = require("./prepare/UTXOBasedTransaction") 14 | , SignDTO = require("./signDTO") 15 | , AddressDTO = require("./addressDTO") 16 | ; 17 | 18 | module.exports = { 19 | WalletServiceDTO, 20 | HDWalletDTO, 21 | SubscriptionForUnconfirmedCoinsTxsDTO, 22 | SubscriptionForUnconfirmedTokensTxsDTO, 23 | SubscriptionForUnconfirmedInternalTxsDTO, 24 | BroadcastSignedTxDTO, 25 | HDAddressesDTO, 26 | ErrorDTO, 27 | ListSyncedAddressesDTO, 28 | AccountBasedTransactionDTO, 29 | UTXOBasedTransactionDTO, 30 | SignDTO, 31 | AddressDTO 32 | }; -------------------------------------------------------------------------------- /src/dtos/listSyncedAddressesDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseDTO = require('./baseDTO'); 4 | 5 | class ListSyncedAddressesDTO extends BaseDTO { 6 | 7 | /** 8 | * @param {Object} object 9 | * @returns {ListSyncedAddressesDTO} 10 | */ 11 | constructor(object) { 12 | super(object); 13 | 14 | return this; 15 | } 16 | 17 | /** 18 | * @returns {Array} 19 | */ 20 | get addresses() { 21 | return this.data.items; 22 | } 23 | } 24 | 25 | module.exports = ListSyncedAddressesDTO; -------------------------------------------------------------------------------- /src/dtos/prepare/UTXOBasedTransaction.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const TransactionDTO = require('./transactionDTO'); 4 | const Decimal = require('decimal.js'); 5 | 6 | class UTXOBasedTransactionDTO extends TransactionDTO { 7 | /** 8 | * @param {Object} object 9 | * @returns {UTXOBasedTransactionDTO} 10 | */ 11 | constructor(object) { 12 | super(object.data.item); 13 | } 14 | 15 | /** 16 | * @param {Object} data 17 | * @return {{transaction: {}, input_signatures: string[]}} 18 | * @protected 19 | */ 20 | _prepareData(data) { 21 | const requiredAttributes = ['vin','vout']; 22 | 23 | for (const attr of requiredAttributes) { 24 | if (!data?.blockchainSpecific.hasOwnProperty(attr)) { 25 | throw new Error(attr + ' is not provided'); 26 | } 27 | } 28 | 29 | if (!Array.isArray(data?.blockchainSpecific['vin']) || data?.blockchainSpecific['vout'].length === 0) { 30 | throw new Error('inputs are empty or not an array'); 31 | } 32 | 33 | if (!Array.isArray(data?.blockchainSpecific['vout']) || data?.blockchainSpecific['vout'].length === 0) { 34 | throw new Error('outputs are empty or not an array'); 35 | } 36 | 37 | const requiredInputAttributes = ['transactionId', 'outputIndex', 'address', 'script', 'change', 'satoshis', 'derivationIndex']; 38 | for (const input of data?.blockchainSpecific['vin']) { 39 | for (const attr of requiredInputAttributes) { 40 | if (!input.hasOwnProperty(attr)) { 41 | throw new Error('Input ' + attr + ' is not provided'); 42 | } 43 | } 44 | } 45 | 46 | const requiredOutputAttributes = ['script','address']; 47 | for (const output of data?.blockchainSpecific['vout']) { 48 | for (const attr of requiredOutputAttributes) { 49 | if (!output.hasOwnProperty(attr)) { 50 | throw new Error('Input ' + attr + ' is not provided'); 51 | } 52 | } 53 | } 54 | 55 | return { 56 | inputs: data.blockchainSpecific.vin.map((input) => { 57 | return { 58 | address: input.address, 59 | txid: input.transactionId, 60 | satoshis: input.satoshis, 61 | script: input.script, 62 | outputIndex: input.outputIndex, 63 | derivationIndex: input.derivationIndex, 64 | change: input.change 65 | } 66 | }), 67 | outputs: data.blockchainSpecific.vout, 68 | locktime: data?.locktime ? data.locktime : null, 69 | replaceable: data?.blockchainSpecific?.replaceable ? data.blockchainSpecific.replaceable : false, 70 | data: data?.data ? data.data : null, 71 | feePerByte: data?.feePerByte ? new Decimal(data.feePerByte).toDecimalPlaces(8).toFixed() : null, 72 | fee: data?.fee ? data.fee : 0, 73 | version: data?.version ? data.version : null, 74 | }; 75 | } 76 | 77 | /** 78 | * @return {Object[]} 79 | */ 80 | get inputs() { 81 | return this.data['inputs']; 82 | } 83 | 84 | /** 85 | * @return {Object[]} 86 | */ 87 | get outputs() { 88 | return this.data['outputs']; 89 | } 90 | 91 | /** 92 | * @return {number|null} 93 | */ 94 | get locktime() { 95 | return this.data['locktime']; 96 | } 97 | 98 | /** 99 | * @return {boolean} 100 | */ 101 | get replaceable() { 102 | return this.data['replaceable']; 103 | } 104 | 105 | /** 106 | * @return {string|null} 107 | */ 108 | get transactionData() { 109 | return this.data['data']; 110 | } 111 | 112 | /** 113 | * @return {number|null} 114 | */ 115 | get feePerByte() { 116 | return Math.round(this.data['feePerByte'] * 100000000); 117 | } 118 | 119 | /** 120 | * @return {number} 121 | */ 122 | get fee() { 123 | return Math.round(this.data['fee'] * 100000000); 124 | } 125 | 126 | /** 127 | * 128 | * @return {number} 129 | */ 130 | get version() { 131 | return this.data['version']; 132 | } 133 | } 134 | 135 | module.exports = UTXOBasedTransactionDTO; 136 | -------------------------------------------------------------------------------- /src/dtos/prepare/accountBasedTransactionDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const TransactionDTO = require("./transactionDTO") 4 | const hex2dec = require("hex2dec"); 5 | 6 | class AccountBasedTransactionDTO extends TransactionDTO { 7 | /** 8 | * @param {Object} object 9 | * @returns {AccountBasedTransactionDTO} 10 | */ 11 | constructor(object) { 12 | super(object.data.item); 13 | } 14 | 15 | /** 16 | * {Object} data 17 | * @return {{transactionType: string, gasLimit: (null|string|string), amount: (null|string|string), sender: *, nonce: (null|string|string), recipient: *}} 18 | * @protected 19 | */ 20 | _prepareData(data) { 21 | const requiredAttributes = ['sender', 'recipient', 'nonce', 'fee']; 22 | for (const attr of requiredAttributes) { 23 | if (!data.hasOwnProperty(attr) && !data?.blockchainSpecific.hasOwnProperty(attr)) { 24 | throw new Error(attr + ' is not provided'); 25 | } 26 | } 27 | 28 | return { 29 | sender: data.sender, 30 | transactionType: data?.transactionType || data?.blockchainSpecific?.transactionType, 31 | recipient: data.recipient, 32 | amount: data?.amount ? hex2dec.decToHex(data.amount) : "0x0", 33 | nonce: data?.blockchainSpecific?.nonce ? hex2dec.decToHex(data?.blockchainSpecific.nonce) : hex2dec.decToHex(data?.nonce), 34 | data: data?.blockchainSpecific?.dataHex, 35 | derivationIndex: data?.blockchainSpecific?.derivationIndex, 36 | gasPrice: hex2dec.decToHex(data?.blockchainSpecific?.fee?.gasPrice), 37 | gasLimit: hex2dec.decToHex(data?.blockchainSpecific?.fee?.gasLimit), 38 | maxFeePerGas: data?.blockchainSpecific?.fee?.maxFeePerGas ? hex2dec.decToHex(data.blockchainSpecific.fee.maxFeePerGas) : null, 39 | maxPriorityFeePerGas: data?.blockchainSpecific?.fee?.maxPriorityFeePerGas ? hex2dec.decToHex(data.blockchainSpecific.fee.maxPriorityFeePerGas) : null, 40 | }; 41 | } 42 | 43 | 44 | /** 45 | * @return {string} 46 | */ 47 | get nonce() { 48 | return this.data.nonce; 49 | } 50 | 51 | /** 52 | * @return {string} 53 | */ 54 | get gasPrice() { 55 | return this.data.gasPrice; 56 | } 57 | 58 | /** 59 | * @return {string} 60 | */ 61 | get gasLimit() { 62 | return this.data.gasLimit; 63 | } 64 | 65 | /** 66 | * @return {string} 67 | */ 68 | get maxFeePerGas() { 69 | return this.data.maxFeePerGas; 70 | } 71 | 72 | /** 73 | * @return {string} 74 | */ 75 | get maxPriorityFeePerGas() { 76 | return this.data.maxPriorityFeePerGas; 77 | } 78 | 79 | /** 80 | * @return {string} 81 | */ 82 | get amount() { 83 | return this.data.amount; 84 | } 85 | 86 | /** 87 | * @return {string} 88 | */ 89 | get sender() { 90 | return this.data.sender; 91 | } 92 | 93 | /** 94 | * @return {string} 95 | */ 96 | get recipient() { 97 | return this.data.recipient; 98 | } 99 | 100 | /** 101 | * @return {string} 102 | */ 103 | get dataHex() { 104 | return this.data.dataHex; 105 | } 106 | 107 | /** 108 | * @return {string} 109 | */ 110 | get derivationIndex() { 111 | return this.data.derivationIndex; 112 | } 113 | 114 | /** 115 | * @return {string} 116 | */ 117 | get transactionType() { 118 | return this.data.transactionType; 119 | } 120 | 121 | /** 122 | * @return {string} 123 | */ 124 | get sigHash() { 125 | return this.data.sigHash; 126 | } 127 | 128 | /** 129 | * @return {Object} 130 | */ 131 | get fee() { 132 | return this.data.fee 133 | } 134 | 135 | } 136 | 137 | module.exports = AccountBasedTransactionDTO; -------------------------------------------------------------------------------- /src/dtos/prepare/transactionDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | class TransactionDTO { 4 | /** 5 | * @param {Object} object 6 | * @throws Error 7 | */ 8 | constructor(object) { 9 | this.data = this._prepareData(object); 10 | } 11 | 12 | /** 13 | * @param {Object} data 14 | * @return {Object} 15 | * @throws Error 16 | * @protected 17 | */ 18 | _prepareData(data) { 19 | throw new Error('Implement _prepareData method for service ' + this.constructor.name); 20 | } 21 | 22 | /** 23 | * @return {Object} 24 | */ 25 | getData() { 26 | return this.data; 27 | } 28 | } 29 | 30 | module.exports = TransactionDTO; -------------------------------------------------------------------------------- /src/dtos/signDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | class SignDTO { 4 | 5 | /** 6 | * @param {Object} data 7 | * @returns {SignDTO} 8 | */ 9 | constructor(data) { 10 | this.data = data; 11 | 12 | return this; 13 | } 14 | 15 | /** 16 | * @returns {string} 17 | */ 18 | get id() { 19 | return this.data.id; 20 | } 21 | 22 | /** 23 | * @returns {string} 24 | */ 25 | get raw() { 26 | return this.data.raw; 27 | } 28 | } 29 | 30 | module.exports = SignDTO; -------------------------------------------------------------------------------- /src/dtos/subscriptionForUnconfirmedCoinsTxsDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseDTO = require('./baseDTO'); 4 | 5 | class SubscriptionForUnconfirmedCoinsTxsDTO extends BaseDTO { 6 | 7 | /** 8 | * @param {Object} object 9 | * @returns {SubscriptionForUnconfirmedCoinsTxsDTO} 10 | */ 11 | constructor(object) { 12 | super(object); 13 | 14 | return this; 15 | } 16 | } 17 | 18 | module.exports = SubscriptionForUnconfirmedCoinsTxsDTO -------------------------------------------------------------------------------- /src/dtos/subscriptionForUnconfirmedInternalTxsDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseDTO = require('./baseDTO'); 4 | 5 | class SubscriptionForUnconfirmedInternalTxsDTO extends BaseDTO { 6 | 7 | /** 8 | * @param {Object} object 9 | * @returns {SubscriptionForUnconfirmedInternalTxsDTO} 10 | */ 11 | constructor(object) { 12 | super(object); 13 | 14 | return this; 15 | } 16 | } 17 | 18 | module.exports = SubscriptionForUnconfirmedInternalTxsDTO -------------------------------------------------------------------------------- /src/dtos/subscriptionForUnconfirmedTokensTxsDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseDTO = require('./baseDTO'); 4 | 5 | class SubscriptionForUnconfirmedTokensTxsDTO extends BaseDTO { 6 | 7 | /** 8 | * @param {Object} object 9 | * @returns {SubscriptionForUnconfirmedTokensTxsDTO} 10 | */ 11 | constructor(object) { 12 | super(object); 13 | 14 | return this; 15 | } 16 | } 17 | 18 | module.exports = SubscriptionForUnconfirmedTokensTxsDTO -------------------------------------------------------------------------------- /src/dtos/walletDTO.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | class WalletDTO { 4 | 5 | /** 6 | * @param {Object} dataObj 7 | * @returns {WalletDTO} 8 | */ 9 | constructor(dataObj) { 10 | this.data = dataObj; 11 | 12 | return this; 13 | } 14 | 15 | /** 16 | * @returns {string} 17 | */ 18 | get blockchain() { 19 | return this.data.blockchain; 20 | } 21 | 22 | /** 23 | * @returns {string} 24 | */ 25 | get network() { 26 | return this.data.network; 27 | } 28 | 29 | /** 30 | * @returns {string} 31 | */ 32 | get mnemonic() { 33 | return this.data.mnemonic; 34 | } 35 | 36 | /** 37 | * @returns {string} 38 | */ 39 | get seed() { 40 | return this.data.seed; 41 | } 42 | 43 | /** 44 | * @returns {Array} 45 | */ 46 | get xPubsList() { 47 | return this.data.xPubsList; 48 | } 49 | 50 | /** 51 | * @returns {Object} 52 | */ 53 | get xPub() { 54 | return this.data.xPubsList[0]; 55 | } 56 | 57 | /** 58 | * @returns {Object} 59 | */ 60 | get yPub() { 61 | return this.data.xPubsList[1]; 62 | } 63 | 64 | /** 65 | * @returns {Object} 66 | */ 67 | get zPub() { 68 | return this.data.xPubsList[2]; 69 | } 70 | } 71 | 72 | module.exports = WalletDTO; -------------------------------------------------------------------------------- /src/enumerations/blockchainEnum.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BITCOIN = 'bitcoin'; 4 | const BITCOIN_CASH = 'bitcoin-cash'; 5 | const LITECOIN = 'litecoin'; 6 | const DOGECOIN = 'dogecoin'; 7 | const DASH = 'dash'; 8 | const ETHEREUM = 'ethereum'; 9 | const ETHEREUM_CLASSIC = 'ethereum-classic'; 10 | const BINANCE_SMART_CHAIN = 'binance-smart-chain'; 11 | const XRP = 'xrp'; 12 | const ZCASH = 'zcash'; 13 | const TRX = 'trx'; 14 | 15 | 16 | const blockchains = { 17 | BITCOIN: BITCOIN, 18 | BITCOIN_CASH: BITCOIN_CASH, 19 | LITECOIN: LITECOIN, 20 | DOGECOIN: DOGECOIN, 21 | DASH: DASH, 22 | ETHEREUM: ETHEREUM, 23 | ETHEREUM_CLASSIC: ETHEREUM_CLASSIC, 24 | XRP: XRP, 25 | TRX: TRX, 26 | BINANCE_SMART_CHAIN: BINANCE_SMART_CHAIN, 27 | ZCASH: ZCASH 28 | }; 29 | 30 | module.exports = { 31 | blockchains, 32 | reversed: { 33 | [BITCOIN]: 'BITCOIN', 34 | [BITCOIN_CASH]: 'BITCOIN_CASH', 35 | [LITECOIN]: 'LITECOIN', 36 | [DOGECOIN]: 'DOGECOIN', 37 | [DASH]: 'DASH', 38 | [ETHEREUM]: 'ETHEREUM', 39 | [ETHEREUM_CLASSIC]: 'ETHEREUM_CLASSIC', 40 | [XRP]: 'XRP', 41 | [BINANCE_SMART_CHAIN]: 'BINANCE_SMART_CHAIN', 42 | [ZCASH]: 'ZCASH', 43 | [TRX]: 'TRX', 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /src/enumerations/feePriorityEnum.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const feePriorityEnum = { 4 | SLOW: 'slow', 5 | STANDARD: 'standard', 6 | FAST: 'fast' 7 | }; 8 | 9 | module.exports = feePriorityEnum; 10 | -------------------------------------------------------------------------------- /src/enumerations/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const blockchainEnum = require('./blockchainEnum') 4 | , feePriorityEnum = require('./feePriorityEnum') 5 | , networkEnum = require('./networkEnum') 6 | , prepareStrategyEnum = require('./prepareStrategyEnum') 7 | , tokenEnum = require('./tokenEnum') 8 | ; 9 | 10 | module.exports = { 11 | blockchainEnum, 12 | feePriorityEnum, 13 | networkEnum, 14 | prepareStrategyEnum, 15 | tokenEnum 16 | }; -------------------------------------------------------------------------------- /src/enumerations/networkEnum.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const {default: ethereumCommon} = require('@ethereumjs/common'); 4 | const {blockchains} = require('./blockchainEnum'); 5 | 6 | const NETWORK_BITCOIN_MAINNET = 'mainnet'; 7 | const NETWORK_BITCOIN_TESTNET = 'testnet'; 8 | 9 | const NETWORK_BITCOIN_CASH_MAINNET = 'mainnet'; 10 | const NETWORK_BITCOIN_CASH_TESTNET = 'testnet'; 11 | 12 | const NETWORK_LITECOIN_MAINNET = 'mainnet'; 13 | const NETWORK_LITECOIN_TESTNET = 'testnet'; 14 | 15 | const NETWORK_DOGECOIN_MAINNET = 'mainnet'; 16 | const NETWORK_DOGECOIN_TESTNET = 'testnet'; 17 | 18 | const NETWORK_DASH_MAINNET = 'mainnet'; 19 | const NETWORK_DASH_TESTNET = 'testnet'; 20 | 21 | const NETWORK_ETHEREUM_MAINNET = 'mainnet'; 22 | const NETWORK_ETHEREUM_GOERLI = 'goerli'; 23 | 24 | const NETWORK_ETHEREUM_CLASSIC_MAINNET = 'mainnet'; 25 | const NETWORK_ETHEREUM_CLASSIC_MORDOR = 'mordor'; 26 | 27 | const NETWORK_ZCASH_MAINNET = 'mainnet'; 28 | const NETWORK_ZCASH_TESTNET = 'testnet'; 29 | 30 | const NETWORK_XRP_MAINNET = 'mainnet'; 31 | const NETWORK_XRP_TESTNET = 'testnet'; 32 | 33 | const NETWORK_BINANCE_SMART_CHAIN_MAINNET = 'mainnet'; 34 | const NETWORK_BINANCE_SMART_CHAIN_TESTNET = 'testnet'; 35 | 36 | const NETWORK_TRX_MAINNET = 'mainnet'; 37 | const NETWORK_TRX_NILE = 'nile'; 38 | 39 | const NETWORKS_CONFIGS = { 40 | [blockchains.BITCOIN]: { 41 | [NETWORK_BITCOIN_MAINNET]: { 42 | messagePrefix: '\x18Bitcoin Signed Message:\n', 43 | bech32: 'bc', 44 | bip32: { 45 | public: 0x0488b21e, 46 | private: 0x0488ade4, 47 | }, 48 | bip49: { 49 | public: 0x049d7cb2, 50 | private: 0x049d7878, 51 | }, 52 | bip84: { 53 | public: 0x04b24746, 54 | private: 0x04b2430c, 55 | }, 56 | pubKeyHash: 0x00, 57 | scriptHash: 0x05, 58 | wif: 0x80, 59 | }, 60 | [NETWORK_BITCOIN_TESTNET]: { 61 | messagePrefix: '\x18Bitcoin Signed Message:\n', 62 | bech32: 'tb', 63 | bip32: { 64 | public: 0x043587cf, 65 | private: 0x04358394, 66 | }, 67 | bip49: { 68 | public: 0x044a5262, 69 | private: 0x044a4e28, 70 | }, 71 | bip84: { 72 | public: 0x045f1cf6, 73 | private: 0x045f18bc, 74 | }, 75 | pubKeyHash: 0x6f, 76 | scriptHash: 0xc4, 77 | wif: 0xef, 78 | }, 79 | }, 80 | [blockchains.BITCOIN_CASH]: { 81 | [NETWORK_BITCOIN_CASH_MAINNET]: { 82 | messagePrefix: 'unused', 83 | bip32: { 84 | public: 0x0488b21e, 85 | private: 0x0488ade4, 86 | }, 87 | pubKeyHash: 0x00, 88 | scriptHash: 0x05, 89 | wif: 0x80 90 | }, 91 | [NETWORK_BITCOIN_CASH_TESTNET]: { 92 | messagePrefix: 'unused', 93 | bip32: { 94 | public: 0x043587cf, 95 | private: 0x04358394, 96 | }, 97 | pubKeyHash: 0x6f, 98 | scriptHash: 0xc4, 99 | wif: 0xef, 100 | }, 101 | }, 102 | [blockchains.LITECOIN]: { 103 | [NETWORK_LITECOIN_MAINNET]: { 104 | bech32: 'ltc', 105 | messagePrefix: '\x19Litecoin Signed Message:\n', 106 | bip32: { 107 | public: 0x019da462, 108 | private: 0x019d9cfe, 109 | }, 110 | bip49: { 111 | public: 0x01b26ef6, 112 | private: 0x01b26792, 113 | }, 114 | bip84: { 115 | public: 0x04b24746, 116 | private: 0x04b2430c, 117 | }, 118 | pubKeyHash: 0x30, 119 | scriptHash: 0x32, 120 | wif: 0xb0 121 | }, 122 | [NETWORK_LITECOIN_TESTNET]: { 123 | bech32: 'tltc', 124 | messagePrefix: '\x18Litecoin Signed Message:\n', 125 | bip32: { 126 | public: 0x0436f6e1, 127 | private: 0x0436ef7d, 128 | }, 129 | bip49: { 130 | public: 0x043587cf, 131 | private: 0x04358394, 132 | }, 133 | bip84: { 134 | public: 0x045f1cf6, 135 | private: 0x045f18bc, 136 | }, 137 | pubKeyHash: 0x6f, 138 | scriptHash: 0xc4, 139 | wif: 0xef, 140 | }, 141 | }, 142 | [blockchains.DASH]: { 143 | [NETWORK_DASH_MAINNET]: { 144 | messagePrefix: 'unused', 145 | bip32: { 146 | public: 0x0488b21e, 147 | private: 0x0488ade4 148 | }, 149 | pubKeyHash: 0x4c, 150 | scriptHash: 0x10, 151 | wif: 0xcc 152 | }, 153 | [NETWORK_DASH_TESTNET]: { 154 | messagePrefix: 'unused', 155 | bip32: { 156 | public: 0x043587cf, 157 | private: 0x04358394 158 | }, 159 | pubKeyHash: 0x8c, 160 | scriptHash: 0x13, 161 | wif: 0xef 162 | }, 163 | }, 164 | [blockchains.DOGECOIN]: { 165 | [NETWORK_DOGECOIN_MAINNET]: { 166 | messagePrefix: '\x19Dogecoin Signed Message:\n', 167 | bip32: { 168 | public: 0x02facafd, 169 | private: 0x02fac398 170 | }, 171 | pubKeyHash: 0x1e, 172 | scriptHash: 0x16, 173 | wif: 0x9e 174 | }, 175 | [NETWORK_DOGECOIN_TESTNET]: { 176 | messagePrefix: '\x19Dogecoin Signed Message:\n', 177 | bip32: { 178 | public: 0x0432a9a8, 179 | private: 0x0432a243 180 | }, 181 | pubKeyHash: 0x71, 182 | scriptHash: 0xc4, 183 | wif: 0xf1 184 | }, 185 | }, 186 | [blockchains.ETHEREUM]: { 187 | [NETWORK_ETHEREUM_MAINNET]: { 188 | common: new ethereumCommon({ 189 | chain: 'mainnet', 190 | hardfork: 'london', 191 | networkId: 1, 192 | chainId: 1 193 | }), 194 | bip32: { 195 | public: 0x0488b21e, 196 | private: 0x0488ade4, 197 | } 198 | }, 199 | [NETWORK_ETHEREUM_GOERLI]: { 200 | common: ethereumCommon.forCustomChain( 201 | 'goerli', 202 | { 203 | name: 'goerli', 204 | networkId: 5, 205 | chainId: 5, 206 | }, 207 | 'london' 208 | ) 209 | }, 210 | }, 211 | [blockchains.ETHEREUM_CLASSIC]: { 212 | [NETWORK_ETHEREUM_CLASSIC_MAINNET]: { 213 | common: ethereumCommon.forCustomChain( 214 | 'mainnet', 215 | { 216 | name: 'mainnet', 217 | networkId: 1, 218 | chainId: 61, 219 | }, 220 | 'petersburg' 221 | ), 222 | bip32: { 223 | public: 0x0488b21e, 224 | private: 0x0488ade4, 225 | } 226 | }, 227 | [NETWORK_ETHEREUM_CLASSIC_MORDOR]: { 228 | common: ethereumCommon.forCustomChain( 229 | 'rinkeby', 230 | { 231 | name: 'mordor', 232 | networkId: 7, 233 | chainId: 63, 234 | }, 235 | 'petersburg' 236 | ), 237 | bip32: { 238 | public: 0x0488b21e, 239 | private: 0x0488ade4, 240 | } 241 | }, 242 | }, 243 | [blockchains.BINANCE_SMART_CHAIN]: { 244 | [NETWORK_BINANCE_SMART_CHAIN_MAINNET]: { 245 | common: ethereumCommon.forCustomChain( 246 | 'mainnet', 247 | { 248 | name: 'mainnet', 249 | networkId: 56, 250 | chainId: 56, 251 | }, 252 | 'petersburg' 253 | ), 254 | bip32: { 255 | public: 0x0488b21e, 256 | private: 0x0488ade4, 257 | } 258 | }, 259 | [NETWORK_BINANCE_SMART_CHAIN_TESTNET]: { 260 | common: ethereumCommon.forCustomChain( 261 | 'ropsten', 262 | { 263 | name: 'testnet', 264 | networkId: 97, 265 | chainId: 97, 266 | }, 267 | 'petersburg' 268 | ) 269 | }, 270 | }, 271 | [blockchains.ZCASH]: { 272 | [NETWORK_ZCASH_MAINNET]: { 273 | messagePrefix: '\x19ZCash Signed Message:\n', 274 | bip32: { 275 | public: 0x0488b21e, 276 | private: 0x0488ade4, 277 | }, 278 | pubKeyHash: 0x1cb8, 279 | scriptHash: 0x1cbd, 280 | wif: 0x80, 281 | consensusBranchId: { 282 | 1: 0x00, 283 | 2: 0x00, 284 | 3: 0x5ba81b19, 285 | 4: 0xE9FF75A6, 286 | }, 287 | coin: 'zec' 288 | }, 289 | [NETWORK_ZCASH_TESTNET]: { 290 | messagePrefix: '\x19ZCash Signed Message:\n', 291 | bip32: { 292 | public: 0x043587cf, 293 | private: 0x04358394, 294 | }, 295 | pubKeyHash: 0x1d25, 296 | scriptHash: 0x1cba, 297 | wif: 0xef, 298 | consensusBranchId: { 299 | 1: 0x00, 300 | 2: 0x00, 301 | 3: 0x5ba81b19, 302 | 4: 0x37519621, 303 | }, 304 | coin: 'zec' 305 | }, 306 | }, 307 | [blockchains.XRP]: { 308 | [NETWORK_XRP_MAINNET]: { 309 | messagePrefix: 'unused', 310 | bip32: { 311 | public: 0x0488b21e, 312 | private: 0x0488ade4, 313 | }, 314 | pubKeyHash: 0x00, 315 | scriptHash: 0x05, 316 | }, 317 | [NETWORK_XRP_TESTNET]: { 318 | messagePrefix: 'unused', 319 | bip32: { 320 | public: 0x0488b21e, 321 | private: 0x0488ade4, 322 | }, 323 | pubKeyHash: 0x00, 324 | scriptHash: 0x05, 325 | }, 326 | }, 327 | [blockchains.TRX]: { 328 | [NETWORK_TRX_MAINNET]: { 329 | versionPrefix: 0x41, 330 | bip32: { 331 | public: 0x0488b21e, 332 | private: 0x0488ade4, 333 | }, 334 | }, 335 | [NETWORK_TRX_NILE]: { 336 | versionPrefix: 0x41, 337 | bip32: { 338 | public: 0x0488b21e, 339 | private: 0x0488ade4, 340 | }, 341 | }, 342 | }, 343 | }; 344 | 345 | module.exports = { 346 | 'NETWORKS': { 347 | [blockchains.BITCOIN]: { 348 | 'NETWORK_BITCOIN_MAINNET': NETWORK_BITCOIN_MAINNET, 349 | 'NETWORK_BITCOIN_TESTNET': NETWORK_BITCOIN_TESTNET, 350 | }, 351 | [blockchains.BITCOIN_CASH]: { 352 | 'NETWORK_BITCOIN_CASH_MAINNET': NETWORK_BITCOIN_CASH_MAINNET, 353 | 'NETWORK_BITCOIN_CASH_TESTNET': NETWORK_BITCOIN_CASH_TESTNET, 354 | }, 355 | [blockchains.LITECOIN]: { 356 | 'NETWORK_LITECOIN_MAINNET': NETWORK_LITECOIN_MAINNET, 357 | 'NETWORK_LITECOIN_TESTNET': NETWORK_LITECOIN_TESTNET, 358 | }, 359 | [blockchains.DOGECOIN]: { 360 | 'NETWORK_DOGECOIN_MAINNET': NETWORK_DOGECOIN_MAINNET, 361 | 'NETWORK_DOGECOIN_TESTNET': NETWORK_DOGECOIN_TESTNET, 362 | }, 363 | [blockchains.DASH]: { 364 | 'NETWORK_DASH_MAINNET': NETWORK_DASH_MAINNET, 365 | 'NETWORK_DASH_TESTNET': NETWORK_DASH_TESTNET, 366 | }, 367 | [blockchains.ETHEREUM]: { 368 | 'NETWORK_ETHEREUM_MAINNET': NETWORK_ETHEREUM_MAINNET, 369 | 'NETWORK_ETHEREUM_GOERLI': NETWORK_ETHEREUM_GOERLI, 370 | }, 371 | [blockchains.ETHEREUM_CLASSIC]: { 372 | 'NETWORK_ETHEREUM_CLASSIC_MAINNET': NETWORK_ETHEREUM_CLASSIC_MAINNET, 373 | 'NETWORK_ETHEREUM_CLASSIC_MORDOR': NETWORK_ETHEREUM_CLASSIC_MORDOR, 374 | }, 375 | [blockchains.BINANCE_SMART_CHAIN]: { 376 | 'NETWORK_BINANCE_SMART_CHAIN_MAINNET': NETWORK_BINANCE_SMART_CHAIN_MAINNET, 377 | 'NETWORK_BINANCE_SMART_CHAIN_TESTNET': NETWORK_BINANCE_SMART_CHAIN_TESTNET, 378 | }, 379 | [blockchains.ZCASH]: { 380 | 'NETWORK_ZCASH_MAINNET': NETWORK_ZCASH_MAINNET, 381 | 'NETWORK_ZCASH_TESTNET': NETWORK_ZCASH_TESTNET, 382 | }, 383 | [blockchains.XRP]: { 384 | 'NETWORK_XRP_MAINNET': NETWORK_XRP_MAINNET, 385 | 'NETWORK_XRP_TESTNET': NETWORK_XRP_TESTNET, 386 | }, 387 | [blockchains.TRX]: { 388 | 'NETWORK_TRX_MAINNET': NETWORK_TRX_MAINNET, 389 | 'NETWORK_TRX_NILE': NETWORK_TRX_NILE, 390 | }, 391 | }, 392 | 'NETWORKS_CONFIGS': NETWORKS_CONFIGS, 393 | } -------------------------------------------------------------------------------- /src/enumerations/prepareStrategyEnum.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const prepareStrategyEnum = { 4 | NONE: 'none', 5 | MINIMIZE_DUST: 'minimize-dust', 6 | OPTIMIZE_SIZE: 'optimize-size' 7 | }; 8 | 9 | module.exports = prepareStrategyEnum; 10 | -------------------------------------------------------------------------------- /src/enumerations/tokenEnum.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {blockchains} = require('./blockchainEnum'); 4 | 5 | const TYPE_ERC_20 = 'erc-20' 6 | , TYPE_BEP_20 = 'bep-20' 7 | , TYPE_ERC_721 = 'erc-721' 8 | , TYPE_BEP_721 = 'bep-721' 9 | ; 10 | 11 | module.exports = { 12 | BLOCKCHAIN_STANDARDS: { 13 | [blockchains.ETHEREUM]: { 14 | ERC_20: TYPE_ERC_20, 15 | ERC_721: TYPE_ERC_721, 16 | }, 17 | [blockchains.ETHEREUM_CLASSIC]: { 18 | ERC_20: TYPE_ERC_20, 19 | }, 20 | [blockchains.BINANCE_SMART_CHAIN]: { 21 | BEP_20: TYPE_BEP_20, 22 | BEP_721: TYPE_BEP_721, 23 | }, 24 | }, 25 | STANDARDS: { 26 | ERC_20: TYPE_ERC_20, 27 | BEP_20: TYPE_BEP_20, 28 | ERC_721: TYPE_ERC_721, 29 | BEP_721: TYPE_BEP_721 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /src/helpers/generateAddress/baseGeneratorHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const NetworksConfigsEnum = require('../../enumerations/networkEnum') 4 | , {BaseBlockchainAwareService} = require("../../services/baseServices") 5 | ; 6 | 7 | 8 | /** 9 | * BaseGeneratorHelper 10 | * 11 | * @class BaseGeneratorHelper 12 | * @extends {BaseBlockchainAwareService} 13 | */ 14 | class BaseGeneratorHelper extends BaseBlockchainAwareService { 15 | /** 16 | * @param {string} blockchain 17 | * @param {string} network 18 | */ 19 | constructor({blockchain, network}) { 20 | super(blockchain, network) 21 | 22 | if (!NetworksConfigsEnum.NETWORKS_CONFIGS.hasOwnProperty(this.blockchain) 23 | || !Object.keys(NetworksConfigsEnum.NETWORKS_CONFIGS[this.blockchain].hasOwnProperty(this.network))) { 24 | throw new Error('Unknown configuration for ' + this.blockchain + ':' + this.network); 25 | } 26 | 27 | this.networkConfig = NetworksConfigsEnum.NETWORKS_CONFIGS[this.blockchain][this.network]; 28 | } 29 | 30 | /** 31 | * @return {AddressDTO} 32 | */ 33 | generateAddress() { 34 | throw new Error('Implement generateAddress method for service ' + this.constructor.name); 35 | } 36 | } 37 | 38 | module.exports = BaseGeneratorHelper; -------------------------------------------------------------------------------- /src/helpers/generateAddress/bscGeneratorHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const EthGeneratorHelper = require('./ethGeneratorHelper'); 4 | 5 | /** 6 | * BscGeneratorHelper 7 | * 8 | * @class BscGeneratorHelper 9 | * 10 | * @extends {EthGeneratorHelper} 11 | */ 12 | class BscGeneratorHelper extends EthGeneratorHelper { 13 | 14 | } 15 | 16 | module.exports = BscGeneratorHelper; -------------------------------------------------------------------------------- /src/helpers/generateAddress/btcGeneratorHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseGeneratorHelper = require('./baseGeneratorHelper') 4 | , {payments} = require('bitcoinjs-lib') 5 | , ecc = require('tiny-secp256k1') 6 | , ecpair = require('ecpair') 7 | , ECPair = ecpair.ECPairFactory(ecc) 8 | , {AddressDTO} = require("../../dtos") 9 | ; 10 | 11 | /** 12 | * BtcGeneratorHelper 13 | * 14 | * @class BtcGeneratorHelper 15 | * 16 | * @extends {BaseGeneratorHelper} 17 | */ 18 | class BtcGeneratorHelper extends BaseGeneratorHelper { 19 | 20 | /** 21 | * @inheritDoc 22 | */ 23 | generateAddress() { 24 | const pair = ECPair.makeRandom({network: this.networkConfig}); 25 | const address = payments.p2wpkh({pubkey: pair.publicKey, network: this.networkConfig}).address 26 | 27 | return new AddressDTO({ 28 | address: address, 29 | publicKey: pair.publicKey.toString('hex'), 30 | privateKey: pair.privateKey.toString('hex'), 31 | }); 32 | }; 33 | } 34 | 35 | module.exports = BtcGeneratorHelper; -------------------------------------------------------------------------------- /src/helpers/generateAddress/etcGeneratorHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const EthGeneratorHelper = require('./ethGeneratorHelper'); 4 | 5 | /** 6 | * EtcGeneratorHelper 7 | * 8 | * @class EtcGeneratorHelper 9 | * 10 | * @extends {EthGeneratorHelper} 11 | */ 12 | class EtcGeneratorHelper extends EthGeneratorHelper { 13 | 14 | } 15 | 16 | module.exports = EtcGeneratorHelper; -------------------------------------------------------------------------------- /src/helpers/generateAddress/ethGeneratorHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseGeneratorHelper = require('./baseGeneratorHelper') 4 | , ecc = require('tiny-secp256k1') 5 | , ecpair = require('ecpair') 6 | , ECPair = ecpair.ECPairFactory(ecc) 7 | , {importPublic, Address} = require('ethereumjs-util') 8 | , {AddressDTO} = require("../../dtos") 9 | ; 10 | 11 | /** 12 | * EthGeneratorHelper 13 | * 14 | * @class EthGeneratorHelper 15 | * 16 | * @extends {BaseGeneratorHelper} 17 | */ 18 | class EthGeneratorHelper extends BaseGeneratorHelper { 19 | /** 20 | * @inheritDoc 21 | */ 22 | generateAddress() { 23 | const pair = ECPair.makeRandom(); 24 | const address = Address.fromPublicKey(importPublic(pair.publicKey)).toString(); 25 | 26 | return new AddressDTO({ 27 | address: address, 28 | publicKey: "0x" + pair.publicKey.toString('hex'), 29 | privateKey: "0x" + pair.privateKey.toString('hex') 30 | }); 31 | }; 32 | } 33 | 34 | module.exports = EthGeneratorHelper; -------------------------------------------------------------------------------- /src/helpers/generateAddress/generatorHelperFactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BtcGeneratorHelper = require('./btcGeneratorHelper') 4 | , EthGeneratorHelper = require('./ethGeneratorHelper') 5 | , BscGeneratorHelper = require('./bscGeneratorHelper') 6 | , EtcGeneratorHelper = require('./bscGeneratorHelper') 7 | , ZcashGeneratorHelper = require('./zcashGeneratorHelper') 8 | , {blockchains} = require('../../enumerations/blockchainEnum') 9 | ; 10 | 11 | class GeneratorHelperFactory { 12 | /** 13 | * @param {string} blockchain 14 | * @param {string} network 15 | * 16 | * @returns {BaseGeneratorHelper} 17 | */ 18 | static create({blockchain, network}) { 19 | const args = { 20 | blockchain, 21 | network 22 | } 23 | 24 | switch (blockchain.toLowerCase()) { 25 | case blockchains.BITCOIN: 26 | return new BtcGeneratorHelper(args); 27 | case blockchains.ETHEREUM: 28 | return new EthGeneratorHelper(args); 29 | case blockchains.BINANCE_SMART_CHAIN: 30 | return new BscGeneratorHelper(args); 31 | case blockchains.ETHEREUM_CLASSIC: 32 | return new EtcGeneratorHelper(args); 33 | case blockchains.ZCASH: 34 | return new ZcashGeneratorHelper(args); 35 | default: 36 | throw new Error('Blockchain not supported'); 37 | } 38 | } 39 | } 40 | 41 | module.exports = GeneratorHelperFactory; -------------------------------------------------------------------------------- /src/helpers/generateAddress/zcash/base58.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const bs58 = require('bs58'); 4 | const Hash = require('./hash'); 5 | 6 | const encode = function(buf) { 7 | let checkedBuf = Buffer.alloc(buf.length + 4); 8 | let hash = Hash.sha256sha256(buf).slice(0, 4); 9 | buf.copy(checkedBuf); 10 | hash.copy(checkedBuf, buf.length); 11 | return bs58.encode(checkedBuf); 12 | }; 13 | 14 | module.exports = { 15 | encode 16 | }; 17 | -------------------------------------------------------------------------------- /src/helpers/generateAddress/zcash/hash.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const crypto = require('crypto'); 4 | 5 | const Hash = module.exports; 6 | 7 | Hash.sha256 = function(buf) { 8 | return crypto.createHash('sha256').update(buf).digest(); 9 | }; 10 | 11 | Hash.ripemd160 = function(buf) { 12 | return crypto.createHash('ripemd160').update(buf).digest(); 13 | }; 14 | 15 | Hash.sha256ripemd160 = function(buf) { 16 | return Hash.ripemd160(Hash.sha256(buf)); 17 | }; 18 | 19 | Hash.sha256sha256 = function(buf) { 20 | return Hash.sha256(Hash.sha256(buf)); 21 | }; 22 | -------------------------------------------------------------------------------- /src/helpers/generateAddress/zcashGeneratorHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseGeneratorHelper = require('./baseGeneratorHelper') 4 | , ecpair = require('ecpair') 5 | , ecc = require('tiny-secp256k1') 6 | , ECPair = ecpair.ECPairFactory(ecc) 7 | , {AddressDTO} = require("../../dtos") 8 | , Base58 = require('./zcash/base58') 9 | , Hash = require('./zcash/hash') 10 | ; 11 | 12 | /** 13 | * ZcashGeneratorHelper 14 | * 15 | * @class ZcashGeneratorHelper 16 | * 17 | * @extends {BaseGeneratorHelper} 18 | */ 19 | class ZcashGeneratorHelper extends BaseGeneratorHelper { 20 | /** 21 | * @inheritDoc 22 | */ 23 | generateAddress() { 24 | const pair = ECPair.makeRandom(); 25 | 26 | let version = Buffer.alloc(2); 27 | version.writeUInt16BE(this.networkConfig.pubKeyHash, 0); 28 | 29 | return new AddressDTO({ 30 | address: Base58.encode(Buffer.concat([version, Hash.sha256ripemd160(pair.publicKey)])), 31 | publicKey: pair.publicKey.toString('hex'), 32 | privateKey: pair.privateKey.toString('hex'), 33 | }); 34 | }; 35 | } 36 | 37 | module.exports = ZcashGeneratorHelper; 38 | -------------------------------------------------------------------------------- /src/helpers/prepare/UTXOBasedPrepareHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BasePrepareTransaction = require("./basePrepareHelper"); 4 | 5 | /** 6 | * UTXObasedPrepareHelper 7 | * 8 | * @class UTXOBasedPrepareHelper 9 | * @extends {BasePrepareTransaction} 10 | */ 11 | class UTXOBasedPrepareHelper extends BasePrepareTransaction { 12 | /** 13 | * Prepare An UTXO-Based Transaction From HD Wallet (xPub, yPub, zPub) 14 | * @param {string} xPub Defines the account extended publicly known key which is used to derive all child public keys 15 | * @param {Array} recipients Represents a list of recipient addresses with the respective amounts 16 | * @param {UTXOBasedFeeOptionsModel} feeOptions Represents the fee options 17 | * @param {Number} locktime Represents the time at which a particular transaction can be added to the blockchain 18 | * @param {Boolean} replaceable Representation of whether the transaction is replaceable 19 | * @param {string} data Representation of the additional data 20 | * 21 | * @returns {Promise|module:model/PrepareAUTXOBasedTransactionFromHDWalletXPubYPubZPubR} 22 | */ 23 | prepare({ 24 | xPub, 25 | recipients, 26 | feeOptions, 27 | locktime, 28 | replaceable, 29 | data, 30 | }) { 31 | const fee = new this.cryptoApis.PrepareAUTXOBasedTransactionFromHDWalletXPubYPubZPubRBDataItemFee() 32 | fee.address = feeOptions.getFeeAddress(); 33 | fee.exactAmount = feeOptions.getFeeAmount() 34 | fee.priority = feeOptions.getPriority(); 35 | 36 | const receivers = recipients.map((recipient) => { 37 | return new this.cryptoApis.PrepareAUTXOBasedTransactionFromHDWalletXPubYPubZPubRBDataItemRecipientsInner( 38 | recipient.getAddress(), 39 | recipient.getAmount()); 40 | }); 41 | 42 | const item = new this.cryptoApis.PrepareAUTXOBasedTransactionFromHDWalletXPubYPubZPubRBDataItem( 43 | xPub, 44 | fee, 45 | receivers, 46 | ); 47 | 48 | item.prepareStrategy = feeOptions.getPrepareStrategy(); 49 | item.additionalData = data; 50 | item.locktime = locktime; 51 | item.replaceable = replaceable; 52 | const postData = new this.cryptoApis.PrepareAUTXOBasedTransactionFromHDWalletXPubYPubZPubRBData(item); 53 | 54 | const opts = { 55 | prepareAUTXOBasedTransactionFromHDWalletXPubYPubZPubRB: new this.cryptoApis.PrepareAUTXOBasedTransactionFromHDWalletXPubYPubZPubRB(postData) 56 | }; 57 | 58 | return this.hdWalletInstance.prepareAUTXOBasedTransactionFromHDWalletXPubYPubZPub(this.blockchain, this.network, opts) 59 | }; 60 | } 61 | 62 | module.exports = UTXOBasedPrepareHelper; -------------------------------------------------------------------------------- /src/helpers/prepare/accountBasedHDWalletPrepareHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BasePrepareHelper = require("./basePrepareHelper"); 4 | 5 | /** 6 | * AccountBasedPrepareTransaction 7 | * 8 | * @class AccountBasedHDWalletPrepareHelper 9 | * 10 | * @extends {BasePrepareHelper} 11 | */ 12 | class AccountBasedHDWalletPrepareHelper extends BasePrepareHelper { 13 | /** 14 | * Prepare An Account-Based Transaction From HD Wallet (xPub, yPub, zPub) 15 | * Through the “Prepare an account-based transaction from HD Wallet” endpoint users can prepare a transaction for signing from a synced with Crypto APIs address from the specific xPub. This endpoint applies to all supported account-based blockchain protocols, e.g. Ethereum, BSC, etc 16 | * @param {string} xPub Defines the account extended publicly known key which is used to derive all child public keys. 17 | * @param {string} sender Represents a sender address 18 | * @param {string} recipient Represents a recipient address 19 | * @param {string} amount Representation of the amount of the transaction 20 | * @param {AccountBasedFeeOptionsModel} feeOptions Represents the fee options 21 | * @param {string|null} nonce Representation of the nonce value 22 | * @param {string|null} data Representation of the additional data 23 | * 24 | * @returns {Promise|module:model/PrepareATransactionFromAnAddressInHDWalletXPubYPubZPubR} 25 | */ 26 | prepare({ 27 | xPub, 28 | sender, 29 | recipient, 30 | amount, 31 | feeOptions, 32 | nonce, 33 | data 34 | }) { 35 | const fee = new this.cryptoApis.PrepareATransactionFromAnAddressInHDWalletXPubYPubZPubRBDataItemFee() 36 | fee.priority = feeOptions.getPriority(); 37 | fee.exactAmount = feeOptions.getFeeAmount(); 38 | 39 | const item = new this.cryptoApis.PrepareATransactionFromAnAddressInHDWalletXPubYPubZPubRBDataItem( 40 | amount, 41 | recipient, 42 | sender, 43 | xPub, 44 | fee, 45 | ); 46 | 47 | item.additionalData = data; 48 | item.nonce = nonce; 49 | const postData = new this.cryptoApis.PrepareATransactionFromAnAddressInHDWalletXPubYPubZPubRBData(item); 50 | 51 | const opts = { 52 | prepareATransactionFromAnAddressInHDWalletXPubYPubZPubRB: new this.cryptoApis.PrepareATransactionFromAnAddressInHDWalletXPubYPubZPubRB(postData) 53 | }; 54 | 55 | return this.hdWalletInstance.prepareATransactionFromAnAddressInHDWalletXPubYPubZPub(this.blockchain, this.network, opts) 56 | }; 57 | } 58 | 59 | module.exports = AccountBasedHDWalletPrepareHelper; 60 | -------------------------------------------------------------------------------- /src/helpers/prepare/accountBasedSingleAddressPrepareHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BasePrepareHelper = require("./basePrepareHelper"); 4 | 5 | /** 6 | * AccountBasedPrepareTransaction 7 | * 8 | * @class AccountBasedSingleAddressPrepareHelper 9 | * 10 | * @extends {BasePrepareHelper} 11 | */ 12 | class AccountBasedSingleAddressPrepareHelper extends BasePrepareHelper { 13 | /** 14 | * Through this endpoint users can prepare a transaction from an address with private and public keys. 15 | * The address does not have to belong to a wallet. The response will include the transaction fee in Wei. 16 | * @param {string} sender Represents a sender address 17 | * @param {string} recipient Represents a recipient address 18 | * @param {string} amount Representation of the amount of the transaction 19 | * @param {AccountBasedFeeOptionsModel} feeOptions Represents the fee options 20 | * @param {string|null} nonce Representation of the nonce value 21 | * @param {string|null} data Representation of the additional data 22 | * 23 | * @returns {Promise|module:model/PrepareTransactionFromAddressR} 24 | */ 25 | prepare({ 26 | sender, 27 | recipient, 28 | amount, 29 | feeOptions, 30 | nonce, 31 | data 32 | }) { 33 | const fee = new this.cryptoApis.PrepareTransactionFromAddressRBDataItemFee() 34 | fee.priority = feeOptions.getPriority(); 35 | fee.exactAmount = feeOptions.getFeeAmount(); 36 | 37 | const item = new this.cryptoApis.PrepareTransactionFromAddressRBDataItem( 38 | amount, 39 | recipient, 40 | sender, 41 | fee, 42 | ); 43 | 44 | item.additionalData = data; 45 | item.nonce = nonce; 46 | const postData = new this.cryptoApis.PrepareTransactionFromAddressRBData(item); 47 | 48 | const opts = { 49 | prepareTransactionFromAddressRB: new this.cryptoApis.PrepareTransactionFromAddressRB(postData) 50 | }; 51 | 52 | return this.featuresApiInstance.prepareTransactionFromAddress(this.blockchain, this.network, opts) 53 | }; 54 | } 55 | 56 | module.exports = AccountBasedSingleAddressPrepareHelper; 57 | -------------------------------------------------------------------------------- /src/helpers/prepare/basePrepareHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const NetworksConfigsEnum = require('../../enumerations/networkEnum'); 4 | const {BaseCryptoAPIsLibAwareService} = require("../../services/baseServices"); 5 | 6 | class BasePrepareHelper extends BaseCryptoAPIsLibAwareService { 7 | /** 8 | * @param {Object} cryptoApis 9 | * @param {string} blockchain 10 | * @param {string} network 11 | */ 12 | constructor(cryptoApis, blockchain, network) { 13 | super(cryptoApis, blockchain, network) 14 | 15 | if (!NetworksConfigsEnum.NETWORKS_CONFIGS.hasOwnProperty(this.blockchain) 16 | || !Object.keys(NetworksConfigsEnum.NETWORKS_CONFIGS[this.blockchain].hasOwnProperty(this.network))) { 17 | throw new Error('Unknown configuration for ' + this.blockchain + ':' + this.network); 18 | } 19 | 20 | this.hdWalletInstance = new this.cryptoApis.HDWalletsApi(); 21 | this.featuresApiInstance = new this.cryptoApis.FeaturesApi(); 22 | } 23 | 24 | /** 25 | * @param {Object} transactionData 26 | * @protected 27 | * 28 | * @return {Promise<*>} 29 | */ 30 | prepare({transactionData}) { 31 | throw new Error('Implement sign method for service ' + this.constructor.name); 32 | }; 33 | } 34 | 35 | module.exports = BasePrepareHelper; -------------------------------------------------------------------------------- /src/helpers/prepare/tokenTransactions/erc20TokenPrepare.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BasePrepareHelper = require("../basePrepareHelper"); 4 | 5 | /** 6 | * ERC20TokenPrepareTransaction 7 | * 8 | * @class ERC20TokenPrepareTransaction 9 | * 10 | * @extends {BasePrepareHelper} 11 | */ 12 | class ERC20TokenPrepareTransaction extends BasePrepareHelper { 13 | /** 14 | * This endpoint is used to prepare a fungible token transfer from an address with private and public keys. 15 | * The address doesn’t have to belong to a wallet. The response will include the transaction fee in Wei 16 | * @param {string} contract Represents a contract address 17 | * @param {string} sender Represents a sender address 18 | * @param {string} recipient Represents a recipient address 19 | * @param {string} amount Representation of the amount of the transaction 20 | * @param {AccountBasedFeeOptionsModel} feeOptions Represents the fee options 21 | * @param {string|null} nonce Representation of the nonce value 22 | * @param {string|null} data Representation of the additional data 23 | * 24 | * @returns {Promise|module:model/PrepareAFungibleTokenTransferFromAddressRB} 25 | */ 26 | prepare({ 27 | contract, 28 | sender, 29 | recipient, 30 | amount, 31 | feeOptions, 32 | nonce, 33 | data 34 | }) { 35 | 36 | const fee = new this.cryptoApis.PrepareAFungibleTokenTransferFromAddressRBDataItemFee() 37 | fee.priority = feeOptions.getPriority(); 38 | fee.exactAmount = feeOptions.getFeeAmount(); 39 | 40 | const item = new this.cryptoApis.PrepareAFungibleTokenTransferFromAddressRBDataItem( 41 | amount, 42 | contract, 43 | recipient, 44 | sender, 45 | fee, 46 | ); 47 | 48 | item.additionalData = data; 49 | item.nonce = nonce; 50 | const postData = new this.cryptoApis.PrepareAFungibleTokenTransferFromAddressRBData(item); 51 | 52 | const opts = { 53 | prepareAFungibleTokenTransferFromAddressRB: new this.cryptoApis.PrepareAFungibleTokenTransferFromAddressRB(postData) 54 | }; 55 | 56 | return this.featuresApiInstance.prepareAFungibleTokenTransferFromAddress(this.blockchain, this.network, opts) 57 | }; 58 | } 59 | 60 | module.exports = ERC20TokenPrepareTransaction; 61 | -------------------------------------------------------------------------------- /src/helpers/prepare/tokenTransactions/erc721TokenPrepare.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BasePrepareHelper = require("../basePrepareHelper"); 4 | 5 | /** 6 | * ERC721TokenPrepareTransaction 7 | * 8 | * @class ERC721TokenPrepareTransaction 9 | * 10 | * @extends {BasePrepareHelper} 11 | */ 12 | class ERC721TokenPrepareTransaction extends BasePrepareHelper { 13 | /** 14 | * This endpoint is used to prepare a non-fungible token transfer from an address with private and public keys. 15 | * The address doesn’t have to belong to a wallet. The response will include the transaction fee in Wei. 16 | * @param {string} contract Represents a contract address 17 | * @param {string} sender Represents a sender address 18 | * @param {string} recipient Represents a recipient address 19 | * @param {string} tokenId Representation of the token id 20 | * @param {AccountBasedFeeOptionsModel} feeOptions Represents the fee options 21 | * @param {string|null} nonce Representation of the nonce value 22 | * @param {string} data Representation of the additional data 23 | * 24 | * @returns {Promise|module:model/PrepareANonFungibleTokenTransferFromAddressR} 25 | */ 26 | prepare({ 27 | contract, 28 | sender, 29 | recipient, 30 | tokenId, 31 | feeOptions, 32 | nonce, 33 | data 34 | }) { 35 | 36 | const fee = new this.cryptoApis.PrepareANonFungibleTokenTransferFromAddressRBDataItemFee() 37 | fee.priority = feeOptions.getPriority(); 38 | fee.exactAmount = feeOptions.getFeeAmount(); 39 | 40 | const item = new this.cryptoApis.PrepareANonFungibleTokenTransferFromAddressRBDataItem( 41 | contract, 42 | recipient, 43 | sender, 44 | tokenId, 45 | fee 46 | ); 47 | 48 | item.additionalData = data; 49 | item.nonce = nonce; 50 | const postData = new this.cryptoApis.PrepareANonFungibleTokenTransferFromAddressRBData(item); 51 | 52 | const opts = { 53 | prepareANonFungibleTokenTransferFromAddressRB: new this.cryptoApis.PrepareANonFungibleTokenTransferFromAddressRB(postData) 54 | }; 55 | 56 | return this.featuresApiInstance.prepareANonFungibleTokenTransferFromAddress(this.blockchain, this.network, opts) 57 | }; 58 | } 59 | 60 | module.exports = ERC721TokenPrepareTransaction; 61 | -------------------------------------------------------------------------------- /src/helpers/prepare/tokenTransactions/tokenPrepareFactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {STANDARDS: token} = require('../../../enumerations/tokenEnum') 4 | , ERC20TokenPrepareTransaction = require('./erc20TokenPrepare') 5 | , ERC721TokenPrepareTransaction = require('./erc721TokenPrepare') 6 | ; 7 | 8 | class TokenPrepareHelperFactory { 9 | /** 10 | * @param {Object} cryptoApis 11 | * @param {string} blockchain 12 | * @param {string} network 13 | * @param {string} tokenStandard 14 | * 15 | * @returns {BasePrepareHelper} 16 | */ 17 | static create({cryptoApis, blockchain, network, tokenStandard}) { 18 | 19 | switch (tokenStandard.toLowerCase()) { 20 | case token.ERC_20: 21 | case token.BEP_20: 22 | return new ERC20TokenPrepareTransaction(cryptoApis, blockchain, network); 23 | case token.ERC_721: 24 | case token.BEP_721: 25 | return new ERC721TokenPrepareTransaction(cryptoApis, blockchain, network); 26 | default: 27 | throw new Error('Token standard type not supported'); 28 | } 29 | } 30 | } 31 | 32 | module.exports = TokenPrepareHelperFactory; -------------------------------------------------------------------------------- /src/helpers/sign/baseSignerHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const NetworksConfigsEnum = require('../../enumerations/networkEnum'); 4 | const {BaseBlockchainAwareService} = require("../../services/baseServices"); 5 | const b58 = require('bs58check'); 6 | const HDKey = require("hdkey"); 7 | const XPRIV_VERSION = "0488ade4"; 8 | 9 | /** 10 | * BaseSignerHelper 11 | * 12 | * @class BaseSignerHelper 13 | * @extends {BaseBlockchainAwareService} 14 | */ 15 | class BaseSignerHelper extends BaseBlockchainAwareService { 16 | /** 17 | * @param {string} blockchain 18 | * @param {string} network 19 | */ 20 | constructor({blockchain, network}) { 21 | super(blockchain, network) 22 | 23 | if (!NetworksConfigsEnum.NETWORKS_CONFIGS.hasOwnProperty(this.blockchain) 24 | || !Object.keys(NetworksConfigsEnum.NETWORKS_CONFIGS[this.blockchain].hasOwnProperty(this.network))) { 25 | throw new Error('Unknown configuration for ' + this.blockchain + ':' + this.network); 26 | } 27 | 28 | this.networkConfig = NetworksConfigsEnum.NETWORKS_CONFIGS[this.blockchain][this.network]; 29 | } 30 | 31 | /** 32 | * @param {string} xPriv account extended xPriv 33 | * @param {TransactionDTO} transaction 34 | * @protected 35 | * @return {{id: string, raw: string}} 36 | */ 37 | sign({xPriv, transaction}) { 38 | throw new Error('Implement sign method for service ' + this.constructor.name); 39 | }; 40 | 41 | /** 42 | * @param {string} extendedPrivateKey 43 | * @return {HDKey} 44 | * @protected 45 | */ 46 | _createHDKey(extendedPrivateKey) { 47 | const data = b58.decode(extendedPrivateKey); 48 | const xPrivData = Buffer.concat([Buffer.from(XPRIV_VERSION, 'hex'), data.slice(4)]); 49 | const xPriv = b58.encode(xPrivData); 50 | 51 | return HDKey.fromExtendedKey(xPriv) 52 | } 53 | 54 | } 55 | 56 | module.exports = BaseSignerHelper; -------------------------------------------------------------------------------- /src/helpers/sign/bchSignerHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseSignerHelper = require('./baseSignerHelper') 4 | , bitcoreLibCash = require('bitcore-lib-cash') 5 | , HDKey = require("hdkey") 6 | , bitcoinjs = require("bitcoinjs-lib") 7 | ; 8 | 9 | /** 10 | * BchSignerHelper 11 | * 12 | * @class BchSignerHelper 13 | * 14 | * @extends {BaseSignerHelper} 15 | */ 16 | class BchSignerHelper extends BaseSignerHelper { 17 | /** 18 | * @inheritDoc 19 | */ 20 | sign({xPriv, transaction}) { 21 | const prepared = new bitcoreLibCash.Transaction({}) 22 | .from(transaction.data.inputs) 23 | ; 24 | 25 | prepared.version = transaction?.version || 2; 26 | 27 | for (const output of transaction.outputs) { 28 | prepared.addOutput(new bitcoreLibCash.Transaction.Output({ 29 | satoshis: output.satoshis, 30 | script: output.script, 31 | })); 32 | } 33 | 34 | if (transaction.feePerByte) { 35 | prepared.feePerByte(transaction.feePerByte); 36 | } 37 | 38 | if (transaction.transactionData) { 39 | prepared.addData(transaction.transactionData); 40 | } 41 | 42 | if (transaction.locktime) { 43 | if (transaction.locktime >= 500000000) { 44 | prepared.lockUntilDate(transaction.locktime); 45 | } else { 46 | prepared.lockUntilBlockHeight(transaction.locktime); 47 | } 48 | } 49 | 50 | const hdKey = this._createHDKey(xPriv); 51 | const privKeys = transaction.inputs.map( (input) => { 52 | const derivationPath = `m/${input.change}/${input.derivationIndex}`; 53 | const derivedPrivKey = hdKey.derive(derivationPath) 54 | const signer = bitcoinjs.ECPair.fromPrivateKey( 55 | Buffer.from(derivedPrivKey.privateKey, 'hex'), 56 | {network: this.networkConfig} 57 | ); 58 | return new bitcoreLibCash.PrivateKey(signer.privateKey.toString('hex')); 59 | }) 60 | 61 | prepared.sign(privKeys); 62 | prepared.isFullySigned(); 63 | 64 | return { 65 | id: prepared.id, 66 | raw: prepared.serialize({ 67 | disableDustOutputs: true, 68 | disableMoreOutputThanInput: true, 69 | disableLargeFees: true, 70 | }), 71 | }; 72 | } 73 | } 74 | 75 | module.exports = BchSignerHelper; -------------------------------------------------------------------------------- /src/helpers/sign/bscSignerHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const EthSignerHelper = require('./ethSignerHelper') 4 | , {Transaction: EthereumTx} = require("@ethereumjs/tx") 5 | ; 6 | 7 | /** 8 | * BscSignerHelper 9 | * 10 | * @class BscSignerHelper 11 | * 12 | * @extends {EthSignerHelper} 13 | */ 14 | class BscSignerHelper extends EthSignerHelper { 15 | 16 | /** 17 | * 18 | * @inheritDoc 19 | */ 20 | _buildTransaction(transaction) { 21 | let txData = { 22 | from: transaction.sender, 23 | to: transaction.recipient, 24 | value: transaction.amount, 25 | gasPrice: transaction.gasPrice, 26 | gasLimit: transaction.gasLimit, 27 | nonce: transaction.nonce, 28 | data: transaction?.data?.data || transaction?.data, 29 | }; 30 | 31 | return new EthereumTx(txData, this.networkConfig); 32 | } 33 | } 34 | 35 | module.exports = BscSignerHelper; -------------------------------------------------------------------------------- /src/helpers/sign/btcSignerHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseSignerHelper = require('./baseSignerHelper') 4 | , bitcoinjs = require('bitcoinjs-lib') 5 | , bitcorejs = require('bitcore-lib') 6 | , HDKey = require("hdkey") 7 | ; 8 | 9 | /** 10 | * BtcSignerHelper 11 | * 12 | * @class BtcSignerHelper 13 | * 14 | * @extends {BaseSignerHelper} 15 | */ 16 | class BtcSignerHelper extends BaseSignerHelper { 17 | /** 18 | * @inheritDoc 19 | */ 20 | sign({xPriv, transaction}) { 21 | const prepared = new bitcorejs.Transaction() 22 | .from(transaction.data.inputs) 23 | ; 24 | 25 | prepared.version = transaction?.version || 2; 26 | 27 | for (const output of transaction.outputs) { 28 | prepared.addOutput(new bitcorejs.Transaction.Output({ 29 | satoshis: output.satoshis, 30 | script: output.script, 31 | })); 32 | } 33 | 34 | if (transaction.feePerByte) { 35 | prepared.feePerByte(transaction.feePerByte); 36 | } 37 | 38 | if (transaction.transactionData) { 39 | prepared.addData(transaction.transactionData); 40 | } 41 | 42 | if (transaction.locktime) { 43 | if (transaction.locktime >= 500000000) { 44 | prepared.lockUntilDate(transaction.locktime); 45 | } else { 46 | prepared.lockUntilBlockHeight(transaction.locktime); 47 | } 48 | } 49 | 50 | if (transaction.replaceable) { 51 | prepared.enableRBF(); 52 | } 53 | 54 | const hdKey = this._createHDKey(xPriv); 55 | const privKeys = transaction.inputs.map( (input) => { 56 | const derivationPath = `m/${input.change}/${input.derivationIndex}`; 57 | const derivedPrivKey = hdKey.derive(derivationPath); 58 | const signer = bitcoinjs.ECPair.fromPrivateKey( 59 | Buffer.from(derivedPrivKey.privateKey, 'hex'), 60 | {network: this.networkConfig} 61 | ); 62 | 63 | return new bitcorejs.PrivateKey(signer.privateKey.toString('hex')); 64 | }) 65 | 66 | prepared.sign(privKeys); 67 | prepared.isFullySigned(); 68 | 69 | return { 70 | id: prepared.id, 71 | raw: prepared.serialize({ 72 | disableDustOutputs: true, 73 | disableMoreOutputThanInput: true, 74 | disableLargeFees: true, 75 | disableSmallFees: true, 76 | }), 77 | }; 78 | }; 79 | } 80 | 81 | module.exports = BtcSignerHelper; -------------------------------------------------------------------------------- /src/helpers/sign/dashSignerHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseSignerHelper = require("./baseSignerHelper") 4 | , bitcoinjs = require('bitcoinjs-lib') 5 | , bitcorejs = require('@dashevo/dashcore-lib') 6 | , HDKey = require("hdkey") 7 | ; 8 | 9 | /** 10 | * DashSignerHelper 11 | * 12 | * @class DashSignerHelper 13 | * 14 | * @extends {BaseSignerHelper} 15 | */ 16 | class DashSignerHelper extends BaseSignerHelper { 17 | 18 | /** 19 | * @inheritDoc 20 | */ 21 | sign({xPriv, transaction}) { 22 | const prepared = new bitcorejs.Transaction({}) 23 | .from(transaction.data.inputs) 24 | ; 25 | 26 | prepared.version = transaction?.version || 2; 27 | 28 | for (const output of transaction.outputs) { 29 | prepared.addOutput(new bitcorejs.Transaction.Output({ 30 | satoshis: output.satoshis, 31 | script: output.script, 32 | })); 33 | } 34 | 35 | if (transaction.feePerByte) { 36 | prepared.feePerKb(Math.round(transaction.feePerByte / 1024)); 37 | } 38 | 39 | if (transaction.transactionData) { 40 | prepared.addData(transaction.transactionData); 41 | } 42 | 43 | if (transaction.locktime) { 44 | if (transaction.locktime >= 500000000) { 45 | prepared.lockUntilDate(transaction.locktime); 46 | } else { 47 | prepared.lockUntilBlockHeight(transaction.locktime); 48 | } 49 | } 50 | 51 | const hdKey = this._createHDKey(xPriv); 52 | const privKeys = transaction.inputs.map((input) => { 53 | const derivationPath = `m/${input.change}/${input.derivationIndex}`; 54 | const derivedPrivKey = hdKey.derive(derivationPath) 55 | const signer = bitcoinjs.ECPair.fromPrivateKey( 56 | Buffer.from(derivedPrivKey.privateKey, 'hex'), 57 | {network: this.networkConfig} 58 | ); 59 | return new bitcorejs.PrivateKey(signer.privateKey.toString('hex')); 60 | }) 61 | 62 | prepared.sign(privKeys); 63 | prepared.isFullySigned(); 64 | 65 | return { 66 | id: prepared.id, 67 | raw: prepared.serialize({ 68 | disableDustOutputs: true, 69 | disableMoreOutputThanInput: true, 70 | disableLargeFees: true, 71 | disableSmallFees: true, 72 | }), 73 | }; 74 | } 75 | } 76 | 77 | module.exports = DashSignerHelper; -------------------------------------------------------------------------------- /src/helpers/sign/dogecoinSignerHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseSignerHelper = require('./baseSignerHelper') 4 | , HDKey = require("hdkey") 5 | , bitcoinjs = require("bitcoinjs-lib") 6 | , bitcorejs = require('bitcore-lib-doge') 7 | ; 8 | 9 | 10 | /** 11 | * DogecoinSignerHelper 12 | * 13 | * @class DogecoinSignerHelper 14 | * 15 | * @extends {BaseSignerHelper} 16 | */ 17 | class DogecoinSignerHelper extends BaseSignerHelper { 18 | /** 19 | * @inheritDoc 20 | */ 21 | sign({xPriv, transaction}) { 22 | const prepared = new bitcorejs.Transaction({}) 23 | .from(transaction.data.inputs) 24 | ; 25 | 26 | prepared.version = transaction?.version || 1; 27 | 28 | for (const output of transaction.outputs) { 29 | prepared.addOutput(new bitcorejs.Transaction.Output({ 30 | satoshis: output.satoshis, 31 | script: output.script, 32 | })); 33 | } 34 | 35 | if (transaction.feePerByte) { 36 | prepared.feePerKb(Math.round(transaction.feePerByte / 1024)); 37 | } 38 | 39 | if (transaction.transactionData) { 40 | prepared.addData(transaction.transactionData); 41 | } 42 | 43 | if (transaction.locktime) { 44 | if (transaction.locktime >= 500000000) { 45 | prepared.lockUntilDate(transaction.locktime); 46 | } else { 47 | prepared.lockUntilBlockHeight(transaction.locktime); 48 | } 49 | } 50 | 51 | const hdKey = this._createHDKey(xPriv); 52 | const privKeys = transaction.inputs.map((input) => { 53 | const derivationPath = `m/${input.change}/${input.derivationIndex}`; 54 | const derivedPrivKey = hdKey.derive(derivationPath) 55 | const signer = bitcoinjs.ECPair.fromPrivateKey( 56 | Buffer.from(derivedPrivKey.privateKey, 'hex'), 57 | {network: this.networkConfig} 58 | ); 59 | return new bitcorejs.PrivateKey(signer.privateKey.toString('hex')); 60 | }) 61 | 62 | prepared.sign(privKeys); 63 | prepared.isFullySigned(); 64 | 65 | return { 66 | id: prepared.id, 67 | raw: prepared.serialize({ 68 | disableDustOutputs: true, 69 | disableMoreOutputThanInput: true, 70 | disableLargeFees: true, 71 | disableSmallFees: true, 72 | }), 73 | }; 74 | } 75 | } 76 | 77 | module.exports = DogecoinSignerHelper; -------------------------------------------------------------------------------- /src/helpers/sign/etcSignerHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const EthSignerHelper = require('./ethSignerHelper') 4 | , EthereumTx = require('@ethereumjs/tx').Transaction 5 | ; 6 | 7 | 8 | /** 9 | * EtcSignerHelper 10 | * 11 | * @class EtcSignerHelper 12 | * 13 | * @extends {EthSignerHelper} 14 | */ 15 | class EtcSignerHelper extends EthSignerHelper { 16 | 17 | /** 18 | * 19 | * @inheritDoc 20 | */ 21 | _buildTransaction(transaction) { 22 | let txData = { 23 | from: transaction?.sender, 24 | to: transaction?.recipient, 25 | value: transaction?.amount, 26 | gasPrice: transaction?.gasPrice, 27 | gasLimit: transaction?.gasLimit, 28 | nonce: transaction?.nonce, 29 | data: transaction?.data?.data || transaction?.data, 30 | }; 31 | 32 | return new EthereumTx(txData, this.networkConfig); 33 | } 34 | } 35 | 36 | module.exports = EtcSignerHelper; -------------------------------------------------------------------------------- /src/helpers/sign/ethSignerHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseSignerHelper = require('./baseSignerHelper') 4 | , {FeeMarketEIP1559Transaction: GasFeeMarketTransaction, Transaction} = require('@ethereumjs/tx') 5 | , AccountBasedTransaction = require('../../dtos/prepare/accountBasedTransactionDTO') 6 | , HDKey = require("hdkey") 7 | , LEGACY_TRANSACTION = 'legacy-transaction' 8 | ; 9 | 10 | /** 11 | * EthSignerHelper 12 | * 13 | * @class EthSignerHelper 14 | * 15 | * @extends {BaseSignerHelper} 16 | */ 17 | class EthSignerHelper extends BaseSignerHelper { 18 | /** 19 | * @inheritDoc 20 | */ 21 | sign({xPriv, transaction}) { 22 | const privKey = this._preparePrivKey(xPriv, transaction?.derivationIndex); 23 | const tx = this._buildTransaction(transaction); 24 | const signedTX = tx.sign(privKey); 25 | const serializedTx = signedTX.serialize(); 26 | 27 | return { 28 | id: '0x' + signedTX.hash().toString('hex'), 29 | raw: '0x' + serializedTx.toString('hex'), 30 | }; 31 | }; 32 | 33 | /** 34 | * @param {string} xPriv 35 | * @param {string} index 36 | * 37 | * @returns Buffer 38 | */ 39 | _preparePrivKey(xPriv, index) { 40 | if (index) { 41 | const hdkey = HDKey.fromExtendedKey(xPriv) 42 | const derivationPath = `m/0/${index}`; 43 | const derivedPrivKey = hdkey.derive(derivationPath); 44 | 45 | return derivedPrivKey.privateKey; 46 | } 47 | if (xPriv.startsWith("0x")) { 48 | xPriv = xPriv.slice(2); 49 | } 50 | return Buffer.from(xPriv, 'hex'); 51 | } 52 | 53 | /** 54 | * 55 | * @param {AccountBasedTransaction} transaction 56 | * 57 | * @return {{}} 58 | */ 59 | _buildTransaction(transaction) { 60 | let txData = { 61 | from: transaction?.sender, 62 | to: transaction?.recipient, 63 | value: transaction?.amount, 64 | maxFeePerGas: transaction?.maxFeePerGas, 65 | maxPriorityFeePerGas: transaction?.maxPriorityFeePerGas, 66 | gasLimit: transaction?.gasLimit, 67 | gasPrice: transaction?.gasPrice, 68 | nonce: transaction?.nonce, 69 | data: transaction?.data?.data, 70 | type: "0x2" 71 | }; 72 | 73 | if (transaction?.transactionType?.toString() === LEGACY_TRANSACTION) { 74 | return Transaction.fromTxData(txData, this.networkConfig) 75 | } 76 | 77 | return GasFeeMarketTransaction.fromTxData(txData, this.networkConfig); 78 | } 79 | } 80 | 81 | module.exports = EthSignerHelper; -------------------------------------------------------------------------------- /src/helpers/sign/ltcSignerHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BaseSignerHelper = require('./baseSignerHelper') 4 | , bitcoinjs = require("bitcoinjs-lib") 5 | , bitcorejs = require("bitcore-lib-ltc") 6 | , HDKey = require("hdkey") 7 | ; 8 | 9 | /** 10 | * LtcSignerHelper 11 | * 12 | * @class LtcSignerHelper 13 | * 14 | * @extends {BaseSignerHelper} 15 | */ 16 | class LtcSignerHelper extends BaseSignerHelper { 17 | /** 18 | * @inheritDoc 19 | */ 20 | sign({xPriv, transaction}) { 21 | const prepared = new bitcorejs.Transaction({}) 22 | .from(transaction.data.inputs) 23 | ; 24 | 25 | prepared.version = transaction?.version || 2; 26 | 27 | for (const output of transaction.outputs) { 28 | prepared.addOutput(new bitcorejs.Transaction.Output({ 29 | satoshis: output.satoshis, 30 | script: output.script, 31 | })); 32 | } 33 | 34 | if (transaction.feePerByte) { 35 | prepared.feePerKb(Math.round(transaction.feePerByte / 1024)); 36 | } 37 | 38 | if (transaction.transactionData) { 39 | prepared.addData(transaction.transactionData); 40 | } 41 | 42 | if (transaction.locktime) { 43 | if (transaction.locktime >= 500000000) { 44 | prepared.lockUntilDate(transaction.locktime); 45 | } else { 46 | prepared.lockUntilBlockHeight(transaction.locktime); 47 | } 48 | } 49 | 50 | if (transaction.replaceable) { 51 | prepared.enableRBF(); 52 | } 53 | 54 | const hdKey = this._createHDKey(xPriv); 55 | const privKeys = transaction.inputs.map((input) => { 56 | const derivationPath = `m/${input.change}/${input.derivationIndex}`; 57 | const derivedPrivKey = hdKey.derive(derivationPath) 58 | const signer = bitcoinjs.ECPair.fromPrivateKey( 59 | Buffer.from(derivedPrivKey.privateKey, 'hex'), 60 | {network: this.networkConfig} 61 | ); 62 | return new bitcorejs.PrivateKey(signer.privateKey.toString('hex')); 63 | }) 64 | 65 | prepared.sign(privKeys); 66 | prepared.isFullySigned(); 67 | 68 | return { 69 | id: prepared.id, 70 | raw: prepared.serialize({ 71 | disableDustOutputs: true, 72 | disableMoreOutputThanInput: true, 73 | disableLargeFees: true, 74 | disableSmallFees: true, 75 | }), 76 | }; 77 | } 78 | } 79 | 80 | module.exports = LtcSignerHelper; -------------------------------------------------------------------------------- /src/helpers/sign/signerHelperFactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const EthSignerHelper = require('./ethSignerHelper') 4 | , BtcSignerHelper = require('./btcSignerHelper') 5 | , EtcSignerHelper = require('./etcSignerHelper') 6 | , BscSignerHelper = require('./bscSignerHelper') 7 | , BchSignerHelper = require('./bchSignerHelper') 8 | , LtcSignerHelper = require('./ltcSignerHelper') 9 | , DogecoinSignerHelper = require('./dogecoinSignerHelper') 10 | , DashSignerHelper = require('./dashSignerHelper') 11 | , {blockchains} = require('../../enumerations/blockchainEnum') 12 | ; 13 | 14 | class SignerHelperFactory { 15 | /** 16 | * @param {string} blockchain 17 | * @param {string} network 18 | * 19 | * @returns {BaseSignerHelper} 20 | */ 21 | static create({blockchain, network}) { 22 | const args = { 23 | blockchain, 24 | network 25 | }; 26 | 27 | switch (blockchain.toLowerCase()) { 28 | case blockchains.BITCOIN: 29 | return new BtcSignerHelper(args); 30 | case blockchains.ETHEREUM: 31 | return new EthSignerHelper(args); 32 | case blockchains.ETHEREUM_CLASSIC: 33 | return new EtcSignerHelper(args); 34 | case blockchains.BINANCE_SMART_CHAIN: 35 | return new BscSignerHelper(args); 36 | case blockchains.BITCOIN_CASH: 37 | return new BchSignerHelper(args); 38 | case blockchains.LITECOIN: 39 | return new LtcSignerHelper(args); 40 | case blockchains.DOGECOIN: 41 | return new DogecoinSignerHelper(args); 42 | case blockchains.DASH: 43 | return new DashSignerHelper(args); 44 | default: 45 | throw new Error('Blockchain signer type not supported'); 46 | } 47 | } 48 | } 49 | 50 | module.exports = SignerHelperFactory; -------------------------------------------------------------------------------- /src/helpers/xpubFormatsHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const {blockchains} = require('../enumerations/blockchainEnum') 4 | , { 5 | NETWORKS_CONFIGS: NetworksConfigsEnum, 6 | NETWORKS: NetworksEnum 7 | } = require('../enumerations/networkEnum') 8 | , bip32 = require('hdkey') 9 | ; 10 | 11 | const XPUB_DERIVATION_TYPE_BIP44 = "BIP44"; 12 | const XPUB_DERIVATION_TYPE_BIP49 = "BIP49"; 13 | const XPUB_DERIVATION_TYPE_BIP84 = "BIP84"; 14 | const XPUB_DERIVATION_PATHS = { 15 | [blockchains.BITCOIN]: { 16 | [NetworksEnum[blockchains.BITCOIN]['NETWORK_BITCOIN_MAINNET']]: { 17 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/0'/0'", 18 | [XPUB_DERIVATION_TYPE_BIP49]: "m/49'/0'/0'", 19 | [XPUB_DERIVATION_TYPE_BIP84]: "m/84'/0'/0'", 20 | }, 21 | [NetworksEnum[blockchains.BITCOIN]["NETWORK_BITCOIN_TESTNET"]]: { 22 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/1'/0'", 23 | [XPUB_DERIVATION_TYPE_BIP49]: "m/49'/1'/0'", 24 | [XPUB_DERIVATION_TYPE_BIP84]: "m/84'/1'/0'", 25 | }, 26 | }, 27 | [blockchains.LITECOIN]: { 28 | [NetworksEnum[blockchains.LITECOIN]["NETWORK_LITECOIN_MAINNET"]]: { 29 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/2'/0'", 30 | [XPUB_DERIVATION_TYPE_BIP49]: "m/49'/2'/0'", 31 | [XPUB_DERIVATION_TYPE_BIP84]: "m/84'/2'/0'", 32 | }, 33 | [NetworksEnum[blockchains.LITECOIN]["NETWORK_LITECOIN_TESTNET"]]: { 34 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/1'/0'", 35 | [XPUB_DERIVATION_TYPE_BIP49]: "m/49'/1'/0'", 36 | [XPUB_DERIVATION_TYPE_BIP84]: "m/84'/1'/0'", 37 | }, 38 | }, 39 | [blockchains.DOGECOIN]: { 40 | [NetworksEnum[blockchains.DOGECOIN]["NETWORK_DOGECOIN_MAINNET"]]: { 41 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/3'/0'", 42 | }, 43 | [NetworksEnum[blockchains.DOGECOIN]["NETWORK_DOGECOIN_TESTNET"]]: { 44 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/1'/0'", 45 | }, 46 | }, 47 | [blockchains.DASH]: { 48 | [NetworksEnum[blockchains.DASH]["NETWORK_DASH_MAINNET"]]: { 49 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/5'/0'", 50 | }, 51 | [NetworksEnum[blockchains.DASH]["NETWORK_DASH_TESTNET"]]: { 52 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/1'/0'", 53 | }, 54 | }, 55 | [blockchains.BITCOIN_CASH]: { 56 | [NetworksEnum[blockchains.BITCOIN_CASH]["NETWORK_BITCOIN_CASH_MAINNET"]]: { 57 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/145'/0'", 58 | }, 59 | [NetworksEnum[blockchains.BITCOIN_CASH]["NETWORK_BITCOIN_CASH_TESTNET"]]: { 60 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/1'/0'", 61 | }, 62 | }, 63 | [blockchains.ETHEREUM]: { 64 | [NetworksEnum[blockchains.ETHEREUM]["NETWORK_ETHEREUM_MAINNET"]]: { 65 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/60'/0'", 66 | }, 67 | [NetworksEnum[blockchains.ETHEREUM]["NETWORK_ETHEREUM_GOERLI"]]: { 68 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/1'/0'", 69 | }, 70 | }, 71 | [blockchains.ETHEREUM_CLASSIC]: { 72 | [NetworksEnum[blockchains.ETHEREUM_CLASSIC]["NETWORK_ETHEREUM_CLASSIC_MAINNET"]]: { 73 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/61'/0'", 74 | }, 75 | [NetworksEnum[blockchains.ETHEREUM_CLASSIC]["NETWORK_ETHEREUM_CLASSIC_MORDOR"]]: { 76 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/1'/0'", 77 | }, 78 | }, 79 | [blockchains.BINANCE_SMART_CHAIN]: { 80 | [NetworksEnum[blockchains.BINANCE_SMART_CHAIN]["NETWORK_BINANCE_SMART_CHAIN_MAINNET"]]: { 81 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/60'/0'", 82 | }, 83 | [NetworksEnum[blockchains.BINANCE_SMART_CHAIN]["NETWORK_BINANCE_SMART_CHAIN_TESTNET"]]: { 84 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/1'/0'", 85 | }, 86 | }, 87 | [blockchains.ZCASH]: { 88 | [NetworksEnum[blockchains.ZCASH]["NETWORK_ZCASH_MAINNET"]]: { 89 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/133'/0'", 90 | }, 91 | [NetworksEnum[blockchains.ZCASH]["NETWORK_ZCASH_TESTNET"]]: { 92 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/1'/0'", 93 | }, 94 | }, 95 | [blockchains.XRP]: { 96 | [NetworksEnum[blockchains.XRP]["NETWORK_XRP_MAINNET"]]: { 97 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/144'/0'", 98 | }, 99 | [NetworksEnum[blockchains.XRP]["NETWORK_XRP_TESTNET"]]: { 100 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/1'/0'", 101 | }, 102 | }, 103 | [blockchains.TRX]: { 104 | [NetworksEnum[blockchains.TRX]["NETWORK_TRX_MAINNET"]]: { 105 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/195'/0'", 106 | }, 107 | [NetworksEnum[blockchains.TRX]["NETWORK_TRX_NILE"]]: { 108 | [XPUB_DERIVATION_TYPE_BIP44]: "m/44'/1'/0'", 109 | }, 110 | } 111 | }; 112 | 113 | const XPUB_DERIVATION_TYPES = { 114 | [blockchains.BITCOIN]: { 115 | [XPUB_DERIVATION_TYPE_BIP44]: (seed, network) => { 116 | let networkConfig = NetworksConfigsEnum[[blockchains.BITCOIN]][network]; 117 | 118 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip32); 119 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.BITCOIN][network][XPUB_DERIVATION_TYPE_BIP44]; 120 | const accountXpriv = rootKey.derive(derivationPath); 121 | 122 | return { 123 | rootKey: rootKey.privateExtendedKey, 124 | derivationType: XPUB_DERIVATION_TYPE_BIP44, 125 | derivationPath: derivationPath, 126 | accountXpriv: accountXpriv.privateExtendedKey, 127 | accountXpub: accountXpriv.publicExtendedKey 128 | } 129 | }, 130 | [XPUB_DERIVATION_TYPE_BIP49]: (seed, network) => { 131 | let networkConfig = NetworksConfigsEnum[[blockchains.BITCOIN]][network]; 132 | 133 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.BITCOIN][network][XPUB_DERIVATION_TYPE_BIP49]; 134 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip49); 135 | const accountXpriv = rootKey.derive(derivationPath); 136 | 137 | return { 138 | rootKey: rootKey.privateExtendedKey, 139 | derivationType: XPUB_DERIVATION_TYPE_BIP49, 140 | derivationPath: derivationPath, 141 | accountXpriv: accountXpriv.privateExtendedKey, 142 | accountXpub: accountXpriv.publicExtendedKey 143 | } 144 | }, 145 | [XPUB_DERIVATION_TYPE_BIP84]: (seed, network) => { 146 | let networkConfig = NetworksConfigsEnum[[blockchains.BITCOIN]][network]; 147 | 148 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.BITCOIN][network][XPUB_DERIVATION_TYPE_BIP84]; 149 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip84); 150 | const accountXpriv = rootKey.derive(derivationPath); 151 | 152 | return { 153 | rootKey: rootKey.privateExtendedKey, 154 | derivationType: XPUB_DERIVATION_TYPE_BIP84, 155 | derivationPath: derivationPath, 156 | accountXpriv: accountXpriv.privateExtendedKey, 157 | accountXpub: accountXpriv.publicExtendedKey 158 | } 159 | }, 160 | }, 161 | [blockchains.LITECOIN]: { 162 | [XPUB_DERIVATION_TYPE_BIP44]: (seed, network) => { 163 | let networkConfig = NetworksConfigsEnum[[blockchains.LITECOIN]][network]; 164 | 165 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip32); 166 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.LITECOIN][network][XPUB_DERIVATION_TYPE_BIP44]; 167 | const accountXpriv = rootKey.derive(derivationPath); 168 | 169 | return { 170 | rootKey: rootKey.privateExtendedKey, 171 | derivationType: XPUB_DERIVATION_TYPE_BIP44, 172 | derivationPath: derivationPath, 173 | accountXpriv: accountXpriv.privateExtendedKey, 174 | accountXpub: accountXpriv.publicExtendedKey 175 | } 176 | }, 177 | 178 | [XPUB_DERIVATION_TYPE_BIP49]: (seed, network) => { 179 | let networkConfig = NetworksConfigsEnum[[blockchains.LITECOIN]][network]; 180 | 181 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.LITECOIN][network][XPUB_DERIVATION_TYPE_BIP49]; 182 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip49); 183 | const accountXpriv = rootKey.derive(derivationPath); 184 | 185 | return { 186 | rootKey: rootKey.privateExtendedKey, 187 | derivationType: XPUB_DERIVATION_TYPE_BIP49, 188 | derivationPath: derivationPath, 189 | accountXpriv: accountXpriv.privateExtendedKey, 190 | accountXpub: accountXpriv.publicExtendedKey 191 | } 192 | }, 193 | [XPUB_DERIVATION_TYPE_BIP84]: (seed, network) => { 194 | let networkConfig = NetworksConfigsEnum[[blockchains.LITECOIN]][network]; 195 | 196 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.LITECOIN][network][XPUB_DERIVATION_TYPE_BIP84]; 197 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip84); 198 | const accountXpriv = rootKey.derive(derivationPath); 199 | 200 | return { 201 | rootKey: rootKey.privateExtendedKey, 202 | derivationType: XPUB_DERIVATION_TYPE_BIP84, 203 | derivationPath: derivationPath, 204 | accountXpriv: accountXpriv.privateExtendedKey, 205 | accountXpub: accountXpriv.publicExtendedKey 206 | } 207 | }, 208 | }, 209 | [blockchains.BITCOIN_CASH]: { 210 | [XPUB_DERIVATION_TYPE_BIP44]: (seed, network) => { 211 | let networkConfig = NetworksConfigsEnum[[blockchains.BITCOIN_CASH]][network]; 212 | 213 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip32); 214 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.BITCOIN_CASH][network][XPUB_DERIVATION_TYPE_BIP44]; 215 | const accountXpriv = rootKey.derive(derivationPath); 216 | 217 | return { 218 | rootKey: rootKey.privateExtendedKey, 219 | derivationType: XPUB_DERIVATION_TYPE_BIP44, 220 | derivationPath: derivationPath, 221 | accountXpriv: accountXpriv.privateExtendedKey, 222 | accountXpub: accountXpriv.publicExtendedKey 223 | } 224 | } 225 | }, 226 | [blockchains.DOGECOIN]: { 227 | [XPUB_DERIVATION_TYPE_BIP44]: (seed, network) => { 228 | let networkConfig = NetworksConfigsEnum[[blockchains.DOGECOIN]][network]; 229 | 230 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip32); 231 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.DOGECOIN][network][XPUB_DERIVATION_TYPE_BIP44]; 232 | const accountXpriv = rootKey.derive(derivationPath); 233 | 234 | return { 235 | rootKey: rootKey.privateExtendedKey, 236 | derivationType: XPUB_DERIVATION_TYPE_BIP44, 237 | derivationPath: derivationPath, 238 | accountXpriv: accountXpriv.privateExtendedKey, 239 | accountXpub: accountXpriv.publicExtendedKey 240 | } 241 | } 242 | }, 243 | [blockchains.DASH]: { 244 | [XPUB_DERIVATION_TYPE_BIP44]: (seed, network) => { 245 | let networkConfig = NetworksConfigsEnum[[blockchains.DASH]][network]; 246 | 247 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip32); 248 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.DASH][network][XPUB_DERIVATION_TYPE_BIP44]; 249 | const accountXpriv = rootKey.derive(derivationPath); 250 | 251 | return { 252 | rootKey: rootKey.privateExtendedKey, 253 | derivationType: XPUB_DERIVATION_TYPE_BIP44, 254 | derivationPath: derivationPath, 255 | accountXpriv: accountXpriv.privateExtendedKey, 256 | accountXpub: accountXpriv.publicExtendedKey 257 | } 258 | } 259 | }, 260 | [blockchains.ETHEREUM]: { 261 | [XPUB_DERIVATION_TYPE_BIP44]: (seed, network) => { 262 | let networkConfig = NetworksConfigsEnum[[blockchains.ETHEREUM]][network]; 263 | 264 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip32); 265 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.ETHEREUM][network][XPUB_DERIVATION_TYPE_BIP44]; 266 | const accountXpriv = rootKey.derive(derivationPath); 267 | 268 | return { 269 | rootKey: rootKey.privateExtendedKey, 270 | derivationType: XPUB_DERIVATION_TYPE_BIP44, 271 | derivationPath: derivationPath, 272 | accountXpriv: accountXpriv.privateExtendedKey, 273 | accountXpub: accountXpriv.publicExtendedKey 274 | } 275 | } 276 | }, 277 | [blockchains.ETHEREUM_CLASSIC]: { 278 | [XPUB_DERIVATION_TYPE_BIP44]: (seed, network) => { 279 | let networkConfig = NetworksConfigsEnum[[blockchains.ETHEREUM_CLASSIC]][network]; 280 | 281 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip32); 282 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.ETHEREUM_CLASSIC][network][XPUB_DERIVATION_TYPE_BIP44]; 283 | const accountXpriv = rootKey.derive(derivationPath); 284 | 285 | return { 286 | rootKey: rootKey.privateExtendedKey, 287 | derivationType: XPUB_DERIVATION_TYPE_BIP44, 288 | derivationPath: derivationPath, 289 | accountXpriv: accountXpriv.privateExtendedKey, 290 | accountXpub: accountXpriv.publicExtendedKey 291 | } 292 | } 293 | }, 294 | [blockchains.BINANCE_SMART_CHAIN]: { 295 | [XPUB_DERIVATION_TYPE_BIP44]: (seed, network) => { 296 | let networkConfig = NetworksConfigsEnum[[blockchains.BINANCE_SMART_CHAIN]][network]; 297 | 298 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip32); 299 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.BINANCE_SMART_CHAIN][network][XPUB_DERIVATION_TYPE_BIP44]; 300 | const accountXpriv = rootKey.derive(derivationPath); 301 | 302 | return { 303 | rootKey: rootKey.privateExtendedKey, 304 | derivationType: XPUB_DERIVATION_TYPE_BIP44, 305 | derivationPath: derivationPath, 306 | accountXpriv: accountXpriv.privateExtendedKey, 307 | accountXpub: accountXpriv.publicExtendedKey 308 | } 309 | } 310 | }, 311 | [blockchains.ZCASH]: { 312 | [XPUB_DERIVATION_TYPE_BIP44]: (seed, network) => { 313 | let networkConfig = NetworksConfigsEnum[[blockchains.ZCASH]][network]; 314 | 315 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip32); 316 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.ZCASH][network][XPUB_DERIVATION_TYPE_BIP44]; 317 | const accountXpriv = rootKey.derive(derivationPath); 318 | 319 | return { 320 | rootKey: rootKey.privateExtendedKey, 321 | derivationType: XPUB_DERIVATION_TYPE_BIP44, 322 | derivationPath: derivationPath, 323 | accountXpriv: accountXpriv.privateExtendedKey, 324 | accountXpub: accountXpriv.publicExtendedKey 325 | } 326 | } 327 | }, 328 | [blockchains.XRP]: { 329 | [XPUB_DERIVATION_TYPE_BIP44]: (seed, network) => { 330 | let networkConfig = NetworksConfigsEnum[[blockchains.XRP]][network]; 331 | 332 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip32); 333 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.XRP][network][XPUB_DERIVATION_TYPE_BIP44]; 334 | const accountXpriv = rootKey.derive(derivationPath); 335 | 336 | return { 337 | rootKey: rootKey.privateExtendedKey, 338 | derivationType: XPUB_DERIVATION_TYPE_BIP44, 339 | derivationPath: derivationPath, 340 | accountXpriv: accountXpriv.privateExtendedKey, 341 | accountXpub: accountXpriv.publicExtendedKey 342 | } 343 | } 344 | }, 345 | [blockchains.TRX]: { 346 | [XPUB_DERIVATION_TYPE_BIP44]: (seed, network) => { 347 | let networkConfig = NetworksConfigsEnum[[blockchains.TRX]][network]; 348 | 349 | const rootKey = bip32.fromMasterSeed(seed, networkConfig.bip32); 350 | const derivationPath = XPUB_DERIVATION_PATHS[blockchains.TRX][network][XPUB_DERIVATION_TYPE_BIP44]; 351 | const accountXpriv = rootKey.derive(derivationPath); 352 | 353 | return { 354 | rootKey: rootKey.privateExtendedKey, 355 | derivationType: XPUB_DERIVATION_TYPE_BIP44, 356 | derivationPath: derivationPath, 357 | accountXpriv: accountXpriv.privateExtendedKey, 358 | accountXpub: accountXpriv.publicExtendedKey 359 | } 360 | } 361 | }, 362 | }; 363 | 364 | module.exports = { 365 | 'XPUB_DERIVATION_PATHS': XPUB_DERIVATION_PATHS, 366 | 'XPUB_DERIVATION_TYPES': XPUB_DERIVATION_TYPES 367 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const KmsClient = require('./kmsClient') 4 | , { 5 | blockchainEnum, 6 | networkEnum, 7 | feePriorityEnum, 8 | prepareStrategyEnum, 9 | tokenEnum 10 | } = require('./enumerations') 11 | , { 12 | XPUB_DERIVATION_PATHS: xPubDerivationPathsEnum, 13 | XPUB_DERIVATION_TYPES: xPubDerivationTypesEnum 14 | } = require('./helpers/xpubFormatsHelper') 15 | , { 16 | WalletService, 17 | SignService, 18 | AddressService 19 | } = require('./services') 20 | , { 21 | AccountBasedFeeOptionsModel, 22 | UTXOBasedFeeOptionsModel, 23 | RecipientModel 24 | } = require('./models') 25 | ; 26 | 27 | module.exports = { 28 | Models: { 29 | AccountBasedFeeOptionsModel: AccountBasedFeeOptionsModel, 30 | UTXOBasedFeeOptionsModel: UTXOBasedFeeOptionsModel, 31 | RecipientModel: RecipientModel, 32 | }, 33 | Enumerations: { 34 | Blockchains: blockchainEnum.blockchains, 35 | Networks: networkEnum.NETWORKS, 36 | FeePriorities: feePriorityEnum, 37 | PrepareStrategies: prepareStrategyEnum, 38 | xPubDerivationPaths: xPubDerivationPathsEnum, 39 | xPubDerivationTypes: xPubDerivationTypesEnum, 40 | TokenStandards: tokenEnum.BLOCKCHAIN_STANDARDS 41 | }, 42 | Services: { 43 | WalletService: WalletService, 44 | SignService: SignService, 45 | AddressService: AddressService 46 | }, 47 | Client: KmsClient, 48 | }; 49 | -------------------------------------------------------------------------------- /src/kmsClient.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const validateConfig = require('./validators/configValidator') 4 | , cryptoApis = require('cryptoapis') 5 | , { 6 | HDWalletDTO, 7 | SubscriptionForUnconfirmedCoinsTxsDTO, 8 | SubscriptionForUnconfirmedTokensTxsDTO, 9 | SubscriptionForUnconfirmedInternalTxsDTO, 10 | BroadcastSignedTxDTO, 11 | HDAddressesDTO, 12 | ListSyncedAddressesDTO, 13 | AccountBasedTransactionDTO, 14 | UTXOBasedTransactionDTO 15 | } = require('./dtos') 16 | , { 17 | HDWalletService, 18 | BroadcastService, 19 | SubscriptionsService, 20 | PrepareService, 21 | } = require('./services') 22 | , feePriorityEnum = require("./enumerations/feePriorityEnum") 23 | , prepareStrategyEnum = require("./enumerations/feePriorityEnum") 24 | , tokenEnum = require("./enumerations/tokenEnum") 25 | 26 | class KmsClient { 27 | /** 28 | * @param {string} apiKey 29 | * @param {string} blockchain Represents the specific blockchain protocol name, e.g. Ethereum, Bitcoin, etc. 30 | * @param {string} network Represents the name of the blockchain network used; blockchain networks are usually identical as technology and software, but they differ in data, e.g. - \"mainnet\" is the live network with actual data while networks like \"testnet\", \"goerli\" are test networks. 31 | */ 32 | constructor(apiKey, blockchain, network) { 33 | validateConfig.init(apiKey, blockchain, network); 34 | 35 | // init API client 36 | const defaultClient = cryptoApis.ApiClient.instance; 37 | const ApiKey = defaultClient.authentications['ApiKey']; 38 | ApiKey.apiKey = apiKey; 39 | 40 | this._apiClient = cryptoApis; 41 | this.network = network.toLowerCase(); 42 | this.blockchain = blockchain.toLowerCase(); 43 | 44 | //init all services 45 | this.hdWalletApiService = new HDWalletService(this._apiClient, this.blockchain, this.network); 46 | this.broadcastApiService = new BroadcastService(this._apiClient, this.blockchain, this.network); 47 | this.subscriptionsApiService = new SubscriptionsService(this._apiClient, this.blockchain, this.network); 48 | this.prepareService = new PrepareService(this._apiClient, this.blockchain, this.network); 49 | } 50 | 51 | /** 52 | * Sync New HD Wallet (xPub yPub zPub) 53 | * Through this endpoint users can add a brand new xPub to the Crypto APIs system to be ready for deriving. Unlike our other similar endpoint “Sync HD Wallet (xPub, yPub, zPub)”, this endpoint does not create new addresses nor syncs old data. 54 | * @param {string} extendedPublicKey 55 | * @param {string|null} context 56 | * @returns {module:model/SyncNewHDWalletXPubYPubZPubR} 57 | */ 58 | syncNewHDWallet(extendedPublicKey, context = null) { 59 | return this.hdWalletApiService.syncNewHDWallet(extendedPublicKey, context).then((data) => { 60 | return new HDWalletDTO(data); 61 | }); 62 | } 63 | 64 | /** 65 | * @param {string} callbackUrl 66 | * @param {string} address 67 | * @param {string|null} context 68 | * @returns {subscriptionForUnconfirmedCoinsTxsDTO} 69 | */ 70 | createSubscriptionForUnconfirmedCoinsTxs(callbackUrl, address, context = null) { 71 | 72 | return this.subscriptionsApiService.newUnconfirmedCoinsTxs(callbackUrl, address, context).then(data => { 73 | return new SubscriptionForUnconfirmedCoinsTxsDTO(data); 74 | }, (error) => { 75 | throw error; 76 | }); 77 | } 78 | 79 | /** 80 | * @param {string} callbackUrl 81 | * @param {string} address 82 | * @param {string|null} context 83 | * @returns {subscriptionForUnconfirmedTokensTxsDTO} 84 | */ 85 | createSubscriptionForUnconfirmedTokensTxs(callbackUrl, address, context = null) { 86 | 87 | return this.subscriptionsApiService.newUnconfirmedTokensTxs(callbackUrl, address, context).then(data => { 88 | return new SubscriptionForUnconfirmedTokensTxsDTO(data); 89 | }, error => { 90 | throw error; 91 | }); 92 | } 93 | 94 | /** 95 | * @param {string} callbackUrl 96 | * @param {string} address 97 | * @param {string|null} context 98 | * @returns {subscriptionForUnconfirmedInternalTxsDTO} 99 | */ 100 | createSubscriptionForUnconfirmedInternalTxs(callbackUrl, address, context = null) { 101 | 102 | return this.subscriptionsApiService.newConfirmedInternalTxs(callbackUrl, address, context).then(data => { 103 | return new SubscriptionForUnconfirmedInternalTxsDTO(data); 104 | }, error => { 105 | throw error; 106 | }); 107 | } 108 | 109 | /** 110 | * Derive And Sync New Change Addresses 111 | * Through this endpoint users can derive 100 change addresses, starting from the last index we have data for, which are then added to the xPub, subscribed for syncing, and start recording data. If no data is available, it will start from index 0. 112 | * @param {string} extendedPublicKey 113 | * @param {String|null} context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. * @param {String} opts.context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. 114 | * @returns {module:model/DeriveAndSyncNewChangeAddressesR} 115 | */ 116 | deriveAndSyncNewChangeAddresses(extendedPublicKey, context = null) { 117 | return this.hdWalletApiService.deriveAndSyncNewChangeAddresses(extendedPublicKey, context).then((data) => { 118 | return new HDAddressesDTO(data); 119 | }); 120 | } 121 | 122 | /** 123 | * Derive And Sync New Receiving Addresses 124 | * Through this endpoint users can derive 100 receiving addresses, starting from the last index we have data for, which are then added to the xPub, subscribed for syncing, and start recording data. If no data is available, it will start from index 0. 125 | * @param {string} extendedPublicKey 126 | * @param {String|null} context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. * @param {String} opts.context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. 127 | * @returns {module:model/DeriveAndSyncNewChangeAddressesR} 128 | */ 129 | deriveAndSyncNewReceivingAddresses(extendedPublicKey, context = null) { 130 | return this.hdWalletApiService.deriveAndSyncNewReceivingAddresses(extendedPublicKey, context).then((data) => { 131 | return new HDAddressesDTO(data); 132 | }); 133 | } 134 | 135 | /** 136 | * List Synced Addresses 137 | * Through this endpoint users can list all addresses that Crypto APIs has synced for a specific xPub. This includes previous and current/new xPubs, what addresses we’ve synced for them, etc. 138 | * @param {String} extendedPublicKey Defines the account extended publicly known key which is used to derive all child public keys. 139 | * @param {Object} opts Optional parameters 140 | * @param {String} opts.context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. 141 | * @param {Boolean} opts.isChangeAddress Defines if the address is change addres or not. (default to true) 142 | * @param {String} opts.addressFormat Represents the format of the address. 143 | * @returns {module:model/ListSyncedAddressesR} 144 | */ 145 | listSyncedAddresses(extendedPublicKey, opts) { 146 | return this.hdWalletApiService.listSyncedAddressesByXpub(extendedPublicKey, opts).then((data) => { 147 | return new ListSyncedAddressesDTO(data); 148 | }); 149 | } 150 | 151 | /** 152 | * Prepare An Account-Based Transaction From HD Wallet (xPub, yPub, zPub) 153 | * Through the “Prepare an account-based transaction from xPub” endpoint users can prepare a transaction for signing from a synced with Crypto APIs address from the specific xPub. This endpoint applies to all supported account-based blockchain protocols, e.g. Ethereum, BSC, etc 154 | * @param {string} xPub Defines the account extended publicly known key which is used to derive all child public keys. 155 | * @param {string} sender Represents a sender address 156 | * @param {string} recipient Represents a recipient address 157 | * @param {string} amount Representation of the amount of the transaction 158 | * @param {AccountBasedFeeOptions} feeOptions Represents the fee options 159 | * @param {string|null} nonce Representation of the nonce value 160 | * @param {string|null} data Representation of the additional data 161 | * 162 | * @returns {Promise|module:model/PrepareAnAccountBasedTransactionFromHDWalletXPubYPubZPubR} 163 | */ 164 | prepareAccountBasedTransactionFromHDWallet({ 165 | xPub, 166 | sender, 167 | recipient, 168 | amount, 169 | feeOptions, 170 | nonce, 171 | data 172 | }){ 173 | return this.prepareService.prepareAccountBasedTransactionFromHDWallet({ 174 | xPub, 175 | sender, 176 | recipient, 177 | amount, 178 | feeOptions, 179 | nonce, 180 | data 181 | }).then((data) => { 182 | return new AccountBasedTransactionDTO(data); 183 | }); 184 | } 185 | 186 | /** 187 | * Prepare An UTXO-Based Transaction From HD Wallet (xPub, yPub, zPub) 188 | * Through the “Prepare a UTXO-based transaction from HD Wallet” endpoint users can prepare a transaction for signing from all synced with Crypto APIs addresses for the specific xPub. This is based on the `selectionStrategy` and the addresses’ balances. In the case a user has an address not synced with Crypto APIs, it will not be included. This endpoint applies to all supported UTXO-based blockchain protocols, e.g. Bitcoin, Litecoin, etc. 189 | * @param {string} xPub Defines the account extended publicly known key which is used to derive all child public keys 190 | * @param {Array} recipients Represents a list of recipient addresses with the respective amounts 191 | * @param {UTXOBasedFeeOptions} feeOptions Represents the fee options 192 | * @param {Number} locktime Represents the time at which a particular transaction can be added to the blockchain. 193 | * @param {Boolean} replaceable Representation of whether the transaction is replaceable 194 | * @param {string} data Representation of the additional data 195 | * 196 | * @returns {Promise|module:model/PrepareAUTXOBasedTransactionFromHDWalletXPubYPubZPubR} 197 | */ 198 | prepareUTXOBasedTransactionFromHDWallet({ 199 | xPub, 200 | recipients, 201 | feeOptions, 202 | locktime, 203 | replaceable, 204 | data, 205 | }){ 206 | 207 | return this.prepareService.prepareUTXOBasedTransactionFromHDWallet({ 208 | xPub, 209 | recipients, 210 | feeOptions, 211 | locktime, 212 | replaceable, 213 | data, 214 | }).then((data) => { 215 | return new UTXOBasedTransactionDTO(data); 216 | }); 217 | } 218 | 219 | /** 220 | * @param {string} signedTransactionHex 221 | * @param {string} callbackSecretKey 222 | * @param {string} callbackUrl 223 | * @param {string|null} context 224 | * @returns {BroadcastSignedTxDTO} 225 | */ 226 | broadcastSignedTx(signedTransactionHex, callbackSecretKey, callbackUrl, context = null) { 227 | return this.broadcastApiService.broadcastLocallySignedTransaction(signedTransactionHex, callbackSecretKey, callbackUrl, context).then(data => { 228 | return new BroadcastSignedTxDTO(data); 229 | }, error => { 230 | throw error; 231 | }); 232 | } 233 | 234 | /** 235 | * Prepare A Token Transaction (ERC-20, ERC-721, BEP-20, BEP-721) 236 | * @param {string} tokenStandard Represents the token standard 237 | * @param {string} contract Represents a contract address 238 | * @param {string} sender Represents a sender address 239 | * @param {string} recipient Represents a recipient address 240 | * @param {string|null} amount Representation of the amount of tokens to be sent 241 | * @param {string|null} tokenId Representation of the token id to be sent 242 | * @param {AccountBasedFeeOptions} feeOptions Represents the fee options 243 | * @param {string|null} nonce Representation of the nonce value 244 | * @param {string|null} data Representation of the additional data 245 | * 246 | * @returns {Promise|module:model/*} 247 | */ 248 | prepareTokenTransaction({ 249 | tokenStandard, 250 | contract, 251 | sender, 252 | recipient, 253 | amount, 254 | tokenId, 255 | feeOptions, 256 | nonce, 257 | data 258 | }){ 259 | 260 | if ((tokenStandard === tokenEnum.STANDARDS.ERC_721 || tokenStandard === tokenEnum.STANDARDS.ERC_721) && !tokenId){ 261 | throw Error('Token Id must be specified'); 262 | } 263 | 264 | return this.prepareService.prepareTokenTransaction({ 265 | tokenStandard, 266 | contract, 267 | sender, 268 | recipient, 269 | amount, 270 | tokenId, 271 | feeOptions, 272 | nonce, 273 | data 274 | }).then((data) => { 275 | return new AccountBasedTransactionDTO(data); 276 | }); 277 | } 278 | 279 | /** 280 | * Through this endpoint users can prepare a transaction from an address with private and public keys. 281 | * The address does not have to belong to a wallet. The response will include the transaction fee in Wei. 282 | * @param {string} sender Represents a sender address 283 | * @param {string} recipient Represents a recipient address 284 | * @param {string} amount Representation of the amount of the transaction 285 | * @param {AccountBasedFeeOptionsModel} feeOptions Represents the fee options 286 | * @param {string|null} nonce Representation of the nonce value 287 | * @param {string|null} data Representation of the additional data 288 | * 289 | * @returns {Promise|module:model/PrepareTransactionFromAddressR} 290 | */ 291 | prepareAccountBasedTransactionFromAddress({ 292 | sender, 293 | recipient, 294 | amount, 295 | feeOptions, 296 | nonce, 297 | data 298 | }){ 299 | 300 | return this.prepareService.prepareAccountBasedTransactionFromAddress({ 301 | sender, 302 | recipient, 303 | amount, 304 | feeOptions, 305 | nonce, 306 | data 307 | }).then((data) => { 308 | return new AccountBasedTransactionDTO(data); 309 | }); 310 | } 311 | } 312 | 313 | module.exports = KmsClient; -------------------------------------------------------------------------------- /src/models/feeOptionsModel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const feePriorityEnum = require('../enumerations/feePriorityEnum') 4 | , prepareStrategyEnum = require('../enumerations/prepareStrategyEnum') 5 | ; 6 | 7 | class FeeOptionsBaseModel { 8 | 9 | /** 10 | * @param {feePriorityEnum} priority 11 | * @param {string} feeAmount 12 | */ 13 | constructor({priority, feeAmount}) { 14 | this._priority = priority; 15 | this._feeAmount = feeAmount; 16 | 17 | if (!this._priority && !this._feeAmount) { 18 | throw new Error('Either priority or fee amount must be set!') 19 | } 20 | } 21 | 22 | /** 23 | * @return {string} 24 | */ 25 | getFeeAmount() { 26 | return this._feeAmount; 27 | } 28 | 29 | /** 30 | * @return {feePriorityEnum} 31 | */ 32 | getPriority() { 33 | return this._priority; 34 | } 35 | } 36 | 37 | class AccountBasedFeeOptionsModel extends FeeOptionsBaseModel {} 38 | 39 | class UTXOBasedFeeOptionsModel extends FeeOptionsBaseModel { 40 | /** 41 | * @param {feePriorityEnum} priority 42 | * @param {string} feeAmount 43 | * @param {prepareStrategyEnum} prepareStrategy 44 | * @param {string} feeAddress 45 | */ 46 | constructor({priority, feeAmount, prepareStrategy, feeAddress}) { 47 | super({priority, feeAmount}); 48 | 49 | this._prepareStrategy = prepareStrategy; 50 | this._feeAddress = feeAddress; 51 | } 52 | 53 | /** 54 | * @return {prepareStrategyEnum} 55 | */ 56 | getPrepareStrategy() { 57 | return this._prepareStrategy; 58 | } 59 | 60 | /** 61 | * @return {string} 62 | */ 63 | getFeeAddress() { 64 | return this._feeAddress; 65 | } 66 | } 67 | 68 | module.exports = { 69 | AccountBasedFeeOptionsModel: AccountBasedFeeOptionsModel, 70 | UTXOBasedFeeOptionsModel: UTXOBasedFeeOptionsModel 71 | }; -------------------------------------------------------------------------------- /src/models/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {AccountBasedFeeOptionsModel, UTXOBasedFeeOptionsModel} = require('./feeOptionsModel') 4 | , RecipientModel = require('./recipientModel') 5 | ; 6 | 7 | module.exports = { 8 | AccountBasedFeeOptionsModel, 9 | UTXOBasedFeeOptionsModel, 10 | RecipientModel 11 | }; -------------------------------------------------------------------------------- /src/models/recipientModel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | class RecipientModel { 4 | /** 5 | * @param {string} address 6 | * @param {string} amount 7 | */ 8 | constructor(address, amount) { 9 | this._address = address; 10 | this._amount = amount; 11 | 12 | if (!this._address || !this._amount) { 13 | throw new Error('Invalid data provided!') 14 | } 15 | } 16 | 17 | /** 18 | * @return {string} 19 | */ 20 | getAddress() { 21 | return this._address; 22 | } 23 | 24 | /** 25 | * @return {string} 26 | */ 27 | getAmount() { 28 | return this._amount; 29 | } 30 | } 31 | 32 | module.exports = RecipientModel; -------------------------------------------------------------------------------- /src/services/addressService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { BaseBlockchainAwareService } = require("./baseServices") 4 | , GeneratorHelperFactory = require("../helpers/generateAddress/generatorHelperFactory") 5 | ; 6 | 7 | /** 8 | * AddressService 9 | * 10 | * @class AddressService 11 | * 12 | * @extends {BaseBlockchainAwareService} 13 | */ 14 | class AddressService extends BaseBlockchainAwareService { 15 | 16 | /** 17 | * @returns {AddressDTO} 18 | */ 19 | generateAddress() { 20 | const generator = GeneratorHelperFactory.create({ 21 | blockchain: this.blockchain, 22 | network: this.network 23 | }) 24 | 25 | return generator.generateAddress(); 26 | } 27 | } 28 | 29 | module.exports = AddressService; 30 | -------------------------------------------------------------------------------- /src/services/baseServices.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Abstract Class BaseBlockchainAwareService 5 | * 6 | * @class BaseBlockchainAwareService 7 | */ 8 | class BaseBlockchainAwareService { 9 | /** 10 | * @param {string} blockchain 11 | * @param {string} network 12 | */ 13 | constructor(blockchain, network) { 14 | if (this.constructor === BaseBlockchainAwareService) { 15 | throw new Error("Abstract classes can't be instantiated."); 16 | } 17 | 18 | this._blockchain = blockchain; 19 | this._network = network; 20 | } 21 | 22 | /** 23 | * @returns {string} 24 | */ 25 | get blockchain() { 26 | return this._blockchain; 27 | } 28 | 29 | /** 30 | * @returns {string} 31 | */ 32 | get network() { 33 | return this._network; 34 | } 35 | } 36 | 37 | /** 38 | * Abstract Class BaseCryptoAPIsLibAwareService 39 | * 40 | * @class BaseCryptoAPIsLibAwareService 41 | * 42 | * @extends {BaseBlockchainAwareService} 43 | */ 44 | class BaseCryptoAPIsLibAwareService extends BaseBlockchainAwareService { 45 | /** 46 | * @param {Object} cryptoApis 47 | * @param {string} blockchain 48 | * @param {string} network 49 | */ 50 | constructor(cryptoApis, blockchain, network) { 51 | super(blockchain, network) 52 | 53 | if (this.constructor === BaseCryptoAPIsLibAwareService) { 54 | throw new Error("Abstract classes can't be instantiated."); 55 | } 56 | 57 | this._cryptoApis = cryptoApis; 58 | } 59 | 60 | /** 61 | * @returns {Object} 62 | */ 63 | get cryptoApis() { 64 | return this._cryptoApis; 65 | } 66 | } 67 | 68 | module.exports = { 69 | BaseBlockchainAwareService, 70 | BaseCryptoAPIsLibAwareService 71 | }; -------------------------------------------------------------------------------- /src/services/broadcastService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { BaseCryptoAPIsLibAwareService } = require("./baseServices"); 4 | 5 | /** 6 | * BroadcastService 7 | * 8 | * @class BroadcastService 9 | * 10 | * @extends {BaseCryptoAPIsLibAwareService} 11 | */ 12 | class BroadcastService extends BaseCryptoAPIsLibAwareService { 13 | /** 14 | * @param {Object} cryptoApis 15 | * @param {string} blockchain. 16 | * @param {string} network 17 | */ 18 | constructor(cryptoApis, blockchain, network) { 19 | super(cryptoApis, blockchain, network) 20 | this.apiInstance = new this.cryptoApis.FeaturesApi(); 21 | } 22 | 23 | /** 24 | * Broadcast Locally Signed Transaction 25 | * Through this endpoint customers can broadcast transactions that have been already signed locally. Instead of using a node for broadcasting a signed transaction users can use this endpoint. We then keep the user posted about the status by sending you a callback with a success or failure status. {warning}This can be prepared and signed **only** locally, not through the API. We can provide support only for the process of broadcasting.{/warning} 26 | * @param {string} signedTransactionHex 27 | * @param {string|null} callbackSecretKey 28 | * @param {string|null} callbackUrl 29 | * @param {String|null} context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. 30 | * @return {module:model/BroadcastLocallySignedTransactionR} 31 | */ 32 | async broadcastLocallySignedTransaction(signedTransactionHex, callbackSecretKey, callbackUrl, context) { 33 | const item = this.cryptoApis.BroadcastLocallySignedTransactionRBDataItem.constructFromObject({ 34 | signedTransactionHex: signedTransactionHex, 35 | callbackSecretKey: callbackSecretKey, 36 | callbackUrl: callbackUrl, 37 | }); 38 | 39 | const postData = new this.cryptoApis.BroadcastLocallySignedTransactionRBData(item); 40 | 41 | const opts = { 42 | context: context, 43 | broadcastLocallySignedTransactionRB: new this.cryptoApis.BroadcastLocallySignedTransactionRB(postData) 44 | }; 45 | 46 | return this.apiInstance.broadcastLocallySignedTransaction(this.blockchain, this.network, opts); 47 | } 48 | } 49 | 50 | module.exports = BroadcastService; -------------------------------------------------------------------------------- /src/services/hdWalletsService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { BaseCryptoAPIsLibAwareService } = require("./baseServices"); 4 | 5 | /** 6 | * HdWalletsService 7 | * 8 | * @class HdWalletsService 9 | * 10 | * @extends {BaseCryptoAPIsLibAwareService} 11 | */ 12 | class HdWalletsService extends BaseCryptoAPIsLibAwareService { 13 | /** 14 | * @param {Object} cryptoApis 15 | * @param {string} blockchain 16 | * @param {string} network 17 | */ 18 | constructor(cryptoApis, blockchain, network) { 19 | super(cryptoApis, blockchain, network) 20 | this.hdWalletInstance = new this.cryptoApis.HDWalletsApi(); 21 | } 22 | 23 | /** 24 | * Sync New HD Wallet (xPub yPub zPub) 25 | * Through this endpoint users can add a brand new xPub to the Crypto APIs system to be ready for deriving. Unlike our other similar endpoint “Sync HD Wallet (xPub, yPub, zPub)”, this endpoint does not create new addresses nor syncs old data. 26 | * @param {string} extendedPublicKey 27 | * @param {String|null} context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. * @param {String} opts.context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. 28 | * @returns {module:model/SyncNewHDWalletXPubYPubZPubR} 29 | */ 30 | async syncNewHDWallet(extendedPublicKey, context) { 31 | const item = new this.cryptoApis.SyncHDWalletXPubYPubZPubRBDataItem(extendedPublicKey); 32 | const data = new this.cryptoApis.SyncHDWalletXPubYPubZPubRBData(item); 33 | 34 | const opts = { 35 | context: context, 36 | syncNewHDWalletXPubYPubZPubRB: new this.cryptoApis.SyncNewHDWalletXPubYPubZPubRB(data) 37 | }; 38 | 39 | return this.hdWalletInstance.syncNewHDWalletXPubYPubZPub(this.blockchain, this.network, opts); 40 | } 41 | 42 | /** 43 | * Derive And Sync New Change Addresses 44 | * Through this endpoint users can derive 100 change addresses, starting from the last index we have data for, which are then added to the xPub, subscribed for syncing, and start recording data. If no data is available, it will start from index 0. 45 | * @param {string} extendedPublicKey 46 | * @param {String|null} context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. * @param {String} opts.context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. 47 | * @returns {module:model/DeriveAndSyncNewChangeAddressesR} 48 | */ 49 | async deriveAndSyncNewChangeAddresses(extendedPublicKey, context) { 50 | const item = new this.cryptoApis.DeriveAndSyncNewChangeAddressesRBDataItem(extendedPublicKey) 51 | const data = new this.cryptoApis.DeriveAndSyncNewChangeAddressesRBData(item) 52 | const opts = { 53 | context: context, 54 | deriveAndSyncNewChangeAddressesRB: new this.cryptoApis.DeriveAndSyncNewChangeAddressesRB(data) 55 | } 56 | 57 | return this.hdWalletInstance.deriveAndSyncNewChangeAddresses(this.blockchain, this.network, opts); 58 | } 59 | 60 | /** 61 | * Derive And Sync New Receiving Addresses 62 | * Through this endpoint users can derive 100 receiving addresses, starting from the last index we have data for, which are then added to the xPub, subscribed for syncing, and start recording data. If no data is available, it will start from index 0. 63 | * @param {string} extendedPublicKey 64 | * @param {String|null} context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. * @param {String} opts.context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. 65 | * @returns {module:model/DeriveAndSyncNewReceivingAddressesR} 66 | */ 67 | async deriveAndSyncNewReceivingAddresses(extendedPublicKey, context) { 68 | const item = new this.cryptoApis.DeriveAndSyncNewReceivingAddressesRBDataItem(extendedPublicKey) 69 | const data = new this.cryptoApis.DeriveAndSyncNewReceivingAddressesRBData(item) 70 | const opts = { 71 | context: context, 72 | deriveAndSyncNewReceivingAddressesRB: new this.cryptoApis.DeriveAndSyncNewReceivingAddressesRB(data) 73 | } 74 | 75 | return this.hdWalletInstance.deriveAndSyncNewReceivingAddresses(this.blockchain, this.network, opts); 76 | } 77 | 78 | /** 79 | * List Synced Addresses 80 | * Through this endpoint users can list all addresses that Crypto APIs has synced for a specific xPub. This includes previous and current/new xPubs, what addresses we’ve synced for them, etc. 81 | * @param {String} extendedPublicKey Defines the account extended publicly known key which is used to derive all child public keys. 82 | * @param {Object} opts Optional parameters 83 | * @param {String} opts.context In batch situations the user can use the context to correlate responses with requests. This property is present regardless of whether the response was successful or returned as an error. `context` is specified by the user. 84 | * @param {Boolean} opts.isChangeAddress Defines if the address is change addres or not. (default to true) 85 | * @param {String} opts.addressFormat Represents the format of the address. 86 | * @returns {module:model/ListSyncedAddressesR} 87 | */ 88 | listSyncedAddressesByXpub(extendedPublicKey, opts) { 89 | return this.hdWalletInstance.listSyncedAddresses(this.blockchain, extendedPublicKey, this.network, opts) 90 | } 91 | } 92 | 93 | module.exports = HdWalletsService; -------------------------------------------------------------------------------- /src/services/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const HDWalletService = require('./hdWalletsService') 4 | , WalletService = require('./walletService') 5 | , BroadcastService = require('./broadcastService') 6 | , SubscriptionsService = require('./subscriptionsService') 7 | , PrepareService = require('./prepareService') 8 | , SignService = require('./signService') 9 | , AddressService = require('./addressService') 10 | ; 11 | 12 | module.exports = { 13 | HDWalletService, 14 | WalletService, 15 | BroadcastService, 16 | SubscriptionsService, 17 | PrepareService, 18 | SignService, 19 | AddressService 20 | }; -------------------------------------------------------------------------------- /src/services/prepareService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const AccountBasedHDWalletPrepareHelper = require("../helpers/prepare/accountBasedHDWalletPrepareHelper") 4 | , AccountBasedSingleAddressPrepareHelper = require("../helpers/prepare/accountBasedSingleAddressPrepareHelper") 5 | , UTXOBasedPrepareHelper = require("../helpers/prepare/UTXOBasedPrepareHelper") 6 | , {BaseCryptoAPIsLibAwareService} = require("./baseServices") 7 | , TokenPrepareHelperFactory = require("../helpers/prepare/tokenTransactions/tokenPrepareFactory") 8 | ; 9 | 10 | /** 11 | * PrepareTransactionService 12 | * 13 | * @class PrepareTransactionService 14 | * 15 | * @extends {BaseCryptoAPIsLibAwareService} 16 | */ 17 | class PrepareTransactionService extends BaseCryptoAPIsLibAwareService { 18 | /** 19 | * Prepare An Account-Based Transaction From HD Wallet (xPub, yPub, zPub) 20 | * Through the “Prepare an account-based transaction from xPub” endpoint users can prepare a transaction for signing from a synced with Crypto APIs address from the specific xPub. This endpoint applies to all supported account-based blockchain protocols, e.g. Ethereum, BSC, etc 21 | * @param {string} xPub Defines the account extended publicly known key which is used to derive all child public keys. 22 | * @param {string} sender Represents a sender address 23 | * @param {string} recipient Represents a recipient address 24 | * @param {string} amount Representation of the amount of the transaction 25 | * @param {AccountBasedFeeOptionsModel} feeOptions Represents the fee options 26 | * @param {string|null} nonce Representation of the nonce value 27 | * @param {string|null} data Representation of the additional data 28 | * 29 | * @returns {Promise|module:model/PrepareATransactionFromAnAddressInHDWalletXPubYPubZPubR} 30 | */ 31 | prepareAccountBasedTransactionFromHDWallet({ 32 | xPub, 33 | sender, 34 | recipient, 35 | amount, 36 | feeOptions, 37 | nonce, 38 | data 39 | }){ 40 | const accountBasedService = new AccountBasedHDWalletPrepareHelper( 41 | this.cryptoApis, 42 | this.blockchain, 43 | this.network 44 | ) 45 | 46 | return accountBasedService.prepare({ 47 | xPub, 48 | sender, 49 | recipient, 50 | amount, 51 | feeOptions, 52 | nonce, 53 | data 54 | }) 55 | }; 56 | 57 | /** 58 | * Prepare An UTXO-Based Transaction From HD Wallet (xPub, yPub, zPub) 59 | * Through the “Prepare a UTXO-based transaction from HD Wallet” endpoint users can prepare a transaction for signing from all synced with Crypto APIs addresses for the specific xPub. This is based on the `selectionStrategy` and the addresses’ balances. In the case a user has an address not synced with Crypto APIs, it will not be included. This endpoint applies to all supported UTXO-based blockchain protocols, e.g. Bitcoin, Litecoin, etc. 60 | * @param {string} xPub Defines the account extended publicly known key which is used to derive all child public keys 61 | * @param {Array} recipients Represents a list of recipient addresses with the respective amounts 62 | * @param {AccountBasedFeeOptionsModel} feeOptions Represents the fee options 63 | * @param {Number} locktime Represents the time at which a particular transaction can be added to the blockchain. 64 | * @param {Boolean} replaceable Representation of whether the transaction is replaceable 65 | * @param {string} data Representation of the additional data 66 | * 67 | * @returns {Promise|module:model/PrepareAUTXOBasedTransactionFromHDWalletXPubYPubZPubR} 68 | */ 69 | prepareUTXOBasedTransactionFromHDWallet({ 70 | xPub, 71 | recipients, 72 | feeOptions, 73 | locktime, 74 | replaceable, 75 | data, 76 | }){ 77 | const UTXOBasedService = new UTXOBasedPrepareHelper( 78 | this.cryptoApis, 79 | this.blockchain, 80 | this.network 81 | ) 82 | 83 | return UTXOBasedService.prepare({ 84 | xPub, 85 | recipients, 86 | feeOptions, 87 | locktime, 88 | replaceable, 89 | data, 90 | }); 91 | } 92 | 93 | /** 94 | * Prepare A Token Transaction (ERC-20, ERC-721, BEP-20, BEP-721) 95 | * @param {string} tokenStandard token standard 96 | * @param {string} contract Represents a contract address 97 | * @param {string} sender Represents a sender address 98 | * @param {string} recipient Represents a recipient address 99 | * @param {string|null} amount Representation of the amount of the token to be sent (ERC-20, BEP-20) 100 | * @param {string|null} tokenId Representation of the token id to be sent (ERC-721, BEP-721) 101 | * @param {AccountBasedFeeOptionsModel} feeOptions Represents the fee options 102 | * @param {string|null} nonce Representation of the nonce value 103 | * @param {string|null} data Representation of the additional data 104 | * 105 | * @returns {Promise<*>} 106 | */ 107 | prepareTokenTransaction({ 108 | tokenStandard, 109 | contract, 110 | sender, 111 | recipient, 112 | amount, 113 | tokenId, 114 | feeOptions, 115 | nonce, 116 | data 117 | }){ 118 | 119 | const tokenService = TokenPrepareHelperFactory.create({ 120 | cryptoApis: this.cryptoApis, 121 | blockchain: this.blockchain, 122 | network: this.network, 123 | tokenStandard: tokenStandard 124 | }); 125 | 126 | return tokenService.prepare({ 127 | tokenStandard, 128 | contract, 129 | sender, 130 | recipient, 131 | amount, 132 | tokenId, 133 | feeOptions, 134 | nonce, 135 | data 136 | }) 137 | }; 138 | 139 | /** 140 | * 141 | * Through this endpoint users can prepare a transaction from an address with private and public keys. 142 | * The address does not have to belong to a wallet. The response will include the transaction fee in Wei. 143 | * @param {string} sender Represents a sender address 144 | * @param {string} recipient Represents a recipient address 145 | * @param {string} amount Representation of the amount of the transaction 146 | * @param {AccountBasedFeeOptionsModel} feeOptions Represents the fee options 147 | * @param {string|null} nonce Representation of the nonce value 148 | * @param {string|null} data Representation of the additional data 149 | * 150 | * @returns {Promise|module:model/PrepareTransactionFromAddressR} 151 | */ 152 | prepareAccountBasedTransactionFromAddress({ 153 | sender, 154 | recipient, 155 | amount, 156 | feeOptions, 157 | nonce, 158 | data 159 | }){ 160 | 161 | const accountBasedService = new AccountBasedSingleAddressPrepareHelper( 162 | this.cryptoApis, 163 | this.blockchain, 164 | this.network 165 | ) 166 | 167 | return accountBasedService.prepare({ 168 | sender, 169 | recipient, 170 | amount, 171 | feeOptions, 172 | nonce, 173 | data 174 | }) 175 | }; 176 | } 177 | 178 | module.exports = PrepareTransactionService; -------------------------------------------------------------------------------- /src/services/signService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const SignerHelperFactory = require("../helpers/sign/signerHelperFactory") 4 | , {BaseBlockchainAwareService} = require("./baseServices") 5 | , {SignDTO} = require("../dtos") 6 | ; 7 | 8 | /** 9 | * SignService 10 | * 11 | * @class SignService 12 | * 13 | * @extends {BaseBlockchainAwareService} 14 | */ 15 | class SignService extends BaseBlockchainAwareService { 16 | /** 17 | * Sign Prepared Transaction Locally 18 | * Through this endpoint users can sign their transactions locally(offline) using the transaction response from Prepare Transaction From XPUB endpoint, both for account-based and UTXO-based 19 | * @param {string} xPriv extended account xPriv 20 | * @param {TransactionDTO} transaction 21 | * @throws {Error} 22 | * @return {SignDTO} 23 | */ 24 | signPreparedTransactionLocally(xPriv, transaction) { 25 | try { 26 | const signer = SignerHelperFactory.create({ 27 | blockchain: this.blockchain, 28 | network: this.network 29 | }); 30 | const signed = signer.sign({xPriv: xPriv, transaction: transaction}); 31 | 32 | return new SignDTO(signed) 33 | } catch (error) { 34 | throw error; 35 | } 36 | } 37 | } 38 | 39 | module.exports = SignService; 40 | -------------------------------------------------------------------------------- /src/services/subscriptionsService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { BaseCryptoAPIsLibAwareService } = require("./baseServices"); 4 | 5 | /** 6 | * SubscriptionsService 7 | * 8 | * @class SubscriptionsService 9 | * 10 | * @extends {BaseCryptoAPIsLibAwareService} 11 | */ 12 | class SubscriptionsService extends BaseCryptoAPIsLibAwareService { 13 | /** 14 | * @param {Object} cryptoApis 15 | * @param {string} blockchain 16 | * @param {string} network 17 | */ 18 | constructor(cryptoApis, blockchain, network) { 19 | super(cryptoApis, blockchain, network) 20 | this.apiInstance = new this.cryptoApis.CreateSubscriptionsForApi(); 21 | } 22 | 23 | /** 24 | * @param {string} callbackUrl 25 | * @param {string} address 26 | * @param {string|null} context 27 | * @returns {newUnconfirmedCoinsTransactions} 28 | */ 29 | newUnconfirmedCoinsTxs(callbackUrl, address, context) { 30 | const item = new this.cryptoApis.NewUnconfirmedCoinsTransactionsRBDataItem(address, callbackUrl); 31 | const postData = new this.cryptoApis.NewUnconfirmedCoinsTransactionsRBData(item); 32 | 33 | const opts = { 34 | context: context, 35 | newUnconfirmedCoinsTransactionsRB: new this.cryptoApis.NewUnconfirmedCoinsTransactionsRB(postData) 36 | }; 37 | 38 | return this.apiInstance.newUnconfirmedCoinsTransactions(this.blockchain, this.network, opts); 39 | } 40 | 41 | /** 42 | * @param {string} callbackUrl 43 | * @param {string} address 44 | * @param {string|null} context 45 | * @returns {newUnconfirmedTokensTransactions} 46 | */ 47 | newUnconfirmedTokensTxs(callbackUrl, address, context) { 48 | const item = new this.cryptoApis.NewUnconfirmedTokensTransactionsRBDataItem(address, callbackUrl); 49 | const postData = new this.cryptoApis.NewUnconfirmedTokensTransactionsRBData(item); 50 | 51 | const opts = { 52 | context: context, 53 | newUnconfirmedTokensTransactionsRB: new this._cryptoApis.NewUnconfirmedTokensTransactionsRB(postData) 54 | }; 55 | 56 | return this.apiInstance.newUnconfirmedTokensTransactions(this.blockchain, this.network, opts); 57 | } 58 | 59 | /** 60 | * @param {string} callbackUrl 61 | * @param {string} address 62 | * @param {string|null} context 63 | * @returns {newConfirmedInternalTransactions} 64 | */ 65 | newConfirmedInternalTxs(callbackUrl, address, context) { 66 | const item = new this.cryptoApis.NewConfirmedInternalTransactionsRBDataItem(address, false, 'secret', callbackUrl); 67 | const postData = new this.cryptoApis.NewConfirmedInternalTransactionsRBData(item); 68 | 69 | const opts = { 70 | context: context, 71 | newConfirmedInternalTransactionsRB: new this.cryptoApis.NewConfirmedInternalTransactionsRB(postData) 72 | }; 73 | 74 | return this.apiInstance.newConfirmedInternalTransactions(this.blockchain, this.network, opts); 75 | } 76 | } 77 | 78 | module.exports = SubscriptionsService; -------------------------------------------------------------------------------- /src/services/walletService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { BaseBlockchainAwareService } = require("./baseServices"); 4 | const bip39 = require('bip39') 5 | , {XPUB_DERIVATION_TYPES: xpubDerivationTypesEnum} = require('../helpers/xpubFormatsHelper') 6 | , WalletDTO = require('../dtos/walletDTO') 7 | ; 8 | 9 | const MNEMONIC_STRENGTH_MULTIPLIER = 16; 10 | 11 | /** 12 | * WalletService 13 | * 14 | * @class WalletService 15 | * 16 | * @extends {BaseBlockchainAwareService} 17 | */ 18 | class WalletService extends BaseBlockchainAwareService { 19 | /** 20 | * @param {number} mnemonicWordsCount 21 | * 22 | * @returns {Promise} 23 | */ 24 | async createHDWallet(mnemonicWordsCount = 12) { 25 | if (![12, 18, 24].includes(mnemonicWordsCount)) { 26 | throw new Error("Possible values for 'mnemonicWordsCount' are 12, 18 or 24"); 27 | } 28 | 29 | const strength = (mnemonicWordsCount / 1.5) * MNEMONIC_STRENGTH_MULTIPLIER; 30 | const mnemonic = bip39.generateMnemonic(strength); 31 | const seed = await bip39.mnemonicToSeed(mnemonic); 32 | const xpubDerivationTypes = xpubDerivationTypesEnum[this.blockchain]; 33 | 34 | let xPubList = []; 35 | for (let derivationType of Object.keys(xpubDerivationTypes)) { 36 | xPubList.push(xpubDerivationTypes[derivationType](seed, this.network)); 37 | } 38 | 39 | return new WalletDTO({ 40 | blockchain: this.blockchain, 41 | network: this.network, 42 | mnemonic: mnemonic, 43 | seed: seed.toString('hex'), 44 | xPubsList: xPubList 45 | }); 46 | } 47 | } 48 | 49 | module.exports = WalletService; -------------------------------------------------------------------------------- /src/validators/blockchainValidator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {blockchains, reversed} = require("../enumerations/blockchainEnum") 4 | , ErrorDTO = require("../dtos/errorDTO") 5 | ; 6 | 7 | module.exports = function validateBlockchain(blockchain) { 8 | const validBlockchain = blockchains.hasOwnProperty(reversed[blockchain]); 9 | 10 | if (validBlockchain === false) { 11 | const blockchainsList = Object.keys(blockchains).map((k) => { 12 | return blockchains[k] 13 | }).join(", "); 14 | 15 | return new ErrorDTO('INVALID_BLOCKCHAIN', {'blockchains': blockchainsList}); 16 | } 17 | 18 | return true; 19 | } -------------------------------------------------------------------------------- /src/validators/configValidator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const validateBlockchain = require("./blockchainValidator") 4 | , {NETWORKS: NetworksEnum} = require('../enumerations/networkEnum') 5 | , errors = require('./customErrors') 6 | , ErrorDTO = require('../dtos/errorDTO') 7 | ; 8 | 9 | module.exports = { 10 | 11 | /** 12 | * @param {string} apiKey 13 | * @param {string} blockchain 14 | * @param {string} network 15 | * @returns {boolean} 16 | */ 17 | init: function (apiKey, blockchain, network) { 18 | if (!apiKey) { 19 | throw errors.getErrorMessage('API_KEY_NOT_FOUND'); 20 | } 21 | 22 | if (!blockchain) { 23 | throw errors.getErrorMessage('BLOCKCHAIN_NOT_FOUND'); 24 | } 25 | 26 | if (!network) { 27 | throw errors.getErrorMessage('NETWORK_NOT_FOUND'); 28 | } 29 | 30 | const error = validateBlockchain(blockchain) 31 | if (error !== true) { 32 | throw error; 33 | } 34 | 35 | const networks = Object.values(NetworksEnum[blockchain]); 36 | if (!networks.includes(network.toLowerCase())) { 37 | throw new ErrorDTO('INVALID_NETWORK', {'networks': networks.join(', ')}); 38 | } 39 | 40 | return true; 41 | }, 42 | } -------------------------------------------------------------------------------- /src/validators/customErrors.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const ERRORS = { 4 | "API_KEY_NOT_FOUND": { 5 | httpCode: 404, 6 | message: 'Please provide API KEY' 7 | }, 8 | 'BLOCKCHAIN_NOT_FOUND': { 9 | httpCode: 404, 10 | message: 'Please provide blockchain' 11 | }, 12 | 'INVALID_BLOCKCHAIN': { 13 | httpCode: 400, 14 | message: 'Please provide one of the following values: {blockchains}' 15 | }, 16 | 'NETWORK_NOT_FOUND': { 17 | httpCode: 404, 18 | message: 'Please provide network' 19 | }, 20 | 'INVALID_NETWORK': { 21 | httpCode: 400, 22 | message: 'Please provide one of the following values: {networks}' 23 | }, 24 | 'INVALID_CALLBACK': { 25 | httpCode: 400, 26 | message: 'Please provide valid callback object' 27 | }, 28 | 'UNEXPECTED_ERROR': { 29 | httpCode: 404, 30 | message: 'Unexpected error occurred!' 31 | } 32 | } 33 | 34 | /** 35 | * @param {string} code 36 | * @param {string|null} placeholders 37 | * @returns {{httpCode: number, message: string}|*} 38 | */ 39 | module.exports.getErrorMessage = function (code, placeholders = null) { 40 | if (ERRORS.hasOwnProperty(code.toUpperCase()) === false) { 41 | return ERRORS['UNEXPECTED_ERROR']; 42 | } 43 | code = code.toUpperCase(); 44 | const result = {}; 45 | const message = ERRORS[code].message; 46 | 47 | if (placeholders !== null) { 48 | Object.keys(placeholders).forEach(function(k) { 49 | result.message = message.replace('{'+k+'}', placeholders[k]); 50 | result.code = ERRORS[code].httpCode; 51 | }); 52 | } 53 | 54 | return result; 55 | } --------------------------------------------------------------------------------