[
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "content": "name: \"🐛 Bug Report\"\ndescription: Report a bug to help us improve the Multichain Crypto Wallet\ntitle: \"[Bug]: \"\nlabels: [\"bug\", \"needs triage\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        ## Thanks for taking the time to report a bug!\n\n  - type: input\n    id: environment\n    attributes:\n      label: Environment\n      description: Provide details about your environment (e.g., OS, browser, Node version)\n      placeholder: \"e.g., macOS Ventura, Chrome 118, Node 18.12.1\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: description\n    attributes:\n      label: Bug Description\n      description: A clear and concise description of what the bug is.\n      placeholder: \"Describe the issue you're facing...\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: steps\n    attributes:\n      label: Steps to Reproduce\n      description: How can we reproduce the issue?\n      placeholder: |\n        1. Go to '...'\n        2. Click on '...'\n        3. Scroll down to '...'\n        4. See error\n    validations:\n      required: true\n\n  - type: textarea\n    id: expected\n    attributes:\n      label: Expected Behavior\n      description: What did you expect to happen?\n      placeholder: \"It should have...\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: actual\n    attributes:\n      label: Actual Behavior\n      description: What actually happened?\n      placeholder: \"Instead, it...\"\n    validations:\n      required: true\n\n  - type: input\n    id: repo-version\n    attributes:\n      label: Wallet Version / Branch\n      description: Which version or branch are you seeing the issue on?\n      placeholder: \"e.g. v1.0.3 or main\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: logs\n    attributes:\n      label: Relevant Logs / Screenshots\n      description: Paste any logs or screenshots that may help us debug.\n      placeholder: \"Copy-paste terminal logs or attach screenshots here.\"\n      render: shell\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.yml",
    "content": "name: \"✨ Feature Request\"\ndescription: Suggest an idea to improve the Multichain Crypto Wallet\ntitle: \"[Feature]: \"\nlabels: [\"enhancement\", \"needs triage\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        ## Thanks for suggesting a feature! Let's make this wallet better together 🙌\n\n  - type: textarea\n    id: feature\n    attributes:\n      label: Describe the Feature\n      description: What's the problem or improvement you're proposing?\n      placeholder: \"It would be great if...\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: motivation\n    attributes:\n      label: Motivation / Use Case\n      description: Why do you want this feature? What problem does it solve?\n      placeholder: \"As a user, I want to...\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: implementation\n    attributes:\n      label: Possible Implementation\n      description: Any thoughts on how this could be built?\n      placeholder: \"Maybe we could use...\"\n      render: markdown\n\n  - type: checkboxes\n    id: impact\n    attributes:\n      label: Potential Impact\n      options:\n        - label: This would improve developer experience\n        - label: This would improve end-user experience\n        - label: This would support new chains or protocols\n        - label: This could affect existing functionality\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "## Description\n\nPlease include a summary of the changes and be sure to follow our [Contribution Guidelines](../CONTRIBUTING.md).\n\n<!--\nOptional if an issue is fixed:\nFixes #(issue)\n-->\n\n## Type of change\n\n<!-- Please delete options that are not relevant. -->\n\n- [ ] Bug fix (non-breaking change which fixes an issue)\n- [ ] New feature (non-breaking change which adds functionality)\n- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)\n\n## Checklist:\n\n- [ ] I have selected the correct base branch.\n- [ ] I have performed a self-review of my own code.\n- [ ] I have commented my code, particularly in hard-to-understand areas.\n- [ ] I have made corresponding changes to the documentation.\n- [ ] My changes generate no new warnings.\n- [ ] Any dependent changes have been merged and published in downstream modules.\n- [ ] I ran `npm run test` and my test cases cover all the lines and branches of the added code.\n- [ ] I ran `npm run build` with success.\n- [ ] I have tested my code on the live network.\n- [ ] I have checked the Deploy Preview and it looks correct."
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: Build, lint, and test\n\non: [push]\n\njobs:\n  build:\n    name: Build, lint, and test on Nodejs \n\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version: [16.x]\n\n    steps:\n      - uses: actions/checkout@v4\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n          cache: yarn\n      - name: Install dependencies\n        run: yarn --ignore-engines\n\n      - name: Build\n        run: yarn build"
  },
  {
    "path": ".gitignore",
    "content": "*.log\n.DS_Store\nnode_modules\ndist\n.vscode"
  },
  {
    "path": ".prettierrc.json",
    "content": "{\n  \"trailingComma\": \"all\",\n  \"tabWidth\": 2,\n  \"semi\": true,\n  \"singleQuote\": true\n}\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "\n# Contributing Guidelines\n\nWe're glad to have you want to contribute to this project! This document will help answer common questions you may have during your first contribution. Following these standards demonstrates that you value the time spent by the developers that manage and maintain this open source project.\n\n#### Before you contribute...\n\nRead this document before you contribute in any form.\n\n## Submitting an Issue\nNot all contributions comes in the form of code. Feautures, bug fixes, and documentation are all valid contributions. \n\n## Setup\nIn order to create a pull request to contribute, the processes are simple\n\n0. Create a new branch. This would be the name of the feature/issue you are working on.\n1. Install dependencies and start the project locally.\n``` javascript\nyarn // npm install\nyan start // npm run start\n```\n2. Run tests. Jest tests are setup to run in watch mode.\n``` javascript\nyarn test // npm run test\n```\n3. Run tests for a specific file. Jest tests are setup to run in watch mode.\n``` javascript\nyarn test test/file.test.ts  // npm run test test/file.test.ts\n```\n4. Make your necessary changes and accompany each function with a test.\n\n\n✨ Thanks for contributing to **multichain-crypto-wallet**! ✨"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2022 iamnotstatic\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# Multichain Crypto Wallet\n\nA Multichain crypto wallet library that supports Ethereum, Bitcoin, Solana, Waves and other EVM compatible blockchains E.g. Binance Smart Chain, Polygon, Avalanche etc.\n\n[![Build](https://img.shields.io/github/actions/workflow/status/iamnotstatic/multichain-crypto-wallet/main.yml)](https://github.com/iamnotstatic/multichain-crypto-wallet)\n[![Version](https://img.shields.io/npm/v/multichain-crypto-wallet)](https://github.com/iamnotstatic/multichain-crypto-wallet)\n[![GitHub issues](https://img.shields.io/github/issues/iamnotstatic/multichain-crypto-wallet)](https://github.com/iamnotstatic/multichain-crypto-wallet/issues)\n[![GitHub stars](https://img.shields.io/github/stars/iamnotstatic/multichain-crypto-wallet)](https://github.com/iamnotstatic/multichain-crypto-wallet/stargazers)\n[![GitHub license](https://img.shields.io/github/license/iamnotstatic/multichain-crypto-wallet)](https://github.com/iamnotstatic/multichain-crypto-wallet)\n[![Total Downloads](https://img.shields.io/npm/dm/multichain-crypto-wallet)](https://github.com/iamnotstatic/multichain-crypto-wallet)\n\n## Installation\n\n```bash\nnpm install multichain-crypto-wallet\n```\n\nUsing yarn,\n\n```bash\nyarn add multichain-crypto-wallet\n```\n\n## Usage\n\n### Javascript\n\n```javascript\nconst multichainWallet = require('multichain-crypto-wallet');\n```\n\n### TypeScript\n\n```typescript\nimport * as multichainWallet from 'multichain-crypto-wallet';\n```\n\n## Methods\n\nThe following methods are available with this SDK:\n\n- [Multichain Crypto Wallet](#multichain-crypto-wallet)\n  - [Installation](#installation)\n  - [Usage](#usage)\n    - [Javascript](#javascript)\n    - [TypeScript](#typescript)\n  - [Methods](#methods)\n    - [Generate mnemonic](#generate-mnemonic)\n      - [Response](#response)\n    - [Create Wallet](#create-wallet)\n      - [Response](#response)\n    - [Get Balance](#get-balance)\n      - [Native coins](#native-coins)\n      - [Tokens](#tokens)\n      - [Response](#response-1)\n    - [Generate Wallet from Mnemonic](#generate-wallet-from-mnemonic)\n      - [Response](#response-2)\n    - [Get Address from Private Key](#get-address-from-private-key)\n      - [Response](#response-3)\n    - [Get Transaction](#get-transaction)\n      - [Response](#response-4)\n    - [Transfer](#transfer)\n      - [Ethereum Network](#ethereum-network)\n      - [Response](#response-5)\n      - [Bitcoin Network](#bitcoin-network)\n      - [Response](#response-6)\n      - [Solana Network](#solana-network)\n      - [Response](#response-7)\n      - [Waves Network](#waves-network)\n      - [Response](#response-8)\n      - [Tron Network](#tron-network)\n      - [Response](#response-9)\n    - [Encryptions](#encryptions)\n      - [Encrypt Private Key](#encrypt-private-key)\n      - [Response](#response-10)\n      - [Decrypt Encrypted JSON](#decrypt-encrypted-json)\n      - [Response](#response-11)\n    - [Token Info](#token-info)\n      - [Get ERC20 Token Info](#get-erc20-token-info)\n      - [Response](#response-12)\n      - [Get SPL Token Info](#get-spl-token-info)\n      - [Response](#response-13)\n      - [Get Waves Token Info](#get-waves-token-info)\n      - [Response](#response-14)\n      - [Get TRC20 Token Info](#get-tron-token-info)\n      - [Response](#response-15)\n    - [Smart Contract Call](#smart-contract-call)\n      - [Ethereum network](#ethereum-network-1)\n      - [Waves network](#waves-network-1)\n      - [Tron network](#tron-network-1)\n      - [Response](#response-17)\n    - [Want to contribute?](#want-to-contribute)\n\n### Generate mnemonic\n\nThis method is used to generate mnemonic. Default number of words is `12` but you can pass a number param if you want to generate more or less.\n\n```javascript\nconst mnemonic = multichainWallet.generateMnemonic();\n\n// Note: Mnemonics with less than 12 words have low entropy and may be guessed by an attacker.\n```\n\n#### Response\n\n```javascript\nnet idle lava mango another capable inhale portion blossom fluid discover cruise\n```\n\n### Create Wallet\n\nThis method creates a new wallet. The method accepts a payload object as the parameter. The parameter of this payload is:\n\n```javascript\n// Creating an Ethereum wallet.\nconst wallet = multichainWallet.createWallet({\n  derivationPath: \"m/44'/60'/0'/0/0\", // Leave empty to use default derivation path\n  network: 'ethereum',\n}); // NOTE - Address generated will work for EVM compatible blockchains E.g. Binance smart chain, Polygon etc\n\n\n// Creating a Bitcoin wallet.\nconst wallet = multichainWallet.createWallet({\n  derivationPath: \"m/44'/0'/0'/0/0\", // Leave empty to use default derivation path\n  network: 'bitcoin', // 'bitcoin' or 'bitcoin-testnet'\n});\n\n// Creating a Solana wallet.\nconst wallet = multichainWallet.createWallet({\n  derivationPath: \"m/44'/501'/0'/0'\", // Leave empty to use default derivation path\n  network: 'solana',\n});\n\n// Creating a Waves wallet.\nconst wallet = await multichainWallet.createWallet({\n  cluster: 'testnet' // Can also be mainnet,\n  network: 'waves',\n});\n\n// Creating a Tron wallet\nconst wallet = await multichainWallet.createWallet({\n  network: 'tron',\n});\n\n```\n\n#### Response\n\n```javascript\n{\n  address: '0xfBE11AC0258cc8288cA24E818691Eb062f7042E9',\n  privateKey: '0xfdf745f45d1942feea79b4c0a3fc1ca67da366899f7e6cebaa06496806ca8127',\n  mnemonic: 'net idle lava mango another capable inhale portion blossom fluid discover cruise'\n}\n```\n\n### Get Balance\n\nThis gets the balance of the address passed in. The method accepts an object as the parameter.\nThe parameters for this object depending on the kind of balance to be gotten is in the form:\n\n#### Native coins\n\n```javascript\n// Get the ETH balance of an address.\nconst data = await multichainWallet.getBalance({\n  address: '0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22',\n  network: 'ethereum',\n  rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n}); // NOTE - For otherEVM compatible blockchains all you have to do is change the rpcUrl.\n\n// Binance Smart chain\nconst data = await multichainWallet.getBalance({\n  address: '0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22',\n  network: 'ethereum',\n  rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n});\n\n// Get the BTC balance of an address.\nconst data = await multichainWallet.getBalance({\n  address: '2NAhbS79dEUeqcnbC27UppwnjoVSwET5bat',\n  network: 'bitcoin-testnet', // 'bitcoin' or 'bitcoin-testnet'\n});\n\n// Get the SOL balance of an address.\nconst data = await multichainWallet.getBalance({\n  address: 'DYgLjazTY6kMqagbDMsNttRHKQj9o6pNS8D6jMjWbmP7',\n  network: 'solana',\n  rpcUrl: 'https://api.devnet.solana.com',\n});\n\n// Get the WAVES balance of an address.\nconst data = await multichainWallet.getBalance({\n  network: 'waves',\n  address: '3NBE5tjbQn9BHczjD6NSSuFDKVHKsBRzTv9',\n  rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n});\n\n// Get the Tron balance of an address.\nconst data = await multichainWallet.getBalance({\n  network: 'tron',\n  address: 'TDdHvW9nU1JaX1P7roYtDvjErTTR17GPJJ',\n  rpcUrl: 'https://nile.trongrid.io',\n});\n```\n\n#### Tokens\n\n```javascript\n// Get the balance of an ERC20 token.\nconst data = await multichainWallet.getBalance({\n  address: '0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22',\n  network: 'ethereum',\n  rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n  tokenAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',\n}); // NOTE - For other EVM compatible blockchains all you have to do is change the rpcUrl.\n\n// Get the balance of a token on Solana.\nconst data = await multichainWallet.getBalance({\n  address: '5PwN5k7hin2XxUUaXveur7jSe5qt2mkWinp1JEiv8xYu',\n  tokenAddress: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',\n  network: 'solana',\n  rpcUrl: 'https://rpc.ankr.com/solana',\n});\n\n// Get the balance of a token on Waves.\nconst data = await multichainWallet.getBalance({\n  network: 'waves',\n  address: '3NBE5tjbQn9BHczjD6NSSuFDKVHKsBRzTv9',\n  rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n  tokenAddress: '39pnv8FVf3BX3xwtC6uhFxffy2sE3seXCPsf25eNn6qG',\n});\n\n// Get the balance of a token on tron.\nconst data = await multichainWallet.getBalance({\n  network: 'tron',\n  address: 'TDdHvW9nU1JaX1P7roYtDvjErTTR17GPJJ',\n  rpcUrl: 'https://nile.trongrid.io',\n  tokenAddress: 'TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj',\n});\n```\n\n#### Response\n\n```javascript\n{\n  balance: '2';\n}\n```\n\n### Generate Wallet from Mnemonic\n\nThis generates a wallet from Mnemonic phrase. The method accepts an object as the parameter. The parameters that this object takes are:\n\n```javascript\n// Generate an Ethereum wallet from mnemonic.\nconst wallet = multichainWallet.generateWalletFromMnemonic({\n  mnemonic:\n    'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat',\n  derivationPath: \"m/44'/60'/0'/0/0\", // Leave empty to use default derivation path\n  network: 'ethereum',\n}); // NOTE - Address generated will work for EVM compatible blockchains E.g. Binance smart chain, Polygon etc\n\n// Generate a Bitcoin wallet from mnemonic.\nconst wallet = multichainWallet.generateWalletFromMnemonic({\n  mnemonic:\n    'excess quit spot inspire stereo scrap cave wife narrow era pizza typical',\n  derivationPath: \"m/44'/0'/0'/0/0\", // Leave empty to use default derivation path\n  network: 'bitcoin', // 'bitcoin' or 'bitcoin-testnet'\n});\n\n// Generate a Solana wallet from mnemonic.\nconst wallet = multichainWallet.generateWalletFromMnemonic({\n  mnemonic:\n    'base dry mango subject neither labor portion weekend range couple right document',\n  derivationPath: \"m/44'/501'/0'/0'\", // Leave empty to use default derivation path\n  network: 'solana',\n});\n\n// Generate a Waves wallet from mnemonic.\nconst wallet = multichainWallet.generateWalletFromMnemonic({\n  mnemonic:\n    'mushroom deliver work spray hire nuclear wrong deputy march six midnight outside motor differ adult',\n  cluster: 'testnet',\n  network: 'waves',\n});\n\n// Generate a Waves wallet from mnemonic.\nconst wallet = multichainWallet.generateWalletFromMnemonic({\n  mnemonic:\n    'mushroom deliver work spray hire nuclear wrong deputy march six midnight outside motor differ adult',\n  cluster: 'testnet',\n  network: 'waves',\n});\n\n// Generate a Tron wallet from mnemonic.\nconst wallet = multichainWallet.generateWalletFromMnemonic({\n  mnemonic:\n    'mushroom deliver work spray hire nuclear wrong deputy march six midnight outside motor differ adult',\n  network: 'tron',\n});\n```\n\n#### Response\n\n```javascript\n{\n  address: '0x627306090abaB3A6e1400e9345bC60c78a8BEf57',\n  privateKey: '0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3',\n  mnemonic: 'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat'\n}\n```\n\n### Get Address from Private Key\n\nThis gets the address from the private key passed in. The method accepts an object as the parameter. The parameters that this object takes are:\n\n```javascript\n// Get the address from the private key on the Ethereum network.\nconst address = multichainWallet.getAddressFromPrivateKey({\n  privateKey:\n    '0f9e5c0bee6c7d06b95204ca22dea8d7f89bb04e8527a2c59e134d185d9af8ad',\n  network: 'ethereum',\n});\n\n// Get the address from the private key on the Bitcoin network.\nconst data = multichainWallet.getAddressFromPrivateKey({\n  privateKey: 'KxqTGtCMnX6oL9rxynDKCRJXt64Gm5ame4AEQcYncFhSSUxFBkeJ',\n  network: 'bitcoin', // 'bitcoin' or 'bitcoin-testnet'\n});\n\n// Get the address from the private key on the Solana network.\nconst address = multichainWallet.getAddressFromPrivateKey({\n  privateKey:\n    'bXXgTj2cgXMFAGpLHkF5GhnoNeUpmcJDsxXDhXQhQhL2BDpJumdwMGeC5Cs66stsN3GfkMH8oyHu24dnojKbtfp',\n  network: 'solana',\n});\n\n// Get the address from the private key on the Tron network.\nconst address = multichainWallet.getAddressFromPrivateKey({\n  privateKey:\n    'fa01dc6efd5fd64e4897aadf255ae715cf34138c7ada5f6a7efb0bdd0bd9c8c4',\n  network: 'tron',\n});\n```\n\n#### Response\n\n```javascript\n{\n  address: '0x1C082D1052fb44134a408651c01148aDBFcCe7Fe';\n}\n```\n\n### Get Transaction\n\nThis gets the transaction receipt of a transaction from the transaction hash. The method accepts an object as the parameter. The parameters that this object takes are:\n\n```javascript\n// Get the transaction receipt on Ethereum network.\nconst receipt = await multichainWallet.getTransaction({\n  hash: '0x5a90cea37e3a5dbee6e10190ff5a3769ad27a0c6f625458682104e26e0491055',\n  network: 'ethereum',\n  rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n}); // NOTE - For other EVM compatible blockchains all you have to do is change the rpcUrl.\n\n// Get the transaction receipt on Bitcoin network.\nconst receipt = await getTransaction({\n  network: 'bitcoin-testnet', // 'bitcoin' or 'bitcoin-testnet'\n  hash: '4f6c3661e0e6d190dbdfb6c0791396fccee653c5bf4a5249b049341c2b539ee1',\n});\n\n// Get the transaction receipt on Solana network.\nconst receipt = await multichainWallet.getTransaction({\n  rpcUrl: 'https://api.devnet.solana.com',\n  hash:\n    'CkG1ynQ2vN8bmNsBUKG8ix3moUUfELWwd8K2f7mmqDd7LifFFfgyFhBux6t22AncbY4NR3PsEU3DbH7mDBMXWk7',\n  network: 'solana',\n});\n\n// Get the transaction receipt on Waves network.\nconst receipt = await multichainWallet.getTransaction({\n  rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n  hash: 'Barwuj1gCiQ9wCfLQ1nbdz2CSyQXLnRxnDEubtdTwJpd',\n  network: 'waves',\n});\n\n// Get the transaction receipt on Tron network.\nconst receipt = await multichainWallet.getTransaction({\n  hash: '34f27486cbe693d5182c4b5e18c1779d918668f86f396ed62a279d8b519b81cc',\n  network: 'tron',\n  rpcUrl: 'https://nile.trongrid.io',\n});\n```\n\n#### Response\n\n```javascript\n{\n  object;\n}\n```\n\n### Transfer\n\nThis transfers the amount of tokens from the source address to the destination address It takes in an object as the parameter. It allows for the transfer of the following:\n\n#### Ethereum Network\n\nAllows for the transfer of ETH, and overriding of transactions.\n\n```javascript\n// Transferring ETH from one address to another.\nconst transfer = await multichainWallet.transfer({\n  recipientAddress: '0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22',\n  amount: 1,\n  network: 'ethereum',\n  rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n  privateKey:\n    '0f9e5c0bee6c7d06b95204ca22dea8d7f89bb04e8527a2c59e134d185d9af8ad',\n  gasPrice: '10', // Gas price is in Gwei. Leave empty to use default gas price\n  data: 'Money for transportation', // Send a message\n}); // NOTE - For other EVM compatible blockchains all you have to do is change the rpcUrl.\n\n// Transferring ERC20 tokens from one address to another.\nconst transfer = await multichainWallet.transfer({\n  recipientAddress: '0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22',\n  amount: 10,\n  network: 'ethereum',\n  rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n  privateKey:\n    '0f9e5c0bee6c7d06b95204ca22dea8d7f89bb04e8527a2c59e134d185d9af8ad',\n  gasPrice: '10', // Gas price is in Gwei. leave empty to use default gas price\n  tokenAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',\n}); // NOTE - For other EVM compatible blockchains all you have to do is change the rpcUrl.\n```\n\nThe optional parameters that the object takes in are: gas price, nonce, and data.\n\n- The gas price is the price of gas in Gwei. The higher the gas price, the faster the transaction will be. It's best to use a higher gas price than the default.\n- The nonce is the number of transactions that have been sent from the source address and is used to ensure that the transaction is unique. The transaction is unique because the nonce is incremented each time a transaction is sent.\n- The data is a string parameter used to pass across a message through the transaction. Can only be used on transfer of ETH.\n\n```javascript\n// Overriding pending ETH transaction.\nconst transfer = await multichainWallet.transfer({\n  recipientAddress: '0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22',\n  amount: 0,\n  network: 'ethereum',\n  rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n  privateKey:\n    '0f9e5c0bee6c7d06b95204ca22dea8d7f89bb04e8527a2c59e134d185d9af8ad',\n  gasPrice: '10',\n  nonce: 1, // The pending transaction nonce\n  data: 'Money for feeding', // Send a message\n});\n\n// Overriding ERC20 token pending transaction.\nconst transfer = await multichainWallet.transfer({\n  recipientAddress: '0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22',\n  amount: 0,\n  network: 'ethereum',\n  rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n  privateKey:\n    '0f9e5c0bee6c7d06b95204ca22dea8d7f89bb04e8527a2c59e134d185d9af8ad',\n  gasPrice: '10',\n  tokenAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',\n  nonce: 1, // The pending transaction nonce\n});\n```\n\n#### Response\n\n```javascript\n{\n  object;\n}\n```\n\n#### Bitcoin Network\n\nAllows for the transfer of BTC from one address to another.\n\n```javascript\n// Transferring BTC from one address to another.\nconst response = await multichainWallet.transfer({\n  privateKey: 'L3tSvMViDit1GSp7mbV2xFCGv6M45kDNuSyNY9xyUxmUPBFrBkc4',\n  recipientAddress: '2NAhbS79dEUeqcnbC27UppwnjoVSwET5bat',\n  amount: 0.001,\n  network: 'bitcoin-testnet', // 'bitcoin' or 'bitcoin-testnet'\n  fee: 10000, // Optional param default value is 10000\n  subtractFee: false, // Optional param default value is false\n});\n```\n\n#### Response\n\n```javascript\n{\n  object;\n}\n```\n\n#### Solana Network\n\nAllows for the transfer of SOL and tokens.\n\n```javascript\n// Transferring SOL from one address to another.\nconst transfer = await multichainWallet.transfer({\n  recipientAddress: '9DSRMyr3EfxPzxZo9wMBPku7mvcazHTHfyjhcfw5yucA',\n  amount: 1,\n  network: 'solana',\n  rpcUrl: 'https://api.devnet.solana.com',\n  privateKey:\n    'bXXgTj2cgXMFAGpLHkF5GhnoNeUpmcJDsxXDhXQhQhL2BDpJumdwMGeC5Cs66stsN3GfkMH8oyHu24dnojKbtfp',\n});\n\n// Transferring a token from one address to another.\nconst transfer = await multichainWallet.transfer({\n  recipientAddress: '9DSRMyr3EfxPzxZo9wMBPku7mvcazHTHfyjhcfw5yucA',\n  tokenAddress: 'DV2exYApRFWEVb9oQkedLRYeSm8ccxNReLfEksEE5FZm',\n  amount: 1,\n  network: 'solana',\n  rpcUrl: 'https://api.devnet.solana.com',\n  privateKey:\n    'h5KUPKU4z8c9nhMCQsvCLq4q6Xn9XK1B1cKjC9bJVLQLgJDvknKCBtZdHKDoKBHuATnSYaHRvjJSDdBWN8P67hh',\n});\n```\n\n#### Response\n\n```javascript\n{\n  hash: '3nGq2yczqCpm8bF2dyvdPtXpnFLJ1oGWkDfD6neLbRay8SjNqYNhWQBKE1ZFunxvFhJ47FyT6igNpYPP293jXCZk';\n}\n```\n\n#### Waves Network\n\nAllows for the transfer of WAVES and tokens.\n\n```javascript\n// Transferring WAVES from one address to another.\n\nconst response = await multichainWallet.transfer({\n  recipientAddress: '3N4x4ML4D6fiU18Tpw86puRoN78FCTs9VQu',\n  amount: 0.0001,\n  network: 'waves',\n  rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n  privateKey:\n    'mushroom deliver work spray hire nuclear wrong deputy march six midnight outside motor differ adult',\n});\n\n// Transferring a token from one address to another.\nconst transfer = await multichainWallet.transfer({\n  recipientAddress: '3N4x4ML4D6fiU18Tpw86puRoN78FCTs9VQu',\n  tokenAddress: '39pnv8FVf3BX3xwtC6uhFxffy2sE3seXCPsf25eNn6qG',\n  amount: 1,\n  network: 'waves',\n  rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n  privateKey:\n    'mushroom deliver work spray hire nuclear wrong deputy march six midnight outside motor differ adult',\n});\n```\n\n#### Response\n\n```javascript\n{\n  type: 4,\n  id: '9CbA3dsyEvbdf52gqeBvVkjEP5zBmCQPANjguNznHryf',\n  fee: 100000,\n  feeAssetId: null,\n  timestamp: 1661781621495,\n  version: 3,\n  chainId: 84,\n  sender: '3NBE5tjbQn9BHczjD6NSSuFDKVHKsBRzTv9',\n  senderPublicKey: '8JEFTsZfqp2Y7HpmaxqgGtiMLfsNAAq3bMkwZwGpUWPV',\n  proofs: [\n    '5m4DpkkYkVY4xkiMNyrNpiVUHNNAtyJrSH5UCkjWSnLTAabkCefLx6wWTFT1Xcb7K8C31H7ndZAX8mWrJLMrsqxr'\n  ],\n  recipient: '3N4x4ML4D6fiU18Tpw86puRoN78FCTs9VQu',\n  assetId: '39pnv8FVf3BX3xwtC6uhFxffy2sE3seXCPsf25eNn6qG',\n  feeAsset: null,\n  amount: 100000000,\n  attachment: ''\n}\n```\n\n#### Tron Network\n\nAllows for the transfer of TRX and TRC20 tokens.\n\n```javascript\n// Transferring TRX from one address to another.\nconst transfer = await multichainWallet.transfer({\n  rpcUrl: 'https://nile.trongrid.io',\n  recipientAddress: 'TEVuGfgLkQCVXs7EtjMiQp3ZSSUkEbNnVS',\n  amount: 0.0001,\n  network: 'tron',\n  privateKey:\n    'fa01dc6efd5fd64e4897aadf255ae715cf34138c7ada5f6a7efb0bdd0bd9c8c4',\n});\n\n// Transferring TRC20 tokens from one address to another.\nconst transfer = await multichainWallet.transfer({\n  rpcUrl: 'https://nile.trongrid.io',\n  recipientAddress: 'TEVuGfgLkQCVXs7EtjMiQp3ZSSUkEbNnVS',\n  privateKey:\n    'fa01dc6efd5fd64e4897aadf255ae715cf34138c7ada5f6a7efb0bdd0bd9c8c4',\n  amount: 0.1,\n  network: 'tron',\n  tokenAddress: 'TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj',\n});\n```\n\n#### Response\n\n```javascript\n{\n  txid\n  ..object;\n}\n```\n\n### Encryptions\n\n#### Encrypt Private Key\n\nIt supports encryption of ethereum and other EVM compatible chains private keys.\n\n```javascript\n// encrypt private key.\n\nconst encrypted = await multichainWallet.getEncryptedJsonFromPrivateKey({\n  network: 'ethereum',\n  privateKey:\n    '0f9e5c0bee6c7d06b95204ca22dea8d7f89bb04e8527a2c59e134d185d9af8ad',\n  password: 'walletpassword',\n});\n```\n\n#### Response\n\n```javascript\n{\n  json: '{\"address\":\"1c082d1052fb44134a408651c01148adbfcce7fe\",\"id\":\"abfb9f10-165a-4b7a-935d-51729f10c310\",\"version\":3,\"Crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"f3fac53ee2d76c293977d1af3a7d73bb\"},\"ciphertext\":\"c5034579cdf32d7a612c9a83801aad899abfebb7436712f363ecf89546bbcbce\",\"kdf\":\"scrypt\",\"kdfparams\":{\"salt\":\"78ff80ece5d681b1aecd829526388472d1889da233229fa5c1416e8f2035b7a8\",\"n\":131072,\"dklen\":32,\"p\":1,\"r\":8},\"mac\":\"0f70eca6138ffe60b174308b6ab7a8a81a0d2b662e2cf5d8727443cf12af766c\"}}';\n}\n```\n\n#### Decrypt Encrypted JSON\n\nIt supports decryption of encrypted JSONs (A.K.A keystore).\n\n```javascript\n// decrypting encrypted JSON.\n\nconst decrypted = await multichainWallet.getWalletFromEncryptedJson({\n  network: 'ethereum',\n  json:\n    '{\"address\":\"1c082d1052fb44134a408651c01148adbfcce7fe\",\"id\":\"abfb9f10-165a-4b7a-935d-51729f10c310\",\"version\":3,\"Crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"f3fac53ee2d76c293977d1af3a7d73bb\"},\"ciphertext\":\"c5034579cdf32d7a612c9a83801aad899abfebb7436712f363ecf89546bbcbce\",\"kdf\":\"scrypt\",\"kdfparams\":{\"salt\":\"78ff80ece5d681b1aecd829526388472d1889da233229fa5c1416e8f2035b7a8\",\"n\":131072,\"dklen\":32,\"p\":1,\"r\":8},\"mac\":\"0f70eca6138ffe60b174308b6ab7a8a81a0d2b662e2cf5d8727443cf12af766c\"}}',\n  password: 'walletpassword',\n});\n```\n\n#### Response\n\n```javascript\n{\n  privateKey: '0x0f9e5c0bee6c7d06b95204ca22dea8d7f89bb04e8527a2c59e134d185d9af8ad',\n  address: '0x1C082D1052fb44134a408651c01148aDBFcCe7Fe'\n}\n\n```\n\n### Token Info\n\n#### Get ERC20 Token Info\n\nAllows for fetching ERC20 tokens info from compatible blockchains by the token address\n\n```javascript\n// getting token info.\n\nconst info = await multichainWallet.getTokenInfo({\n  address: '0x7fe03a082fd18a80a7dbd55e9b216bcf540557e4',\n  network: 'ethereum',\n  rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n}); // NOTE - For other EVM compatible blockchains all you have to do is change the rpcUrl.\n```\n\n#### Response\n\n```javascript\n{\n  name: 'Mocked USDT',\n  symbol: 'USDT',\n  decimals: 6,\n  address: '0x7fe03a082fd18a80a7dbd55e9b216bcf540557e4',\n  totalSupply: '1000000000000'\n}\n```\n\n#### Get SPL Token Info\n\nAllows for fetching SPL tokens info on the solana by the token address.\nNote: Token has to be available on the solana token list registry\n\n```javascript\n// getting token info.\n\nconst info = await multichainWallet.getTokenInfo({\n  address: '7Xn4mM868daxsGVJmaGrYxg8CZiuqBnDwUse66s5ALmr',\n  network: 'solana',\n  rpcUrl: 'https://api.devnet.solana.com',\n  cluster: 'devnet',\n});\n```\n\n#### Response\n\n```javascript\n{\n  object;\n}\n```\n\n#### Get ERC20 Token Info\n\nAllows for fetching ERC20 tokens info from compatible blockchains by the token address\n\n```javascript\n// getting token info.\n\nconst info = await multichainWallet.getTokenInfo({\n  address: '0x7fe03a082fd18a80a7dbd55e9b216bcf540557e4',\n  network: 'ethereum',\n  rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n}); // NOTE - For other EVM compatible blockchains all you have to do is change the rpcUrl.\n```\n\n#### Response\n\n```javascript\n{\n  name: 'Mocked USDT',\n  symbol: 'USDT',\n  decimals: 6,\n  address: '0x7fe03a082fd18a80a7dbd55e9b216bcf540557e4',\n  totalSupply: '1000000000000'\n}\n```\n\n\n#### Get Tron Token Info\n\nAllows for fetching Tron token info\n\n```javascript\nconst info = await multichainWallet.getTokenInfo({\n  address: 'TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj',\n  network: 'tron',\n  rpcUrl: 'https://nile.trongrid.io',\n});\n```\n\n#### Response\n\n```javascript\n{\n  name: 'Tether USD',\n  symbol: 'USDT',\n  address: 'TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj',\n  decimals: 6,\n  totalSupply: '2100000000000000'\n}\n```\n\n### Smart Contract Call\n\nThis can be used to make custom smart contract interaction by specifying the contract ABI and function types.\n\n#### Ethereum network\n\n```javascript\n// Calling a write smart contract function.\nconst data = await multichainWallet.smartContractCall({\n  rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n  network: 'ethereum',\n  contractAddress: '0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa',\n  method: 'transfer',\n  methodType: 'write',\n  params: ['0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22', '1000000000000000000'],\n  contractAbi: [\n    {\n      constant: false,\n      inputs: [\n        { name: '_to', type: 'address' },\n        { name: '_value', type: 'uint256' },\n      ],\n      name: 'transfer',\n      outputs: [{ name: '', type: 'bool' }],\n      payable: false,\n      stateMutability: 'nonpayable',\n      type: 'function',\n    },\n  ],\n  privateKey:\n    '0f9e5c0bee6c7d06b95204ca22dea8d7f89bb04e8527a2c59e134d185d9af8ad',\n}); // NOTE - For other EVM compatible blockchains all you have to do is change the rpcUrl.\n\n// calling a read smart contract function.\nconst data = await multichainWallet.smartContractCall({\n  rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n  network: 'ethereum',\n  contractAddress: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',\n  method: 'factory',\n  methodType: 'read',\n  params: [],\n  contractAbi: [\n    {\n      inputs: [],\n      name: 'factory',\n      outputs: [{ internalType: 'address', name: '', type: 'address' }],\n      stateMutability: 'view',\n      type: 'function',\n    },\n  ],\n}); // NOTE - For other EVM compatible blockchains all you have to do is change the rpcUrl.\n```\n\n#### Waves network\n\n```javascript\n// calling a read smart contract function.\nconst data = await multichainWallet.smartContractCall({\n  network: 'waves',\n  methodType: 'read',\n  rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n  contractAddress: '3N9uzrTiArce1h9VCqK3QUUZmFqBgg5rZSW',\n  method: '3N1gVpA5MVY4WsMpzQ6RfcscpDDdqBbLx6n_balance',\n  params: [],\n});\n\n// calling a write smart contract function.\nconst data = await multichainWallet.smartContractCall({\n  network: 'waves',\n  methodType: 'write',\n  rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n  contractAddress: '3N9uzrTiArce1h9VCqK3QUUZmFqBgg5rZSW',\n  privateKey:\n    'mushroom deliver work spray hire nuclear wrong deputy march six midnight outside motor differ adult',\n  method: 'deposit',\n  payment: [{ assetId: null, amount: 1000 }],\n  params: [],\n});\n```\n\n#### Tron network\n\n```javascript\n// Calling a write smart contract function.\nconst data = await multichainWallet.smartContractCall({\n  network: 'tron',\n  rpcUrl: 'https://nile.trongrid.io',\n  contractAddress: 'TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj',\n  method: 'transfer(address,uint256)',\n  methodType: 'write',\n  contractAbi: [\n    {\n      constant: false,\n      inputs: [\n        { name: '_to', type: 'address' },\n        { name: '_value', type: 'uint256' },\n      ],\n      name: 'transfer',\n      outputs: [{ name: '', type: 'bool' }],\n      payable: false,\n      stateMutability: 'nonpayable',\n      type: 'function',\n    },\n  ],\n  params: [\n    { type: 'address', value: 'TEVuGfgLkQCVXs7EtjMiQp3ZSSUkEbNnVS' },\n    { type: 'uint256', value: 1000000 },\n  ],\n  privateKey:\n    'fa01dc6efd5fd64e4897aadf255ae715cf34138c7ada5f6a7efb0bdd0bd9c8c4',\n});\n\n// calling a read smart contract function.\nconst data = await multichainWallet.smartContractCall({\n  network: 'tron',\n  rpcUrl: 'https://nile.trongrid.io',\n  contractAddress: 'TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj',\n  method: 'balanceOf',\n  methodType: 'read',\n  contractAbi: [\n    {\n      constant: true,\n      inputs: [{ name: '_owner', type: 'address' }],\n      name: 'balanceOf',\n      outputs: [{ name: 'balance', type: 'uint256' }],\n      payable: false,\n      stateMutability: 'view',\n      type: 'function',\n    },\n  ],\n  params: [{ type: 'address', value: 'TEVuGfgLkQCVXs7EtjMiQp3ZSSUkEbNnVS' }],\n});\n```\n\nSome of the parameters available in this function are:\n\n- The **method** parameter is the name of the smart contract function to be interacted with.\n- The **method type** is the type of action the method is meant to perform.\n- The **params** parameter is the parameter of the smart contract function if it requires any. It must be in the same order as the smart contract function. If the smart contract function does not require any parameters, leave it as an empty array.\n\nThe optional parameters that the object takes in are: value, contractAbi, gas price, gas limit, nonce, and private key.\n\n- The **value** is the amount of ETH you want to send while interacting with the function.\n- The **contractAbi** is the ABI of the smart contract. Every smart contract has an ABI that can be used to interact with the smart contract functions. If this is not specified. You can interact with all the [ERC20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) token standard functions by default.\n- The **gas price** is the price of gas in Gwei. The higher the gas price, the faster the transaction gets mined. It's best to use a higher gas price than the default.\n- The **gas limit** is the maximum amount of gas you are willing to pay for the transaction.\n- The **nonce** is the number of transactions that have been sent from the source address and is used to ensure that the transaction is unique. The transaction is unique because the nonce is incremented each time a transaction is sent.\n- The **private key** is a string parameter that can be passed to use as the signer. It is used to sign the transaction. This parameter is not needed when calling a smart contract read function.\n- The **payment** (only on Waves) payment is the payment (WAVES or Waves Asset) sent to the smart contract while interacting with it. If the smart contract function does not require any payment.\n- The **feeLimt** (only on Tron) is the max amount of fee you're willing to pay for the transaction\n\n#### Response\n\n```javascript\n{\n  data: object;\n}\n```\n\n### Want to contribute?\n\nContributions are welcome! Kindly refer to the [contribution guidelines](CONTRIBUTING.md).\n"
  },
  {
    "path": "jest.config.js",
    "content": "const config = {\n  testTimeout: 100000, \n  moduleNameMapper: {\n    '^axios$': 'axios/dist/axios.js',\n  },\n  globals: {\n    'ts-jest': {\n      isolatedModules: true,\n    },\n  },\n  setupFiles: ['./jest.setup.js'],\n};\n\nmodule.exports = config;\n"
  },
  {
    "path": "jest.setup.js",
    "content": "const crypto = require('crypto');\n\nObject.defineProperty(global, 'crypto', {\n  value: {\n    getRandomValues: arr => crypto.randomFillSync(arr),\n  },\n});\n\ntry {\n  const noble = require('@noble/hashes/utils');\n  if (noble) {\n    noble.randomBytes = length => {\n      return crypto.randomBytes(length);\n    };\n  }\n} catch (e) {\n  console.warn('Could not patch @noble/hashes');\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"version\": \"0.2.10\",\n  \"license\": \"MIT\",\n  \"main\": \"dist/index.js\",\n  \"typings\": \"dist/index.d.ts\",\n  \"files\": [\n    \"dist\",\n    \"src\"\n  ],\n  \"engines\": {\n    \"node\": \">=10\"\n  },\n  \"scripts\": {\n    \"start\": \"tsdx watch\",\n    \"build\": \"tsdx build\",\n    \"test\": \"tsdx test\",\n    \"test:btc\": \"tsdx test --testPathPattern=bitcoin\",\n    \"test:eth\": \"tsdx test --testPathPattern=ethereum\",\n    \"test:sol\": \"tsdx test --testPathPattern=solana\",\n    \"test:tron\": \"tsdx test --testPathPattern=tron\",\n    \"test:waves\": \"tsdx test --testPathPattern=waves\",\n    \"lint\": \"tsdx lint\",\n    \"prepare\": \"tsdx build\",\n    \"size\": \"size-limit\",\n    \"analyze\": \"size-limit --why\"\n  },\n  \"peerDependencies\": {},\n  \"husky\": {\n    \"hooks\": {\n      \"pre-commit\": \"tsdx lint\"\n    }\n  },\n  \"prettier\": {\n    \"printWidth\": 80,\n    \"semi\": true,\n    \"singleQuote\": true,\n    \"trailingComma\": \"es5\"\n  },\n  \"name\": \"multichain-crypto-wallet\",\n  \"author\": \"Abdulfatai Suleiman <abdulfataisuleiman67@gmail.com>\",\n  \"keywords\": [\n    \"multichain\",\n    \"crypto\",\n    \"wallet\",\n    \"ethereum\",\n    \"blockchain\",\n    \"cryptocurrency\",\n    \"evm\",\n    \"solana\",\n    \"bitcoin\",\n    \"evm\",\n    \"binance smart chain\",\n    \"polygon\",\n    \"avalanche\",\n    \"waves\",\n    \"cryptography\",\n    \"tron\",\n    \"tronweb\",\n    \"TRC20\",\n    \"ERC20\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/iamnotstatic/multichain-crypto-wallet\"\n  },\n  \"homepage\": \"https://github.com/iamnotstatic/multichain-crypto-wallet/blob/main/README.md\",\n  \"module\": \"dist/multichain-crypto-wallet.esm.js\",\n  \"size-limit\": [\n    {\n      \"path\": \"dist/multichain-crypto-wallet.cjs.production.min.js\",\n      \"limit\": \"500 KB\"\n    },\n    {\n      \"path\": \"dist/multichain-crypto-wallet.esm.js\",\n      \"limit\": \"500 KB\"\n    }\n  ],\n  \"devDependencies\": {\n    \"@size-limit/preset-small-lib\": \"^7.0.8\",\n    \"husky\": \"^7.0.4\",\n    \"size-limit\": \"^7.0.8\",\n    \"tsdx\": \"^0.14.1\",\n    \"tslib\": \"^2.3.1\",\n    \"typescript\": \"^4.6.3\"\n  },\n  \"dependencies\": {\n    \"@bitgo/utxo-lib\": \"https://github.com/ren-forks/bitgo-utxo-lib#b848585e65b42c48b98c207e72d7d3006c9a5da0\",\n    \"@solana/spl-token\": \"^0.2.0\",\n    \"@solana/web3.js\": \"^1.39.1\",\n    \"@truffle/hdwallet-provider\": \"^2.0.5\",\n    \"@waves/ts-lib-crypto\": \"^1.4.4-beta.1\",\n    \"@waves/waves-transactions\": \"^4.2.10\",\n    \"axios\": \"^0.27.2\",\n    \"bip32\": \"^3.0.1\",\n    \"bip39\": \"^3.1.0\",\n    \"bitcoinjs-lib\": \"^6.0.1\",\n    \"bs58\": \"^5.0.0\",\n    \"buffer-layout\": \"^1.2.2\",\n    \"ecpair\": \"^2.0.1\",\n    \"ed25519-hd-key\": \"^1.2.0\",\n    \"ethers\": \"^5.6.2\",\n    \"immutable\": \"^4.1.0\",\n    \"tiny-secp256k1\": \"^2.2.1\",\n    \"tronweb\": \"^6.0.2\",\n    \"url\": \"^0.11.0\"\n  },\n  \"browser\": {\n    \"stream\": false\n  }\n}\n"
  },
  {
    "path": "src/abis/erc20.json",
    "content": "[\n    {\n      \"constant\": true,\n      \"inputs\": [],\n      \"name\": \"name\",\n      \"outputs\": [{ \"name\": \"\", \"type\": \"string\" }],\n      \"payable\": false,\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"constant\": false,\n      \"inputs\": [\n        { \"name\": \"_spender\", \"type\": \"address\" },\n        { \"name\": \"_value\", \"type\": \"uint256\" }\n      ],\n      \"name\": \"approve\",\n      \"outputs\": [{ \"name\": \"\", \"type\": \"bool\" }],\n      \"payable\": false,\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"constant\": true,\n      \"inputs\": [],\n      \"name\": \"totalSupply\",\n      \"outputs\": [{ \"name\": \"\", \"type\": \"uint256\" }],\n      \"payable\": false,\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"constant\": false,\n      \"inputs\": [\n        { \"name\": \"_from\", \"type\": \"address\" },\n        { \"name\": \"_to\", \"type\": \"address\" },\n        { \"name\": \"_value\", \"type\": \"uint256\" }\n      ],\n      \"name\": \"transferFrom\",\n      \"outputs\": [{ \"name\": \"\", \"type\": \"bool\" }],\n      \"payable\": false,\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"constant\": true,\n      \"inputs\": [],\n      \"name\": \"decimals\",\n      \"outputs\": [{ \"name\": \"\", \"type\": \"uint8\" }],\n      \"payable\": false,\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"constant\": true,\n      \"inputs\": [{ \"name\": \"_owner\", \"type\": \"address\" }],\n      \"name\": \"balanceOf\",\n      \"outputs\": [{ \"name\": \"balance\", \"type\": \"uint256\" }],\n      \"payable\": false,\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"constant\": true,\n      \"inputs\": [],\n      \"name\": \"symbol\",\n      \"outputs\": [{ \"name\": \"\", \"type\": \"string\" }],\n      \"payable\": false,\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    {\n      \"constant\": false,\n      \"inputs\": [\n        { \"name\": \"_to\", \"type\": \"address\" },\n        { \"name\": \"_value\", \"type\": \"uint256\" }\n      ],\n      \"name\": \"transfer\",\n      \"outputs\": [{ \"name\": \"\", \"type\": \"bool\" }],\n      \"payable\": false,\n      \"stateMutability\": \"nonpayable\",\n      \"type\": \"function\"\n    },\n    {\n      \"constant\": true,\n      \"inputs\": [\n        { \"name\": \"_owner\", \"type\": \"address\" },\n        { \"name\": \"_spender\", \"type\": \"address\" }\n      ],\n      \"name\": \"allowance\",\n      \"outputs\": [{ \"name\": \"\", \"type\": \"uint256\" }],\n      \"payable\": false,\n      \"stateMutability\": \"view\",\n      \"type\": \"function\"\n    },\n    { \"payable\": true, \"stateMutability\": \"payable\", \"type\": \"fallback\" },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        { \"indexed\": true, \"name\": \"owner\", \"type\": \"address\" },\n        { \"indexed\": true, \"name\": \"spender\", \"type\": \"address\" },\n        { \"indexed\": false, \"name\": \"value\", \"type\": \"uint256\" }\n      ],\n      \"name\": \"Approval\",\n      \"type\": \"event\"\n    },\n    {\n      \"anonymous\": false,\n      \"inputs\": [\n        { \"indexed\": true, \"name\": \"from\", \"type\": \"address\" },\n        { \"indexed\": true, \"name\": \"to\", \"type\": \"address\" },\n        { \"indexed\": false, \"name\": \"value\", \"type\": \"uint256\" }\n      ],\n      \"name\": \"Transfer\",\n      \"type\": \"event\"\n    }\n]"
  },
  {
    "path": "src/common/apis/blockchain.ts",
    "content": "import axios from 'axios';\nimport { URLSearchParams } from 'url';\n\nimport { sortUTXOs, UTXO } from '../utils/utxo';\nimport { DEFAULT_TIMEOUT } from './timeout';\n\nexport enum BlockchainNetwork {\n  Bitcoin = 'btc',\n  BitcoinCash = 'bch',\n  BitcoinTestnet = 'btc-testnet',\n  BitcoinCashTestnet = 'bch-testnet',\n}\n\ninterface BlockchainTransaction {\n  txid: string; // \"550b293355f5274e513c65f846311fd5817d13bcfcd492ab94ff2725ba94f21e\"\n  size: number; // 124\n  version: number; // 1\n  locktime: number; // 0\n  fee: number; // 0\n  inputs: [\n    {\n      coinbase: boolean; // true\n      txid: string; // \"0000000000000000000000000000000000000000000000000000000000000000\"\n      output: number; // 4294967295\n      sigscript: string; // \"03e3b9162f696d2f\"\n      sequence: number; // 4294967295\n      pkscript: null;\n      value: null;\n      address: null;\n      witness: unknown[];\n    }\n  ];\n  outputs: [\n    {\n      address: string; // \"bchtest:qp7k5sm9dcmvse2rgmkj2ktylm9fgqcnv5kp2hrs0h\"\n      pkscript: string; // \"76a9147d6a43656e36c8654346ed255964feca9403136588ac\"\n      value: number; // 39062500\n      spent: boolean; // false\n      spender: null;\n    },\n    {\n      address: null;\n      pkscript: string; // \"6a14883805620000000000000000faee4177fe240000\"\n      value: number; // 0\n      spent: boolean; // false\n      spender: null;\n    }\n  ];\n  block: {\n    height?: number; // 1489379\n    position?: number; // 0\n    mempool?: number;\n  };\n  deleted: boolean; // false\n  time: number; // 1646186011\n  rbf: boolean; // false\n  weight: number; // 496\n}\n\nconst fetchLatestBlock = async (\n  network: BlockchainNetwork\n): Promise<number> => {\n  const statsUrl = `https://api.blockchain.info/haskoin-store/${network}/block/best?notx=true`;\n  const statsResponse = (await axios.get<{ height: number }>(statsUrl)).data;\n  return statsResponse.height;\n};\n\nconst fetchUTXO = (network: BlockchainNetwork) => async (\n  txHash: string,\n  vOut: number\n): Promise<UTXO> => {\n  const url = `https://api.blockchain.info/haskoin-store/${network}/transaction/${txHash}`;\n\n  const response = (\n    await axios.get<BlockchainTransaction>(`${url}`, {\n      timeout: DEFAULT_TIMEOUT,\n    })\n  ).data;\n\n  const confirmations =\n    !response.block || !response.block.height\n      ? 0\n      : Math.max(\n          (await fetchLatestBlock(network)) - response.block.height + 1,\n          0\n        );\n\n  return {\n    txHash,\n    block: response.block && response.block.height ? response.block.height : 0,\n    amount: response.outputs[vOut].value,\n    confirmations,\n  };\n};\n\nconst fetchUTXOs = (network: BlockchainNetwork) => async (\n  address: string,\n  confirmations: number,\n  limit: number = 25,\n  offset: number = 0\n): Promise<readonly UTXO[]> =>\n  fetchTXs(network)(address, confirmations, limit, offset, true);\n\nconst fetchTXs = (network: BlockchainNetwork) => async (\n  address: string,\n  confirmations: number = 0,\n  limit: number = 25,\n  offset: number = 0,\n  onlyUnspent: boolean = false\n): Promise<readonly UTXO[]> => {\n  const url = `https://api.blockchain.info/haskoin-store/${network}/address/${address}/transactions/full?limit=${limit}&offset=${offset}`;\n  const response = (\n    await axios.get<BlockchainTransaction[]>(url, {\n      timeout: DEFAULT_TIMEOUT,\n    })\n  ).data;\n\n  let latestBlock: number | undefined;\n\n  const received: UTXO[] = [];\n\n  for (const tx of response) {\n    latestBlock = latestBlock || (await fetchLatestBlock(network));\n    const txConfirmations =\n      tx.block && tx.block.height\n        ? Math.max(latestBlock - tx.block.height + 1, 0)\n        : 0;\n    for (let i = 0; i < tx.outputs.length; i++) {\n      const vout = tx.outputs[i];\n      if (\n        vout.address === address &&\n        // If the onlyUnspent flag is true, check that the tx is unspent.\n        (!onlyUnspent || vout.spent === false)\n      ) {\n        received.push({\n          txHash: tx.txid,\n          amount: vout.value,\n          vOut: i,\n          confirmations: txConfirmations,\n        });\n      }\n    }\n  }\n\n  return received\n    .filter(utxo => confirmations === 0 || utxo.confirmations >= confirmations)\n    .sort(sortUTXOs);\n};\n\nexport const broadcastTransaction = (network: BlockchainNetwork) => async (\n  txHex: string\n): Promise<string> => {\n  if (network !== BlockchainNetwork.Bitcoin) {\n    throw new Error(\n      `Broadcasting ${network} transactions not supported by endpoint.`\n    );\n  }\n  const url = `https://blockchain.info/pushtx`;\n\n  const params = new URLSearchParams();\n  params.append('tx', txHex);\n\n  const response = await axios.post(url, params, {\n    timeout: DEFAULT_TIMEOUT,\n  });\n  if ((response.data as any).error) {\n    throw new Error((response.data as any).error);\n  }\n\n  return response.data;\n};\n\nexport const Blockchain = {\n  networks: BlockchainNetwork,\n  fetchUTXO,\n  fetchUTXOs,\n  broadcastTransaction,\n  fetchTXs,\n};\n"
  },
  {
    "path": "src/common/apis/blockchair.ts",
    "content": "import axios from 'axios';\n\nimport { sortUTXOs, UTXO } from '../utils/utxo';\nimport { DEFAULT_TIMEOUT } from './timeout';\n\nconst fetchUTXO = (network: string) => async (\n  txHash: string,\n  vOut: number\n): Promise<UTXO> => {\n  const url = `https://api.blockchair.com/${network}/dashboards/transaction/${txHash}`;\n\n  const response = (\n    await axios.get<TransactionResponse>(`${url}`, {\n      timeout: DEFAULT_TIMEOUT,\n    })\n  ).data;\n\n  if (!response.data[txHash]) {\n    throw new Error(`Transaction not found.`);\n  }\n\n  const tx = response.data[txHash];\n\n  let latestBlock = response.context.state;\n  if (latestBlock === 0) {\n    const statsUrl = `https://api.blockchair.com/${network}/stats`;\n    const statsResponse = (await axios.get(statsUrl)).data;\n    latestBlock = statsResponse.data.blocks - 1;\n  }\n\n  const confirmations =\n    tx.transaction.block_id === -1\n      ? 0\n      : Math.max(latestBlock - tx.transaction.block_id + 1, 0);\n\n  return {\n    txHash,\n    block: tx.transaction.block_id === -1 ? 0 : tx.transaction.block_id,\n    amount: tx.outputs[vOut].value,\n    confirmations,\n  };\n};\n\nconst fetchUTXOs = (network: string) => async (\n  address: string,\n  confirmations: number\n): Promise<readonly UTXO[]> => {\n  const url = `https://api.blockchair.com/${network}/dashboards/address/${address}?limit=0,100`;\n  const response = (\n    await axios.get<AddressResponse>(url, { timeout: DEFAULT_TIMEOUT })\n  ).data;\n\n  let latestBlock = response.context.state;\n  if (latestBlock === 0) {\n    const statsUrl = `https://api.blockchair.com/${network}/stats`;\n    const statsResponse = (await axios.get(statsUrl)).data;\n    latestBlock = statsResponse.data.blocks - 1;\n  }\n\n  return response.data[address].utxo\n    .map(utxo => ({\n      txHash: utxo.transaction_hash,\n      amount: utxo.value,\n      vOut: utxo.index,\n      confirmations: utxo.block_id === -1 ? 0 : latestBlock - utxo.block_id + 1,\n    }))\n    .filter(utxo => confirmations === 0 || utxo.confirmations >= confirmations)\n    .sort(sortUTXOs);\n};\n\nconst fetchTXs = (network: string) => async (\n  address: string,\n  confirmations: number = 0,\n  limit: number = 25\n): Promise<readonly UTXO[]> => {\n  const url = `https://api.blockchair.com/${network}/dashboards/address/${address}?limit=${limit},0`;\n  const response = (\n    await axios.get<AddressResponse>(url, { timeout: DEFAULT_TIMEOUT })\n  ).data;\n\n  let latestBlock = response.context.state;\n  if (latestBlock === 0) {\n    const statsUrl = `https://api.blockchair.com/${network}/stats`;\n    const statsResponse = (await axios.get(statsUrl)).data;\n    latestBlock = statsResponse.data.blocks - 1;\n  }\n\n  const txHashes = response.data[address].transactions;\n\n  let txDetails: { [txHash: string]: TransactionResponse['data'][''] } = {};\n\n  // Fetch in sets of 10\n  for (let i = 0; i < Math.ceil(txHashes.length / 10); i++) {\n    const txUrl = `https://api.blockchair.com/${network}/dashboards/transactions/${txHashes\n      .slice(i * 10, (i + 1) * 10)\n      .join(',')}`;\n    const txResponse = (\n      await axios.get<TransactionResponse>(txUrl, {\n        timeout: DEFAULT_TIMEOUT,\n      })\n    ).data;\n    txDetails = {\n      ...txDetails,\n      ...txResponse.data,\n    };\n  }\n\n  const received: UTXO[] = [];\n\n  for (const txHash of txHashes) {\n    const tx = txDetails[txHash];\n    const txConfirmations =\n      tx.transaction.block_id === -1\n        ? 0\n        : Math.max(latestBlock - tx.transaction.block_id + 1, 0);\n    for (let i = 0; i < tx.outputs.length; i++) {\n      const vout = tx.outputs[i];\n      if (vout.recipient === address) {\n        received.push({\n          txHash: tx.transaction.hash,\n          amount: vout.value,\n          vOut: i,\n          confirmations: txConfirmations,\n        });\n      }\n    }\n  }\n\n  return received\n    .filter(utxo => confirmations === 0 || utxo.confirmations >= confirmations)\n    .sort(sortUTXOs);\n};\n\nexport const broadcastTransaction = (network: string) => async (\n  txHex: string\n): Promise<string> => {\n  const url = `https://api.blockchair.com/${network}/push/transaction`;\n  const response = await axios.post<{ data: { transaction_hash: string } }>(\n    url,\n    { data: txHex },\n    { timeout: DEFAULT_TIMEOUT }\n  );\n  if ((response.data as any).error) {\n    throw new Error((response.data as any).error);\n  }\n\n  return response.data.data.transaction_hash;\n};\n\nenum Networks {\n  BITCOIN = 'bitcoin',\n  BITCOIN_CASH = 'bitcoin-cash',\n  LITECOIN = 'litecoin',\n  BITCOIN_SV = 'bitcoin-sv',\n  DOGECOIN = 'dogecoin',\n  DASH = 'dash',\n  GROESTLCOIN = 'groestlcoin',\n  BITCOIN_TESTNET = 'bitcoin/testnet',\n}\n\nexport const Blockchair = {\n  networks: Networks,\n  fetchUTXO,\n  fetchUTXOs,\n  broadcastTransaction,\n  fetchTXs,\n};\n\ninterface BlockchairContext {\n  code: number; // 200\n  source: string; // \"D\"\n  time: number; // 0.2793741226196289\n  limit: string; // \"0,100\"\n  offset: string; // \"0,0\"\n  results: number; // 0\n  state: number; // 611807\n  cache: {\n    live: boolean;\n    duration: number;\n    since: string;\n    until: string;\n    time: null;\n  };\n  api: {\n    version: string;\n    last_major_update: string;\n    next_major_update: null | string;\n    documentation: 'https://blockchair.com/api/docs';\n    notice?: string;\n  };\n}\n\n/** TYPES */\n\ninterface AddressResponse {\n  data: {\n    [addr: string]: {\n      address: {\n        type: 'pubkey';\n        script_hex: string; // \"4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac\"\n        balance: number; // 6820995737\n        balance_usd: number; // 527582.1930705917\n        received: number; // 6820995737\n        received_usd: number; // 15963.6287\n        spent: number; // 0\n        spent_usd: number; // 0\n        output_count: number; // 1924\n        unspent_output_count: number; // 1924\n        first_seen_receiving: string; // \"2009-01-03 18:15:05\"\n        last_seen_receiving: string; // \"2020-01-07 22:38:01\"\n        first_seen_spending: null;\n        last_seen_spending: null;\n        transaction_count: null;\n      };\n      transactions: string[];\n      utxo: Array<{\n        block_id: number; // 611802,\n        transaction_hash: string; // \"f3c8e9b5964703f5634261a6769d6c9d836e3175fbfbebd204837aa15ef382f7\"\n        index: number; // 29\n        value: number; // 7043123\n      }>;\n    };\n  };\n  context: BlockchairContext;\n}\n\ninterface InputOrOutput {\n  block_id: number; // 9\n  transaction_id: number; // 9\n  index: number; // 0\n  transaction_hash: string; // \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\"\n  date: string; // \"2009-01-09\"\n  time: string; // \"2009-01-09 03:54:39\"\n  value: number; // 5000000000\n  value_usd: number; // 0.5\n  recipient: string; // \"12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S\"\n  type: string; // \"pubkey\"\n  script_hex: string; // \"410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac\"\n  is_from_coinbase: boolean; // true\n  is_spendable: boolean; // true\n  is_spent: boolean; // true\n  spending_block_id: number; // 170,\n  spending_transaction_id: number; // 171,\n  spending_index: number; // 0,\n  spending_transaction_hash: string; // \"f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16\"\n  spending_date: string; // \"2009-01-12\"\n  spending_time: string; // \"2009-01-12 03:30:25\"\n  spending_value_usd: number; // 0.5\n  spending_sequence: number; // 4294967295\n  spending_signature_hex: string; // \"47304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901\"\n  spending_witness: string; // \"\"\n  lifespan: number; // 257746\n  cdd: number; // 149.15856481481\n}\n\ninterface TransactionResponse {\n  data: {\n    [utxo: string]: {\n      transaction: {\n        block_id: number; // 170\n        id: number; // 171\n        hash: string; // \"f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16\"\n        date: string; // \"2009-01-12\"\n        time: string; // \"2009-01-12 03:30:25\"\n        size: number; // 275\n        weight: number; // 1100\n        version: number; // 1\n        lock_time: number; // 0\n        is_coinbase: boolean; // false\n        has_witness: boolean; // false\n        input_count: number; // 1\n        output_count: number; // 2\n        input_total: number; // 5000000000\n        input_total_usd: number; // 0.5\n        output_total: number; // 5000000000\n        output_total_usd: number; // 0.5\n        fee: number; // 0\n        fee_usd: number; // 0\n        fee_per_kb: number; // 0\n        fee_per_kb_usd: number; // 0\n        fee_per_kwu: number; // 0\n        fee_per_kwu_usd: number; // 0\n        cdd_total: number; // 149.15856481481\n        is_rbf: boolean;\n      };\n      inputs: InputOrOutput[];\n      outputs: InputOrOutput[];\n    };\n  };\n  context: BlockchairContext;\n}\n"
  },
  {
    "path": "src/common/apis/blockstream.ts",
    "content": "import axios from 'axios';\n\nimport { sortUTXOs, UTXO } from '../utils/utxo';\nimport { DEFAULT_TIMEOUT } from './timeout';\n\ninterface BlockstreamUTXO<vout = number> {\n  status:\n    | {\n        confirmed: false;\n      }\n    | {\n        confirmed: true;\n        block_height: number;\n        block_hash: string;\n        block_time: number;\n      };\n  txid: string;\n  value: number;\n  vout: vout; // vout is a number for utxos, or an array of utxos for a tx\n}\n\ninterface BlockstreamTX\n  extends BlockstreamUTXO<\n    Array<{\n      scriptpubkey: string;\n      scriptpubkey_asm: string;\n      scriptpubkey_type: string;\n      scriptpubkey_address: string;\n      value: number; // e.g. 1034439\n    }>\n  > {\n  version: number;\n  locktime: number;\n  vin: Array<{\n    txid: string;\n    vout: number;\n    prevout: any;\n    scriptsig: string;\n    scriptsig_asm: string;\n    is_coinbase: false;\n    sequence: number;\n  }>;\n  size: number;\n  weight: number;\n  fee: number;\n}\n\nconst getAPIUrl = (testnet: boolean) =>\n  `https://blockstream.info/${testnet ? 'testnet/' : ''}api`;\n\nconst fetchUTXO = (testnet: boolean) => async (\n  txHash: string,\n  vOut: number\n): Promise<UTXO> => {\n  const apiUrl = getAPIUrl(testnet);\n  const utxo = (\n    await axios.get<BlockstreamTX>(`${apiUrl}/tx/${txHash}`, {\n      timeout: DEFAULT_TIMEOUT,\n    })\n  ).data;\n\n  const heightResponse = (\n    await axios.get<string>(`${apiUrl}/blocks/tip/height`, {\n      timeout: DEFAULT_TIMEOUT,\n    })\n  ).data;\n\n  const confirmations = utxo.status.confirmed\n    ? Math.max(1 + parseInt(heightResponse, 10) - utxo.status.block_height, 0)\n    : 0;\n\n  return {\n    txHash,\n    block: utxo.status.confirmed ? utxo.status.block_height : 0,\n    amount: utxo.vout[vOut].value,\n    confirmations,\n  };\n};\n\nconst fetchUTXOs = (testnet: boolean) => async (\n  address: string,\n  confirmations: number\n): Promise<readonly UTXO[]> => {\n  const apiUrl = getAPIUrl(testnet);\n  const response = await axios.get<ReadonlyArray<BlockstreamUTXO>>(\n    `${apiUrl}/address/${address}/utxo`,\n    { timeout: DEFAULT_TIMEOUT }\n  );\n\n  const heightResponse = await axios.get<string>(\n    `${apiUrl}/blocks/tip/height`,\n    { timeout: DEFAULT_TIMEOUT }\n  );\n\n  return response.data\n    .map(utxo => ({\n      txHash: utxo.txid,\n      amount: utxo.value,\n      vOut: utxo.vout,\n      confirmations: utxo.status.confirmed\n        ? 1 + parseInt(heightResponse.data, 10) - utxo.status.block_height\n        : 0,\n    }))\n    .filter(utxo => confirmations === 0 || utxo.confirmations >= confirmations)\n    .sort(sortUTXOs);\n};\n\nconst fetchTXs = (testnet: boolean) => async (\n  address: string,\n  confirmations: number = 0\n): Promise<readonly UTXO[]> => {\n  const apiUrl = getAPIUrl(testnet);\n\n  const response = await axios.get<ReadonlyArray<BlockstreamTX>>(\n    `${apiUrl}/address/${address}/txs`,\n    { timeout: DEFAULT_TIMEOUT }\n  );\n\n  const heightResponse = await axios.get<string>(\n    `${apiUrl}/blocks/tip/height`,\n    { timeout: DEFAULT_TIMEOUT }\n  );\n\n  const received: UTXO[] = [];\n\n  for (const tx of response.data) {\n    for (let i = 0; i < tx.vout.length; i++) {\n      const vout = tx.vout[i];\n      if (vout.scriptpubkey_address === address) {\n        received.push({\n          txHash: tx.txid,\n          amount: vout.value,\n          vOut: i,\n          confirmations: tx.status.confirmed\n            ? 1 + parseInt(heightResponse.data, 10) - tx.status.block_height\n            : 0,\n        });\n      }\n    }\n  }\n\n  return received\n    .filter(utxo => confirmations === 0 || utxo.confirmations >= confirmations)\n    .sort(sortUTXOs);\n};\n\nconst broadcastTransaction = (testnet: boolean) => async (\n  txHex: string\n): Promise<string> => {\n  const apiUrl = getAPIUrl(testnet);\n  const response = await axios.post<string>(`${apiUrl}/tx`, txHex, {\n    timeout: DEFAULT_TIMEOUT,\n  });\n\n  return response.data;\n};\n\nexport const Blockstream = {\n  fetchUTXO,\n  fetchUTXOs,\n  broadcastTransaction,\n  fetchTXs,\n};\n"
  },
  {
    "path": "src/common/apis/electrumx.ts",
    "content": "import axios from 'axios';\n\nimport { sortUTXOs, UTXO } from '../utils/utxo';\n\nconst getURL = (network: string, testnet: boolean) =>\n  `https://multichain-web-proxy.herokuapp.com/electrumx-${network}-${\n    testnet ? 'testnet' : 'mainnet'\n  }`;\n\nconst fetchUTXOs = (network: string, testnet: boolean) => async (\n  address: string,\n  confirmations: number,\n  scriptHash?: string\n): Promise<readonly UTXO[]> => {\n  if (!scriptHash) {\n    throw new Error('Must provide script hash.' + address);\n  }\n  const url = getURL(network, testnet);\n\n  const latestBlock = (\n    await axios.post<{\n      result: {\n        hex: string;\n        height: number;\n      };\n      error: null;\n      id: number;\n    }>(url, {\n      jsonrpc: '1.0',\n      id: '67',\n      method: 'blockchain.scripthash.listunspent',\n      params: [scriptHash],\n    })\n  ).data.result.height;\n\n  const response = await axios.post<{\n    result: [\n      {\n        tx_hash: string; // \"fd742de094de839845c1c94e4e5d1804b3f869c2b5a777fc33792e68719ce113\";\n        tx_pos: number; // 0;\n        height: number; // 2001083;\n        value: number; // 100000;\n      }\n    ];\n    error: null;\n    id: '67';\n  }>(url, {\n    jsonrpc: '1.0',\n    id: '67',\n    method: 'blockchain.scripthash.listunspent',\n    params: [scriptHash],\n  });\n  return response.data.result\n    .map(utxo => ({\n      txHash: utxo.tx_hash,\n      amount: utxo.value,\n      vOut: utxo.tx_pos,\n      confirmations: utxo.height ? 1 + latestBlock - utxo.height : 0,\n    }))\n    .filter(utxo => confirmations === 0 || utxo.confirmations >= confirmations)\n    .sort(sortUTXOs);\n};\n\nexport const ElectrumX = {\n  fetchUTXOs,\n};\n"
  },
  {
    "path": "src/common/apis/jsonrpc.ts",
    "content": "import axios from 'axios';\n\nimport { DEFAULT_TIMEOUT } from './timeout';\n\nexport const MULTICHAIN_URLS = {\n  BTC: 'https://multichain-web-proxy.herokuapp.com/multichain-bitcoin',\n  BTCTEST:\n    'https://multichain-web-proxy.herokuapp.com/multichain-bitcoin-testnet',\n  ZEC: 'https://multichain-web-proxy.herokuapp.com/multichain-zcash',\n  ZECTEST:\n    'https://multichain-web-proxy.herokuapp.com/multichain-zcash-testnet',\n  BCH: 'https://multichain-web-proxy.herokuapp.com/multichain-bitcoincash',\n  BCHTEST:\n    'https://multichain-web-proxy.herokuapp.com/multichain-bitcoincash-testnet',\n};\n\nconst broadcastTransaction = (url: string) => async (\n  txHex: string\n): Promise<string> => {\n  const response = await axios.post<{\n    result: string;\n    error: null;\n    id: string | number;\n  }>(\n    url,\n    {\n      jsonrpc: '1.0',\n      id: '67',\n      method: 'sendrawtransaction',\n      params: [txHex],\n    },\n    { timeout: DEFAULT_TIMEOUT }\n  );\n\n  return response.data.result;\n};\n\nexport const JSONRPC = {\n  broadcastTransaction,\n};\n"
  },
  {
    "path": "src/common/apis/sochain.ts",
    "content": "import axios from 'axios';\n\nimport { fixUTXO, fixUTXOs, sortUTXOs, UTXO } from '../utils/utxo';\nimport { DEFAULT_TIMEOUT } from './timeout';\n\nexport interface SoChainUTXO {\n  txid: string; // hex string without 0x prefix\n  value: number; // satoshis\n  script_asm: string;\n  script_hex: string; // hex string without 0x prefix\n  output_no: number;\n  confirmations: number;\n  time: number;\n}\n\nexport interface SoChainTX {\n  network: string; // \"BTC\";\n  txid: string; // \"756548eb92505a7214b66faa8d1a77116e92d81d40b8d5a5c997dd83d1efb53b\";\n  blockhash: string | null;\n  confirmations: number; // 0;\n  time: number; // 1600217073;\n  inputs: Array<{\n    input_no: number; // 0;\n    value: string; // \"0.06498884\";\n    address: string; // \"1JHKKk18HD6bgy4FKkJaVxCZpBx3hhRocf\";\n    type: 'pubkeyhash';\n    script: string; // \"3045022100dccc5915d63e50506c962179cd11e78e94d86b1c6815daf1ad8362e75543196a022053285e92aa92dce92745d59c5a6cafd349c4657f5c1007ca31592fda63c9437d01 0363dd6554e3d3263df30c24beaf3f4fb5b2db3d0679d92615fb2e67d697648085\";\n    witness: null;\n    from_output: {\n      txid: string; // \"229833c1bb68984721dba4ccfcfb092ec8ea000fd96de300baa49a2009ae5def\";\n      output_no: number; // 1;\n    };\n  }>;\n  outputs: Array<{\n    output_no: 0;\n    value: string; // \"0.00980175\";\n    address: string; // \"19Hb9HH2QK5v38NAwQuEmLwngu5HJqqRjm\";\n    type: 'pubkeyhash';\n    script: string; // \"OP_DUP OP_HASH160 5ae429a0a453e9d3e4e350717569315092e1f917 OP_EQUALVERIFY OP_CHECKSIG\";\n  }>;\n  tx_hex: string;\n  size: number;\n  version: 1;\n  locktime: 0;\n}\n\nconst fetchUTXO = (network: string) => async (\n  txHash: string,\n  vOut: number\n): Promise<UTXO> => {\n  const url = `https://sochain.com/api/v2/get_tx/${network}/${txHash}`;\n  const response = await axios.get<{\n    readonly data: SoChainTX;\n  }>(url, { timeout: DEFAULT_TIMEOUT });\n\n  const tx = response.data.data;\n\n  return fixUTXO(\n    {\n      txHash: tx.txid,\n      amount: parseInt(tx.outputs[vOut].value, 10),\n      // scriptPubKey: tx.script_hex,\n      vOut,\n      confirmations: tx.confirmations,\n    },\n    8\n  );\n};\n\nconst fetchUTXOs = (network: string) => async (\n  address: string,\n  confirmations: number\n): Promise<UTXO[]> => {\n  const url = `https://sochain.com/api/v2/get_tx_unspent/${network}/${address}/${confirmations}`;\n  const response = await axios.get<{\n    readonly data: { readonly txs: readonly SoChainUTXO[] };\n  }>(url, { timeout: DEFAULT_TIMEOUT });\n\n  return fixUTXOs(\n    response.data.data.txs.map(utxo => ({\n      txHash: utxo.txid,\n      amount: utxo.value,\n      // scriptPubKey: utxo.script_hex,\n      vOut: utxo.output_no,\n      confirmations: utxo.confirmations,\n    })),\n    8\n  )\n    .filter(utxo => confirmations === 0 || utxo.confirmations >= confirmations)\n    .sort(sortUTXOs);\n};\n\nconst fetchTXs = (network: string) => async (\n  address: string,\n  confirmations: number = 0\n): Promise<UTXO[]> => {\n  const url = `https://sochain.com/api/v2/get_tx_received/${network}/${address}/${confirmations}`;\n  const response = await axios.get<{\n    readonly data: { readonly txs: readonly SoChainUTXO[] };\n  }>(url, { timeout: DEFAULT_TIMEOUT });\n\n  return fixUTXOs(\n    response.data.data.txs.map(utxo => ({\n      txHash: utxo.txid,\n      amount: utxo.value,\n      // scriptPubKey: utxo.script_hex,\n      vOut: utxo.output_no,\n      confirmations: utxo.confirmations,\n    })),\n    8\n  )\n    .filter(utxo => confirmations === 0 || utxo.confirmations >= confirmations)\n    .sort(sortUTXOs);\n};\n\nconst broadcastTransaction = (network: string) => async (\n  txHex: string\n): Promise<string> => {\n  const response = await axios.post<{\n    status: 'success';\n    data: {\n      network: string;\n      txid: string; // Hex without 0x\n    };\n  }>(\n    `https://sochain.com/api/v2/send_tx/${network}`,\n    { tx_hex: txHex },\n    { timeout: DEFAULT_TIMEOUT }\n  );\n\n  return response.data.data.txid;\n};\n\nexport const Sochain = {\n  fetchUTXOs,\n  broadcastTransaction,\n  fetchUTXO,\n  fetchTXs,\n};\n"
  },
  {
    "path": "src/common/apis/timeout.ts",
    "content": "const SECONDS = 1000;\nexport const DEFAULT_TIMEOUT = 30 * SECONDS;\n"
  },
  {
    "path": "src/common/fallbacks/btc.ts",
    "content": "import { Blockchain, BlockchainNetwork } from '../../common/apis/blockchain';\nimport { Blockstream } from '../../common/apis/blockstream';\nimport { Sochain } from '../../common/apis/sochain';\nimport { Blockchair } from '../../common/apis/blockchair';\nimport { ElectrumX } from '../../common/apis/electrumx';\nimport { JSONRPC, MULTICHAIN_URLS } from '../../common/apis/jsonrpc';\nimport { shuffleArray } from '../utils/index';\n\nexport const _apiFallbacks = {\n  fetchUTXO: (testnet: boolean, txHash: string, vOut: number) => [\n    ...shuffleArray(\n      () => Blockstream.fetchUTXO(testnet)(txHash, vOut),\n      () =>\n        Blockchair.fetchUTXO(\n          testnet\n            ? Blockchair.networks.BITCOIN_TESTNET\n            : Blockchair.networks.BITCOIN\n        )(txHash, vOut)\n    ),\n    () =>\n      Blockchain.fetchUTXO(\n        testnet ? BlockchainNetwork.BitcoinTestnet : BlockchainNetwork.Bitcoin\n      )(txHash, vOut),\n  ],\n\n  fetchUTXOs: (\n    testnet: boolean,\n    address: string,\n    confirmations: number,\n    scriptHash?: string\n  ) => [\n    ...shuffleArray(\n      () => Blockstream.fetchUTXOs(testnet)(address, confirmations),\n      () =>\n        Blockchair.fetchUTXOs(\n          testnet\n            ? Blockchair.networks.BITCOIN_TESTNET\n            : Blockchair.networks.BITCOIN\n        )(address, confirmations)\n    ),\n    () =>\n      Sochain.fetchUTXOs(testnet ? 'BTCTEST' : 'BTC')(address, confirmations),\n    () =>\n      Blockchain.fetchUTXOs(\n        testnet ? BlockchainNetwork.BitcoinTestnet : BlockchainNetwork.Bitcoin\n      )(address, confirmations),\n    () =>\n      ElectrumX.fetchUTXOs('bitcoin', testnet)(\n        address,\n        confirmations,\n        scriptHash\n      ),\n  ],\n\n  fetchTXs: (testnet: boolean, address: string, confirmations: number = 0) => [\n    ...shuffleArray(\n      () => Blockstream.fetchTXs(testnet)(address),\n      () =>\n        Blockchair.fetchTXs(\n          testnet\n            ? Blockchair.networks.BITCOIN_TESTNET\n            : Blockchair.networks.BITCOIN\n        )(address, confirmations),\n      () =>\n        Sochain.fetchTXs(testnet ? 'BTCTEST' : 'BTC')(address, confirmations),\n      () =>\n        Blockchain.fetchUTXOs(\n          testnet ? BlockchainNetwork.BitcoinTestnet : BlockchainNetwork.Bitcoin\n        )(address, confirmations)\n    ),\n  ],\n\n  broadcastTransaction: (testnet: boolean, hex: string) => [\n    ...shuffleArray(\n      () => Blockstream.broadcastTransaction(testnet)(hex),\n      () =>\n        Blockchair.broadcastTransaction(\n          testnet\n            ? Blockchair.networks.BITCOIN_TESTNET\n            : Blockchair.networks.BITCOIN\n        )(hex)\n    ),\n    () => Sochain.broadcastTransaction(testnet ? 'BTCTEST' : 'BTC')(hex),\n    () =>\n      JSONRPC.broadcastTransaction(\n        testnet ? MULTICHAIN_URLS.BTCTEST : MULTICHAIN_URLS.BTC\n      )(hex),\n    testnet\n      ? undefined\n      : () => Blockchain.broadcastTransaction(BlockchainNetwork.Bitcoin)(hex),\n  ],\n};\n"
  },
  {
    "path": "src/common/helpers/bitcoinHelper.ts",
    "content": "import * as bitcoin from 'bitcoinjs-lib';\nimport * as ecc from 'tiny-secp256k1';\nimport { BIP32Factory } from 'bip32';\nimport { ECPairFactory } from 'ecpair';\nimport * as bip39 from 'bip39';\nimport { successResponse } from '../utils';\nimport BigNumber from 'bignumber.js';\nimport { List } from 'immutable';\nimport * as utxolib from '@bitgo/utxo-lib';\n\nimport { _apiFallbacks } from '../fallbacks/btc';\nimport { fallback, retryNTimes } from '../utils/retry';\nimport {\n  BalancePayload,\n  CreateWalletPayload,\n  GenerateWalletFromMnemonicPayload,\n  GetAddressFromPrivateKeyPayload,\n  GetTransactionPayload,\n  IResponse,\n  Network,\n  TransferPayload,\n} from '../utils/types';\nimport { BitgoUTXOLib } from '../libs/bitgoUtxoLib';\n\nconst bip32 = BIP32Factory(ecc);\nconst ECPair = ECPairFactory(ecc);\n\nconst createWallet = ({\n  network,\n  derivationPath,\n}: CreateWalletPayload): IResponse => {\n  if (derivationPath) {\n    const purpose = derivationPath?.split('/')[1];\n    if (purpose !== \"44'\") {\n      throw new Error('Invalid derivation path');\n    }\n  }\n\n  const path = derivationPath || \"m/44'/0'/0'/0/0\";\n  const mnemonic = bip39.generateMnemonic();\n  const seed = bip39.mnemonicToSeedSync(mnemonic);\n\n  const node = bip32.fromSeed(seed);\n  const child = node.derivePath(path);\n  const actualNetwork = getNetwork(network);\n\n  const { address } = bitcoin.payments.p2pkh({\n    pubkey: child.publicKey,\n    network: actualNetwork,\n  });\n\n  const privateKey = child.toWIF();\n\n  return successResponse({\n    address,\n    privateKey,\n    mnemonic,\n  });\n};\n\nconst generateWalletFromMnemonic = ({\n  network,\n  mnemonic,\n  derivationPath,\n}: GenerateWalletFromMnemonicPayload): IResponse => {\n  if (derivationPath) {\n    const purpose = derivationPath?.split('/')[1];\n    if (purpose !== \"44'\") {\n      throw new Error('Invalid derivation path ');\n    }\n  }\n\n  const seed = bip39.mnemonicToSeedSync(mnemonic);\n  const path = derivationPath || \"m/44'/0'/0'/0/0\";\n\n  const node = bip32.fromSeed(seed);\n  const child = node.derivePath(path);\n  const actualNetwork = getNetwork(network);\n\n  const { address } = bitcoin.payments.p2pkh({\n    pubkey: child.publicKey,\n    network: actualNetwork,\n  });\n\n  const privateKey = child.toWIF();\n\n  return successResponse({\n    address,\n    privateKey,\n    mnemonic,\n  });\n};\n\nconst getAddressFromPrivateKey = ({\n  privateKey,\n  network,\n}: GetAddressFromPrivateKeyPayload): IResponse => {\n  const actualNetwork = getNetwork(network);\n\n  const keyPair = ECPair.fromWIF(privateKey);\n\n  const { address } = bitcoin.payments.p2pkh({\n    pubkey: keyPair.publicKey,\n    network: actualNetwork,\n  });\n\n  return successResponse({\n    address,\n  });\n};\n\nconst getBalance = async ({\n  address,\n  network,\n}: BalancePayload): Promise<IResponse> => {\n  const testnet = isTestnet(network);\n\n  const endpoints = _apiFallbacks.fetchUTXOs(testnet, address, 0);\n  const utxos = await fallback(endpoints);\n\n  const bn = utxos\n    .reduce((sum, utxo) => sum.plus(utxo.amount), new BigNumber(0))\n    .dividedBy(new BigNumber(10).exponentiatedBy(8));\n\n  return successResponse({\n    balance: bn.toNumber(),\n  });\n};\n\nconst transfer = async (args: TransferPayload): Promise<IResponse> => {\n  const testnet = isTestnet(args.network);\n\n  const keyPair = ECPair.fromWIF(args.privateKey);\n\n  const privateKey = utxolib.ECPair.fromPrivateKeyBuffer(\n    keyPair.privateKey,\n    args.network === 'bitcoin'\n      ? utxolib.networks.bitcoin\n      : utxolib.networks.testnet\n  );\n\n  const fromAddress = getAddressFromPrivateKey({\n    privateKey: args.privateKey,\n    network: args.network,\n  }).address;\n\n  const changeAddress = fromAddress;\n  const endpoints = _apiFallbacks.fetchUTXOs(testnet, fromAddress, 0);\n\n  const utxos = List(await fallback(endpoints))\n    .sortBy(utxo => utxo.amount)\n    .reverse()\n    .toArray();\n\n  const amount = new BigNumber(args.amount.toString());\n\n  const built = await BitgoUTXOLib.buildUTXO(\n    testnet ? utxolib.networks.testnet : utxolib.networks.bitcoin,\n    privateKey,\n    changeAddress,\n    args.recipientAddress,\n    amount.times(new BigNumber(10).exponentiatedBy(8)),\n    utxos,\n    {\n      fee: args.fee,\n      subtractFee: args.subtractFee,\n    }\n  );\n\n  const txHash = await retryNTimes(\n    () => fallback(_apiFallbacks.broadcastTransaction(testnet, built.toHex())),\n    3\n  );\n\n  try {\n    const transaction = await fallback(\n      _apiFallbacks.fetchUTXO(testnet, txHash, 0)\n    );\n\n    const bigAmount = new BigNumber(transaction.amount);\n\n    // Convert amount from Satoshi to Bitcoin\n    const amountToBtc = bigAmount.dividedBy(\n      new BigNumber(10).exponentiatedBy(8)\n    );\n\n    return successResponse({\n      ...transaction,\n      amount: amountToBtc.toNumber(),\n    });\n  } catch (e) {\n    return successResponse({\n      txHash,\n    });\n  }\n};\n\nconst getTransaction = async ({\n  hash,\n  network,\n}: GetTransactionPayload): Promise<IResponse> => {\n  const testnet = isTestnet(network);\n\n  const transaction = await fallback(_apiFallbacks.fetchUTXO(testnet, hash, 0));\n  const bigAmount = new BigNumber(transaction.amount);\n\n  const amount = bigAmount.dividedBy(new BigNumber(10).exponentiatedBy(8));\n\n  return successResponse({\n    ...transaction,\n    amount: amount.toNumber(),\n  });\n};\n\nfunction getNetwork(network: Network) {\n  return network === 'bitcoin'\n    ? bitcoin.networks.bitcoin\n    : network === 'bitcoin-testnet'\n    ? bitcoin.networks.testnet\n    : bitcoin.networks.bitcoin;\n}\n\nfunction isTestnet(network: Network) {\n  return network === 'bitcoin-testnet';\n}\n\nexport default {\n  createWallet,\n  generateWalletFromMnemonic,\n  getAddressFromPrivateKey,\n  getBalance,\n  transfer,\n  getTransaction,\n};\n"
  },
  {
    "path": "src/common/helpers/ethereumHelper.ts",
    "content": "import provider from '../utils/ethers';\nimport erc20Abi from '../../abis/erc20.json';\nimport { ethers } from 'ethers';\nimport {\n  BalancePayload,\n  GetEncryptedJsonFromPrivateKey,\n  GetTransactionPayload,\n  GetWalletFromEncryptedjsonPayload,\n  TransferPayload,\n  IGetTokenInfoPayload,\n  ITokenInfo,\n  ISmartContractCallPayload,\n  CreateWalletPayload,\n  GetAddressFromPrivateKeyPayload,\n  GenerateWalletFromMnemonicPayload,\n  IResponse,\n} from '../utils/types';\nimport { successResponse } from '../utils';\n\ninterface GetContract {\n  rpcUrl?: string;\n  privateKey?: string;\n  contractAddress?: string;\n  abi?: any[];\n}\n\nconst getContract = async ({\n  contractAddress,\n  rpcUrl,\n  privateKey,\n  abi,\n}: GetContract) => {\n  if (!rpcUrl) {\n    throw new Error('RPC URL is required');\n  }\n\n  const providerInstance = provider(rpcUrl);\n  const gasPrice = await providerInstance.getGasPrice();\n  const gas = ethers.BigNumber.from(21000);\n\n  let nonce;\n  let contract;\n  let signer;\n  const contractAbi = abi || erc20Abi;\n\n  if (privateKey && contractAddress) {\n    signer = new ethers.Wallet(privateKey, providerInstance);\n    nonce = providerInstance.getTransactionCount(signer.getAddress());\n    contract = new ethers.Contract(contractAddress, contractAbi, signer);\n  } else if (privateKey && !contractAddress) {\n    signer = new ethers.Wallet(privateKey, providerInstance);\n    nonce = providerInstance.getTransactionCount(signer.getAddress());\n  } else if (contractAddress && !privateKey) {\n    contract = new ethers.Contract(\n      contractAddress,\n      contractAbi,\n      providerInstance\n    );\n  }\n\n  return {\n    contract,\n    signer,\n    gasPrice,\n    gas,\n    nonce,\n    providerInstance,\n  };\n};\n\nconst createWallet = ({ derivationPath }: CreateWalletPayload): IResponse => {\n  const path = derivationPath || \"m/44'/60'/0'/0/0\";\n  const wallet = ethers.Wallet.createRandom({\n    path,\n  });\n\n  return successResponse({\n    address: wallet.address,\n    privateKey: wallet.privateKey,\n    mnemonic: wallet.mnemonic.phrase,\n  });\n};\n\nconst getAddressFromPrivateKey = ({\n  privateKey,\n}: GetAddressFromPrivateKeyPayload): IResponse => {\n  const wallet = new ethers.Wallet(privateKey);\n\n  return successResponse({\n    address: wallet.address,\n  });\n};\n\nconst generateWalletFromMnemonic = ({\n  mnemonic,\n  derivationPath,\n}: GenerateWalletFromMnemonicPayload): IResponse => {\n  const path = derivationPath || \"m/44'/60'/0'/0/0\";\n  const wallet = ethers.Wallet.fromMnemonic(mnemonic, path);\n\n  return successResponse({\n    address: wallet.address,\n    privateKey: wallet.privateKey,\n    mnemonic: wallet.mnemonic.phrase,\n  });\n};\n\nconst getBalance = async ({\n  rpcUrl,\n  tokenAddress,\n  address,\n}: BalancePayload): Promise<IResponse> => {\n  const { contract, providerInstance } = await getContract({\n    rpcUrl,\n    contractAddress: tokenAddress,\n  });\n\n  try {\n    let balance;\n\n    if (contract) {\n      const decimals = await contract.decimals();\n\n      balance = await contract.balanceOf(address);\n\n      return successResponse({\n        balance: parseFloat(ethers.utils.formatUnits(balance, decimals)),\n      });\n    }\n\n    balance = await providerInstance.getBalance(address);\n\n    return successResponse({\n      balance: parseFloat(ethers.utils.formatEther(balance)),\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst transfer = async ({\n  privateKey,\n  tokenAddress,\n  rpcUrl,\n  ...args\n}: TransferPayload): Promise<IResponse> => {\n  const { contract, providerInstance, gasPrice, nonce } = await getContract({\n    rpcUrl,\n    privateKey,\n    contractAddress: tokenAddress,\n  });\n\n  let wallet = new ethers.Wallet(privateKey, providerInstance);\n\n  try {\n    let tx;\n\n    if (contract) {\n      const decimals = await contract.decimals();\n      const estimatedGas = await contract.estimateGas.transfer(\n        args.recipientAddress,\n        ethers.utils.parseUnits(args.amount.toString(), decimals)\n      );\n\n      tx = await contract.transfer(\n        args.recipientAddress,\n        ethers.utils.parseUnits(args.amount.toString(), decimals),\n        {\n          gasPrice: args.gasPrice\n            ? ethers.utils.parseUnits(args.gasPrice.toString(), 'gwei')\n            : gasPrice,\n          nonce: args.nonce || nonce,\n          gasLimit: args.gasLimit || estimatedGas,\n        }\n      );\n    } else {\n      tx = await wallet.sendTransaction({\n        to: args.recipientAddress,\n        value: ethers.utils.parseEther(args.amount.toString()),\n        gasPrice: args.gasPrice\n          ? ethers.utils.parseUnits(args.gasPrice.toString(), 'gwei')\n          : gasPrice,\n        nonce: args.nonce || nonce,\n        data: args.data\n          ? ethers.utils.hexlify(ethers.utils.toUtf8Bytes(args.data as string))\n          : '0x',\n      });\n    }\n\n    return successResponse({\n      ...tx,\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst getTransaction = async ({ hash, rpcUrl }: GetTransactionPayload): Promise<IResponse> => {\n  const { providerInstance } = await getContract({ rpcUrl });\n\n  try {\n    const tx = await providerInstance.getTransactionReceipt(hash);\n    return successResponse({\n      ...tx,\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst getEncryptedJsonFromPrivateKey = async (\n  args: GetEncryptedJsonFromPrivateKey\n): Promise<IResponse> => {\n  const wallet = new ethers.Wallet(args.privateKey);\n  const json = await wallet.encrypt(args.password);\n\n  return successResponse({ json });\n};\n\nconst getWalletFromEncryptedJson = async (\n  args: GetWalletFromEncryptedjsonPayload\n): Promise<IResponse> => {\n  const wallet = await ethers.Wallet.fromEncryptedJson(\n    args.json,\n    args.password\n  );\n\n  return successResponse({\n    privateKey: wallet.privateKey,\n    address: wallet.address,\n  });\n};\n\nconst getTokenInfo = async ({ address, rpcUrl }: IGetTokenInfoPayload): Promise<IResponse> => {\n  const { contract } = await getContract({ contractAddress: address, rpcUrl });\n\n  if (contract) {\n    const [name, symbol, decimals, totalSupply] = await Promise.all([\n      contract.name(),\n      contract.symbol(),\n      contract.decimals(),\n      contract.totalSupply(),\n    ]);\n\n    const data: ITokenInfo = {\n      name,\n      symbol,\n      decimals,\n      address: contract.address,\n      totalSupply: ethers.utils.formatUnits(totalSupply, decimals).toString(),\n    };\n    return successResponse({ ...data });\n  }\n\n  throw new Error('Contract not found');\n};\n\nconst smartContractCall = async (args: ISmartContractCallPayload): Promise<IResponse> => {\n  const { contract, gasPrice, nonce } = await getContract({\n    rpcUrl: args.rpcUrl,\n    contractAddress: args.contractAddress,\n    abi: args.contractAbi,\n    privateKey: args.privateKey,\n  });\n\n  try {\n    let tx;\n    let overrides = {} as any;\n\n    if (args.methodType === 'read') {\n      overrides = {};\n    } else if (args.methodType === 'write') {\n      overrides = {\n        gasPrice: args.gasPrice\n          ? ethers.utils.parseUnits(args.gasPrice, 'gwei')\n          : gasPrice,\n        nonce: args.nonce || nonce,\n        value: args.value ? ethers.utils.parseEther(args.value.toString()) : 0,\n      };\n\n      if (args.gasLimit) {\n        overrides.gasLimit = args.gasLimit;\n      }\n    }\n\n    if (args.params.length > 0) {\n      tx = await contract?.[args.method](...args.params, overrides);\n    } else {\n      tx = await contract?.[args.method](overrides);\n    }\n\n    return successResponse({\n      data: tx,\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nexport default {\n  getBalance,\n  createWallet,\n  getAddressFromPrivateKey,\n  generateWalletFromMnemonic,\n  transfer,\n  getTransaction,\n  getEncryptedJsonFromPrivateKey,\n  getWalletFromEncryptedJson,\n  getTokenInfo,\n  smartContractCall,\n};\n"
  },
  {
    "path": "src/common/helpers/solanaHelper.ts",
    "content": "import provider from '../utils/solana';\nimport * as solanaWeb3 from '@solana/web3.js';\nimport {\n  getOrCreateAssociatedTokenAccount,\n  transfer as transferToken,\n  getMint,\n} from '@solana/spl-token';\nimport {\n  BalancePayload,\n  CreateWalletPayload,\n  GenerateWalletFromMnemonicPayload,\n  GetAddressFromPrivateKeyPayload,\n  GetTransactionPayload,\n  IGetTokenInfoPayload,\n  IResponse,\n  ISplTokenInfo,\n  ITokenInfo,\n  TransferPayload,\n} from '../utils/types';\nimport * as bs58 from 'bs58';\nimport { successResponse } from '../utils';\nimport * as bip39 from 'bip39';\nimport { derivePath } from 'ed25519-hd-key';\n// @ts-ignore\nimport * as BufferLayout from 'buffer-layout';\nimport axios from 'axios';\n\nexport const ACCOUNT_LAYOUT = BufferLayout.struct([\n  BufferLayout.blob(32, 'mint'),\n  BufferLayout.blob(32, 'owner'),\n  BufferLayout.nu64('amount'),\n  BufferLayout.blob(93),\n]);\nexport const chainId = {\n  'mainnet-beta': 101,\n  testnet: 102,\n  devnet: 103,\n};\n\nconst getConnection = (rpcUrl?: string) => {\n  const connection = provider(rpcUrl);\n\n  return connection;\n};\n\nconst createWallet = ({ derivationPath }: CreateWalletPayload) => {\n  const path = derivationPath || \"m/44'/501'/0'/0'\";\n\n  const mnemonic = bip39.generateMnemonic();\n  const seed = bip39.mnemonicToSeedSync(mnemonic);\n  const derivedSeed = derivePath(path, seed.toString('hex')).key;\n\n  const keyPair = solanaWeb3.Keypair.fromSeed(\n    (derivedSeed as unknown) as Uint8Array\n  );\n\n  return successResponse({\n    address: keyPair.publicKey.toBase58(),\n    privateKey: bs58.encode(keyPair.secretKey),\n    mnemonic,\n  });\n};\n\nconst generateWalletFromMnemonic = ({\n  mnemonic,\n  derivationPath,\n}: GenerateWalletFromMnemonicPayload): IResponse => {\n  const path = derivationPath || \"m/44'/501'/0'/0'\";\n  const seed = bip39.mnemonicToSeedSync(mnemonic);\n  const derivedSeed = derivePath(path, seed.toString('hex')).key;\n\n  const keyPair = solanaWeb3.Keypair.fromSeed(\n    (derivedSeed as unknown) as Uint8Array\n  );\n\n  return successResponse({\n    address: keyPair.publicKey.toBase58(),\n    privateKey: bs58.encode(keyPair.secretKey),\n    mnemonic,\n  });\n};\n\nconst getAddressFromPrivateKey = ({\n  privateKey,\n}: GetAddressFromPrivateKeyPayload): IResponse => {\n  let secretKey;\n\n  if (privateKey.split(',').length > 1) {\n    secretKey = new Uint8Array(privateKey.split(',') as any);\n  } else {\n    secretKey = bs58.decode(privateKey);\n  }\n\n  const keyPair = solanaWeb3.Keypair.fromSecretKey(secretKey, {\n    skipValidation: true,\n  });\n\n  return successResponse({\n    address: keyPair.publicKey.toBase58(),\n  });\n};\n\nconst getBalance = async (args: BalancePayload): Promise<IResponse> => {\n  const connection = getConnection(args.rpcUrl);\n\n  try {\n    let balance;\n    if (args.tokenAddress) {\n      const account = await connection.getTokenAccountsByOwner(\n        new solanaWeb3.PublicKey(args.address),\n        {\n          mint: new solanaWeb3.PublicKey(args.tokenAddress),\n        }\n      );\n\n      balance =\n        account.value.length > 0\n          ? ACCOUNT_LAYOUT.decode(account.value[0].account.data).amount\n          : 0;\n\n      return successResponse({\n        balance: balance / solanaWeb3.LAMPORTS_PER_SOL,\n      });\n    }\n\n    const publicKey = new solanaWeb3.PublicKey(args.address);\n    balance = await connection.getBalance(publicKey);\n\n    return successResponse({\n      balance: balance / solanaWeb3.LAMPORTS_PER_SOL,\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst transfer = async (args: TransferPayload): Promise<IResponse> => {\n  const connection = getConnection(args.rpcUrl);\n\n  try {\n    const recipient = new solanaWeb3.PublicKey(args.recipientAddress);\n    let secretKey;\n    let signature;\n\n    if (args.privateKey.split(',').length > 1) {\n      secretKey = new Uint8Array(args.privateKey.split(',') as any);\n    } else {\n      secretKey = bs58.decode(args.privateKey);\n    }\n\n    const from = solanaWeb3.Keypair.fromSecretKey(secretKey, {\n      skipValidation: true,\n    });\n\n    if (args.tokenAddress) {\n      // Get token mint\n      const mint = await getMint(\n        connection,\n        new solanaWeb3.PublicKey(args.tokenAddress)\n      );\n\n      // Get the token account of the from address, and if it does not exist, create it\n      const fromTokenAccount = await getOrCreateAssociatedTokenAccount(\n        connection,\n        from,\n        mint.address,\n        from.publicKey\n      );\n\n      // Get the token account of the recipient address, and if it does not exist, create it\n      const recipientTokenAccount = await getOrCreateAssociatedTokenAccount(\n        connection,\n        from,\n        mint.address,\n        recipient\n      );\n\n      signature = await transferToken(\n        connection,\n        from,\n        fromTokenAccount.address,\n        recipientTokenAccount.address,\n        from.publicKey,\n        solanaWeb3.LAMPORTS_PER_SOL * args.amount\n      );\n    } else {\n      const transaction = new solanaWeb3.Transaction().add(\n        solanaWeb3.SystemProgram.transfer({\n          fromPubkey: from.publicKey,\n          toPubkey: recipient,\n          lamports: solanaWeb3.LAMPORTS_PER_SOL * args.amount,\n        })\n      );\n\n      signature = await solanaWeb3.sendAndConfirmTransaction(\n        connection,\n        transaction,\n        [from]\n      );\n    }\n\n    const tx = await connection.getTransaction(signature, {\n      maxSupportedTransactionVersion: 0,\n    });\n\n    return successResponse({\n      ...tx,\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst getTransaction = async (\n  args: GetTransactionPayload\n): Promise<IResponse> => {\n  const connection = getConnection(args.rpcUrl);\n\n  try {\n    const tx = await connection.getTransaction(args.hash, {\n      maxSupportedTransactionVersion: 0,\n    });\n\n    return successResponse({\n      ...tx,\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst getTokenInfo = async (args: IGetTokenInfoPayload): Promise<IResponse> => {\n  try {\n    const connection = getConnection(args.rpcUrl);\n    const tokenList = await getTokenList(args.cluster!);\n    const token = tokenList.find(token => token.address === args.address);\n\n    if (!token) {\n      throw new Error('Token not found');\n    }\n\n    const data: ITokenInfo = {\n      name: token.name,\n      symbol: token.symbol,\n      address: token.address,\n      decimals: token.decimals,\n      logoUrl: token.logoURI,\n      totalSupply: '0',\n    };\n\n    const tokenSupply = await connection.getTokenSupply(\n      new solanaWeb3.PublicKey(data.address)\n    );\n    data.totalSupply = tokenSupply.value.uiAmount!.toString();\n\n    return successResponse({ ...data });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst getTokenList = async (\n  cluster: 'mainnet-beta' | 'testnet' | 'devnet'\n): Promise<ISplTokenInfo[]> => {\n  const tokenListUrl =\n    'https://raw.githubusercontent.com/solana-labs/token-list/main/src/tokens/solana.tokenlist.json';\n  const response = await axios.get(tokenListUrl);\n\n  if (response.data && response.data.tokens) {\n    return response.data.tokens.filter(\n      (data: ISplTokenInfo) => data.chainId === chainId[cluster]\n    );\n  }\n\n  return [];\n};\n\nexport default {\n  getBalance,\n  createWallet,\n  generateWalletFromMnemonic,\n  transfer,\n  getAddressFromPrivateKey,\n  getTransaction,\n  getTokenInfo,\n};\n"
  },
  {
    "path": "src/common/helpers/tronHelper.ts",
    "content": "import { TronWeb, utils } from 'tronweb';\nimport { successResponse } from '../utils';\nimport erc20Abi from '../../abis/erc20.json';\nimport {\n  BalancePayload,\n  CreateWalletPayload,\n  GenerateWalletFromMnemonicPayload,\n  GetAddressFromPrivateKeyPayload,\n  GetTransactionPayload,\n  IGetTokenInfoPayload,\n  IResponse,\n  ISmartContractCallPayload,\n  TransferPayload,\n} from '../utils/types';\n\ninterface GetContract {\n  rpcUrl?: string;\n  apiKey?: string;\n  privateKey?: string;\n  contractAddress?: string;\n  abi?: any[];\n}\n\nconst getContract = async ({\n  contractAddress,\n  rpcUrl,\n  apiKey,\n  privateKey,\n  abi,\n}: GetContract) => {\n  if (!rpcUrl) {\n    throw new Error('RPC URL is required');\n  }\n\n  let tronWeb = new TronWeb({\n    fullHost: rpcUrl,\n    headers: apiKey ? { 'TRON-PRO-API-KEY': apiKey } : undefined,\n  });\n\n  if (privateKey) {\n    tronWeb.setPrivateKey(privateKey);\n  }\n\n  let contract;\n  if (contractAddress) {\n    if (privateKey) {\n      const wallet = TronWeb.address.fromPrivateKey(privateKey);\n      tronWeb.setAddress(wallet as string);\n    } else {\n      tronWeb.setAddress(contractAddress);\n    }\n\n    contract = tronWeb.contract(abi || erc20Abi, contractAddress);\n  }\n\n  return {\n    contract,\n    tronWeb,\n  };\n};\n\nconst createWallet = ({ derivationPath }: CreateWalletPayload): IResponse => {\n  const path = derivationPath || \"m/44'/195'/0'/0/0\";\n  const account = TronWeb.createRandom(undefined, path);\n\n  return successResponse({\n    address: account.address,\n    privateKey: account.privateKey,\n    mnemonic: account.mnemonic?.phrase,\n  });\n};\n\nconst getAddressFromPrivateKey = ({\n  privateKey,\n}: GetAddressFromPrivateKeyPayload): IResponse => {\n  const account = TronWeb.address.fromPrivateKey(privateKey);\n\n  return successResponse({\n    address: account,\n  });\n};\n\nconst generateWalletFromMnemonic = ({\n  mnemonic,\n  derivationPath,\n}: GenerateWalletFromMnemonicPayload): IResponse => {\n  const path = derivationPath || \"m/44'/195'/0'/0/0\";\n  const account = TronWeb.fromMnemonic(mnemonic, path);\n\n  const privateKey = account.privateKey.startsWith('0x')\n    ? account.privateKey.substring(2)\n    : account.privateKey;\n\n  return successResponse({\n    address: account.address,\n    privateKey: privateKey,\n    mnemonic: mnemonic,\n  });\n};\n\nconst getBalance = async ({\n  rpcUrl,\n  tokenAddress,\n  address,\n}: BalancePayload): Promise<IResponse> => {\n  const { tronWeb, contract } = await getContract({\n    rpcUrl,\n    contractAddress: tokenAddress,\n  });\n\n  try {\n    if (contract && tokenAddress) {\n      const balance = await contract.methods.balanceOf(address).call();\n\n      return successResponse({\n        balance: TronWeb.fromSun(Number(balance)),\n      });\n    }\n\n    const balance = await tronWeb.trx.getBalance(address);\n\n    return successResponse({\n      balance: TronWeb.fromSun(balance).toString(),\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst transfer = async ({\n  privateKey,\n  tokenAddress,\n  rpcUrl,\n  recipientAddress,\n  amount,\n  feeLimit,\n}: TransferPayload): Promise<IResponse> => {\n  const { tronWeb, contract } = await getContract({\n    rpcUrl,\n    privateKey,\n    contractAddress: tokenAddress,\n  });\n\n  try {\n    let tx;\n\n    if (contract && tokenAddress) {\n      const amountInSun = TronWeb.toSun(amount);\n      const functionSelector = 'transfer(address,uint256)';\n      const parameter = [\n        { type: 'address', value: recipientAddress },\n        { type: 'uint256', value: amountInSun.toString() },\n      ];\n\n      const txRaw = await tronWeb.transactionBuilder.triggerSmartContract(\n        tokenAddress,\n        functionSelector,\n        feeLimit ? { feeLimit } : {},\n        parameter\n      );\n      const signedTx = await tronWeb.trx.sign(txRaw.transaction);\n      const result = await tronWeb.trx.sendRawTransaction(signedTx);\n\n      tx = result;\n    } else {\n      const amountInSun = TronWeb.toSun(amount);\n      tx = await tronWeb.trx.sendTransaction(\n        recipientAddress,\n        Number(amountInSun.toString())\n      );\n    }\n\n    return successResponse({\n      ...tx,\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst getTransaction = async ({ hash, rpcUrl }: GetTransactionPayload): Promise<IResponse> => {\n  const { tronWeb } = await getContract({ rpcUrl });\n\n  try {\n    const tx = await tronWeb.trx.getTransactionInfo(hash);\n    return successResponse({\n      ...tx,\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst getTokenInfo = async ({\n  address,\n  rpcUrl,\n  apiKey,\n}: IGetTokenInfoPayload): Promise<IResponse> => {\n  const { contract } = await getContract({\n    contractAddress: address,\n    rpcUrl,\n    apiKey,\n  });\n\n  if (contract) {\n    try {\n      const [name, symbol, decimals, totalSupply] = await Promise.all([\n        contract.methods.name().call(),\n        contract.methods.symbol().call(),\n        contract.methods.decimals().call(),\n        contract.methods.totalSupply().call(),\n      ]);\n\n      const data = {\n        name,\n        symbol,\n        decimals: Number(decimals),\n        address,\n        totalSupply: TronWeb.fromSun(Number(totalSupply)).toString(),\n      };\n\n      return successResponse({ ...data });\n    } catch (error) {\n      throw error;\n    }\n  }\n\n  throw new Error('Contract not found');\n};\n\nconst smartContractCall = async ({\n  rpcUrl,\n  contractAddress,\n  privateKey,\n  method,\n  params = [],\n  methodType,\n  feeLimit,\n  contractAbi,\n}: ISmartContractCallPayload): Promise<IResponse> => {\n  const { tronWeb } = await getContract({\n    rpcUrl,\n    contractAddress,\n    privateKey,\n  });\n\n  try {\n    if (!contractAbi) {\n      throw new Error('Contract ABI is required');\n    }\n\n    let result;\n\n    if (methodType === 'read') {\n      const functionAbi = contractAbi.find(abi => abi.name === method);\n      const functionSelector = `${functionAbi.name}(${functionAbi.inputs\n        .map((input: { type: string }) => input.type)\n        .join(',')})`;\n\n      result = await tronWeb.transactionBuilder.triggerConstantContract(\n        contractAddress,\n        functionSelector,\n        {},\n        params\n      );\n\n      const prefixedHex = result.constant_result[0].startsWith('0x')\n        ? result.constant_result[0]\n        : `0x${result.constant_result[0]}`;\n\n      const decoded = utils.abi.decodeParamsV2ByABI(functionAbi, prefixedHex);\n      result = decoded.toString();\n    } else if (methodType === 'write') {\n      const txRaw = await tronWeb.transactionBuilder.triggerSmartContract(\n        contractAddress,\n        method,\n        feeLimit ? { feeLimit } : {},\n        params\n      );\n      const signedTx = await tronWeb.trx.sign(txRaw.transaction);\n      result = await tronWeb.trx.sendRawTransaction(signedTx);\n    }\n\n    return successResponse({\n      data: result,\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nexport default {\n  getBalance,\n  createWallet,\n  getAddressFromPrivateKey,\n  generateWalletFromMnemonic,\n  transfer,\n  getTransaction,\n  getTokenInfo,\n  smartContractCall,\n};\n"
  },
  {
    "path": "src/common/helpers/wavesHelper.ts",
    "content": "import { successResponse } from '../utils';\nimport {\n  BalancePayload,\n  CreateWalletPayload,\n  GenerateWalletFromMnemonicPayload,\n  GetAddressFromPrivateKeyPayload,\n  GetTransactionPayload,\n  IGetTokenInfoPayload,\n  IResponse,\n  ISmartContractCallPayload,\n  ITokenInfo,\n  TransferPayload,\n} from '../utils/types';\nimport {\n  MAIN_NET_CHAIN_ID,\n  TEST_NET_CHAIN_ID,\n  address,\n  privateKey,\n  randomSeed,\n} from '@waves/ts-lib-crypto';\nimport {\n  nodeInteraction,\n  transfer as transferAsset,\n  invokeScript,\n  IInvokeScriptParams,\n  ITransferParams,\n} from '@waves/waves-transactions';\nimport axios from 'axios';\n\nconst WAVES_DECIMALS = 8;\n\nconst createWallet = ({ cluster }: CreateWalletPayload): IResponse => {\n  const seed = randomSeed();\n  const chainId = getChainIdWithCluster(cluster);\n\n  return successResponse({\n    address: address(seed, chainId),\n    privateKey: privateKey(seed),\n    mnemonic: seed,\n  });\n};\n\nconst generateWalletFromMnemonic = ({\n  mnemonic,\n  cluster,\n}: GenerateWalletFromMnemonicPayload): IResponse => {\n  const chainId = getChainIdWithCluster(cluster);\n\n  return successResponse({\n    address: address(mnemonic, chainId),\n    privateKey: privateKey(mnemonic),\n    mnemonic: mnemonic,\n  });\n};\n\nconst getAddressFromPrivateKey = ({\n  privateKey,\n}: GetAddressFromPrivateKeyPayload): IResponse => {\n  const chainId = getChainIdWithAddress(privateKey);\n\n  return successResponse({\n    address: address(privateKey, chainId),\n  });\n};\n\nconst getBalance = async (args: BalancePayload): Promise<IResponse> => {\n  try {\n    if (!args.rpcUrl) {\n      throw new Error('Error: Node URL is required');\n    }\n\n    if (args.tokenAddress) {\n      const balance = await nodeInteraction.assetBalance(\n        args.tokenAddress,\n        args.address,\n        args.rpcUrl\n      );\n\n      const tokenInfo = await getTokenInfo({\n        address: args.tokenAddress,\n        rpcUrl: args.rpcUrl,\n        network: args.network,\n      });\n\n      return successResponse({\n        balance: Number(balance) / Math.pow(10, tokenInfo.decimals),\n      });\n    }\n\n    const balance = await nodeInteraction.balance(args.address, args.rpcUrl);\n\n    return successResponse({\n      balance: balance / Math.pow(10, WAVES_DECIMALS),\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst transfer = async (args: TransferPayload): Promise<IResponse> => {\n  try {\n    if (!args.rpcUrl) {\n      throw new Error('Error: Node URL is required');\n    }\n\n    let amount;\n    if (args.tokenAddress) {\n      const tokenInfo = await getTokenInfo({\n        address: args.tokenAddress,\n        rpcUrl: args.rpcUrl,\n        network: args.network,\n      });\n\n      amount = args.amount * Math.pow(10, tokenInfo.decimals);\n    } else {\n      amount = args.amount * Math.pow(10, WAVES_DECIMALS);\n    }\n\n    const params = {\n      assetId: args.tokenAddress,\n      recipient: args.recipientAddress,\n      amount: parseInt(String(amount)),\n      chainId: getChainIdWithAddress(args.recipientAddress),\n    } as ITransferParams;\n\n    const signedTx = transferAsset(params, args.privateKey);\n    const broadcastedTx = await nodeInteraction.broadcast(\n      signedTx,\n      args.rpcUrl\n    );\n\n    return successResponse({\n      ...broadcastedTx,\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst getTransaction = async (\n  args: GetTransactionPayload\n): Promise<IResponse> => {\n  try {\n    if (!args.rpcUrl) {\n      throw new Error('Error: Node URL is required');\n    }\n\n    const tx = await nodeInteraction.transactionById(args.hash, args.rpcUrl);\n\n    return successResponse({\n      ...tx,\n    });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst getTokenInfo = async (args: IGetTokenInfoPayload): Promise<IResponse> => {\n  try {\n    const url = new URL(`assets/details/${args.address}`, args.rpcUrl);\n    const { data } = await axios.get(url.toString());\n\n    const info: ITokenInfo = {\n      name: data.name,\n      symbol: data.name,\n      address: data.assetId,\n      decimals: data.decimals,\n      totalSupply: data.quantity.toString(),\n    };\n\n    return successResponse({ ...info });\n  } catch (error) {\n    throw error;\n  }\n};\n\nconst smartContractCall = async (\n  args: ISmartContractCallPayload\n): Promise<IResponse> => {\n  let data;\n\n  if (args.methodType === 'write') {\n    const params = {\n      dApp: args.contractAddress,\n      call: {\n        function: args.method,\n        args: [...(args.params || [])],\n      },\n      payment: [...(args.payment || [])],\n      chainId: getChainIdWithAddress(args.contractAddress),\n    } as IInvokeScriptParams;\n\n    const signedTx = invokeScript(params, args.privateKey!);\n    data = await nodeInteraction.broadcast(signedTx, args.rpcUrl);\n  } else if (args.methodType === 'read') {\n    const response = await nodeInteraction.accountDataByKey(\n      args.method,\n      args.contractAddress,\n      args.rpcUrl\n    );\n\n    data = response?.value;\n  }\n\n  return successResponse({\n    data,\n  });\n};\n\nfunction getChainIdWithCluster(cluster?: string) {\n  return cluster === 'testnet'\n    ? TEST_NET_CHAIN_ID\n    : cluster === 'mainnet'\n    ? MAIN_NET_CHAIN_ID\n    : undefined;\n}\n\nfunction getChainIdWithAddress(address: string) {\n  return address.startsWith('3P') ? MAIN_NET_CHAIN_ID : TEST_NET_CHAIN_ID;\n}\n\nexport default {\n  getBalance,\n  createWallet,\n  generateWalletFromMnemonic,\n  getAddressFromPrivateKey,\n  transfer,\n  getTransaction,\n  getTokenInfo,\n  smartContractCall,\n};\n"
  },
  {
    "path": "src/common/libs/bitgoUtxoLib.ts",
    "content": "import BigNumber from 'bignumber.js';\nimport * as bitcoin from '@bitgo/utxo-lib';\n\nimport { UTXO } from '../utils/utxo';\n\nconst buildUTXO = async (\n  network: typeof bitcoin.networks.bitcoin,\n  privateKey: any,\n  changeAddress: string,\n  toAddress: string,\n  valueIn: BigNumber,\n  utxos: UTXO[],\n  options?: {\n    subtractFee?: boolean;\n    fee?: number;\n    signFlag?: number;\n    version?: number;\n    versionGroupID?: number;\n    expiryHeight?: number;\n    lockTime?: number;\n    consensusBranchId?: number;\n  }\n): Promise<{ toHex: () => string }> => {\n  const fees = new BigNumber(\n    options && options.fee !== undefined ? options.fee : 10000\n  );\n\n  const value = options && options.subtractFee ? valueIn.minus(fees) : valueIn;\n  if (value.lt(0)) {\n    throw new Error(\n      `Unable to include fee in value, fee exceeds value (${fees.toFixed()} > ${valueIn.toFixed()})`\n    );\n  }\n\n  const tx = new bitcoin.TransactionBuilder(network);\n  if (options && options.version) {\n    tx.setVersion(options.version);\n  }\n  if (options && options.versionGroupID) {\n    tx.setVersionGroupId(options.versionGroupID);\n  }\n  if (options && options.expiryHeight) {\n    tx.setExpiryHeight(options.expiryHeight);\n  }\n  if (options && options.lockTime) {\n    tx.setLockTime(options.lockTime);\n  }\n  if (options && options.consensusBranchId) {\n    tx.setConsensusBranchId(options.consensusBranchId);\n  }\n\n  // Only use the required utxos\n  const [usedUTXOs, sum] = utxos.reduce(\n    ([utxoAcc, total], utxo) =>\n      total.lt(value.plus(fees))\n        ? [[...utxoAcc, utxo], total.plus(utxo.amount)]\n        : [utxoAcc, total],\n    [[] as UTXO[], new BigNumber(0)]\n  );\n\n  if (sum.lt(value.plus(fees))) {\n    throw new Error('Insufficient balance to broadcast transaction');\n  }\n\n  // Add all inputs\n  usedUTXOs.map(utxo => tx.addInput(utxo.txHash, utxo.vOut));\n\n  const change = sum.minus(value).minus(fees);\n\n  // Add outputs\n  tx.addOutput(toAddress, value.toNumber());\n  if (change.gt(0)) {\n    tx.addOutput(changeAddress, change.toNumber());\n  }\n\n  // Sign inputs\n  usedUTXOs.map((utxo, i) =>\n    tx.sign(\n      i,\n      privateKey,\n      null,\n      options && options.signFlag !== undefined ? options.signFlag : null,\n      utxo.amount\n    )\n  );\n\n  return tx.build();\n};\n\nexport const BitgoUTXOLib = {\n  buildUTXO,\n};\n"
  },
  {
    "path": "src/common/utils/ethers.ts",
    "content": "import { ethers } from 'ethers';\n\nconst provider = (rpcUrl?: string) => {\n  return new ethers.providers.JsonRpcProvider(rpcUrl);\n};\n\nexport default provider;\n"
  },
  {
    "path": "src/common/utils/index.ts",
    "content": "import { IResponse } from './types';\nimport * as base64 from 'base64-js';\n\nexport const successResponse = (args: IResponse): IResponse => {\n  return args;\n};\n\n/**\n * Remove 0x prefix from a hex string. If the input doesn't have a 0x prefix,\n * it's returned unchanged.\n *\n * @param hex The hex value to be prefixed.\n */\nexport const strip0x = (hex: string): string => {\n  return hex.substring(0, 2) === '0x' ? hex.slice(2) : hex;\n};\n\n/**\n * Convert a Uint8Array to a hex string (with no \"0x\"-prefix).\n */\nexport const toHex = (array: Uint8Array): string =>\n  array.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');\n\n/**\n * Add a 0x prefix to a hex value, converting to a string first. If the input\n * is already prefixed, it's returned unchanged.\n *\n * @param hexInput The hex value to be prefixed.\n */\nexport const Ox = (\n  hexInput: Uint8Array | string | number,\n  { prefix } = { prefix: '0x' }\n): string => {\n  let hexString: string =\n    hexInput instanceof Uint8Array\n      ? toHex(hexInput)\n      : typeof hexInput === 'number'\n      ? hexInput.toString(16)\n      : hexInput;\n\n  if (hexString.length % 2 === 1) {\n    hexString = '0' + hexString;\n  }\n  return hexString.substring(0, 2) === prefix\n    ? hexString\n    : `${prefix}${hexString}`;\n};\n\n/**\n * Convert a hex string to a Uint8Array.\n */\nexport const fromHex = (hexString: string): Uint8Array => {\n  // Strip \"0x\" prefix.\n  hexString = strip0x(hexString);\n\n  // Pad the hex string.\n  if (hexString.length % 2) {\n    hexString = '0' + hexString;\n  }\n\n  // Split the string into bytes.\n  const match = hexString.match(/.{1,2}/g);\n  if (!match) {\n    return new Uint8Array();\n  }\n\n  // Parse each byte and create a Uint8Array.\n  return new Uint8Array(match.map(byte => parseInt(byte, 16)));\n};\n\n/**\n * https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array/12646864#12646864\n * Randomize array element order in-place.\n * Using Durstenfeld shuffle algorithm.\n */\nexport const shuffleArray = <T>(...arrayIn: T[] | T[][]): T[] => {\n  const array: T[] =\n    arrayIn.length === 1 && Array.isArray(arrayIn[0])\n      ? (arrayIn[0] as T[])\n      : (arrayIn as T[]);\n\n  for (let i = array.length - 1; i > 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1));\n    [array[i], array[j]] = [array[j], array[i]];\n  }\n\n  return array;\n};\n\nexport const toUTF8String = (input: Uint8Array): string => {\n  let TextDecoderConstructor =\n    (window || {}).TextDecoder || require('util').TextDecoder;\n  const textDecoder = new TextDecoderConstructor();\n  return textDecoder.decode(input);\n};\n\nexport const fromUTF8String = (input: string): Uint8Array => {\n  let TextEncoderConstructor =\n    (window || {}).TextEncoder || require('util').TextEncoder;\n  const textEncoder = new TextEncoderConstructor();\n  return textEncoder.encode(input);\n};\n\n/**\n * Convert a base64 string to a Uint8Array.\n */\nexport const fromBase64 = (base64String: string): Uint8Array => {\n  return base64.toByteArray(base64String);\n};\n\nexport const toBase64 = (input: Uint8Array): string => {\n  return base64.fromByteArray(input);\n};\n"
  },
  {
    "path": "src/common/utils/retry.ts",
    "content": "export const sleep = (ms: number) =>\n  new Promise(resolve => setTimeout(resolve, ms));\n\nexport const extractError = (error: any): string => {\n  if (error && typeof error === 'object') {\n    if (error.response) {\n      return extractError(error.response);\n    }\n    if (error.error) {\n      return extractError(error.error);\n    }\n    if (error.message) {\n      return extractError(error.message);\n    }\n    if (error.data) {\n      return extractError(error.data);\n    }\n    if (error.context) {\n      return extractError(error.context);\n    }\n    if (error.statusText) {\n      return extractError(error.statusText);\n    }\n    try {\n      return JSON.stringify(error);\n    } catch (error) {\n      // Ignore JSON error\n    }\n  }\n  // Remove `Error: ` prefix.\n  try {\n    if (typeof error === 'string') {\n      if (error.slice(0, 7).toLowerCase() === 'Error: ') {\n        // tslint:disable-next-line: no-parameter-reassignment\n        error = error.slice(7);\n      }\n      return error;\n    }\n    return JSON.stringify(error);\n  } catch (error) {\n    // Ignore JSON error\n  }\n  return String(error);\n};\n\n// export const onlyMainnet = <T>(x: any, testnet: boolean) =>\n//     testnet ? undefined : x;\n// export const onlyTestnet = <T>(x: any, testnet: boolean) =>\n//     testnet ? x : undefined;\n\nexport const fallback = async <T>(\n  fallbacks: Array<undefined | (() => Promise<T>)>\n): Promise<T> => {\n  let firstError: Error | undefined;\n  for (const fn of fallbacks) {\n    if (!fn) {\n      continue;\n    }\n    try {\n      return await fn();\n    } catch (error) {\n      firstError = firstError || (error as Error);\n    }\n  }\n  throw firstError || new Error('No result returned');\n};\n\nexport const retryNTimes = async <T>(\n  fnCall: () => Promise<T>,\n  retries: number\n) => {\n  let returnError;\n  for (let i = 0; i < retries; i++) {\n    try {\n      return await fnCall();\n    } catch (error) {\n      if (String(error).match(/timeout of .* exceeded/)) {\n        returnError = error;\n      } else {\n        const errorMessage = extractError(error);\n        if (errorMessage) {\n          // tslint:disable-next-line: no-object-mutation\n          error.message += ` (${errorMessage})`;\n        }\n        throw error;\n      }\n    }\n    await sleep(500);\n  }\n  throw returnError;\n};\n"
  },
  {
    "path": "src/common/utils/solana.ts",
    "content": "import * as solanaWeb3 from '@solana/web3.js';\n\nconst provider = (rpcUrl?: string) => {\n  return new solanaWeb3.Connection(rpcUrl as string);\n};\n\nexport default provider;\n"
  },
  {
    "path": "src/common/utils/types.ts",
    "content": "import bitcoinHelper from '../../common/helpers/bitcoinHelper';\nimport ethereumHelper from '../../common/helpers/ethereumHelper';\nimport solanaHelper from '../../common/helpers/solanaHelper';\nimport wavesHelper from '../../common/helpers/wavesHelper';\nimport tronHelper from '../../common/helpers/tronHelper';\n\nexport type Network =\n  | 'ethereum'\n  | 'solana'\n  | 'tron'\n  | 'waves'\n  | 'bitcoin'\n  | 'bitcoin-testnet';\n\nexport type NetworkHelper<T extends Network> = {\n  [key in T]:\n    | typeof bitcoinHelper\n    | typeof ethereumHelper\n    | typeof solanaHelper\n    | typeof wavesHelper\n    | typeof tronHelper;\n};\n\nexport interface TransferPayload {\n  recipientAddress: string;\n  amount: number;\n  network: Network;\n  rpcUrl?: string;\n  apiKey?: string;\n  privateKey: string;\n  gasPrice?: string;\n  tokenAddress?: string;\n  nonce?: number;\n  data?: string;\n  gasLimit?: number;\n  fee?: number; // defaults to 10000\n  feeLimit?: number;\n  subtractFee?: boolean; // defaults to false\n}\n\nexport interface BalancePayload {\n  address: string;\n  network: Network;\n  rpcUrl?: string;\n  apiKey?: string;\n  tokenAddress?: string;\n}\n\nexport interface CreateWalletPayload {\n  derivationPath?: string;\n  cluster?: string;\n  network: Network;\n}\n\nexport interface GetAddressFromPrivateKeyPayload {\n  privateKey: string;\n  network: Network;\n}\n\nexport interface GetTransactionPayload {\n  rpcUrl?: string;\n  apiKey?: string;\n  hash: string;\n  network: Network;\n}\n\nexport interface GenerateWalletFromMnemonicPayload {\n  mnemonic: string;\n  derivationPath?: string;\n  cluster?: string;\n  network: Network;\n}\n\nexport interface IResponse {\n  [key: string]: any;\n}\n\nexport interface GetEncryptedJsonFromPrivateKey {\n  password: string;\n  privateKey: string;\n  network: Network;\n}\n\nexport interface GetWalletFromEncryptedjsonPayload {\n  json: string;\n  password: string;\n  network: Network;\n}\n\nexport interface IGetTokenInfoPayload {\n  network: Network;\n  rpcUrl: string;\n  address: string;\n  cluster?: 'mainnet-beta' | 'testnet' | 'devnet';\n  apiKey?: string;\n}\n\nexport interface ITokenInfo {\n  name: string;\n  symbol: string;\n  address: string;\n  decimals: number;\n  totalSupply: string;\n  logoUrl?: string;\n}\n\nexport interface ISplTokenInfo {\n  chainId: number;\n  address: string;\n  symbol: string;\n  name: string;\n  decimals: number;\n  logoURI?: string;\n  tags: string[];\n  extensions: any;\n}\n\nexport interface ISmartContractCallPayload {\n  rpcUrl: string;\n  apiKey?: string;\n  network: Network;\n  contractAddress: string;\n  method: string;\n  methodType: 'read' | 'write';\n  params: any[];\n  payment?: any[];\n  value?: number;\n  contractAbi?: any[];\n  gasPrice?: string;\n  gasLimit?: number;\n  feeLimit?: number;\n  nonce?: number;\n  privateKey?: string;\n}\n\nexport interface INetworkHelper {\n  getAddressFromPrivateKey: (args: GetAddressFromPrivateKeyPayload) => IResponse;\n  generateWalletFromMnemonic: (args: GenerateWalletFromMnemonicPayload) => IResponse;\n  createWallet: (args: CreateWalletPayload) => IResponse;\n  getBalance: (args: BalancePayload) => Promise<IResponse>;\n  transfer: (args: TransferPayload) => Promise<IResponse>;\n  getTransaction: (args: GetTransactionPayload) => Promise<IResponse>;\n  getEncryptedJsonFromPrivateKey?: (args: GetEncryptedJsonFromPrivateKey) => Promise<IResponse>;\n  getWalletFromEncryptedJson?: (args: GetWalletFromEncryptedjsonPayload) => Promise<IResponse>;\n  getTokenInfo?: (args: IGetTokenInfoPayload) => Promise<IResponse>;\n  smartContractCall?: (args: ISmartContractCallPayload) => Promise<IResponse>;\n}\n"
  },
  {
    "path": "src/common/utils/utxo.ts",
    "content": "import BigNumber from 'bignumber.js';\n\nexport interface UTXO {\n  readonly txHash: string; // hex string without 0x prefix\n  readonly vOut?: number;\n  readonly amount: number; // in sats\n  readonly scriptPubKey?: string; // hex string without 0x prefix\n  readonly confirmations: number;\n  readonly block?: number;\n}\n\n/**\n * sortUTXOs compares two UTXOs by amount, then confirmations and then hash.\n *\n * @example\n * sortUTXOs({amount: 1, confirmations: 1}, {amount: 2, confirmations: 0});\n * // -1, representing that the first parameter should be ordered first.\n *\n * @returns a negative value to represent that a should come before b or a\n * positive value to represent that b should come before a.\n */\nexport const sortUTXOs = (a: UTXO, b: UTXO): number => {\n  // Sort greater values first\n  if (a.amount !== b.amount) {\n    return b.amount - a.amount;\n  }\n  // Sort older UTXOs first\n  if (a.confirmations !== b.confirmations) {\n    return a.confirmations - b.confirmations;\n  }\n  return a.txHash <= b.txHash ? -1 : 1;\n};\n\n/**\n * fixValue turns a readable value, e.g. `0.0001` BTC, to the value in the smallest\n * unit, e.g. `10000` sats.\n *\n * @example\n * fixValue(0.0001, 8) = 10000;\n *\n * @param value Value in the readable representation, e.g. `0.0001` BTC.\n * @param decimals The number of decimals to shift by, e.g. 8.\n */\nexport const fixValue = (value: number, decimals: number) =>\n  new BigNumber(value)\n    .multipliedBy(new BigNumber(10).exponentiatedBy(decimals))\n    .decimalPlaces(0)\n    .toNumber();\n\n/**\n * fixUTXO calls {{fixValue}} on the value of the UTXO.\n */\nexport const fixUTXO = (utxo: UTXO, decimals: number): UTXO => ({\n  ...utxo,\n  amount: fixValue(utxo.amount, decimals),\n});\n\n/**\n * fixUTXOs maps over an array of UTXOs and calls {{fixValue}}.\n */\nexport const fixUTXOs = (utxos: readonly UTXO[], decimals: number) => {\n  return utxos.map(utxo => fixUTXO(utxo, decimals));\n};\n"
  },
  {
    "path": "src/index.ts",
    "content": "export * from './services/wallet';\n"
  },
  {
    "path": "src/services/wallet/index.ts",
    "content": "import * as bip39 from 'bip39';\n\nimport bitcoinHelper from '../../common/helpers/bitcoinHelper';\nimport ethereumHelper from '../../common/helpers/ethereumHelper';\nimport solanaHelper from '../../common/helpers/solanaHelper';\nimport wavesHelper from '../../common/helpers/wavesHelper';\nimport tronHelper from '../../common/helpers/tronHelper';\n\nimport {\n  TransferPayload,\n  BalancePayload,\n  CreateWalletPayload,\n  GetAddressFromPrivateKeyPayload,\n  GenerateWalletFromMnemonicPayload,\n  GetTransactionPayload,\n  GetWalletFromEncryptedjsonPayload,\n  GetEncryptedJsonFromPrivateKey,\n  IGetTokenInfoPayload,\n  ISmartContractCallPayload,\n  Network,\n  INetworkHelper,\n} from '../../common/utils/types';\n\n/**\n * Mapping of supported networks to their corresponding helper implementations.\n */\nconst networkHelpers: Record<Network, INetworkHelper> = {\n  ethereum: ethereumHelper,\n  solana: solanaHelper,\n  tron: tronHelper,\n  waves: wavesHelper,\n  bitcoin: bitcoinHelper,\n  'bitcoin-testnet': bitcoinHelper,\n};\n\n/**\n * Core features available for all networks.\n */\nconst baseFeatures = [\n  'createWallet',\n  'getAddressFromPrivateKey',\n  'generateWalletFromMnemonic',\n  'getBalance',\n  'transfer',\n  'getTransaction',\n];\n\n/**\n * Feature support matrix for each network.\n */\nconst supportedFeatures: Record<Network, string[]> = {\n  ethereum: [\n    ...baseFeatures,\n    'getEncryptedJsonFromPrivateKey',\n    'getWalletFromEncryptedJson',\n    'getTokenInfo',\n    'smartContractCall',\n  ],\n  solana: [...baseFeatures, 'getTokenInfo'],\n  bitcoin: [...baseFeatures],\n  'bitcoin-testnet': [...baseFeatures],\n  waves: [...baseFeatures, 'getTokenInfo', 'smartContractCall'],\n  tron: [...baseFeatures, 'getTokenInfo', 'smartContractCall'],\n};\n\n/**\n * Retrieves the helper for the specified network or throws if unsupported.\n *\n * @param network - The blockchain network identifier.\n * @returns The network helper implementation.\n * @throws {Error} When an unsupported network is provided.\n */\nfunction getNetworkHelper(network: Network): INetworkHelper {\n  const helper = networkHelpers[network];\n  if (!helper) {\n    throw new Error(`Unsupported network: ${network}`);\n  }\n  return helper;\n}\n\n/**\n * Checks if a given feature is supported on the specified network.\n *\n * @param network - The blockchain network identifier.\n * @param feature - The feature to check support for.\n * @returns True if supported; otherwise, false.\n */\nfunction isFeatureSupported(network: Network, feature: string): boolean {\n  return supportedFeatures[network]?.includes(feature) || false;\n}\n\n/**\n * Generates a mnemonic phrase.\n *\n * @param numWords - The number of words in the mnemonic (default is 12).\n * @returns A mnemonic phrase as a string.\n * @remarks The strength is calculated as (numWords / 3) * 32.\n */\nfunction generateMnemonic(numWords: number = 12): string {\n  const strength = (numWords / 3) * 32;\n  return bip39.generateMnemonic(strength);\n}\n\n/**\n * Retrieves the blockchain address from a private key.\n *\n * @param args - The payload containing the private key and network information.\n * @returns The derived blockchain address.\n * @throws {Error} When an unsupported or invalid network is provided.\n * @remarks Supported networks: Ethereum, Solana, and Bitcoin variants.\n */\nfunction getAddressFromPrivateKey(\n  args: GetAddressFromPrivateKeyPayload\n) {\n  if (!isFeatureSupported(args.network, 'getAddressFromPrivateKey')) {\n    throw new Error(\n      `getAddressFromPrivateKey is not supported for ${args.network}`\n    );\n  }\n  const helper = getNetworkHelper(args.network);\n  return helper.getAddressFromPrivateKey(args);\n}\n\n/**\n * Generates a wallet from a mnemonic phrase.\n *\n * @param args - The payload containing the mnemonic, derivation path, and network details.\n * @returns A wallet object generated from the provided mnemonic.\n * @throws {Error} When an unsupported or invalid network is provided.\n * @remarks Supported networks: Ethereum, Solana, Bitcoin variants, and Waves.\n */\nfunction generateWalletFromMnemonic(\n  args: GenerateWalletFromMnemonicPayload\n) {\n  if (!isFeatureSupported(args.network, 'generateWalletFromMnemonic')) {\n    throw new Error(\n      `generateWalletFromMnemonic is not supported for ${args.network}`\n    );\n  }\n  const helper = getNetworkHelper(args.network);\n  return helper.generateWalletFromMnemonic(args);\n}\n\n/**\n * Creates a new wallet for the specified network.\n *\n * @param args - The payload containing network information and configuration parameters\n *               (such as derivation path or cluster details).\n * @returns The newly created wallet.\n * @throws {Error} When an unsupported or invalid network is provided.\n * @remarks Supported networks: Ethereum, Solana, Bitcoin variants, and Waves.\n */\nfunction createWallet(args: CreateWalletPayload) {\n  if (!isFeatureSupported(args.network, 'createWallet')) {\n    throw new Error(`createWallet is not supported for ${args.network}`);\n  }\n  const helper = getNetworkHelper(args.network);\n  return helper.createWallet(args);\n}\n\n/**\n * Retrieves the balance for a given address or wallet.\n *\n * @param args - The payload containing the address and network information.\n * @returns The balance of the specified address or wallet.\n * @throws {Error} When an unsupported or invalid network is provided.\n * @remarks Supported networks: Ethereum, Solana, Bitcoin variants, and Waves.\n */\nasync function getBalance(args: BalancePayload) {\n  if (!isFeatureSupported(args.network, 'getBalance')) {\n    throw new Error(`getBalance is not supported for ${args.network}`);\n  }\n  const helper = getNetworkHelper(args.network);\n  return helper.getBalance(args);\n}\n\n/**\n * Executes a transfer transaction on the specified network.\n *\n * @param args - The payload containing transfer details, including sender, recipient, amount, and network.\n * @returns The result of the transfer operation.\n * @throws {Error} When an unsupported or invalid network is provided.\n * @remarks Supported networks: Ethereum, Solana, Bitcoin variants, and Waves.\n */\nasync function transfer(args: TransferPayload) {\n  if (!isFeatureSupported(args.network, 'transfer')) {\n    throw new Error(`transfer is not supported for ${args.network}`);\n  }\n  const helper = getNetworkHelper(args.network);\n  return helper.transfer(args);\n}\n\n/**\n * Retrieves details of a specific transaction.\n *\n * @param args - The payload containing transaction identification and network details.\n * @returns The transaction details.\n * @throws {Error} When an unsupported or invalid network is provided.\n * @remarks Supported networks: Ethereum, Solana, Bitcoin variants, and Waves.\n */\nasync function getTransaction(args: GetTransactionPayload) {\n  if (!isFeatureSupported(args.network, 'getTransaction')) {\n    throw new Error(`getTransaction is not supported for ${args.network}`);\n  }\n  const helper = getNetworkHelper(args.network);\n  return helper.getTransaction(args);\n}\n\n/**\n * Generates an encrypted JSON wallet from a private key for Ethereum.\n *\n * @param args - The payload containing the private key and network information.\n * @returns A promise that resolves to the encrypted JSON wallet.\n * @throws {Error} When an unsupported or invalid network is provided.\n * @remarks Currently, only the Ethereum network is supported.\n */\nasync function getEncryptedJsonFromPrivateKey(\n  args: GetEncryptedJsonFromPrivateKey\n) {\n  if (!isFeatureSupported(args.network, 'getEncryptedJsonFromPrivateKey')) {\n    throw new Error(\n      `getEncryptedJsonFromPrivateKey is not supported for ${args.network}`\n    );\n  }\n  const helper = getNetworkHelper(args.network);\n  return helper.getEncryptedJsonFromPrivateKey?.(args);\n}\n\n/**\n * Retrieves a wallet from its encrypted JSON representation for Ethereum.\n *\n * @param args - The payload containing the encrypted JSON and network details.\n * @returns A promise that resolves to the decrypted wallet.\n * @throws {Error} When an unsupported or invalid network is provided.\n * @remarks Currently, only the Ethereum network is supported.\n */\nasync function getWalletFromEncryptedJson(\n  args: GetWalletFromEncryptedjsonPayload\n) {\n  if (!isFeatureSupported(args.network, 'getWalletFromEncryptedJson')) {\n    throw new Error(\n      `getWalletFromEncryptedJson is not supported for ${args.network}`\n    );\n  }\n  const helper = getNetworkHelper(args.network);\n  return helper.getWalletFromEncryptedJson?.(args);\n}\n\n/**\n * Fetches token information from the specified network.\n *\n * @param args - The payload containing token and network details.\n * @returns The token information.\n * @throws {Error} When an unsupported or invalid network is provided.\n * @remarks Supported networks: Ethereum, Solana, and Waves.\n */\nasync function getTokenInfo(args: IGetTokenInfoPayload) {\n  if (!isFeatureSupported(args.network, 'getTokenInfo')) {\n    throw new Error(`getTokenInfo is not supported for ${args.network}`);\n  }\n  const helper = getNetworkHelper(args.network);\n  return helper.getTokenInfo?.(args);\n}\n\n/**\n * Executes a smart contract call on the specified network.\n *\n * @param args - The payload containing smart contract call details and network information.\n * @returns The result of the smart contract call.\n * @throws {Error} When an unsupported or invalid network is provided, or if the network is not Ethereum or Waves.\n * @remarks Currently, only Ethereum and Waves networks are supported.\n */\nasync function smartContractCall(args: ISmartContractCallPayload) {\n  if (!isFeatureSupported(args.network, 'smartContractCall')) {\n    throw new Error(`smartContractCall is not supported for ${args.network}`);\n  }\n  const helper = getNetworkHelper(args.network);\n  return helper.smartContractCall?.(args);\n}\n\nexport {\n  generateMnemonic,\n  getAddressFromPrivateKey,\n  generateWalletFromMnemonic,\n  createWallet,\n  getBalance,\n  transfer,\n  getTransaction,\n  getEncryptedJsonFromPrivateKey,\n  getWalletFromEncryptedJson,\n  getTokenInfo,\n  smartContractCall,\n};\n"
  },
  {
    "path": "src/types/declarations.d.ts",
    "content": "declare module '@bitgo/utxo-lib';\n"
  },
  {
    "path": "test/wallet.bitcoin.test.ts",
    "content": "import {\n  generateMnemonic,\n  createWallet,\n  generateWalletFromMnemonic,\n  getAddressFromPrivateKey,\n  getBalance,\n  transfer,\n  getTransaction,\n} from '../src';\n\ndescribe('MultichainCryptoWallet Bitcoin tests', () => {\n  it('generateMnemonic', () => {\n    const mnemonic = generateMnemonic(); // default is 12\n\n    expect(typeof mnemonic).toBe('string');\n  });\n\n  it('createWallet', () => {\n    const wallet = createWallet({\n      derivationPath: \"m/44'/0'/0'/0/0\", // Leave empty to use default derivation path\n      network: 'bitcoin', // 'bitcoin' or 'bitcoin-testnet'\n    });\n\n    expect(typeof wallet).toBe('object');\n  });\n\n  it('generateWalletFromMnemonic', () => {\n    const wallet = generateWalletFromMnemonic({\n      mnemonic:\n        'excess quit spot inspire stereo scrap cave wife narrow era pizza typical',\n      derivationPath: \"m/44'/0'/0'/0/0\", // Leave empty to use default derivation path\n      network: 'bitcoin', // 'bitcoin' or 'bitcoin-testnet'\n    });\n\n    expect(wallet.address).toBe('1NV8FPKDW1hxJFxc2dNVZDAp7iCqxCLeFu');\n    expect(wallet.privateKey).toBe(\n      'KxqTGtCMnX6oL9rxynDKCRJXt64Gm5ame4AEQcYncFhSSUxFBkeJ'\n    );\n    expect(wallet.mnemonic).toBe(\n      'excess quit spot inspire stereo scrap cave wife narrow era pizza typical'\n    );\n  });\n\n  it('getAddressFromPrivateKey', () => {\n    const data = getAddressFromPrivateKey({\n      privateKey: 'KxqTGtCMnX6oL9rxynDKCRJXt64Gm5ame4AEQcYncFhSSUxFBkeJ',\n      network: 'bitcoin', // 'bitcoin' or 'bitcoin-testnet'\n    });\n\n    expect(data.address).toBe('1NV8FPKDW1hxJFxc2dNVZDAp7iCqxCLeFu');\n  });\n\n  it('getBalance', async () => {\n    const data = await getBalance({\n      address: 'bc1q7yh99tgvqnpuzgja4etahdgznxldwu3flrf2fl',\n      network: 'bitcoin', // 'bitcoin' or 'bitcoin-testnet'\n    });\n\n    expect(typeof data.balance).toBe('number');\n  });\n\n  it('Get transaction', async () => {\n    const receipt = await getTransaction({\n      network: 'bitcoin', // 'bitcoin' or 'bitcoin-testnet'\n      hash: 'e499940336c523ed7bb6dce45f3e6fc9a68442cb814ca2f84c2c0c1cdca37c6d',\n    });\n\n    expect(typeof receipt).toBe('object');\n  });\n\n  it('Transfer', async () => {\n    const response = await transfer({\n      privateKey: 'L3tSvMViDit1GSp7mbV2xFCGv6M45kDNuSyNY9xyUxmUPBFrBkc4',\n      recipientAddress: '2NAhbS79dEUeqcnbC27UppwnjoVSwET5bat',\n      amount: 0.0000001,\n      network: 'bitcoin-testnet', // 'bitcoin' or 'bitcoin-testnet'\n      fee: 10000, // Optional param default value is 10000\n      subtractFee: false, // Optional param default value is false\n    });\n\n    expect(typeof response).toBe('object');\n  });\n});\n"
  },
  {
    "path": "test/wallet.ethereum.test.ts",
    "content": "import {\n  createWallet,\n  generateMnemonic,\n  generateWalletFromMnemonic,\n  getAddressFromPrivateKey,\n  getBalance,\n  getTransaction,\n  transfer,\n  getWalletFromEncryptedJson,\n  getEncryptedJsonFromPrivateKey,\n  getTokenInfo,\n  smartContractCall,\n} from '../src';\n\ndescribe('MultichainCryptoWallet Ethereum tests', () => {\n  it('createWallet', () => {\n    const wallet = createWallet({\n      derivationPath: \"m/44'/60'/0'/0/0\", // Leave empty to use default derivation path\n      network: 'ethereum',\n    });\n\n    expect(typeof wallet).toBe('object');\n  });\n\n  it('generateMnemonic', () => {\n    const mnemonic = generateMnemonic(); // default is 12\n\n    expect(typeof mnemonic).toBe('string');\n  });\n\n  it('generateWalletFromMnemonic', () => {\n    const wallet = generateWalletFromMnemonic({\n      mnemonic:\n        'candy maple cake sugar pudding cream honey rich smooth crumble sweet treat',\n      derivationPath: \"m/44'/60'/0'/0/0\", // Leave empty to use default derivation path\n      network: 'ethereum',\n    });\n\n    expect(typeof wallet).toBe('object');\n  });\n\n  it('getAddressFromPrivateKey', () => {\n    const address = getAddressFromPrivateKey({\n      privateKey:\n        '0f9e5c0bee6c7d06b95204ca22dea8d7f89bb04e8527a2c59e134d185d9af8ad',\n      network: 'ethereum',\n    });\n\n    expect(typeof address).toBe('object');\n  });\n\n  it('getBalance ETH balance', async () => {\n    const data = await getBalance({\n      address: '0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22',\n      network: 'ethereum',\n      rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n    });\n\n    expect(typeof data).toBe('object');\n  });\n\n  it('getBalance ERC20 token balance', async () => {\n    const data = await getBalance({\n      address: '0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22',\n      network: 'ethereum',\n      rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n      tokenAddress: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n    });\n\n    expect(typeof data).toBe('object');\n  });\n\n  it('transfer', async () => {\n    const data = await transfer({\n      recipientAddress: '0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22',\n      amount: 0.0001,\n      network: 'ethereum',\n      rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n      privateKey:\n        '0f9e5c0bee6c7d06b95204ca22dea8d7f89bb04e8527a2c59e134d185d9af8ad',\n    });\n\n    const tx = await getTransaction({\n      hash: data.hash,\n      network: 'ethereum',\n      rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n    });\n\n    expect(typeof data).toBe('object');\n    expect(typeof tx).toBe('object');\n  });\n\n  it('transfer ERC20 Token', async () => {\n    const response = await transfer({\n      recipientAddress: '0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22',\n      amount: 0.00001,\n      network: 'ethereum',\n      rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n      privateKey:\n        '0f9e5c0bee6c7d06b95204ca22dea8d7f89bb04e8527a2c59e134d185d9af8ad',\n      tokenAddress: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n    });\n    expect(typeof response).toBe('object');\n  });\n\n  it('Get transaction', async () => {\n    const receipt = await getTransaction({\n      rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n      hash:\n        '0x45aa3634a7a15a7f5e23265fc98b229adba9ffa89ad68c1b48d6b0a27ef51398',\n      network: 'ethereum',\n    });\n\n    expect(typeof receipt).toBe('object');\n  });\n\n  it('encrypts ethereum address privatekey and returns the encrypted json', async () => {\n    const data = await getEncryptedJsonFromPrivateKey({\n      privateKey:\n        '0xdc062e5c5013699c844ee942b517b0ee663bd22786e186e6e437db45e8790d2c',\n      network: 'ethereum',\n      password: 'walletpassword',\n    });\n\n    expect(typeof data).toBe('object');\n    expect(typeof (data && data.json)).toBe('string');\n  });\n\n  it('decrypts ethereum address and returns the wallet details', async () => {\n    const data = await getWalletFromEncryptedJson({\n      json:\n        '{\"address\":\"1c082d1052fb44134a408651c01148adbfcce7fe\",\"id\":\"ca8b45b0-e69d-4e5e-8003-8f3dbb1082cf\",\"version\":3,\"Crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"fe66bd308ad315126ae6f09f0d6599f4\"},\"ciphertext\":\"5f2abe02e49868c36df36f884680b132333e541f89cd7eb375247ff7c8a6ccdd\",\"kdf\":\"scrypt\",\"kdfparams\":{\"salt\":\"2570bf687cb7d9cd694e1c79f6e817c9c66467e81b04013104620670f0664bf5\",\"n\":131072,\"dklen\":32,\"p\":1,\"r\":8},\"mac\":\"35f69fb7283c65d75c000a0c93042c063d2903efe9b9e6f03b05d842f47ed1e9\"}}',\n      network: 'ethereum',\n      password: 'walletpassword',\n    });\n\n    expect(typeof data).toBe('object');\n    expect(typeof (data && data.privateKey)).toBe('string');\n    expect(typeof (data && data.address)).toBe('string');\n  });\n\n  it('get ERC20 token info', async () => {\n    const data = await getTokenInfo({\n      address: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n      network: 'ethereum',\n      rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n    });\n\n    expect(typeof data).toBe('object');\n    expect(typeof (data && data.name)).toBe('string');\n    expect(typeof (data && data.symbol)).toBe('string');\n    expect(typeof (data && data.address)).toBe('string');\n    expect(typeof (data && data.decimals)).toBe('number');\n    expect(typeof (data && data.totalSupply)).toBe('string');\n  });\n\n  it('smart contract call (get token Balance)', async () => {\n    const data = await smartContractCall({\n      rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n      network: 'ethereum',\n      contractAddress: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n      method: 'balanceOf',\n      methodType: 'read',\n      params: ['0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22'],\n    });\n\n    expect(typeof data).toBe('object');\n  });\n\n  it('smart contract call (ERC20 token transfer)', async () => {\n    const data = await smartContractCall({\n      rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n      network: 'ethereum',\n      contractAddress: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n      method: 'transfer',\n      methodType: 'write',\n      params: [\n        '0x2455eC6700092991Ce0782365A89d5Cd89c8Fa22',\n        '1000000000000000000',\n      ],\n      contractAbi: [\n        {\n          constant: false,\n          inputs: [\n            { name: '_to', type: 'address' },\n            { name: '_value', type: 'uint256' },\n          ],\n          name: 'transfer',\n          outputs: [{ name: '', type: 'bool' }],\n          payable: false,\n          stateMutability: 'nonpayable',\n          type: 'function',\n        },\n      ],\n      privateKey:\n        '0f9e5c0bee6c7d06b95204ca22dea8d7f89bb04e8527a2c59e134d185d9af8ad',\n    });\n\n    expect(typeof data).toBe('object');\n  });\n\n  it('smart contract call (get factory Uniswap)', async () => {\n    const data = await smartContractCall({\n      rpcUrl: 'https://ethereum-sepolia-rpc.publicnode.com',\n      network: 'ethereum',\n      contractAddress: '0xeE567Fe1712Faf6149d80dA1E6934E354124CfE3',\n      method: 'factory',\n      methodType: 'read',\n      params: [],\n      contractAbi: [\n        {\n          inputs: [],\n          name: 'factory',\n          outputs: [{ internalType: 'address', name: '', type: 'address' }],\n          stateMutability: 'view',\n          type: 'function',\n        },\n      ],\n    });\n\n    expect(typeof data).toBe('object');\n  });\n});\n"
  },
  {
    "path": "test/wallet.solana.test.ts",
    "content": "import {\n  createWallet,\n  generateMnemonic,\n  generateWalletFromMnemonic,\n  getAddressFromPrivateKey,\n  getBalance,\n  getTransaction,\n  transfer,\n  getTokenInfo,\n} from '../src';\n\ndescribe('MultichainCryptoWallet Solana tests', () => {\n  it('generateMnemonic', () => {\n    const mnemonic = generateMnemonic();\n\n    expect(typeof mnemonic).toBe('string');\n  });\n\n  it('createWallet', () => {\n    const wallet = createWallet({\n      derivationPath: \"m/44'/501'/0'/0'\", // Leave empty to use default derivation path\n      network: 'solana',\n    });\n\n    expect(typeof wallet).toBe('object');\n  });\n\n  it('generateWalletFromMnemonic', () => {\n    const wallet = generateWalletFromMnemonic({\n      mnemonic:\n        'base dry mango subject neither labor portion weekend range couple right document',\n      derivationPath: \"m/44'/501'/0'/0'\", // Leave empty to use default derivation path\n      network: 'solana',\n    });\n\n    expect(typeof wallet).toBe('object');\n  });\n\n  it('getAddressFromPrivateKey', () => {\n    const address = getAddressFromPrivateKey({\n      privateKey:\n        'bXXgTj2cgXMFAGpLHkF5GhnoNeUpmcJDsxXDhXQhQhL2BDpJumdwMGeC5Cs66stsN3GfkMH8oyHu24dnojKbtfp',\n      network: 'solana',\n    });\n\n    expect(typeof address).toBe('object');\n  });\n\n  it('getBalance SOL', async () => {\n    const data = await getBalance({\n      address: '9DSRMyr3EfxPzxZo9wMBPku7mvcazHTHfyjhcfw5yucA',\n      network: 'solana',\n      rpcUrl: 'https://api.devnet.solana.com',\n    });\n\n    expect(typeof data).toBe('object');\n  });\n\n  it('getBalance token', async () => {\n    const data = await getBalance({\n      address: '9DSRMyr3EfxPzxZo9wMBPku7mvcazHTHfyjhcfw5yucA',\n      tokenAddress: '6xRPFqbtpkS7iVd9SysZDXdYn6iWceXF7p3T91N3EcAc',\n      network: 'solana',\n      rpcUrl: 'https://api.devnet.solana.com',\n    });\n\n    expect(typeof data).toBe('object');\n  });\n\n  it('transfer', async () => {\n    const response = await transfer({\n      recipientAddress: '9DSRMyr3EfxPzxZo9wMBPku7mvcazHTHfyjhcfw5yucA',\n      amount: 0.0001,\n      network: 'solana',\n      rpcUrl: 'https://api.devnet.solana.com',\n      privateKey:\n        'qUfgDqNZ8EmZtG7FCdvo8ETTQb8crmzcYUdrVdpjfxZiVkrwSjQ9L2ov55oRt25ZSJXCjHw6hqtKJnxdnoGtp1M',\n    });\n\n    expect(typeof response).toBe('object');\n  });\n\n  it('transfer Token on Solana', async () => {\n    const response = await transfer({\n      recipientAddress: '9DSRMyr3EfxPzxZo9wMBPku7mvcazHTHfyjhcfw5yucA',\n      tokenAddress: '6xRPFqbtpkS7iVd9SysZDXdYn6iWceXF7p3T91N3EcAc',\n      amount: 1,\n      network: 'solana',\n      rpcUrl: 'https://api.devnet.solana.com',\n      privateKey:\n        'qUfgDqNZ8EmZtG7FCdvo8ETTQb8crmzcYUdrVdpjfxZiVkrwSjQ9L2ov55oRt25ZSJXCjHw6hqtKJnxdnoGtp1M',\n    });\n\n    expect(typeof response).toBe('object');\n  });\n\n  it('Get transaction', async () => {\n    const receipt = await getTransaction({\n      rpcUrl: 'https://api.devnet.solana.com',\n      hash:\n        'CkG1ynQ2vN8bmNsBUKG8ix3moUUfELWwd8K2f7mmqDd7LifFFfgyFhBux6t22AncbY4NR3PsEU3DbH7mDBMXWk7',\n      network: 'solana',\n    });\n\n    expect(typeof receipt).toBe('object');\n  });\n\n  it('get SPL token info', async () => {\n    const data = await getTokenInfo({\n      address: '7Xn4mM868daxsGVJmaGrYxg8CZiuqBnDwUse66s5ALmr',\n      network: 'solana',\n      rpcUrl: 'https://api.devnet.solana.com',\n      cluster: 'devnet',\n    });\n\n    expect(typeof data).toBe('object');\n    expect(typeof (data && data.name)).toBe('string');\n    expect(typeof (data && data.symbol)).toBe('string');\n    expect(typeof (data && data.address)).toBe('string');\n    expect(typeof (data && data.decimals)).toBe('number');\n    expect(typeof (data && data.totalSupply)).toBe('string');\n  });\n});\n"
  },
  {
    "path": "test/wallet.tron.test.ts",
    "content": "import {\n  createWallet,\n  generateMnemonic,\n  generateWalletFromMnemonic,\n  getAddressFromPrivateKey,\n  getBalance,\n  transfer,\n  getTransaction,\n  getTokenInfo,\n  smartContractCall,\n} from '../src';\n\ndescribe('MultichainCryptoWallet Tron tests', () => {\n  it('generateMnemonic', () => {\n    const mnemonic = generateMnemonic();\n\n    expect(mnemonic).toBeDefined();\n  });\n\n  it('createWallet', () => {\n    const wallet = createWallet({\n      network: 'tron',\n      derivationPath: \"m/44'/195'/0'/0/0\",\n    });\n    expect(wallet).toBeDefined();\n  });\n\n  it('generateWalletFromMnemonic', () => {\n    const wallet = generateWalletFromMnemonic({\n      mnemonic:\n        'crop traffic saddle addict foster split make luxury scissors daughter bike exit',\n      network: 'tron',\n    });\n    expect(wallet).toBeDefined();\n  });\n\n  it('getAddressFromPrivateKey', () => {\n    const address = getAddressFromPrivateKey({\n      privateKey:\n        'fa01dc6efd5fd64e4897aadf255ae715cf34138c7ada5f6a7efb0bdd0bd9c8c4',\n      network: 'tron',\n    });\n    expect(address).toBeDefined();\n  });\n\n  it('getBalance TRX balance', async () => {\n    const balance = await getBalance({\n      rpcUrl: 'https://nile.trongrid.io',\n      address: 'TDdHvW9nU1JaX1P7roYtDvjErTTR17GPJJ',\n      network: 'tron',\n    });\n    expect(balance).toBeDefined();\n    expect(typeof balance.balance).toBe('string');\n  });\n\n  it('getBalance TRC20 token balance', async () => {\n    const balance = await getBalance({\n      rpcUrl: 'https://nile.trongrid.io',\n      address: 'TEVuGfgLkQCVXs7EtjMiQp3ZSSUkEbNnVS',\n      network: 'tron',\n      tokenAddress: 'TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj',\n    });\n    expect(balance).toBeDefined();\n    expect(typeof balance.balance).toBe('string');\n  });\n\n  it('transfer TRX', async () => {\n    const tx = await transfer({\n      rpcUrl: 'https://nile.trongrid.io',\n      recipientAddress: 'TEVuGfgLkQCVXs7EtjMiQp3ZSSUkEbNnVS',\n      amount: 0.0001,\n      network: 'tron',\n      privateKey:\n        'fa01dc6efd5fd64e4897aadf255ae715cf34138c7ada5f6a7efb0bdd0bd9c8c4',\n    });\n\n    expect(tx).toBeDefined();\n    expect(tx.txid).toBeDefined();\n  });\n\n  it('transfer TRC20 token', async () => {\n    const tx = await transfer({\n      rpcUrl: 'https://nile.trongrid.io',\n      recipientAddress: 'TEVuGfgLkQCVXs7EtjMiQp3ZSSUkEbNnVS',\n      privateKey:\n        'fa01dc6efd5fd64e4897aadf255ae715cf34138c7ada5f6a7efb0bdd0bd9c8c4',\n      amount: 0.1,\n      network: 'tron',\n      tokenAddress: 'TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj',\n    });\n\n    expect(tx).toBeDefined();\n    expect(tx.txid).toBeDefined();\n  });\n\n  it('getTransaction by hash', async () => {\n    const tx = await getTransaction({\n      hash: '34f27486cbe693d5182c4b5e18c1779d918668f86f396ed62a279d8b519b81cc',\n      network: 'tron',\n      rpcUrl: 'https://nile.trongrid.io',\n    });\n\n    expect(tx).toBeDefined();\n  });\n\n  it('getTokenInfo TRC20 token', async () => {\n    const data = await getTokenInfo({\n      address: 'TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj',\n      network: 'tron',\n      rpcUrl: 'https://nile.trongrid.io',\n    });\n\n    expect(typeof data).toBe('object');\n    expect(typeof (data && data.name)).toBe('string');\n    expect(typeof (data && data.symbol)).toBe('string');\n    expect(typeof (data && data.address)).toBe('string');\n    expect(typeof (data && data.decimals)).toBe('number');\n    expect(typeof (data && data.totalSupply)).toBe('string');\n  });\n\n  it('smartContractCall write TRC20 token transfer', async () => {\n    const { data } = await smartContractCall({\n      network: 'tron',\n      rpcUrl: 'https://nile.trongrid.io',\n      contractAddress: 'TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj',\n      method: 'transfer(address,uint256)',\n      methodType: 'write',\n      contractAbi: [\n        {\n          constant: false,\n          inputs: [\n            { name: '_to', type: 'address' },\n            { name: '_value', type: 'uint256' },\n          ],\n          name: 'transfer',\n          outputs: [{ name: '', type: 'bool' }],\n          payable: false,\n          stateMutability: 'nonpayable',\n          type: 'function',\n        },\n      ],\n      params: [\n        { type: 'address', value: 'TEVuGfgLkQCVXs7EtjMiQp3ZSSUkEbNnVS' },\n        { type: 'uint256', value: 1000000 },\n      ],\n      privateKey:\n        'fa01dc6efd5fd64e4897aadf255ae715cf34138c7ada5f6a7efb0bdd0bd9c8c4',\n    });\n\n    expect(data).toBeDefined();\n    expect(data.txid).toBeDefined();\n  });\n\n  it('smartContractCall read TRC20 token balance', async () => {\n    const { data } = await smartContractCall({\n      network: 'tron',\n      rpcUrl: 'https://nile.trongrid.io',\n      contractAddress: 'TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj',\n      method: 'balanceOf',\n      methodType: 'read',\n      contractAbi: [\n        {\n          constant: true,\n          inputs: [{ name: '_owner', type: 'address' }],\n          name: 'balanceOf',\n          outputs: [{ name: 'balance', type: 'uint256' }],\n          payable: false,\n          stateMutability: 'view',\n          type: 'function',\n        },\n      ],\n      params: [\n        { type: 'address', value: 'TEVuGfgLkQCVXs7EtjMiQp3ZSSUkEbNnVS' },\n      ],\n    });\n\n    expect(data).toBeDefined();\n    expect(typeof data).toBe('string');\n  });\n});\n"
  },
  {
    "path": "test/wallet.waves.test.ts",
    "content": "import {\n  generateMnemonic,\n  createWallet,\n  generateWalletFromMnemonic,\n  getBalance,\n  getTransaction,\n  getTokenInfo,\n  transfer,\n  smartContractCall,\n  getAddressFromPrivateKey,\n} from '../src';\n\ndescribe('MultichainCryptoWallet Waves tests', () => {\n  it('generateMnemonic', () => {\n    const mnemonic = generateMnemonic();\n\n    expect(typeof mnemonic).toBe('string');\n  });\n\n  it('createWallet', () => {\n    const wallet = createWallet({ cluster: 'mainnet', network: 'waves' });\n\n    expect(typeof wallet).toBe('object');\n    expect(typeof wallet.address).toBe('string');\n    expect(typeof wallet.mnemonic).toBe('string');\n    expect(typeof wallet.privateKey).toBe('string');\n  });\n\n  it('generateWalletFromMnemonic', () => {\n    const wallet = generateWalletFromMnemonic({\n      mnemonic:\n        'mushroom deliver work spray hire nuclear wrong deputy march six midnight outside motor differ adult',\n      cluster: 'testnet',\n      network: 'waves',\n    });\n\n    expect(typeof wallet).toBe('object');\n    expect(typeof wallet.address).toBe('string');\n    expect(typeof wallet.mnemonic).toBe('string');\n    expect(typeof wallet.privateKey).toBe('string');\n    expect(wallet.address).toBe('3NBE5tjbQn9BHczjD6NSSuFDKVHKsBRzTv9');\n  });\n\n  it('getAddressFromPrivateKey', () => {\n    const address = getAddressFromPrivateKey({\n      privateKey:\n        'mushroom deliver work spray hire nuclear wrong deputy march six midnight outside motor differ adult',\n      network: 'waves',\n    });\n\n    expect(typeof address).toBe('object');\n    expect(typeof address.address).toBe('string');\n    expect(address.address).toBe('3NBE5tjbQn9BHczjD6NSSuFDKVHKsBRzTv9');\n  });\n\n  it('getBalance WAVES', async () => {\n    const data = await getBalance({\n      network: 'waves',\n      address: '3NBE5tjbQn9BHczjD6NSSuFDKVHKsBRzTv9',\n      rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n    });\n\n    expect(typeof data).toBe('object');\n    expect(typeof data.balance).toBe('number');\n  });\n\n  it('getBalance token', async () => {\n    const data = await getBalance({\n      network: 'waves',\n      address: '3NBE5tjbQn9BHczjD6NSSuFDKVHKsBRzTv9',\n      rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n      tokenAddress: '39pnv8FVf3BX3xwtC6uhFxffy2sE3seXCPsf25eNn6qG',\n    });\n\n    expect(typeof data).toBe('object');\n    expect(typeof data.balance).toBe('number');\n  });\n\n  it('transfer WAVES', async () => {\n    const response = await transfer({\n      recipientAddress: '3N4x4ML4D6fiU18Tpw86puRoN78FCTs9VQu',\n      amount: 0.0001,\n      network: 'waves',\n      rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n      privateKey:\n        'mushroom deliver work spray hire nuclear wrong deputy march six midnight outside motor differ adult',\n    });\n\n    expect(typeof response).toBe('object');\n\n    expect(response.assetId).toBe(null);\n    expect(typeof response.id).toBe('string');\n    expect(typeof response.sender).toBe('string');\n    expect(typeof response.recipient).toBe('string');\n  });\n\n  it('transfer Token on Waves', async () => {\n    const response = await transfer({\n      recipientAddress: '3N4x4ML4D6fiU18Tpw86puRoN78FCTs9VQu',\n      tokenAddress: '39pnv8FVf3BX3xwtC6uhFxffy2sE3seXCPsf25eNn6qG',\n      amount: 1,\n      network: 'waves',\n      rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n      privateKey:\n        'mushroom deliver work spray hire nuclear wrong deputy march six midnight outside motor differ adult',\n    });\n\n    expect(typeof response).toBe('object');\n    expect(typeof response.id).toBe('string');\n    expect(typeof response.sender).toBe('string');\n    expect(typeof response.assetId).toBe('string');\n    expect(typeof response.recipient).toBe('string');\n  });\n\n  it('Get transaction', async () => {\n    const receipt = await getTransaction({\n      rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n      hash: 'Barwuj1gCiQ9wCfLQ1nbdz2CSyQXLnRxnDEubtdTwJpd',\n      network: 'waves',\n    });\n\n    expect(typeof receipt).toBe('object');\n    expect(typeof receipt.id).toBe('string');\n    expect(typeof receipt.amount).toBe('number');\n    expect(typeof receipt.height).toBe('number');\n    expect(typeof receipt.sender).toBe('string');\n    expect(typeof receipt.chainId).toBe('number');\n    expect(typeof receipt.recipient).toBe('string');\n    expect(typeof receipt.timestamp).toBe('number');\n    expect(Array.isArray(receipt.proofs)).toBeTruthy();\n  });\n\n  it('get WAVES token info', async () => {\n    const data = await getTokenInfo({\n      network: 'waves',\n      rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n      address: '39pnv8FVf3BX3xwtC6uhFxffy2sE3seXCPsf25eNn6qG',\n    });\n\n    expect(typeof data).toBe('object');\n  });\n\n  it('call (write) to smart contract', async () => {\n    const data = await smartContractCall({\n      network: 'waves',\n      methodType: 'write',\n      rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n      contractAddress: '3N9uzrTiArce1h9VCqK3QUUZmFqBgg5rZSW',\n      privateKey:\n        'mushroom deliver work spray hire nuclear wrong deputy march six midnight outside motor differ adult',\n      method: 'deposit',\n      payment: [{ assetId: null, amount: 1000 }],\n      params: [],\n    });\n\n    expect(typeof data).toBe('object');\n  });\n\n  it('call (read) smart contract data', async () => {\n    const data = await smartContractCall({\n      network: 'waves',\n      methodType: 'read',\n      rpcUrl: 'https://nodes-testnet.wavesnodes.com',\n      contractAddress: '3N9uzrTiArce1h9VCqK3QUUZmFqBgg5rZSW',\n      method: '3N1gVpA5MVY4WsMpzQ6RfcscpDDdqBbLx6n_balance',\n      params: [],\n    });\n\n    expect(typeof data).toBe('object');\n  });\n});\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    /* Visit https://aka.ms/tsconfig.json to read more about this file */\n\n    /* Basic Options */\n    // \"incremental\": true,                         /* Enable incremental compilation */\n    \"target\": \"es5\",                                /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */\n    \"module\": \"ESNext\",                           /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */\n    \"lib\": [\"DOM\",\"ESNext\"],                                   /* Specify library files to be included in the compilation. */\n    // \"allowJs\": true,                             /* Allow javascript files to be compiled. */\n    // \"checkJs\": true,                             /* Report errors in .js files. */\n    \"jsx\": \"react\",                           /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */\n    \"declaration\": true,                         /* Generates corresponding '.d.ts' file. */\n    // \"declarationMap\": true,                      /* Generates a sourcemap for each corresponding '.d.ts' file. */\n    \"sourceMap\": true,                           /* Generates corresponding '.map' file. */\n    // \"outFile\": \"./\",                             /* Concatenate and emit output to single file. */\n    // \"outDir\": \"./\",                              /* Redirect output structure to the directory. */\n    \"rootDir\": \"./src\",                             /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */\n    // \"composite\": true,                           /* Enable project compilation */\n    // \"tsBuildInfoFile\": \"./\",                     /* Specify file to store incremental compilation information */\n    // \"removeComments\": true,                      /* Do not emit comments to output. */\n    \"noEmit\": true,                              /* Do not emit outputs. */\n    \"importHelpers\": true,                       /* Import emit helpers from 'tslib'. */\n    // \"downlevelIteration\": true,                  /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */\n    // \"isolatedModules\": true,                     /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */\n\n    /* Strict Type-Checking Options */\n    \"strict\": true,                                 /* Enable all strict type-checking options. */\n    // \"noImplicitAny\": true,                       /* Raise error on expressions and declarations with an implied 'any' type. */\n    // \"strictNullChecks\": true,                    /* Enable strict null checks. */\n    // \"strictFunctionTypes\": true,                 /* Enable strict checking of function types. */\n    // \"strictBindCallApply\": true,                 /* Enable strict 'bind', 'call', and 'apply' methods on functions. */\n    // \"strictPropertyInitialization\": true,        /* Enable strict checking of property initialization in classes. */\n    // \"noImplicitThis\": true,                      /* Raise error on 'this' expressions with an implied 'any' type. */\n    // \"alwaysStrict\": true,                        /* Parse in strict mode and emit \"use strict\" for each source file. */\n\n    /* Additional Checks */\n    \"noUnusedLocals\": true,                      /* Report errors on unused locals. */\n    \"noUnusedParameters\": true,                  /* Report errors on unused parameters. */\n    \"noImplicitReturns\": true,                   /* Report error when not all code paths in function return a value. */\n    \"noFallthroughCasesInSwitch\": true,          /* Report errors for fallthrough cases in switch statement. */\n    // \"noUncheckedIndexedAccess\": true,            /* Include 'undefined' in index signature results */\n    // \"noImplicitOverride\": true,                  /* Ensure overriding members in derived classes are marked with an 'override' modifier. */\n    // \"noPropertyAccessFromIndexSignature\": true,  /* Require undeclared properties from index signatures to use element accesses. */\n\n    /* Module Resolution Options */\n    \"moduleResolution\": \"node\",                  /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */\n    // \"baseUrl\": \"./\",                             /* Base directory to resolve non-absolute module names. */\n    // \"paths\": {},                                 /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */\n    // \"rootDirs\": [],                              /* List of root folders whose combined content represents the structure of the project at runtime. */\n    // \"typeRoots\": [],                             /* List of folders to include type definitions from. */\n    // \"types\": [],                                 /* Type declaration files to be included in compilation. */\n    // \"allowSyntheticDefaultImports\": true,        /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */\n    \"esModuleInterop\": true,                        /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */\n    // \"preserveSymlinks\": true,                    /* Do not resolve the real path of symlinks. */\n    // \"allowUmdGlobalAccess\": true,                /* Allow accessing UMD globals from modules. */\n\n    /* Source Map Options */\n    // \"sourceRoot\": \"\",                            /* Specify the location where debugger should locate TypeScript files instead of source locations. */\n    // \"mapRoot\": \"\",                               /* Specify the location where debugger should locate map files instead of generated locations. */\n    // \"inlineSourceMap\": true,                     /* Emit a single file with source maps instead of having a separate file. */\n    // \"inlineSources\": true,                       /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */\n\n    /* Experimental Options */\n    // \"experimentalDecorators\": true,              /* Enables experimental support for ES7 decorators. */\n    // \"emitDecoratorMetadata\": true,               /* Enables experimental support for emitting type metadata for decorators. */\n\n    /* Advanced Options */\n    \"skipLibCheck\": true,                           /* Skip type checking of declaration files. */\n    \"forceConsistentCasingInFileNames\": true ,       /* Disallow inconsistently-cased references to the same file. */\n    \"resolveJsonModule\": true,\n    \"useUnknownInCatchVariables\": false,           /* Allow using unknown as a type in a catch clause. */\n  },\n  \"include\": [\"src\", \"types\"],\n}\n"
  }
]