├── .eslint.js ├── .eslintrc.js ├── .gitattributes ├── .github ├── CODEOWNERS └── workflows │ ├── build.yml │ └── codeql.yml ├── .gitignore ├── LICENSE ├── README.md ├── lerna.json ├── package.json ├── packages ├── chains │ ├── chains-bitcoin │ │ ├── README.md │ │ ├── package.json │ │ ├── src │ │ │ ├── APIs │ │ │ │ ├── API.ts │ │ │ │ ├── bitcoinDotCom.ts │ │ │ │ ├── blockbook.ts │ │ │ │ ├── blockchain.ts │ │ │ │ ├── blockchair.ts │ │ │ │ ├── blockstream.ts │ │ │ │ ├── insight.ts │ │ │ │ └── sochain.ts │ │ │ ├── base.ts │ │ │ ├── bitcoin.ts │ │ │ ├── bitcoincash.ts │ │ │ ├── declarations │ │ │ │ └── declarations.d.ts │ │ │ ├── digibyte.ts │ │ │ ├── dogecoin.ts │ │ │ ├── index.ts │ │ │ ├── script │ │ │ │ ├── index.ts │ │ │ │ ├── opcodes.ts │ │ │ │ └── script.ts │ │ │ ├── utils │ │ │ │ ├── bchaddrjs.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils.ts │ │ │ └── zcash.ts │ │ ├── test │ │ │ ├── addressValidation.spec.ts │ │ │ ├── bch.spec.ts │ │ │ ├── broadcastTransaction.spec.ts │ │ │ ├── btcAndZec.spec.ts │ │ │ ├── digibyte.spec.ts │ │ │ ├── getUTXOs.spec.ts │ │ │ ├── script.spec.ts │ │ │ └── utils.spec.ts │ │ ├── tsconfig.json │ │ └── tsconfig.module.json │ ├── chains-ethereum │ │ ├── README.md │ │ ├── package.json │ │ ├── src │ │ │ ├── arbitrum.ts │ │ │ ├── avalanche.ts │ │ │ ├── base.ts │ │ │ ├── bsc.ts │ │ │ ├── catalog.ts │ │ │ ├── contracts │ │ │ │ ├── ABIs │ │ │ │ │ ├── BasicBridge.json │ │ │ │ │ ├── ERC20.json │ │ │ │ │ ├── GatewayRegistryV2.json │ │ │ │ │ ├── LockGatewayV3.json │ │ │ │ │ ├── MintGatewayV3.json │ │ │ │ │ └── TransferWithLog.json │ │ │ │ ├── index.ts │ │ │ │ └── typechain │ │ │ │ │ ├── BasicBridge.ts │ │ │ │ │ ├── ERC20.ts │ │ │ │ │ ├── GatewayRegistryV2.ts │ │ │ │ │ ├── LockGatewayV3.ts │ │ │ │ │ ├── MintGatewayV3.ts │ │ │ │ │ ├── TransferWithLog.ts │ │ │ │ │ └── common.ts │ │ │ ├── ethereum.ts │ │ │ ├── fantom.ts │ │ │ ├── goerli.ts │ │ │ ├── index.ts │ │ │ ├── kava.ts │ │ │ ├── moonbeam.ts │ │ │ ├── optimism.ts │ │ │ ├── polygon.ts │ │ │ └── utils │ │ │ │ ├── abi.ts │ │ │ │ ├── errors.ts │ │ │ │ ├── evmTxSubmitter.ts │ │ │ │ ├── gatewayRegistry.ts │ │ │ │ ├── generic.ts │ │ │ │ ├── payloads │ │ │ │ ├── evmAddressPayload.ts │ │ │ │ ├── evmApprovalPayload.ts │ │ │ │ ├── evmContractPayload.ts │ │ │ │ ├── evmNoncePayload.ts │ │ │ │ ├── evmParams.ts │ │ │ │ └── evmTxPayload.ts │ │ │ │ └── types.ts │ │ ├── test │ │ │ ├── abi.spec.ts │ │ │ ├── assets.spec.ts │ │ │ ├── initialization.spec.ts │ │ │ ├── logs.spec.ts │ │ │ └── utils.spec.ts │ │ ├── tsconfig.json │ │ └── tsconfig.module.json │ ├── chains-filecoin │ │ ├── README.md │ │ ├── package.json │ │ ├── src │ │ │ ├── filecoin.ts │ │ │ ├── index.ts │ │ │ └── utils │ │ │ │ ├── declarations.d.ts │ │ │ │ ├── deposit.ts │ │ │ │ ├── filfox.ts │ │ │ │ ├── lotus.ts │ │ │ │ └── utils.ts │ │ ├── test │ │ │ ├── explorers.spec.ts │ │ │ └── index.spec.ts │ │ ├── tsconfig.json │ │ └── tsconfig.module.json │ ├── chains-solana │ │ ├── README.md │ │ ├── package.json │ │ ├── src │ │ │ ├── declarations │ │ │ │ └── declarations.d.ts │ │ │ ├── index.ts │ │ │ ├── layouts.ts │ │ │ ├── networks.ts │ │ │ ├── solana.ts │ │ │ ├── solanaTxSubmitter.ts │ │ │ ├── types │ │ │ │ └── types.ts │ │ │ ├── utils.ts │ │ │ ├── utils │ │ │ │ └── associatedTokenAccount.ts │ │ │ └── wallet.ts │ │ ├── test │ │ │ ├── solana.spec.ts │ │ │ └── utils.spec.ts │ │ ├── tsconfig.json │ │ └── tsconfig.module.json │ ├── chains-terra │ │ ├── README.md │ │ ├── package.json │ │ ├── src │ │ │ ├── api │ │ │ │ ├── stakeId.ts │ │ │ │ ├── terraDev.ts │ │ │ │ └── types.ts │ │ │ ├── index.ts │ │ │ ├── terra.ts │ │ │ └── utils.ts │ │ ├── test │ │ │ ├── index.spec.ts │ │ │ └── utils.spec.ts │ │ ├── tsconfig.json │ │ └── tsconfig.module.json │ └── chains │ │ ├── README.md │ │ ├── package.json │ │ ├── src │ │ ├── declarations │ │ │ └── declarations.d.ts │ │ └── index.ts │ │ ├── test │ │ ├── index.spec.ts │ │ └── utils.spec.ts │ │ ├── tsconfig.json │ │ └── tsconfig.module.json ├── mock-provider │ ├── README.md │ ├── package.json │ ├── src │ │ ├── MockChain.ts │ │ ├── MockProvider.ts │ │ ├── index.ts │ │ └── utils.ts │ ├── test │ │ └── index.spec.ts │ ├── tsconfig.json │ └── tsconfig.module.json ├── provider │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── methods │ │ │ ├── index.ts │ │ │ ├── ren_queryBlock.ts │ │ │ ├── ren_queryBlockState.ts │ │ │ ├── ren_queryConfig.ts │ │ │ ├── ren_submitGateway.ts │ │ │ └── ren_submitTx.ts │ │ ├── provider.ts │ │ ├── rpc │ │ │ └── jsonRpc.ts │ │ ├── rpcUrls.ts │ │ ├── types │ │ │ └── core.ts │ │ └── unmarshal.ts │ ├── test │ │ ├── mockResponses │ │ │ ├── ren_queryBlockState.json │ │ │ ├── ren_queryState.json │ │ │ └── selectPublicKey.json │ │ ├── pack.spec.ts │ │ └── selectPublicKey.spec.ts │ ├── tsconfig.json │ └── tsconfig.module.json ├── ren │ ├── README.md │ ├── package.json │ ├── src │ │ ├── gateway.ts │ │ ├── gatewayTransaction.ts │ │ ├── index.ts │ │ ├── params.ts │ │ ├── renVMTxSubmitter.ts │ │ └── utils │ │ │ ├── config.ts │ │ │ ├── defaultTransactionHandler.ts │ │ │ ├── fees.ts │ │ │ ├── inputAndOutputTypes.ts │ │ │ └── transactionEmitter.ts │ ├── test │ │ └── index.spec.ts │ ├── tsconfig.json │ └── tsconfig.module.json └── utils │ ├── README.md │ ├── package.json │ ├── src │ ├── common.ts │ ├── errors.ts │ ├── index.ts │ ├── internal │ │ ├── assert.ts │ │ ├── common.ts │ │ ├── extractError.ts │ │ ├── hashes.ts │ │ ├── index.ts │ │ ├── network.ts │ │ └── sleep.ts │ ├── libraries │ │ ├── pack │ │ │ ├── README.md │ │ │ ├── binaryMarshal.ts │ │ │ ├── common.ts │ │ │ ├── index.ts │ │ │ ├── types.ts │ │ │ └── unmarshal.ts │ │ └── promiEvent │ │ │ ├── LICENSE │ │ │ └── index.ts │ ├── pack │ │ └── README.md │ ├── renVMHashes.ts │ ├── txSubmitter.ts │ └── types │ │ ├── chain.ts │ │ ├── eventEmitter.ts │ │ ├── index.ts │ │ ├── logger.ts │ │ ├── renNetwork.ts │ │ ├── shard.ts │ │ └── types.ts │ ├── test │ ├── assert.spec.ts │ ├── common.spec.ts │ ├── hash.spec.ts │ ├── marshalPack.spec.ts │ ├── renVMHashes.spec.ts │ ├── signatureUtils.spec.ts │ ├── txHash.spec.ts │ └── workingtx.spec.ts │ ├── tsconfig.json │ └── tsconfig.module.json ├── test ├── gateway.spec.ts ├── index.ts ├── quickstart.spec.ts ├── simple.spec.ts └── utils │ ├── defaultGatewayHandler.ts │ └── testUtils.ts ├── tsconfig.json ├── webpack.config.js └── yarn.lock /.eslint.js: -------------------------------------------------------------------------------- 1 | .eslintrc.js -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @jazg @tok-kkk 2 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | matrix: 10 | node-version: [14.x, 16.x, 18.x] 11 | os: [ubuntu-latest, windows-latest] 12 | name: Build on ${{ matrix.os }} with Node.js ${{ matrix.node-version }} 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Setup Node.js 16 | uses: actions/setup-node@v2 17 | with: 18 | node-version: ${{ matrix.node-version }} 19 | cache: "yarn" 20 | - name: Install dependencies 21 | run: | 22 | yarn install --network-concurrency 1 23 | - name: Lint 24 | run: | 25 | yarn lint 26 | - name: Build 27 | run: | 28 | yarn build 29 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master, release/* ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '25 6 * * 6' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Any file in src or build will get pushed to npm 2 | !src 3 | build 4 | 5 | # Environment variables/secrets 6 | *.env 7 | 8 | # Typedoc output 9 | docs 10 | 11 | # NPM/Yarn files 12 | node_modules 13 | package-lock.json 14 | .npmrc 15 | .yarnrc 16 | .yarn 17 | lerna-debug.log 18 | yarn-error.log 19 | .cache 20 | 21 | # Misc. logs 22 | *.log 23 | 24 | # Coverage 25 | .nyc_output 26 | coverage 27 | reports 28 | 29 | # IDE/OS specific 30 | .vscode 31 | .idea 32 | .dir-locals.el 33 | .editorconfig 34 | .DS_Store 35 | 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Ren Project 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `🛠️ ren-js` 2 | 3 | [![Version](https://img.shields.io/npm/v/@renproject/ren)](https://www.npmjs.com/package/@renproject/ren) 4 | 5 | The official Javascript SDK for interacting with [RenVM](https://renproject.io). 6 | 7 | ```sh 8 | yarn add @renproject/ren @renproject/chains 9 | ``` 10 | 11 | ## Docs 12 | 13 | See [Ren Client Docs](https://renproject.github.io/ren-client-docs/ren-js/) 14 | 15 | ## RenJS v3 16 | 17 | RenJS v3 is currently available as an alpha release: 18 | 19 | ```sh 20 | yarn add @renproject/ren @renproject/chains 21 | ``` 22 | 23 | [RenJS v3 Docs](https://renproject.github.io/ren-client-docs/ren-js/ren-js-v3) (WIP) 24 | 25 | ## Changelog 26 | 27 | See the [Releases page](https://github.com/renproject/ren-js/releases). 28 | 29 | ## Package list 30 | 31 | - [`ren`](./packages/ren) - Javascript SDK for interacting with RenVM. 32 | - [`provider`](./packages/provider) - JSON-RPC provider. 33 | - [`utils`](./packages/utils) - Helper functions used by the other packages. 34 | - [`mock-provider`](./packages/mock-provider) - For testing locally with Ganache/Hardhat 35 | - chains, for enabling support for blockchains and assets: 36 | - - [`chains-bitcoin`](./packages/chains/chains-bitcoin) - Bitcoin and Bitcoin forks 37 | - - [`chains-ethereum`](./packages/chains/chains-ethereum) - Ethereum and other EVM chains 38 | - - [`chains-terra`](./packages/chains/chains-terra) - Terra/LUNA 39 | - - [`chains-filecoin`](./packages/chains/chains-filecoin) - Filecoin 40 | - - [`chains-solana`](./packages/chains/chains-solana) - Solana 41 | - - [`chains`](./packages/chains/chains) - Combines all of the above chains into one package 42 | 43 |
44 | 45 |
46 | Developer docs - click to expand 47 | 48 |
49 | 50 | ## Developing locally 51 | 52 | ```sh 53 | # Clone repository 54 | git clone git@github.com:renproject/ren-js.git && cd ren-js 55 | 56 | # Install dependencies 57 | yarn 58 | 59 | # Build every package 60 | yarn run build 61 | ``` 62 | 63 | ## Linking 64 | 65 | If you want to use your local version of RenJS in another repository, run 66 | 67 | ```sh 68 | # In the ren-js repository 69 | yarn run link:all 70 | ``` 71 | 72 | You can now link it to any other local repository by running: 73 | 74 | ```sh 75 | # In other local repositories 76 | yarn link @renproject/ren @renproject/chains @renproject/utils @renproject/provider 77 | ``` 78 | 79 | ## Running tests 80 | 81 | You'll need to: 82 | 83 | 1. Generate a mnemonic and send ETH (goerli for testnet) (path: `m/44'/60'/0'/0/`). 84 | - `let w = require("ethers").Wallet.createRandom(); console.debug(w.address, w.mnemonic.phrase);` 85 | 2. Generate a private key and send testnet crypto funds. 86 | - `require("send-crypto").newPrivateKey();` 87 | 3. Optionally generate an [Infura](https://infura.io) API key. 88 | 89 | Create a `.env` file which contains the following exported variables: 90 | 91 | ```sh 92 | export MNEMONIC="your mnemonic here" 93 | export TESTNET_PRIVATE_KEY="your bitcoin private key" 94 | 95 | # Optional 96 | export INFURA_KEY="your infura key" 97 | ``` 98 | 99 | To run the tests: 100 | 101 | ```sh 102 | yarn run test 103 | ``` 104 | 105 |
106 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "useWorkspaces": true, 4 | "version": "3.6.0" 5 | } 6 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/README.md: -------------------------------------------------------------------------------- 1 | # `@renproject/chains-bitcoin` 2 | 3 | This package is part of [RenJS](https://github.com/renproject.ren-js). 4 | 5 | See [`@renproject/chains-bitcoin` docs](https://renproject.github.io/ren-js-v3-docs/modules/_renproject_chains_bitcoin.html) 6 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@renproject/chains-bitcoin", 3 | "version": "3.6.0", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/renproject/ren-js.git" 7 | }, 8 | "publishConfig": { 9 | "access": "public", 10 | "directory": "build" 11 | }, 12 | "author": "Ren", 13 | "license": "MIT", 14 | "bugs": { 15 | "url": "https://github.com/renproject/ren-js/issues" 16 | }, 17 | "main": "./build/index.js", 18 | "typings": "./build/index.d.ts", 19 | "module": "./build/module/index.js", 20 | "scripts": { 21 | "clean": "yarn rimraf ./build ./node_modules", 22 | "link": "yarn build:link && cd build && yarn link", 23 | "unlink": "yarn unlink", 24 | "build": "run-s build:*", 25 | "build:main": "tsc -p tsconfig.json", 26 | "build:module": "tsc -p tsconfig.module.json", 27 | "build:link": "cp package.json build && cp README.md build && sed -i.tmp 's/\\/build\\//\\//' ./build/package.json && rm ./build/package.json.tmp", 28 | "prettier": "yarn fix:prettier", 29 | "lint": "run-s lint:*", 30 | "lint:eslint": "eslint --config ../../../.eslintrc.js src", 31 | "lint:prettier": "prettier --check \"./(src|test)/**/*.ts*\"", 32 | "fix": "run-s fix:*", 33 | "fix:eslint": "yarn lint:eslint --fix", 34 | "fix:prettier": "prettier --write './(src|test)/**/*.ts*'", 35 | "test": "run-s test:* lint", 36 | "test:unit": "nyc ../../../node_modules/ts-mocha/bin/ts-mocha --bail --sort --exit --timeout 180000 --paths -p ./tsconfig.json ./test/*.spec.ts ./test/**/*.spec.ts --ignore ./test/testutils/chai.d.ts", 37 | "watch": "run-s build:main && run-s \"build:main -- -w\"", 38 | "cov": "run-s build:main test:unit cov:html && echo \"\n\nTo see coverage, run: 'open coverage/index.html'\n\n\"", 39 | "cov:html": "nyc report --reporter=html", 40 | "cov:send": "nyc report --reporter=lcov && codecov", 41 | "cov:check": "nyc report && nyc check-coverage --lines 0 --functions 0 --branches 0", 42 | "prepare": "yarn build" 43 | }, 44 | "dependencies": { 45 | "@noble/hashes": "1.1.2", 46 | "@renproject/utils": "^3.6.0", 47 | "@types/bchaddrjs": "0.4.0", 48 | "@types/bs58": "4.0.1", 49 | "@types/bs58check": "2.1.0", 50 | "@types/cashaddrjs": "0.3.0", 51 | "bchaddrjs": "0.5.2", 52 | "bech32": "2.0.0", 53 | "bignumber.js": "9.0.2", 54 | "bs58": "5.0.0", 55 | "bs58check": "2.1.2", 56 | "cashaddrjs": "0.4.4", 57 | "qs": "6.11.0", 58 | "wallet-address-validator": "0.2.4" 59 | }, 60 | "nyc": { 61 | "extends": "@istanbuljs/nyc-config-typescript", 62 | "exclude": [ 63 | "**/*.d.ts", 64 | "**/*.spec.js" 65 | ], 66 | "include": [ 67 | "src" 68 | ] 69 | }, 70 | "prettier": { 71 | "printWidth": 80, 72 | "semi": true, 73 | "singleQuote": false, 74 | "tabWidth": 4, 75 | "trailingComma": "all", 76 | "endOfLine": "lf", 77 | "arrowParens": "always" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/src/bitcoin.ts: -------------------------------------------------------------------------------- 1 | import { RenNetwork } from "@renproject/utils"; 2 | 3 | import { Blockchain, BlockchainNetwork } from "./APIs/blockchain"; 4 | import { Blockchair } from "./APIs/blockchair"; 5 | import { Blockstream } from "./APIs/blockstream"; 6 | import { SoChain } from "./APIs/sochain"; 7 | import { BitcoinBaseChain } from "./base"; 8 | import { 9 | BitcoinNetworkConfig, 10 | BitcoinNetworkConfigMap, 11 | BitcoinNetworkInput, 12 | } from "./utils/types"; 13 | import { 14 | resolveBitcoinNetworkConfig, 15 | StandardBitcoinExplorer, 16 | } from "./utils/utils"; 17 | 18 | const BitcoinMainnet: BitcoinNetworkConfig = { 19 | label: "Bitcoin", 20 | 21 | selector: "Bitcoin", 22 | 23 | nativeAsset: { 24 | name: "Bitcoin", 25 | symbol: "BTC", 26 | decimals: 8, 27 | }, 28 | averageConfirmationTime: 60 * 10, 29 | 30 | explorer: StandardBitcoinExplorer("https://live.blockcypher.com/btc/"), 31 | p2shPrefix: new Uint8Array([0x05]), 32 | providers: [ 33 | new Blockstream(), 34 | new Blockchair(), 35 | { api: new SoChain(), priority: 15 }, 36 | { api: new Blockchain(BlockchainNetwork.Bitcoin), priority: 20 }, 37 | ], 38 | // validateAddress: (address: string) => 39 | // validateAddress(address, "BTC", "mainnet"), 40 | }; 41 | 42 | const BitcoinTestnet: BitcoinNetworkConfig = { 43 | label: "Bitcoin Testnet", 44 | 45 | selector: "Bitcoin", 46 | 47 | nativeAsset: { 48 | name: "Testnet Bitcoin", 49 | symbol: "BTC", 50 | decimals: 8, 51 | }, 52 | averageConfirmationTime: 60 * 10, 53 | 54 | isTestnet: true, 55 | explorer: StandardBitcoinExplorer( 56 | "https://live.blockcypher.com/btc-testnet/", 57 | ), 58 | p2shPrefix: new Uint8Array([0xc4]), 59 | providers: [ 60 | new Blockstream({ testnet: true }), 61 | { api: new Blockchain(BlockchainNetwork.BitcoinTestnet), priority: 20 }, 62 | // new Blockchair(BlockchairNetwork.BITCOIN_TESTNET), 63 | // { api: new SoChain(SoChainNetwork.BTCTEST), priority: 15 }, 64 | ], 65 | // validateAddress: (address: string) => 66 | // validateAddress(address, "BTC", "testnet"), 67 | }; 68 | 69 | /** 70 | * The Bitcoin class adds support for the asset BTC. 71 | */ 72 | export class Bitcoin extends BitcoinBaseChain { 73 | public static chain = "Bitcoin" as const; 74 | public static configMap: BitcoinNetworkConfigMap = { 75 | [RenNetwork.Mainnet]: BitcoinMainnet, 76 | [RenNetwork.Testnet]: BitcoinTestnet, 77 | }; 78 | public configMap = Bitcoin.configMap; 79 | 80 | public static assets = { 81 | [RenNetwork.Mainnet]: { 82 | BTC: "BTC", 83 | }, 84 | [RenNetwork.Testnet]: { 85 | BTC: "BTC", 86 | }, 87 | }; 88 | 89 | public assets: 90 | | typeof Bitcoin.assets[RenNetwork.Mainnet] 91 | | typeof Bitcoin.assets[RenNetwork.Testnet]; 92 | 93 | public constructor({ network }: { network: BitcoinNetworkInput }) { 94 | super({ 95 | network: resolveBitcoinNetworkConfig(Bitcoin.configMap, network), 96 | }); 97 | this.assets = 98 | Bitcoin.assets[ 99 | this.network.isTestnet ? RenNetwork.Testnet : RenNetwork.Mainnet 100 | ]; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/src/declarations/declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module "wallet-address-validator"; 2 | declare module "wallet-address-validator/src/bitcoin_validator"; 3 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./base"; 2 | export * from "./bitcoin"; 3 | export * from "./bitcoincash"; 4 | export * from "./digibyte"; 5 | export * from "./dogecoin"; 6 | export * from "./utils/types"; 7 | export * from "./zcash"; 8 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/src/script/index.ts: -------------------------------------------------------------------------------- 1 | import { Script } from "./script"; 2 | 3 | const gatewayScript = (gGubKeyHash: Uint8Array, gHash: Uint8Array): Script => 4 | new Script() 5 | .addData(gHash) 6 | .addOp(Script.OP.OP_DROP) 7 | .addOp(Script.OP.OP_DUP) 8 | .addOp(Script.OP.OP_HASH160) 9 | .addData(gGubKeyHash) 10 | .addOp(Script.OP.OP_EQUALVERIFY) 11 | .addOp(Script.OP.OP_CHECKSIG); 12 | 13 | export const createAddressArray = ( 14 | gGubKeyHash: Uint8Array, 15 | gHash: Uint8Array, 16 | prefix: Uint8Array, 17 | ): Uint8Array => gatewayScript(gGubKeyHash, gHash).toAddress(prefix); 18 | 19 | export const calculatePubKeyScript = ( 20 | gGubKeyHash: Uint8Array, 21 | gHash: Uint8Array, 22 | ): Uint8Array => gatewayScript(gGubKeyHash, gHash).toScriptHashOut(); 23 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/src/script/opcodes.ts: -------------------------------------------------------------------------------- 1 | export enum Opcode { 2 | OP_FALSE = 0, 3 | OP_0 = 0, 4 | OP_PUSHDATA1 = 76, 5 | OP_PUSHDATA2 = 77, 6 | OP_PUSHDATA4 = 78, 7 | OP_1NEGATE = 79, 8 | OP_RESERVED = 80, 9 | OP_TRUE = 81, 10 | OP_1 = 81, 11 | OP_2 = 82, 12 | OP_3 = 83, 13 | OP_4 = 84, 14 | OP_5 = 85, 15 | OP_6 = 86, 16 | OP_7 = 87, 17 | OP_8 = 88, 18 | OP_9 = 89, 19 | OP_10 = 90, 20 | OP_11 = 91, 21 | OP_12 = 92, 22 | OP_13 = 93, 23 | OP_14 = 94, 24 | OP_15 = 95, 25 | OP_16 = 96, 26 | OP_NOP = 97, 27 | OP_VER = 98, 28 | OP_IF = 99, 29 | OP_NOTIF = 100, 30 | OP_VERIF = 101, 31 | OP_VERNOTIF = 102, 32 | OP_ELSE = 103, 33 | OP_ENDIF = 104, 34 | OP_VERIFY = 105, 35 | OP_RETURN = 106, 36 | OP_TOALTSTACK = 107, 37 | OP_FROMALTSTACK = 108, 38 | OP_2DROP = 109, 39 | OP_2DUP = 110, 40 | OP_3DUP = 111, 41 | OP_2OVER = 112, 42 | OP_2ROT = 113, 43 | OP_2SWAP = 114, 44 | OP_IFDUP = 115, 45 | OP_DEPTH = 116, 46 | OP_DROP = 117, 47 | OP_DUP = 118, 48 | OP_NIP = 119, 49 | OP_OVER = 120, 50 | OP_PICK = 121, 51 | OP_ROLL = 122, 52 | OP_ROT = 123, 53 | OP_SWAP = 124, 54 | OP_TUCK = 125, 55 | OP_CAT = 126, 56 | OP_SUBSTR = 127, 57 | OP_LEFT = 128, 58 | OP_RIGHT = 129, 59 | OP_SIZE = 130, 60 | OP_INVERT = 131, 61 | OP_AND = 132, 62 | OP_OR = 133, 63 | OP_XOR = 134, 64 | OP_EQUAL = 135, 65 | OP_EQUALVERIFY = 136, 66 | OP_RESERVED1 = 137, 67 | OP_RESERVED2 = 138, 68 | OP_1ADD = 139, 69 | OP_1SUB = 140, 70 | OP_2MUL = 141, 71 | OP_2DIV = 142, 72 | OP_NEGATE = 143, 73 | OP_ABS = 144, 74 | OP_NOT = 145, 75 | OP_0NOTEQUAL = 146, 76 | OP_ADD = 147, 77 | OP_SUB = 148, 78 | OP_MUL = 149, 79 | OP_DIV = 150, 80 | OP_MOD = 151, 81 | OP_LSHIFT = 152, 82 | OP_RSHIFT = 153, 83 | OP_BOOLAND = 154, 84 | OP_BOOLOR = 155, 85 | OP_NUMEQUAL = 156, 86 | OP_NUMEQUALVERIFY = 157, 87 | OP_NUMNOTEQUAL = 158, 88 | OP_LESSTHAN = 159, 89 | OP_GREATERTHAN = 160, 90 | OP_LESSTHANOREQUAL = 161, 91 | OP_GREATERTHANOREQUAL = 162, 92 | OP_MIN = 163, 93 | OP_MAX = 164, 94 | OP_WITHIN = 165, 95 | OP_RIPEMD160 = 166, 96 | OP_SHA1 = 167, 97 | OP_SHA256 = 168, 98 | OP_HASH160 = 169, 99 | OP_HASH256 = 170, 100 | OP_CODESEPARATOR = 171, 101 | OP_CHECKSIG = 172, 102 | OP_CHECKSIGVERIFY = 173, 103 | OP_CHECKMULTISIG = 174, 104 | OP_CHECKMULTISIGVERIFY = 175, 105 | OP_CHECKLOCKTIMEVERIFY = 177, 106 | OP_CHECKSEQUENCEVERIFY = 178, 107 | OP_NOP1 = 176, 108 | OP_NOP2 = 177, 109 | OP_NOP3 = 178, 110 | OP_NOP4 = 179, 111 | OP_NOP5 = 180, 112 | OP_NOP6 = 181, 113 | OP_NOP7 = 182, 114 | OP_NOP8 = 183, 115 | OP_NOP9 = 184, 116 | OP_NOP10 = 185, 117 | OP_PUBKEYHASH = 253, 118 | OP_PUBKEY = 254, 119 | OP_INVALIDOPCODE = 255, 120 | } 121 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/src/script/script.ts: -------------------------------------------------------------------------------- 1 | import { utils } from "@renproject/utils"; 2 | 3 | import { hash160 } from "../utils/utils"; 4 | import { Opcode } from "./opcodes"; 5 | 6 | const checksum = (hash: Uint8Array) => 7 | utils.sha256(utils.sha256(hash)).slice(0, 4); 8 | 9 | export class Script { 10 | private script: Uint8Array; 11 | 12 | public static OP = Opcode; 13 | public OP = Opcode; 14 | 15 | public constructor() { 16 | this.script = new Uint8Array(); 17 | } 18 | 19 | public addOp = (op: Opcode): this => { 20 | this.script = new Uint8Array([...this.script, op]); 21 | return this; 22 | }; 23 | 24 | public addData = (data: Uint8Array): this => { 25 | this.script = new Uint8Array([...this.script, data.length, ...data]); 26 | return this; 27 | }; 28 | 29 | public bytes = (): Uint8Array => { 30 | return this.script; 31 | }; 32 | 33 | public toScriptHashOut = (): Uint8Array => { 34 | return new Script() 35 | .addOp(Script.OP.OP_HASH160) 36 | .addData(hash160(this.bytes())) 37 | .addOp(Script.OP.OP_EQUAL) 38 | .bytes(); 39 | }; 40 | 41 | public toAddress = (prefix: Uint8Array | Uint8Array): Uint8Array => { 42 | // Hash 43 | const hash = hash160(this.bytes()); 44 | 45 | // Prepend prefix 46 | const hashWithPrefix = utils.concat([prefix, hash]); 47 | 48 | // Append checksum 49 | const hashWithChecksum = utils.concat([ 50 | hashWithPrefix, 51 | checksum(hashWithPrefix), 52 | ]); 53 | 54 | return hashWithChecksum; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/src/utils/types.ts: -------------------------------------------------------------------------------- 1 | import { ChainTransaction, RenNetwork } from "@renproject/utils"; 2 | 3 | import { APIWithPriority, BitcoinAPI } from "../APIs/API"; 4 | 5 | export type BitcoinInputPayload = 6 | | { 7 | chain: string; 8 | type?: "gatewayAddress"; 9 | } 10 | | { 11 | chain: string; 12 | type: "transaction"; 13 | params: { 14 | tx: ChainTransaction; 15 | }; 16 | }; 17 | 18 | export interface BitcoinOutputPayload { 19 | chain: string; 20 | type?: "address"; 21 | params: { 22 | address: string; 23 | }; 24 | } 25 | 26 | export interface BitcoinNetworkConfig { 27 | label: string; 28 | 29 | selector: string; 30 | 31 | nativeAsset: { 32 | name: string; 33 | symbol: string; 34 | decimals: number; 35 | }; 36 | averageConfirmationTime: number; 37 | 38 | isTestnet?: boolean; 39 | p2shPrefix: Uint8Array; 40 | explorer: { 41 | url: string; 42 | address: (address: string) => string; 43 | transaction: (txid: string) => string; 44 | }; 45 | providers: Array; 46 | } 47 | 48 | export const isBitcoinNetworkConfig = ( 49 | input: unknown, 50 | ): input is BitcoinNetworkConfig => 51 | !!(input as BitcoinNetworkConfig).label && 52 | !!(input as BitcoinNetworkConfig).selector && 53 | !!(input as BitcoinNetworkConfig).nativeAsset && 54 | !!(input as BitcoinNetworkConfig).p2shPrefix && 55 | !!(input as BitcoinNetworkConfig).explorer && 56 | !!(input as BitcoinNetworkConfig).providers; 57 | 58 | export type BitcoinNetworkConfigMap = { 59 | [network in RenNetwork]?: BitcoinNetworkConfig; 60 | }; 61 | 62 | export type BitcoinNetworkInput = 63 | | RenNetwork 64 | | `${RenNetwork}` 65 | | BitcoinNetworkConfig; 66 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/src/zcash.ts: -------------------------------------------------------------------------------- 1 | import { RenNetwork } from "@renproject/utils"; 2 | 3 | import { Blockbook } from "./APIs/blockbook"; 4 | import { Blockchair, BlockchairNetwork } from "./APIs/blockchair"; 5 | import { Insight } from "./APIs/insight"; 6 | import { SoChain, SoChainNetwork } from "./APIs/sochain"; 7 | import { BitcoinBaseChain } from "./base"; 8 | import { 9 | BitcoinNetworkConfig, 10 | BitcoinNetworkConfigMap, 11 | BitcoinNetworkInput, 12 | } from "./utils/types"; 13 | import { resolveBitcoinNetworkConfig, SoChainExplorer } from "./utils/utils"; 14 | 15 | const ZcashMainnet: BitcoinNetworkConfig = { 16 | label: "Zcash", 17 | selector: "Zcash", 18 | 19 | nativeAsset: { 20 | name: "Zcash", 21 | symbol: "ZEC", 22 | decimals: 8, 23 | }, 24 | averageConfirmationTime: 75, 25 | 26 | explorer: SoChainExplorer("zcash", "ZEC"), 27 | p2shPrefix: new Uint8Array([0x1c, 0xbd]), 28 | providers: [ 29 | new Blockbook("https://zecblockexplorer.com/api/"), 30 | new Blockchair(BlockchairNetwork.ZCASH), 31 | { api: new SoChain(SoChainNetwork.ZEC), priority: 15 }, 32 | { api: new Insight("https://explorer.z.cash/api/"), priority: 20 }, // TODO: test again, currently broken 33 | { api: new Insight("https://zechain.net/api/v1/"), priority: 20 }, // TODO: test again, currently broken 34 | ], 35 | // validateAddress: (address: string) => 36 | // validateAddress(address, "ZEC", "mainnet"), 37 | }; 38 | 39 | const ZcashTestnet: BitcoinNetworkConfig = { 40 | label: "Zcash Testnet", 41 | selector: "Zcash", 42 | 43 | nativeAsset: { 44 | name: "Testnet Zcash", 45 | symbol: "ZEC", 46 | decimals: 8, 47 | }, 48 | averageConfirmationTime: 75, 49 | 50 | isTestnet: true, 51 | explorer: SoChainExplorer("testnet/zcash", "ZECTEST"), 52 | p2shPrefix: new Uint8Array([0x1c, 0xba]), 53 | providers: [ 54 | new Insight("https://explorer.testnet.z.cash/api/"), 55 | { api: new SoChain(SoChainNetwork.ZECTEST), priority: 15 }, 56 | ], 57 | // validateAddress: (address: string) => 58 | // validateAddress(address, "ZEC", "testnet"), 59 | }; 60 | 61 | export class Zcash extends BitcoinBaseChain { 62 | public static chain = "Zcash" as const; 63 | public static configMap: BitcoinNetworkConfigMap = { 64 | [RenNetwork.Mainnet]: ZcashMainnet, 65 | [RenNetwork.Testnet]: ZcashTestnet, 66 | }; 67 | public configMap = Zcash.configMap; 68 | 69 | public static assets = { 70 | [RenNetwork.Mainnet]: { 71 | ZEC: "ZEC", 72 | }, 73 | [RenNetwork.Testnet]: { 74 | ZEC: "ZEC", 75 | }, 76 | }; 77 | 78 | public assets: 79 | | typeof Zcash.assets[RenNetwork.Mainnet] 80 | | typeof Zcash.assets[RenNetwork.Testnet]; 81 | 82 | public constructor({ network }: { network: BitcoinNetworkInput }) { 83 | super({ 84 | network: resolveBitcoinNetworkConfig(Zcash.configMap, network), 85 | }); 86 | this.assets = 87 | Zcash.assets[ 88 | this.network.isTestnet ? RenNetwork.Testnet : RenNetwork.Mainnet 89 | ]; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/test/bch.spec.ts: -------------------------------------------------------------------------------- 1 | import { utils } from "@renproject/utils"; 2 | import { expect } from "chai"; 3 | /* eslint-disable no-console */ 4 | import { describe, it } from "mocha"; 5 | 6 | import { BitcoinCash } from "../src"; 7 | 8 | describe("BCH", () => { 9 | it("address to buffer", () => { 10 | const bch = new BitcoinCash({ network: "testnet" }); 11 | expect( 12 | utils.toHex( 13 | bch.addressToBytes( 14 | "bchtest:pq35hhjj35we555szq8xsa47ry093mkasudz8aetvr", 15 | ), 16 | ), 17 | ).to.equal("08234bde528d1d9a5290100e6876be191e58eedd87"); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/test/broadcastTransaction.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { describe, it } from "mocha"; 3 | 4 | import { Blockchain, BlockchainNetwork } from "../src/APIs/blockchain"; 5 | 6 | describe.skip("broadcast transaction", () => { 7 | it("blockchain.com", async () => { 8 | const blockchain = new Blockchain(BlockchainNetwork.Bitcoin); 9 | console.debug(await blockchain.broadcastTransaction("123456")); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/test/digibyte.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { RenNetwork } from "@renproject/utils"; 3 | import { expect } from "chai"; 4 | import { describe, it } from "mocha"; 5 | 6 | import { DigiByte } from "../src"; 7 | import { APIWithPriority, BitcoinAPI } from "../src/APIs/API"; 8 | 9 | describe("DigiByte", () => { 10 | it("watch for deposits", async () => { 11 | const digibyte = new DigiByte({ network: "mainnet" }); 12 | const providerConfig = 13 | digibyte.configMap[RenNetwork.Mainnet].providers[0]; 14 | const provider: BitcoinAPI = 15 | (providerConfig as APIWithPriority).api || 16 | (providerConfig as BitcoinAPI); 17 | 18 | const txs = await provider.fetchUTXOs( 19 | "DRNiw2k4iFuHGS2fF1wMahounXo6H9iGbh", 20 | ); 21 | 22 | expect(txs[txs.length - 1]).to.deep.equal({ 23 | txid: "9f5c0a8146e7633911cbf5be44ebebb9b65bb360511f6795bea04c650ed600b8", 24 | amount: "16205616929", 25 | txindex: "2", 26 | height: "3127600", 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/test/getUTXOs.spec.ts: -------------------------------------------------------------------------------- 1 | // import { renMainnet, renTestnet } from "@renproject/chains"; 2 | import chai from "chai"; 3 | 4 | // import RenJS from "@renproject/ren"; 5 | 6 | chai.should(); 7 | 8 | describe("mercury.ts", () => { 9 | // it("Testnet BTC UTXOS", async () => { 10 | // const utxos = await RenJS.utils.btc.getUTXOs(renTestnet)("n2e9DLJqFoAiaqjo2JFQSW1GVC6gMLXEPa", 0); 11 | // utxos.length.should.be.greaterThan(0); 12 | // utxos[0].txHash.should.equal("af946e4182f1e5cbf0e682233b037a3ec8a5692b4f037cf016c7d11f0a97766d"); 13 | // utxos[0].amount.should.equal(13370); 14 | // utxos[0].confirmations.should.be.greaterThan(0); 15 | // }); 16 | // it("Testnet BTC UTXOS [second API]", async () => { 17 | // const utxos = await RenJS.utils.btc.getUTXOs(renTestnet)("n2e9DLJqFoAiaqjo2JFQSW1GVC6gMLXEPa", 0); 18 | // utxos.length.should.be.greaterThan(0); 19 | // utxos[0].txHash.should.equal("af946e4182f1e5cbf0e682233b037a3ec8a5692b4f037cf016c7d11f0a97766d"); 20 | // utxos[0].amount.should.equal(13370); 21 | // utxos[0].confirmations.should.be.greaterThan(0); 22 | // }); 23 | // it("Testnet ZCash UTXOS", async () => { 24 | // const utxos = await RenJS.utils.zec.getUTXOs(renTestnet)("tm9iMLAuYMzJHDJZAFmzVmEa81uddHz1viK", 0); 25 | // utxos.length.should.be.greaterThan(0); 26 | // utxos[0].txHash.should.equal("6d6f1781c589d9eafc923d480fa39656da088110b4553c043f9da2cf843d2b03"); 27 | // utxos[0].amount.should.equal(100000000); 28 | // utxos[0].confirmations.should.be.greaterThan(0); 29 | // }); 30 | // it("Mainnet BTC UTXOS", async () => { 31 | // const utxos = await RenJS.utils.btc.getUTXOs(renMainnet)("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX", 0); 32 | // utxos.length.should.be.greaterThan(0); 33 | // utxos[0].txHash.should.equal("27c3a32f18d6274eb348dfd401defe6cccc2738eda277c4e55ae44370f91d98f"); 34 | // utxos[0].amount.should.equal(12772); 35 | // utxos[0].confirmations.should.be.greaterThan(0); 36 | // }); 37 | // it("Mainnet ZEC UTXOS", async () => { 38 | // const utxos = await RenJS.utils.zec.getUTXOs(renMainnet)("t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd", 0); 39 | // utxos.length.should.be.greaterThan(0); 40 | // utxos[0].txHash.should.equal("6482a18a61cea7da8abb7ac8c44939b701889343afac7130fec4898ad1b29307"); 41 | // utxos[0].amount.should.equal(7873358); 42 | // utxos[0].confirmations.should.be.greaterThan(0); 43 | // }); 44 | // it("Mainnet BCH UTXOS", async () => { 45 | // const utxos = await RenJS.utils.bch.getUTXOs(renMainnet)("bitcoincash:qqt6g6wul02yakpt05amm0hey67lhh7wagrrqxcmys", 0); 46 | // utxos.length.should.be.greaterThan(0); 47 | // utxos[0].txHash.should.equal("2d05f0c9c3e1c226e63b5fac240137687544cf631cd616fd34fd188fc9020866"); 48 | // utxos[0].amount.should.equal(5000000000); 49 | // utxos[0].confirmations.should.be.greaterThan(0); 50 | // }); 51 | // it.skip("Testnet BCH UTXOS", async () => { 52 | // const utxos = await RenJS.utils.bch.getUTXOs(renTestnet)("bchtest:qrhfzqeen0a59gy3576n00k54p2ja9s3egxdkyy7hr", 0); 53 | // utxos.length.should.be.greaterThan(0); 54 | // utxos[0].txHash.should.equal("d9d587c9f77996e5618141a564d46f3bb7c92a7cdd8cbe9142bc43eb18a63887"); 55 | // utxos[0].amount.should.equal(13999000); 56 | // utxos[0].confirmations.should.be.greaterThan(0); 57 | // }); 58 | }); 59 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/test/script.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it } from "mocha"; 2 | 3 | /* eslint-disable no-console */ 4 | import { RenNetwork, utils } from "@renproject/utils"; 5 | 6 | import { Bitcoin, BitcoinCash, Dogecoin, Zcash } from "../src"; 7 | import { hash160 } from "../src/utils/utils"; 8 | 9 | describe("Common", () => { 10 | for (const ChainClass of [Bitcoin, Zcash, BitcoinCash, Dogecoin]) { 11 | for (const network of [RenNetwork.Mainnet, RenNetwork.Testnet]) { 12 | it(ChainClass.chain, async () => { 13 | const chain = new ChainClass({ network }); 14 | const gHash = utils.fromBase64( 15 | "cQ+CJ8bOP4RMopOCNDvbQ020Eu8KRpYykurZyKNFM1I=", 16 | ); 17 | 18 | const publicKey = utils.fromHex( 19 | "030dd65f7db2920bb229912e3f4213dd150e5f972c9b73e9be714d844561ac355c", 20 | ); 21 | 22 | const address = await chain.createGatewayAddress( 23 | chain.assets[Object.keys(chain.assets)[0]], 24 | { 25 | chain: chain.chain, 26 | }, 27 | hash160(publicKey), 28 | gHash, 29 | ); 30 | 31 | if (false as boolean) { 32 | console.debug(`${chain.chain} ${network}: ${address}`); 33 | } 34 | }); 35 | } 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/test/utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | 3 | import { Bitcoin, Dogecoin } from "../src"; 4 | 5 | describe("Utils", () => { 6 | it("validateTransaction", () => { 7 | const bitcoin = new Bitcoin({ 8 | network: "testnet", 9 | }); 10 | 11 | expect( 12 | bitcoin.validateTransaction({ 13 | txHash: "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", 14 | }), 15 | ).to.be.true; 16 | 17 | expect( 18 | bitcoin.validateTransaction({ 19 | txHash: "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", 20 | txid: "jdT1-9XpgPwC81xs4UWTWxHihGBb9ZmhPG1BXbVdB6E", 21 | txindex: "1", 22 | }), 23 | ).to.be.true; 24 | 25 | const dogecoinMainnet = new Dogecoin({ network: "mainnet" }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "outDir": "build", 5 | "rootDir": "src", 6 | "moduleResolution": "node", 7 | "module": "commonjs", 8 | "declaration": true, 9 | "removeComments": false, 10 | "esModuleInterop": true, 11 | "strict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "traceResolution": false, 17 | "listEmittedFiles": false, 18 | "listFiles": false, 19 | "pretty": true, 20 | "lib": ["es2017", "dom"], 21 | "types": ["node"], 22 | "typeRoots": ["node_modules/@types", "src/types"], 23 | "resolveJsonModule": true, 24 | "forceConsistentCasingInFileNames": true, 25 | "noImplicitThis": true, 26 | "noImplicitAny": true, 27 | "strictNullChecks": true, 28 | "suppressImplicitAnyIndexErrors": true, 29 | "strictPropertyInitialization": true, 30 | "alwaysStrict": true, 31 | "strictFunctionTypes": true, 32 | "sourceMap": true, 33 | "declarationMap": true 34 | }, 35 | "include": ["src/**/*.ts"], 36 | "exclude": ["node_modules/**"], 37 | "compileOnSave": false 38 | } 39 | -------------------------------------------------------------------------------- /packages/chains/chains-bitcoin/tsconfig.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "outDir": "build/module", 6 | "module": "es6" 7 | }, 8 | "exclude": ["node_modules/**"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/README.md: -------------------------------------------------------------------------------- 1 | # `@renproject/chains-ethereum` 2 | 3 | This package is part of [RenJS](https://github.com/renproject.ren-js). 4 | 5 | See [`@renproject/chains-ethereum` docs](https://renproject.github.io/ren-js-v3-docs/modules/_renproject_chains_ethereum.html) 6 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@renproject/chains-ethereum", 3 | "version": "3.6.0", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/renproject/ren-js.git" 7 | }, 8 | "publishConfig": { 9 | "access": "public", 10 | "directory": "build" 11 | }, 12 | "author": "Ren", 13 | "license": "MIT", 14 | "bugs": { 15 | "url": "https://github.com/renproject/ren-js/issues" 16 | }, 17 | "main": "./build/index.js", 18 | "typings": "./build/index.d.ts", 19 | "module": "./build/module/index.js", 20 | "scripts": { 21 | "clean": "yarn rimraf ./build ./node_modules", 22 | "link": "yarn build:link && cd build && yarn link", 23 | "unlink": "yarn unlink", 24 | "build": "run-s build:*", 25 | "build:main": "tsc -p tsconfig.json", 26 | "build:module": "tsc -p tsconfig.module.json", 27 | "build:link": "cp package.json build && cp README.md build && sed -i.tmp 's/\\/build\\//\\//' ./build/package.json && rm ./build/package.json.tmp", 28 | "prettier": "yarn fix:prettier", 29 | "lint": "run-s lint:*", 30 | "lint:eslint": "eslint --config ../../../.eslintrc.js src", 31 | "lint:prettier": "prettier --check \"./(src|test)/**/*.ts*\"", 32 | "fix": "run-s fix:*", 33 | "fix:eslint": "yarn lint:eslint --fix", 34 | "fix:prettier": "prettier --write './(src|test)/**/*.ts*'", 35 | "test": "run-s test:* lint", 36 | "test:unit": "nyc ../../../node_modules/ts-mocha/bin/ts-mocha --bail --sort --exit --timeout 180000 --paths -p ./tsconfig.json ./test/*.spec.ts ./test/**/*.spec.ts --ignore ./test/testutils/chai.d.ts", 37 | "watch": "run-s build:main && run-s \"build:main -- -w\"", 38 | "cov": "run-s build:main test:unit cov:html && echo \"\n\nTo see coverage, run: 'open coverage/index.html'\n\n\"", 39 | "cov:html": "nyc report --reporter=html", 40 | "cov:send": "nyc report --reporter=lcov && codecov", 41 | "cov:check": "nyc report && nyc check-coverage --lines 0 --functions 0 --branches 0", 42 | "prepare": "yarn build" 43 | }, 44 | "dependencies": { 45 | "@ethersproject/abi": "5.7.0", 46 | "@ethersproject/bytes": "5.7.0", 47 | "@ethersproject/providers": "5.7.2", 48 | "@renproject/utils": "^3.6.0", 49 | "@types/elliptic": "6.4.14", 50 | "bignumber.js": "9.0.2", 51 | "elliptic": "6.5.4", 52 | "ethers": "5.7.2" 53 | }, 54 | "nyc": { 55 | "extends": "@istanbuljs/nyc-config-typescript", 56 | "exclude": [ 57 | "**/*.d.ts", 58 | "**/*.spec.js" 59 | ], 60 | "include": [ 61 | "src" 62 | ] 63 | }, 64 | "prettier": { 65 | "printWidth": 80, 66 | "semi": true, 67 | "singleQuote": false, 68 | "tabWidth": 4, 69 | "trailingComma": "all", 70 | "endOfLine": "lf", 71 | "arrowParens": "always" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/arbitrum.ts: -------------------------------------------------------------------------------- 1 | import { RenNetwork } from "@renproject/utils"; 2 | 3 | import { EthereumBaseChain } from "./base"; 4 | import { resolveEVMNetworkConfig } from "./utils/generic"; 5 | 6 | const configMap: EthereumBaseChain["configMap"] = { 7 | [RenNetwork.Mainnet]: { 8 | selector: "Arbitrum", 9 | 10 | nativeAsset: { name: "Arbitrum Ether", symbol: "ArbETH", decimals: 18 }, 11 | averageConfirmationTime: 4, 12 | 13 | config: { 14 | chainId: "0xa4b1", 15 | chainName: "Arbitrum One", 16 | nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, 17 | rpcUrls: [ 18 | "https://arb1.arbitrum.io/rpc", 19 | "https://rpc.ankr.com/arbitrum", 20 | "https://arb-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}", 21 | // "https://arbitrum-mainnet.infura.io/v3/${INFURA_API_KEY}", 22 | ], 23 | blockExplorerUrls: ["https://arbiscan.io"], 24 | }, 25 | 26 | logRequestLimit: 20000, 27 | addresses: { 28 | GatewayRegistry: "0xf36666C230Fa12333579b9Bd6196CB634D6BC506", 29 | BasicBridge: "0x82DF02A52E2e76C0c233367f2fE6c9cfe51578c5", 30 | }, 31 | }, 32 | [RenNetwork.Testnet]: { 33 | selector: "Arbitrum", 34 | isTestnet: true, 35 | 36 | nativeAsset: { 37 | name: "Arbitrum Görli Ether", 38 | symbol: "ArbETH", 39 | decimals: 18, 40 | }, 41 | averageConfirmationTime: 4, 42 | 43 | config: { 44 | chainId: "0x66eeb", 45 | chainName: "Arbitrum Görli", 46 | nativeCurrency: { 47 | name: "Arbitrum Görli Ether", 48 | symbol: "ARETH", 49 | decimals: 18, 50 | }, 51 | rpcUrls: [ 52 | "https://goerli-rollup.arbitrum.io/rpc", 53 | "https://arb-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}", 54 | "wss://arb-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}", 55 | ], 56 | blockExplorerUrls: ["https://goerli.arbiscan.io"], 57 | }, 58 | 59 | logRequestLimit: 20000, 60 | addresses: { 61 | GatewayRegistry: "0x5076a1F237531fa4dC8ad99bb68024aB6e1Ff701", 62 | BasicBridge: "0x081636b68aBD7695006e0baE4d8663b91EC5Cfc1", 63 | }, 64 | }, 65 | }; 66 | 67 | /** 68 | * Arbitrum/arbETH configuration. 69 | */ 70 | export class Arbitrum extends EthereumBaseChain { 71 | // Static members. 72 | public static chain = "Arbitrum" as const; 73 | public static configMap = configMap; 74 | public static assets = { 75 | [RenNetwork.Mainnet]: { ArbETH: "ArbETH" as const }, 76 | [RenNetwork.Testnet]: { ArbETH: "ArbETH" as const }, 77 | }; 78 | 79 | public configMap = configMap; 80 | public assets: 81 | | typeof Arbitrum.assets[RenNetwork.Mainnet] 82 | | typeof Arbitrum.assets[RenNetwork.Testnet]; 83 | 84 | public constructor({ 85 | network, 86 | ...params 87 | }: ConstructorParameters[0]) { 88 | super({ 89 | ...params, 90 | network: resolveEVMNetworkConfig(configMap, network), 91 | }); 92 | this.assets = 93 | Arbitrum.assets[ 94 | this.network.isTestnet ? RenNetwork.Testnet : RenNetwork.Mainnet 95 | ]; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/avalanche.ts: -------------------------------------------------------------------------------- 1 | import { RenNetwork } from "@renproject/utils"; 2 | 3 | import { EthereumBaseChain } from "./base"; 4 | import { resolveEVMNetworkConfig } from "./utils/generic"; 5 | 6 | const configMap: EthereumBaseChain["configMap"] = { 7 | [RenNetwork.Mainnet]: { 8 | selector: "Avalanche", 9 | 10 | nativeAsset: { name: "Avalanche", symbol: "AVAX", decimals: 18 }, 11 | averageConfirmationTime: 2, 12 | 13 | config: { 14 | chainId: "0xa86a", 15 | chainName: "Avalanche C-Chain", 16 | nativeCurrency: { name: "Avalanche", symbol: "AVAX", decimals: 18 }, 17 | rpcUrls: [ 18 | "https://api.avax.network/ext/bc/C/rpc", 19 | "https://rpc.ankr.com/avalanche", 20 | "https://ava-mainnet.public.blastapi.io/ext/bc/C/rpc", 21 | ], 22 | blockExplorerUrls: ["https://snowtrace.io"], 23 | }, 24 | 25 | logRequestLimit: 2048, 26 | addresses: { 27 | GatewayRegistry: "0xf36666C230Fa12333579b9Bd6196CB634D6BC506", 28 | BasicBridge: "0x82DF02A52E2e76C0c233367f2fE6c9cfe51578c5", 29 | }, 30 | }, 31 | 32 | [RenNetwork.Testnet]: { 33 | selector: "Avalanche", 34 | isTestnet: true, 35 | 36 | nativeAsset: { 37 | name: "Testnet Avalanche", 38 | symbol: "AVAX", 39 | decimals: 18, 40 | }, 41 | averageConfirmationTime: 2, 42 | 43 | config: { 44 | chainId: "0xa869", 45 | chainName: "Avalanche Fuji Testnet", 46 | nativeCurrency: { name: "Avalanche", symbol: "AVAX", decimals: 18 }, 47 | rpcUrls: ["https://api.avax-test.network/ext/bc/C/rpc"], 48 | blockExplorerUrls: ["https://testnet.snowtrace.io"], 49 | }, 50 | 51 | logRequestLimit: 2048, 52 | addresses: { 53 | GatewayRegistry: "0x5076a1F237531fa4dC8ad99bb68024aB6e1Ff701", 54 | BasicBridge: "0xcb6bD6B6c7D7415C0157e393Bb2B6Def7555d518", 55 | }, 56 | }, 57 | }; 58 | 59 | /** 60 | * Avalanche/AVAX configuration. 61 | */ 62 | export class Avalanche extends EthereumBaseChain { 63 | // Static members. 64 | public static chain = "Avalanche" as const; 65 | public static configMap = configMap; 66 | public static assets = { 67 | [RenNetwork.Mainnet]: { AVAX: "AVAX" as const }, 68 | [RenNetwork.Testnet]: { AVAX: "AVAX" as const }, 69 | }; 70 | 71 | public configMap = configMap; 72 | public assets: 73 | | typeof Avalanche.assets[RenNetwork.Mainnet] 74 | | typeof Avalanche.assets[RenNetwork.Testnet]; 75 | 76 | public constructor({ 77 | network, 78 | ...params 79 | }: ConstructorParameters[0]) { 80 | super({ 81 | ...params, 82 | network: resolveEVMNetworkConfig(configMap, network), 83 | }); 84 | this.assets = 85 | Avalanche.assets[ 86 | this.network.isTestnet ? RenNetwork.Testnet : RenNetwork.Mainnet 87 | ]; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/catalog.ts: -------------------------------------------------------------------------------- 1 | import { RenNetwork } from "@renproject/utils"; 2 | 3 | import { EthereumBaseChain } from "./base"; 4 | import { resolveEVMNetworkConfig } from "./utils/generic"; 5 | 6 | const configMap: EthereumBaseChain["configMap"] = { 7 | [RenNetwork.Mainnet]: { 8 | selector: "Catalog", 9 | 10 | nativeAsset: { name: "DCE EVM", symbol: "dceETH", decimals: 18 }, 11 | averageConfirmationTime: 15, 12 | 13 | config: { 14 | chainId: "0xC30", 15 | chainName: "Catalog Mainnet", 16 | nativeCurrency: { name: "DCE EVM", symbol: "dceETH", decimals: 18 }, 17 | rpcUrls: ["https://mainnet.catalog.fi/rpc"], 18 | blockExplorerUrls: null, 19 | }, 20 | 21 | addresses: { 22 | GatewayRegistry: "0x44c2CdaE368F90544A01522C413376fC72ebd4F2", 23 | BasicBridge: "0x5D952fA25eD90b1151473d57F2B6C6DB568b865d", 24 | }, 25 | }, 26 | 27 | [RenNetwork.Testnet]: { 28 | selector: "Catalog", 29 | 30 | nativeAsset: { name: "DCE EVM", symbol: "dceETH", decimals: 18 }, 31 | averageConfirmationTime: 15, 32 | 33 | config: { 34 | chainId: "0x47EE", 35 | chainName: "Catalog Testnet", 36 | nativeCurrency: { name: "DCE EVM", symbol: "dceETH", decimals: 18 }, 37 | rpcUrls: ["https://rpc.catalog.fi/testnet"], 38 | blockExplorerUrls: null, 39 | }, 40 | 41 | addresses: { 42 | GatewayRegistry: "0x44c2CdaE368F90544A01522C413376fC72ebd4F2", 43 | BasicBridge: "0xfc5681F4343803C11eB5Bb7aFd2108238bbd7177", 44 | }, 45 | }, 46 | }; 47 | 48 | /** 49 | * Catalog configuration. 50 | */ 51 | export class Catalog extends EthereumBaseChain { 52 | // Static members. 53 | public static chain = "Catalog" as const; 54 | public static configMap = configMap; 55 | public static assets = { 56 | [RenNetwork.Mainnet]: {}, 57 | [RenNetwork.Testnet]: {}, 58 | }; 59 | 60 | public configMap = configMap; 61 | public assets: 62 | | typeof Catalog.assets[RenNetwork.Mainnet] 63 | | typeof Catalog.assets[RenNetwork.Testnet]; 64 | 65 | public constructor({ 66 | network, 67 | ...params 68 | }: ConstructorParameters[0]) { 69 | super({ 70 | ...params, 71 | network: resolveEVMNetworkConfig(configMap, network), 72 | }); 73 | this.assets = 74 | Catalog.assets[ 75 | this.network.isTestnet ? RenNetwork.Testnet : RenNetwork.Mainnet 76 | ]; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/contracts/ABIs/TransferWithLog.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "anonymous": false, 4 | "inputs": [ 5 | { 6 | "indexed": true, 7 | "internalType": "address", 8 | "name": "from", 9 | "type": "address" 10 | }, 11 | { 12 | "indexed": true, 13 | "internalType": "address", 14 | "name": "to", 15 | "type": "address" 16 | }, 17 | { 18 | "indexed": false, 19 | "internalType": "uint256", 20 | "name": "amount", 21 | "type": "uint256" 22 | } 23 | ], 24 | "name": "LogTransferred", 25 | "type": "event" 26 | }, 27 | { 28 | "inputs": [], 29 | "name": "NAME", 30 | "outputs": [ 31 | { 32 | "internalType": "string", 33 | "name": "", 34 | "type": "string" 35 | } 36 | ], 37 | "stateMutability": "view", 38 | "type": "function" 39 | }, 40 | { 41 | "inputs": [ 42 | { 43 | "internalType": "address payable", 44 | "name": "to", 45 | "type": "address" 46 | } 47 | ], 48 | "name": "transferWithLog", 49 | "outputs": [], 50 | "stateMutability": "payable", 51 | "type": "function" 52 | } 53 | ] 54 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/contracts/index.ts: -------------------------------------------------------------------------------- 1 | import { Provider } from "@ethersproject/providers"; 2 | import { utils } from "@renproject/utils"; 3 | import { Contract, Signer } from "ethers"; 4 | 5 | import { AbiItem } from "../utils/abi"; 6 | import BasicBridgeJSON from "./ABIs/BasicBridge.json"; 7 | import ERC20JSON from "./ABIs/ERC20.json"; 8 | import GatewayRegistryJSON from "./ABIs/GatewayRegistryV2.json"; 9 | import LockGatewayJSON from "./ABIs/LockGatewayV3.json"; 10 | import MintGatewayJSON from "./ABIs/MintGatewayV3.json"; 11 | import TransferWithLogJSON from "./ABIs/TransferWithLog.json"; 12 | import { ERC20 } from "./typechain/ERC20"; 13 | import { GatewayRegistryV2 } from "./typechain/GatewayRegistryV2"; 14 | import { LockGatewayV3 } from "./typechain/LockGatewayV3"; 15 | import { MintGatewayV3 } from "./typechain/MintGatewayV3"; 16 | 17 | export const BasicBridgeABI = BasicBridgeJSON as AbiItem[]; 18 | export const ERC20ABI = ERC20JSON as AbiItem[]; 19 | export const GatewayRegistryABI = GatewayRegistryJSON as AbiItem[]; 20 | export const LockGatewayABI = LockGatewayJSON as AbiItem[]; 21 | export const MintGatewayABI = MintGatewayJSON as AbiItem[]; 22 | export const TransferWithLogABI = TransferWithLogJSON as AbiItem[]; 23 | 24 | export const findABIMethod = (abi: AbiItem[], name: string): AbiItem => { 25 | const first = abi.filter((item) => item.name === name)[0]; 26 | if (!first) { 27 | throw new Error(`No ABI entry found for "${name}".`); 28 | } 29 | return first; 30 | }; 31 | 32 | export const getEventTopic = (abiItem: AbiItem): Uint8Array => { 33 | const parameters = 34 | abiItem.inputs && abiItem.inputs.length > 0 35 | ? abiItem.inputs.map((input) => input.type).join(",") 36 | : ""; 37 | if (!abiItem.name) { 38 | throw new Error( 39 | `No name found in ABI item (parameters: ${parameters}).`, 40 | ); 41 | } 42 | const eventSignature = `${abiItem.name}(${parameters})`; 43 | return utils.keccak256(utils.fromUTF8String(eventSignature)); 44 | }; 45 | 46 | export const getMintGatewayInstance = ( 47 | signerOrProvider: Signer | Provider, 48 | address: string, 49 | ): MintGatewayV3 => 50 | new Contract(address, MintGatewayABI, signerOrProvider) as MintGatewayV3; 51 | 52 | export const getLockGatewayInstance = ( 53 | signerOrProvider: Signer | Provider, 54 | address: string, 55 | ): LockGatewayV3 => 56 | new Contract(address, LockGatewayABI, signerOrProvider) as LockGatewayV3; 57 | 58 | export const getGatewayRegistryInstance = ( 59 | signerOrProvider: Signer | Provider, 60 | address: string, 61 | ): GatewayRegistryV2 => 62 | new Contract( 63 | address, 64 | GatewayRegistryABI, 65 | signerOrProvider, 66 | ) as GatewayRegistryV2; 67 | 68 | export const getERC20Instance = ( 69 | signerOrProvider: Signer | Provider, 70 | address: string, 71 | ): ERC20 => new Contract(address, ERC20ABI, signerOrProvider) as ERC20; 72 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/contracts/typechain/common.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | import type { Listener } from "@ethersproject/providers"; 5 | import type { Event, EventFilter } from "ethers"; 6 | 7 | export interface TypedEvent< 8 | TArgsArray extends Array = any, 9 | TArgsObject = any, 10 | > extends Event { 11 | args: TArgsArray & TArgsObject; 12 | } 13 | 14 | export interface TypedEventFilter<_TEvent extends TypedEvent> 15 | extends EventFilter {} 16 | 17 | export interface TypedListener { 18 | (...listenerArg: [...__TypechainArgsArray, TEvent]): void; 19 | } 20 | 21 | type __TypechainArgsArray = T extends TypedEvent ? U : never; 22 | 23 | export interface OnEvent { 24 | ( 25 | eventFilter: TypedEventFilter, 26 | listener: TypedListener, 27 | ): TRes; 28 | (eventName: string, listener: Listener): TRes; 29 | } 30 | 31 | export type MinEthersFactory = { 32 | deploy(...a: ARGS[]): Promise; 33 | }; 34 | 35 | export type GetContractTypeFromFactory = F extends MinEthersFactory< 36 | infer C, 37 | any 38 | > 39 | ? C 40 | : never; 41 | 42 | export type GetARGsTypeFromFactory = F extends MinEthersFactory 43 | ? Parameters 44 | : never; 45 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/fantom.ts: -------------------------------------------------------------------------------- 1 | import { RenNetwork } from "@renproject/utils"; 2 | 3 | import { EthereumBaseChain } from "./base"; 4 | import { resolveEVMNetworkConfig } from "./utils/generic"; 5 | 6 | const configMap: EthereumBaseChain["configMap"] = { 7 | [RenNetwork.Mainnet]: { 8 | selector: "Fantom", 9 | 10 | nativeAsset: { name: "Fantom", symbol: "FTM", decimals: 18 }, 11 | averageConfirmationTime: 1, 12 | 13 | config: { 14 | chainId: "0xfa", 15 | chainName: "Fantom Opera", 16 | nativeCurrency: { name: "Fantom", symbol: "FTM", decimals: 18 }, 17 | rpcUrls: [ 18 | "https://rpc.ftm.tools", 19 | "https://fantom-mainnet.gateway.pokt.network/v1/lb/62759259ea1b320039c9e7ac", 20 | "https://rpc.ankr.com/fantom", 21 | "https://rpc.fantom.network", 22 | "https://rpc2.fantom.network", 23 | "https://rpc3.fantom.network", 24 | "https://rpcapi.fantom.network", 25 | "https://fantom-mainnet.public.blastapi.io", 26 | ], 27 | blockExplorerUrls: ["https://ftmscan.com"], 28 | }, 29 | 30 | addresses: { 31 | GatewayRegistry: "0xf36666C230Fa12333579b9Bd6196CB634D6BC506", 32 | BasicBridge: "0x82DF02A52E2e76C0c233367f2fE6c9cfe51578c5", 33 | }, 34 | }, 35 | 36 | [RenNetwork.Testnet]: { 37 | selector: "Fantom", 38 | 39 | nativeAsset: { name: "Testnet Fantom", symbol: "FTM", decimals: 18 }, 40 | averageConfirmationTime: 1, 41 | 42 | config: { 43 | chainId: "0xfa2", 44 | chainName: "Fantom Testnet", 45 | nativeCurrency: { name: "Fantom", symbol: "FTM", decimals: 18 }, 46 | rpcUrls: ["https://rpc.testnet.fantom.network"], 47 | blockExplorerUrls: ["https://testnet.ftmscan.com"], 48 | }, 49 | 50 | addresses: { 51 | GatewayRegistry: "0x5076a1F237531fa4dC8ad99bb68024aB6e1Ff701", 52 | BasicBridge: "0xcb6bD6B6c7D7415C0157e393Bb2B6Def7555d518", 53 | }, 54 | }, 55 | }; 56 | 57 | export class Fantom extends EthereumBaseChain { 58 | // Static members. 59 | public static chain = "Fantom" as const; 60 | public static configMap = configMap; 61 | public static assets = { 62 | [RenNetwork.Mainnet]: { FTM: "FTM" as const }, 63 | [RenNetwork.Testnet]: { FTM: "FTM" as const }, 64 | }; 65 | 66 | public configMap = Fantom.configMap; 67 | public assets: 68 | | typeof Fantom.assets[RenNetwork.Mainnet] 69 | | typeof Fantom.assets[RenNetwork.Testnet]; 70 | 71 | public constructor({ 72 | network, 73 | ...params 74 | }: ConstructorParameters[0]) { 75 | super({ 76 | ...params, 77 | network: resolveEVMNetworkConfig(configMap, network), 78 | }); 79 | this.assets = 80 | Fantom.assets[ 81 | this.network.isTestnet ? RenNetwork.Testnet : RenNetwork.Mainnet 82 | ]; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/goerli.ts: -------------------------------------------------------------------------------- 1 | import { RenNetwork } from "@renproject/utils"; 2 | 3 | import { EthereumBaseChain } from "./base"; 4 | import { EthereumTestnet, goerliConfigMap } from "./ethereum"; 5 | import { resolveEVMNetworkConfig } from "./utils/generic"; 6 | 7 | export class Goerli extends EthereumBaseChain { 8 | // Static members. 9 | public static chain = "Goerli" as const; 10 | public static configMap = goerliConfigMap; 11 | public static assets = { 12 | [RenNetwork.Testnet]: { 13 | gETH: "gETH" as const, 14 | REN: "REN_Goerli" as const, 15 | DAI: "DAI_Goerli" as const, 16 | USDC: "USDC_Goerli" as const, 17 | USDT: "USDT_Goerli" as const, 18 | 19 | // Aliases 20 | ETH: "gETH" as const, 21 | ETH_Goerli: "gETH" as const, 22 | REN_Goerli: "REN_Goerli" as const, 23 | DAI_Goerli: "DAI_Goerli" as const, 24 | USDC_Goerli: "USDC_Goerli" as const, 25 | USDT_Goerli: "USDT_Goerli" as const, 26 | }, 27 | }; 28 | 29 | public configMap = goerliConfigMap; 30 | public assets: typeof Goerli.assets[RenNetwork.Testnet]; 31 | 32 | public constructor({ 33 | network, 34 | ...params 35 | }: ConstructorParameters[0] & { 36 | defaultTestnet?: EthereumTestnet.Goerli | `${EthereumTestnet.Goerli}`; 37 | }) { 38 | super({ 39 | ...params, 40 | network: resolveEVMNetworkConfig(goerliConfigMap, network), 41 | }); 42 | this.assets = Goerli.assets[RenNetwork.Testnet]; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./utils/types"; 2 | export { EVMParam } from "./utils/payloads/evmParams"; 3 | export { EVM_ERROR } from "./utils/errors"; 4 | export { EthereumBaseChain } from "./base"; 5 | export { 6 | resolveRpcEndpoints, 7 | isEVMNetworkConfig, 8 | resolveEVMNetworkConfig, 9 | } from "./utils/generic"; 10 | 11 | // Chains 12 | export { Arbitrum } from "./arbitrum"; 13 | export { Avalanche } from "./avalanche"; 14 | export { BinanceSmartChain } from "./bsc"; 15 | export { Catalog } from "./catalog"; 16 | export { Ethereum } from "./ethereum"; 17 | export { Fantom } from "./fantom"; 18 | export { Goerli } from "./goerli"; 19 | export { Kava } from "./kava"; 20 | export { Moonbeam } from "./moonbeam"; 21 | export { Optimism } from "./optimism"; 22 | export { Polygon } from "./polygon"; 23 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/kava.ts: -------------------------------------------------------------------------------- 1 | import { RenNetwork } from "@renproject/utils"; 2 | 3 | import { EthereumBaseChain } from "./base"; 4 | import { resolveEVMNetworkConfig } from "./utils/generic"; 5 | 6 | const configMap: EthereumBaseChain["configMap"] = { 7 | [RenNetwork.Mainnet]: { 8 | selector: "Kava", 9 | 10 | nativeAsset: { name: "Kava", symbol: "KAVA", decimals: 18 }, 11 | averageConfirmationTime: 5, 12 | logRequestLimit: 10000, 13 | 14 | config: { 15 | chainId: "0x8ae", 16 | chainName: "Kava EVM", 17 | nativeCurrency: { name: "Kava", symbol: "KAVA", decimals: 18 }, 18 | rpcUrls: [ 19 | "https://evm.kava.io", 20 | "https://evm2.kava.io", 21 | "wss://wevm.kava.io", 22 | "wss://wevm2.kava.io", 23 | ], 24 | blockExplorerUrls: ["https://explorer.kava.io"], 25 | }, 26 | 27 | addresses: { 28 | GatewayRegistry: "0xf36666C230Fa12333579b9Bd6196CB634D6BC506", 29 | BasicBridge: "0xa3FA9A73D22618FfdF6958Ba6285FB3F565e1443", 30 | }, 31 | }, 32 | 33 | [RenNetwork.Testnet]: { 34 | selector: "Kava", 35 | 36 | nativeAsset: { name: "Testnet Kava", symbol: "KAVA", decimals: 18 }, 37 | averageConfirmationTime: 5, 38 | logRequestLimit: 10000, 39 | 40 | config: { 41 | chainId: "0x8ad", 42 | chainName: "Kava EVM Testnet", 43 | nativeCurrency: { name: "Kava", symbol: "KAVA", decimals: 18 }, 44 | rpcUrls: [ 45 | "https://evm.testnet.kava.io", 46 | "wss://wevm.testnet.kava.io", 47 | ], 48 | blockExplorerUrls: ["https://explorer.testnet.kava.io"], 49 | }, 50 | 51 | addresses: { 52 | GatewayRegistry: "0x5076a1F237531fa4dC8ad99bb68024aB6e1Ff701", 53 | BasicBridge: "0xcb6bD6B6c7D7415C0157e393Bb2B6Def7555d518", 54 | }, 55 | }, 56 | }; 57 | 58 | export class Kava extends EthereumBaseChain { 59 | // Static members. 60 | public static chain = "Kava" as const; 61 | public static configMap = configMap; 62 | public static assets = { 63 | [RenNetwork.Mainnet]: { KAVA: "KAVA" as const }, 64 | [RenNetwork.Testnet]: { KAVA: "KAVA" as const }, 65 | }; 66 | 67 | public configMap = configMap; 68 | public assets: 69 | | typeof Kava.assets[RenNetwork.Mainnet] 70 | | typeof Kava.assets[RenNetwork.Testnet]; 71 | 72 | public constructor({ 73 | network, 74 | ...params 75 | }: ConstructorParameters[0]) { 76 | super({ 77 | ...params, 78 | network: resolveEVMNetworkConfig(configMap, network), 79 | }); 80 | this.assets = 81 | Kava.assets[ 82 | this.network.isTestnet ? RenNetwork.Testnet : RenNetwork.Mainnet 83 | ]; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/moonbeam.ts: -------------------------------------------------------------------------------- 1 | import { RenNetwork } from "@renproject/utils"; 2 | 3 | import { EthereumBaseChain } from "./base"; 4 | import { resolveEVMNetworkConfig } from "./utils/generic"; 5 | 6 | const configMap: EthereumBaseChain["configMap"] = { 7 | [RenNetwork.Mainnet]: { 8 | selector: "Moonbeam", 9 | 10 | nativeAsset: { name: "Glimmer", symbol: "GLMR", decimals: 18 }, 11 | averageConfirmationTime: 12, 12 | logRequestLimit: 2000, 13 | 14 | config: { 15 | chainId: "0x504", 16 | chainName: "Moonbeam", 17 | nativeCurrency: { name: "Glimmer", symbol: "GLMR", decimals: 18 }, 18 | rpcUrls: [ 19 | "https://rpc.api.moonbeam.network", 20 | "wss://wss.api.moonbeam.network", 21 | ], 22 | blockExplorerUrls: ["https://moonbeam.moonscan.io"], 23 | }, 24 | 25 | addresses: { 26 | GatewayRegistry: "0xf36666C230Fa12333579b9Bd6196CB634D6BC506", 27 | BasicBridge: "0xa3FA9A73D22618FfdF6958Ba6285FB3F565e1443", 28 | }, 29 | }, 30 | 31 | [RenNetwork.Testnet]: { 32 | selector: "Moonbeam", 33 | 34 | nativeAsset: { name: "Glimmer", symbol: "GLMR", decimals: 18 }, 35 | averageConfirmationTime: 12, 36 | logRequestLimit: 2000, 37 | 38 | config: { 39 | chainId: "0x507", 40 | chainName: "Moonbase Alpha", 41 | nativeCurrency: { name: "Dev", symbol: "DEV", decimals: 18 }, 42 | rpcUrls: [ 43 | "https://rpc.api.moonbase.moonbeam.network", 44 | "https://rpc.testnet.moonbeam.network", 45 | ], 46 | blockExplorerUrls: ["https://moonbase.moonscan.io"], 47 | }, 48 | 49 | addresses: { 50 | GatewayRegistry: "0x5076a1F237531fa4dC8ad99bb68024aB6e1Ff701", 51 | BasicBridge: "0xcb6bD6B6c7D7415C0157e393Bb2B6Def7555d518", 52 | }, 53 | }, 54 | }; 55 | 56 | export class Moonbeam extends EthereumBaseChain { 57 | // Static members. 58 | public static chain = "Moonbeam" as const; 59 | public static configMap = configMap; 60 | public static assets = { 61 | [RenNetwork.Mainnet]: { GLMR: "GLMR" as const }, 62 | [RenNetwork.Testnet]: { GLMR: "GLMR" as const }, 63 | }; 64 | 65 | public configMap = configMap; 66 | public assets: 67 | | typeof Moonbeam.assets[RenNetwork.Mainnet] 68 | | typeof Moonbeam.assets[RenNetwork.Testnet]; 69 | 70 | public constructor({ 71 | network, 72 | ...params 73 | }: ConstructorParameters[0]) { 74 | super({ 75 | ...params, 76 | network: resolveEVMNetworkConfig(configMap, network), 77 | }); 78 | this.assets = 79 | Moonbeam.assets[ 80 | this.network.isTestnet ? RenNetwork.Testnet : RenNetwork.Mainnet 81 | ]; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/optimism.ts: -------------------------------------------------------------------------------- 1 | import { RenNetwork } from "@renproject/utils"; 2 | 3 | import { EthereumBaseChain } from "./base"; 4 | import { resolveEVMNetworkConfig } from "./utils/generic"; 5 | 6 | const configMap: EthereumBaseChain["configMap"] = { 7 | [RenNetwork.Mainnet]: { 8 | selector: "Optimism", 9 | 10 | nativeAsset: { name: "Optimism Ether", symbol: "oETH", decimals: 18 }, 11 | averageConfirmationTime: 5, 12 | logRequestLimit: 10000, 13 | 14 | config: { 15 | chainId: "0xA", 16 | chainName: "Optimism", 17 | nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, 18 | rpcUrls: [ 19 | "https://mainnet.optimism.io/", 20 | "https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}", 21 | "wss://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}", 22 | ], 23 | blockExplorerUrls: ["https://optimistic.etherscan.io"], 24 | }, 25 | 26 | addresses: { 27 | GatewayRegistry: "0xf36666C230Fa12333579b9Bd6196CB634D6BC506", 28 | BasicBridge: "0xa3FA9A73D22618FfdF6958Ba6285FB3F565e1443", 29 | }, 30 | }, 31 | 32 | [RenNetwork.Testnet]: { 33 | selector: "Optimism", 34 | 35 | nativeAsset: { 36 | name: "Optimism Görli Ether", 37 | symbol: "oETH", 38 | decimals: 18, 39 | }, 40 | averageConfirmationTime: 5, 41 | logRequestLimit: 10000, 42 | 43 | config: { 44 | chainId: "0x45", 45 | chainName: "Optimism Görli", 46 | nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, 47 | rpcUrls: [ 48 | "https://goerli.optimism.io", 49 | "https://opt-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}", 50 | "wss://opt-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}", 51 | ], 52 | blockExplorerUrls: ["https://goerli-optimism.etherscan.io"], 53 | }, 54 | 55 | addresses: { 56 | GatewayRegistry: "0x5076a1F237531fa4dC8ad99bb68024aB6e1Ff701", 57 | BasicBridge: "0x081636b68aBD7695006e0baE4d8663b91EC5Cfc1", 58 | }, 59 | }, 60 | }; 61 | 62 | export class Optimism extends EthereumBaseChain { 63 | // Static members. 64 | public static chain = "Optimism" as const; 65 | public static configMap = configMap; 66 | public static assets = { 67 | [RenNetwork.Mainnet]: { oETH: "oETH" as const }, 68 | [RenNetwork.Testnet]: { oETH: "oETH" as const }, 69 | }; 70 | 71 | public configMap = configMap; 72 | public assets: 73 | | typeof Optimism.assets[RenNetwork.Mainnet] 74 | | typeof Optimism.assets[RenNetwork.Testnet]; 75 | 76 | public constructor({ 77 | network, 78 | ...params 79 | }: ConstructorParameters[0]) { 80 | super({ 81 | ...params, 82 | network: resolveEVMNetworkConfig(configMap, network), 83 | }); 84 | this.assets = 85 | Optimism.assets[ 86 | this.network.isTestnet ? RenNetwork.Testnet : RenNetwork.Mainnet 87 | ]; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/utils/errors.ts: -------------------------------------------------------------------------------- 1 | export enum EVM_ERROR { 2 | ASSET_NOT_SUPPORTED = "RENJS:ASSET_NOT_SUPPORTED", 3 | NETWORK_ERROR = "RENJS:NETWORK_ERROR", 4 | } 5 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/utils/gatewayRegistry.ts: -------------------------------------------------------------------------------- 1 | import { Provider } from "@ethersproject/providers"; 2 | import { ErrorWithCode, utils } from "@renproject/utils"; 3 | 4 | import { getGatewayRegistryInstance } from "../contracts"; 5 | import { EVM_ERROR } from "./errors"; 6 | import { EVMNetworkConfig } from "./types"; 7 | 8 | /** 9 | * Utilities for fetching gateway contract addresses and token addresses. 10 | */ 11 | 12 | /** The equivalent to `address(0x0)` in Solidity. */ 13 | const EMPTY_ADDRESS = "0x" + "00".repeat(20); 14 | 15 | enum GatewayRegistryLookup { 16 | MintGateway = "Mint Gateway", 17 | LockGateway = "Lock Gateway", 18 | RenAsset = "Ren Asset", 19 | LockAsset = "Lock Asset", 20 | } 21 | 22 | const gatewayRegistryMethods = { 23 | [GatewayRegistryLookup.MintGateway]: "getMintGatewayBySymbol", 24 | [GatewayRegistryLookup.LockGateway]: "getLockGatewayBySymbol", 25 | [GatewayRegistryLookup.RenAsset]: "getRenAssetBySymbol", 26 | [GatewayRegistryLookup.LockAsset]: "getLockAssetBySymbol", 27 | }; 28 | 29 | const createGatewayRegistryFetcher = 30 | (lookup: GatewayRegistryLookup) => 31 | async ( 32 | network: EVMNetworkConfig, 33 | provider: Provider, 34 | asset: string, 35 | ): Promise => { 36 | try { 37 | const registry = getGatewayRegistryInstance( 38 | provider, 39 | network.addresses.GatewayRegistry, 40 | ); 41 | const registryAddress: string = utils.Ox( 42 | await registry[gatewayRegistryMethods[lookup]](asset), 43 | ); 44 | if (!registryAddress || registryAddress === EMPTY_ADDRESS) { 45 | throw new ErrorWithCode( 46 | `${asset} not supported on ${network.selector} - unable to get ${asset} ${lookup}`, 47 | EVM_ERROR.ASSET_NOT_SUPPORTED, 48 | ); 49 | } 50 | return registryAddress; 51 | } catch (error: unknown) { 52 | throw ErrorWithCode.updateError( 53 | error, 54 | EVM_ERROR.NETWORK_ERROR, 55 | `Error looking up ${asset} ${lookup}`, 56 | ); 57 | } 58 | }; 59 | 60 | export const getMintGateway = createGatewayRegistryFetcher( 61 | GatewayRegistryLookup.MintGateway, 62 | ); 63 | export const getLockGateway = createGatewayRegistryFetcher( 64 | GatewayRegistryLookup.LockGateway, 65 | ); 66 | export const getRenAsset = createGatewayRegistryFetcher( 67 | GatewayRegistryLookup.RenAsset, 68 | ); 69 | export const getLockAsset = createGatewayRegistryFetcher( 70 | GatewayRegistryLookup.LockAsset, 71 | ); 72 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/utils/payloads/evmNoncePayload.ts: -------------------------------------------------------------------------------- 1 | import { PopulatedTransaction } from "ethers"; 2 | 3 | import { EVMPayloadInterface, PayloadHandler } from "./evmParams"; 4 | 5 | export type EVMNoncePayload = EVMPayloadInterface< 6 | "nonce", 7 | { 8 | nonce: string | number; 9 | } 10 | >; 11 | 12 | export const noncePayloadHandler: PayloadHandler = { 13 | export: (): PopulatedTransaction => { 14 | throw new Error(`Unable to export nonce payload.`); 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/src/utils/payloads/evmTxPayload.ts: -------------------------------------------------------------------------------- 1 | import { ChainTransaction } from "@renproject/utils"; 2 | import { PopulatedTransaction } from "ethers"; 3 | 4 | import { EVMPayloadInterface, PayloadHandler } from "./evmParams"; 5 | 6 | export type EVMTxPayload = EVMPayloadInterface< 7 | "transaction", 8 | { 9 | tx: ChainTransaction; 10 | } 11 | >; 12 | 13 | export const txPayloadHandler: PayloadHandler = { 14 | export: (): PopulatedTransaction => { 15 | throw new Error(`Unable to export transaction payload.`); 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/test/abi.spec.ts: -------------------------------------------------------------------------------- 1 | import chai, { expect } from "chai"; 2 | 3 | import { payloadToABI, payloadToMintABI } from "../src/utils/abi"; 4 | 5 | chai.should(); 6 | 7 | describe("abi.ts", () => { 8 | it("payloadToABI", () => { 9 | const expectedABI = [ 10 | { 11 | name: "functionName", 12 | type: "function", 13 | inputs: [ 14 | { type: "address", name: "_spender" }, 15 | { type: "uint256", name: "_value" }, 16 | ], 17 | stateMutability: "payable", 18 | outputs: [], 19 | }, 20 | ]; 21 | 22 | payloadToABI("functionName", [ 23 | { name: "_spender", type: "address", value: "ethereum.eth" }, 24 | { name: "_value", type: "uint256", value: 1 }, 25 | ]).should.deep.eq(expectedABI); 26 | }); 27 | 28 | it("payloadToMintABI", () => { 29 | const expectedABI = { 30 | constant: false, 31 | inputs: [ 32 | { name: "_spender", type: "address" }, 33 | { name: "_value", type: "uint256" }, 34 | { name: "_amount", type: "uint256" }, 35 | { name: "_nHash", type: "bytes32" }, 36 | { name: "_sig", type: "bytes" }, 37 | ], 38 | name: "functionName", 39 | outputs: [], 40 | payable: true, 41 | stateMutability: "payable", 42 | type: "function", 43 | }; 44 | 45 | payloadToMintABI("functionName", [ 46 | { name: "_spender", type: "address", value: "ethereum.eth" }, 47 | { name: "_value", type: "uint256", value: 1 }, 48 | ]).should.deep.eq(expectedABI); 49 | }); 50 | 51 | it("fixTuple", () => { 52 | expect( 53 | payloadToABI("methodWithTuple", [ 54 | { 55 | type: "tuple(address,uint256,address,bytes)", 56 | name: "param", 57 | value: [ 58 | "0x0000000000000000000000000000000000000000", 59 | 0, 60 | "0x0000000000000000000000000000000000000000", 61 | Buffer.from([0]), 62 | ], 63 | }, 64 | ])[0].inputs[0].components.length, 65 | ).to.equal(4); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/test/assets.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { join } from "path"; 4 | 5 | import { RenNetwork } from "@renproject/utils"; 6 | import chai, { expect } from "chai"; 7 | import { config as loadDotEnv } from "dotenv"; 8 | 9 | import { Goerli, resolveRpcEndpoints } from "../src"; 10 | 11 | loadDotEnv({ path: join(__dirname, "../../../../.env") }); 12 | 13 | chai.should(); 14 | 15 | describe("asset", () => { 16 | it("Fetch lock and mint assets", async () => { 17 | const chain = new Goerli({ 18 | provider: resolveRpcEndpoints( 19 | Goerli.configMap["testnet"].config.rpcUrls, 20 | { 21 | INFURA_API_KEY: process.env.INFURA_KEY, 22 | }, 23 | )[0], 24 | network: RenNetwork.Testnet, 25 | defaultTestnet: "goerli", 26 | }); 27 | 28 | expect(await chain.getLockAsset("DAI_Goerli")).to.not.be.empty; 29 | expect(await chain.getLockAsset("USDC_Goerli")).to.not.be.empty; 30 | expect(await chain.getLockAsset("REN_Goerli")).to.not.be.empty; 31 | expect(await chain.getLockAsset("USDT_Goerli")).to.not.be.empty; 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/test/initialization.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { join } from "path"; 4 | 5 | import { RenNetwork } from "@renproject/utils"; 6 | import chai, { expect } from "chai"; 7 | import { config as loadDotEnv } from "dotenv"; 8 | 9 | import { Ethereum } from "../src/ethereum"; 10 | 11 | loadDotEnv({ path: join(__dirname, "../../../../.env") }); 12 | 13 | chai.should(); 14 | 15 | describe("Initialization", () => { 16 | it("Initialize with correct testnet", async () => { 17 | const mainnet = new Ethereum({ 18 | network: RenNetwork.Mainnet, 19 | provider: "", 20 | defaultTestnet: "goerli", 21 | }); 22 | 23 | expect(mainnet.configMap.mainnet.selector).to.equal("Ethereum"); 24 | expect(mainnet.assets.ETH).to.equal("ETH"); 25 | 26 | const goerli = new Ethereum({ 27 | network: RenNetwork.Testnet, 28 | provider: "", 29 | defaultTestnet: "goerli", 30 | }); 31 | 32 | expect(goerli.configMap.testnet.selector).to.equal("Goerli"); 33 | expect(goerli.assets.ETH).to.equal("gETH"); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/test/logs.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { join } from "path"; 4 | 5 | import { RenNetwork } from "@renproject/utils"; 6 | import chai from "chai"; 7 | import { config as loadDotEnv } from "dotenv"; 8 | import { providers } from "ethers"; 9 | 10 | import { BinanceSmartChain } from "../src"; 11 | import { findABIMethod, LockGatewayABI } from "../src/contracts"; 12 | import { LogLockToChainEvent } from "../src/contracts/typechain/LockGatewayV3"; 13 | import { Ethereum } from "../src/ethereum"; 14 | import { getMintGateway } from "../src/utils/gatewayRegistry"; 15 | import { 16 | filterLogs, 17 | mapLockLogToInputChainTransaction, 18 | } from "../src/utils/generic"; 19 | 20 | loadDotEnv({ path: join(__dirname, "../../../../.env") }); 21 | 22 | chai.should(); 23 | 24 | describe("Logs", () => { 25 | it.skip("LogLock", async () => { 26 | const network = RenNetwork.Testnet; 27 | const ethNetwork = Ethereum.configMap[network]; 28 | 29 | const infuraURL = ethNetwork.config.rpcUrls[0]; 30 | 31 | const provider = new providers.JsonRpcProvider(infuraURL); 32 | 33 | const txHash = 34 | "0x9c272d76e8067833c391af3e0cb5f3e23699db508216816c6a8288fdfbe243a1"; 35 | const receipt = await provider.getTransactionReceipt(txHash); 36 | 37 | const logLockABI = findABIMethod(LockGatewayABI, "LogLockToChain"); 38 | const lockDetails = filterLogs( 39 | receipt.logs, 40 | logLockABI, 41 | ).map((e) => 42 | mapLockLogToInputChainTransaction("Ethereun", "BTC", e.event, ""), 43 | ); 44 | console.debug(lockDetails); 45 | }); 46 | 47 | it("Get mint gateway", async () => { 48 | const network = RenNetwork.Testnet; 49 | const ethNetwork = BinanceSmartChain.configMap[network]; 50 | 51 | const infuraURL = ethNetwork.config.rpcUrls[0]; 52 | 53 | const provider = new providers.JsonRpcProvider(infuraURL); 54 | 55 | console.debug(await getMintGateway(ethNetwork, provider, "DAI")); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "outDir": "build", 5 | "rootDir": "src", 6 | "moduleResolution": "node", 7 | "module": "commonjs", 8 | "declaration": true, 9 | "removeComments": false, 10 | "esModuleInterop": true, 11 | "strict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "traceResolution": false, 17 | "listEmittedFiles": false, 18 | "listFiles": false, 19 | "pretty": true, 20 | "lib": ["es2017", "dom"], 21 | "types": ["node"], 22 | "typeRoots": ["node_modules/@types", "src/types"], 23 | "resolveJsonModule": true, 24 | "forceConsistentCasingInFileNames": true, 25 | "noImplicitThis": true, 26 | "noImplicitAny": true, 27 | "strictNullChecks": true, 28 | "suppressImplicitAnyIndexErrors": true, 29 | "strictPropertyInitialization": true, 30 | "alwaysStrict": true, 31 | "strictFunctionTypes": true, 32 | "sourceMap": true, 33 | "declarationMap": true 34 | }, 35 | "include": ["src/**/*.ts"], 36 | "exclude": ["node_modules/**"], 37 | "compileOnSave": false 38 | } 39 | -------------------------------------------------------------------------------- /packages/chains/chains-ethereum/tsconfig.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "outDir": "build/module", 6 | "module": "es6" 7 | }, 8 | "exclude": ["node_modules/**"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/chains/chains-filecoin/README.md: -------------------------------------------------------------------------------- 1 | # `@renproject/chains-filecoin` 2 | 3 | This package is part of [RenJS](https://github.com/renproject.ren-js). 4 | 5 | See [`@renproject/chains-filecoin` docs](https://renproject.github.io/ren-js-v3-docs/modules/_renproject_chains_filecoin.html) 6 | -------------------------------------------------------------------------------- /packages/chains/chains-filecoin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@renproject/chains-filecoin", 3 | "version": "3.6.0", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/renproject/ren-js.git" 7 | }, 8 | "publishConfig": { 9 | "access": "public", 10 | "directory": "build" 11 | }, 12 | "author": "Ren", 13 | "license": "MIT", 14 | "bugs": { 15 | "url": "https://github.com/renproject/ren-js/issues" 16 | }, 17 | "main": "./build/index.js", 18 | "typings": "./build/index.d.ts", 19 | "module": "./build/module/index.js", 20 | "scripts": { 21 | "clean": "yarn rimraf ./build ./node_modules", 22 | "link": "yarn build:link && cd build && yarn link", 23 | "unlink": "yarn unlink", 24 | "build": "run-s build:*", 25 | "build:main": "tsc -p tsconfig.json", 26 | "build:module": "tsc -p tsconfig.module.json", 27 | "build:link": "cp package.json build && cp README.md build && sed -i.tmp 's/\\/build\\//\\//' ./build/package.json && rm ./build/package.json.tmp", 28 | "prettier": "yarn fix:prettier", 29 | "lint": "run-s lint:*", 30 | "lint:eslint": "eslint --config ../../../.eslintrc.js src", 31 | "lint:prettier": "prettier --check \"./(src|test)/**/*.ts*\"", 32 | "fix": "run-s fix:*", 33 | "fix:eslint": "yarn lint:eslint --fix", 34 | "fix:prettier": "prettier --write './(src|test)/**/*.ts*'", 35 | "test": "run-s test:* lint", 36 | "test:unit": "nyc ../../../node_modules/ts-mocha/bin/ts-mocha --bail --sort --exit --timeout 180000 --paths -p ./tsconfig.json ./test/*.spec.ts ./test/**/*.spec.ts --ignore ./test/testutils/chai.d.ts", 37 | "watch": "run-s build:main && run-s \"build:main -- -w\"", 38 | "cov": "run-s build:main test:unit cov:html && echo \"\n\nTo see coverage, run: 'open coverage/index.html'\n\n\"", 39 | "cov:html": "nyc report --reporter=html", 40 | "cov:send": "nyc report --reporter=lcov && codecov", 41 | "cov:check": "nyc report && nyc check-coverage --lines 0 --functions 0 --branches 0", 42 | "prepare": "yarn build" 43 | }, 44 | "dependencies": { 45 | "@glif/filecoin-address": "1.1.0", 46 | "@glif/filecoin-rpc-client": "1.1.0", 47 | "@renproject/utils": "^3.6.0", 48 | "@types/elliptic": "6.4.14", 49 | "bignumber.js": "9.0.2", 50 | "blakejs": "1.2.1", 51 | "elliptic": "6.5.4", 52 | "multiformats": "9.7.1" 53 | }, 54 | "nyc": { 55 | "extends": "@istanbuljs/nyc-config-typescript", 56 | "exclude": [ 57 | "**/*.d.ts", 58 | "**/*.spec.js" 59 | ], 60 | "include": [ 61 | "src" 62 | ] 63 | }, 64 | "prettier": { 65 | "printWidth": 80, 66 | "semi": true, 67 | "singleQuote": false, 68 | "tabWidth": 4, 69 | "trailingComma": "all", 70 | "endOfLine": "lf", 71 | "arrowParens": "always" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /packages/chains/chains-filecoin/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./filecoin"; 2 | -------------------------------------------------------------------------------- /packages/chains/chains-filecoin/src/utils/declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module "blakejs"; 2 | -------------------------------------------------------------------------------- /packages/chains/chains-filecoin/src/utils/deposit.ts: -------------------------------------------------------------------------------- 1 | export enum FilNetwork { 2 | Mainnet = "mainnet", 3 | Testnet = "testnet", 4 | } 5 | 6 | export interface FilTransaction { 7 | cid: string; 8 | 9 | amount: string; // 18 decimal places 10 | params: string; // base64 11 | confirmations: number; 12 | nonce: number; 13 | 14 | reverted?: boolean; 15 | } 16 | 17 | export interface FilExplorer { 18 | fetchDeposits: ( 19 | address: string, 20 | params?: string | undefined, 21 | page?: number, 22 | ) => Promise; 23 | } 24 | -------------------------------------------------------------------------------- /packages/chains/chains-filecoin/src/utils/lotus.ts: -------------------------------------------------------------------------------- 1 | import FilecoinClient from "@glif/filecoin-rpc-client"; 2 | 3 | import { FilTransaction } from "./deposit"; 4 | 5 | export const getHeight = async (client: FilecoinClient): Promise => { 6 | const chainHead = await client.request("ChainHead"); 7 | return chainHead.Height; 8 | }; 9 | 10 | export const fetchDeposits = async ( 11 | client: FilecoinClient, 12 | address: string, 13 | // params: string | undefined | null, 14 | addressPrefix: string, 15 | fromHeight: number, 16 | latestHeight: number, 17 | ): Promise => { 18 | const latestTXs: Array<{ "/": string }> = await client.request( 19 | "StateListMessages", 20 | { 21 | Version: 0, 22 | To: address, 23 | From: null, 24 | Nonce: 0, 25 | Value: "0", 26 | GasPrice: "0", 27 | GasLimit: 0, 28 | Method: 0, 29 | Params: undefined, 30 | }, 31 | [], 32 | fromHeight, 33 | ); 34 | 35 | return await Promise.all( 36 | (latestTXs || []).map(async (cid) => 37 | fetchMessage(client, cid["/"], addressPrefix, latestHeight), 38 | ), 39 | ); 40 | }; 41 | 42 | export const fetchMessage = async ( 43 | client: FilecoinClient, 44 | cid: string, 45 | addressPrefix: string, 46 | height?: number, 47 | ): Promise => { 48 | const [details, receipt, { Height: chainHeight }]: [ 49 | ChainMessage, 50 | StateMsg | undefined, 51 | { Height: number }, 52 | ] = await Promise.all([ 53 | client.request("ChainGetMessage", { "/": cid }), 54 | client.request("StateSearchMsg", { "/": cid }).catch(() => undefined), 55 | height ? { Height: height } : client.request("ChainHead"), 56 | ]); 57 | 58 | // Fix addresses. 59 | details.To = details.To.replace(/^f/, addressPrefix); 60 | details.From = details.From.replace(/^f/, addressPrefix); 61 | 62 | const tx: FilTransaction = { 63 | cid, 64 | amount: details.Value, 65 | params: details.Params || "", 66 | nonce: details.Nonce, 67 | confirmations: receipt ? chainHeight - receipt.Height : 0, 68 | }; 69 | 70 | return tx; 71 | }; 72 | 73 | export interface ChainMessage { 74 | Version: number; // 0; 75 | To: string; // "t1gvyvits5chiahib7cz6uyh6kijgqgycnaiuj47i"; 76 | From: string; // "t14wczuvodunv3xzexobzywpbj6qpr6jwdrbkrmbq"; 77 | Nonce: number; // 20; 78 | Value: string; // "1000000000000000000"; 79 | GasLimit: number; // 609960; 80 | GasFeeCap: string; // "101409"; 81 | GasPremium: string; // "100355"; 82 | Method: number; // 0; 83 | Params: string | null; // null; 84 | CID: { 85 | "/": string; // "bafy2bzacebhs4svm2bl5zq5geaxtywctwlo2sys7udbefpggsrouwfcepv5vu"; 86 | }; 87 | } 88 | 89 | export interface StateMsg { 90 | Message: { 91 | "/": string; // "bafy2bzaceaq23gg46ii4zowpnzpo33252t5lsdxxfpa5d7cyezsaczqdzefl2"; 92 | }; 93 | Receipt: { 94 | ExitCode: number; // 0; 95 | Return: null; // null; 96 | GasUsed: number; // 487968 97 | }; 98 | ReturnDec: null; // null; 99 | TipSet: [ 100 | { 101 | "/": string; // "bafy2bzaced6lrvssnkr27dd5akp4zxr2awjxjl73s5meaq42j7sacfwastfpi"; 102 | }, 103 | ]; 104 | Height: number; // 174172; 105 | } 106 | -------------------------------------------------------------------------------- /packages/chains/chains-filecoin/src/utils/utils.ts: -------------------------------------------------------------------------------- 1 | import { CID } from "multiformats"; 2 | 3 | /** 4 | * Convert a Filecoin transaction hash from its standard format to the format 5 | * required by RenVM. 6 | * 7 | * @param txHash A Filecoin transaction hash formatted as a CID string. 8 | * @returns The same Filecoin transaction hash as bytes. 9 | */ 10 | export const txHashToBytes = (txHash: string): Uint8Array => { 11 | return new Uint8Array(CID.parse(txHash).bytes); 12 | }; 13 | 14 | /** 15 | * Convert a Filecoin transaction hash from the format required by RenVM to its 16 | * standard format. 17 | * 18 | * @param bytes A Filecoin transaction hash as bytes. 19 | * @returns The same Filecoin transaction hash formatted as a CID string. 20 | */ 21 | export const txHashFromBytes = (bytes: Uint8Array): string => { 22 | return CID.decode(bytes).toString(); 23 | }; 24 | -------------------------------------------------------------------------------- /packages/chains/chains-filecoin/test/explorers.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { join } from "path"; 4 | 5 | import chai from "chai"; 6 | import { config as loadDotEnv } from "dotenv"; 7 | 8 | import { Filfox } from "../src/utils/filfox"; 9 | 10 | chai.should(); 11 | 12 | loadDotEnv({ path: join(__dirname, "../../../../.env") }); 13 | 14 | describe.skip("Filecoin explorers", () => { 15 | it("mint to contract", async () => { 16 | const filfox = new Filfox("mainnet"); 17 | 18 | console.debug( 19 | "filfox", 20 | await filfox.fetchDeposits( 21 | "f15wjyn36z6x5ypq7f73yaolqbxyiiwkg5mmuyo2q", 22 | 0, 23 | 1, 24 | ), 25 | ); 26 | }).timeout(100000000000); 27 | }); 28 | -------------------------------------------------------------------------------- /packages/chains/chains-filecoin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "outDir": "build", 5 | "rootDir": "src", 6 | "moduleResolution": "node", 7 | "module": "commonjs", 8 | "declaration": true, 9 | "removeComments": false, 10 | "esModuleInterop": true, 11 | "strict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "traceResolution": false, 17 | "listEmittedFiles": false, 18 | "listFiles": false, 19 | "pretty": true, 20 | "lib": ["es2017", "dom"], 21 | "types": ["node"], 22 | "typeRoots": ["node_modules/@types", "src/types"], 23 | "resolveJsonModule": true, 24 | "forceConsistentCasingInFileNames": true, 25 | "noImplicitThis": true, 26 | "noImplicitAny": true, 27 | "strictNullChecks": true, 28 | "suppressImplicitAnyIndexErrors": true, 29 | "strictPropertyInitialization": true, 30 | "alwaysStrict": true, 31 | "strictFunctionTypes": true, 32 | "sourceMap": true, 33 | "declarationMap": true 34 | }, 35 | "include": ["src/**/*.ts"], 36 | "exclude": ["node_modules/**"], 37 | "compileOnSave": false 38 | } 39 | -------------------------------------------------------------------------------- /packages/chains/chains-filecoin/tsconfig.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "outDir": "build/module", 6 | "module": "es6" 7 | }, 8 | "exclude": ["node_modules/**"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/chains/chains-solana/README.md: -------------------------------------------------------------------------------- 1 | # `@renproject/chains-solana` 2 | 3 | This package is part of [RenJS](https://github.com/renproject.ren-js). 4 | 5 | See [`@renproject/chains-solana` docs](https://renproject.github.io/ren-js-v3-docs/modules/_renproject_chains_solana.html) 6 | -------------------------------------------------------------------------------- /packages/chains/chains-solana/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@renproject/chains-solana", 3 | "version": "3.6.0", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/renproject/ren-js.git" 7 | }, 8 | "publishConfig": { 9 | "access": "public", 10 | "directory": "build" 11 | }, 12 | "author": "Ren", 13 | "license": "MIT", 14 | "bugs": { 15 | "url": "https://github.com/renproject/ren-js/issues" 16 | }, 17 | "main": "./build/index.js", 18 | "typings": "./build/index.d.ts", 19 | "module": "./build/module/index.js", 20 | "scripts": { 21 | "clean": "yarn rimraf ./build ./node_modules", 22 | "link": "yarn build:link && cd build && yarn link", 23 | "unlink": "yarn unlink", 24 | "build": "run-s build:*", 25 | "build:main": "tsc -p tsconfig.json", 26 | "build:module": "tsc -p tsconfig.module.json", 27 | "build:link": "cp package.json build && cp README.md build && sed -i.tmp 's/\\/build\\//\\//' ./build/package.json && rm ./build/package.json.tmp", 28 | "prettier": "yarn fix:prettier", 29 | "lint": "run-s lint:*", 30 | "lint:eslint": "eslint --config ../../../.eslintrc.js src", 31 | "lint:prettier": "prettier --check \"./(src|test)/**/*.ts*\"", 32 | "fix": "run-s fix:*", 33 | "fix:eslint": "yarn lint:eslint --fix", 34 | "fix:prettier": "prettier --write './(src|test)/**/*.ts*'", 35 | "test": "run-s test:* lint", 36 | "test:unit": "nyc ../../../node_modules/ts-mocha/bin/ts-mocha --bail --sort --exit --timeout 180000 --paths -p ./tsconfig.json ./test/*.spec.ts ./test/**/*.spec.ts --ignore ./test/testutils/chai.d.ts", 37 | "watch": "run-s build:main && run-s \"build:main -- -w\"", 38 | "cov": "run-s build:main test:unit cov:html && echo \"\n\nTo see coverage, run: 'open coverage/index.html'\n\n\"", 39 | "cov:html": "nyc report --reporter=html", 40 | "cov:send": "nyc report --reporter=lcov && codecov", 41 | "cov:check": "nyc report && nyc check-coverage --lines 0 --functions 0 --branches 0", 42 | "prepare": "yarn build" 43 | }, 44 | "dependencies": { 45 | "@renproject/utils": "^3.6.0", 46 | "@scure/bip39": "1.1.0", 47 | "@solana/spl-token": "0.2.0", 48 | "@solana/web3.js": "1.50.1", 49 | "@types/bs58": "4.0.1", 50 | "@types/node-fetch": "2.6.2", 51 | "bignumber.js": "9.0.2", 52 | "bs58": "5.0.0", 53 | "buffer-layout": "1.2.2", 54 | "ed25519-hd-key": "1.3.0", 55 | "tweetnacl": "1.0.3" 56 | }, 57 | "nyc": { 58 | "extends": "@istanbuljs/nyc-config-typescript", 59 | "exclude": [ 60 | "**/*.d.ts", 61 | "**/*.spec.js" 62 | ], 63 | "include": [ 64 | "src" 65 | ] 66 | }, 67 | "prettier": { 68 | "printWidth": 80, 69 | "semi": true, 70 | "singleQuote": false, 71 | "tabWidth": 4, 72 | "trailingComma": "all", 73 | "endOfLine": "lf", 74 | "arrowParens": "always" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /packages/chains/chains-solana/src/declarations/declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module "buffer-layout"; 2 | -------------------------------------------------------------------------------- /packages/chains/chains-solana/src/index.ts: -------------------------------------------------------------------------------- 1 | export { Solana } from "./solana"; 2 | export * from "./types/types"; 3 | 4 | export { SolNetworkConfig, renMainnet, renTestnet } from "./networks"; 5 | export { signerFromPrivateKey } from "./utils"; 6 | -------------------------------------------------------------------------------- /packages/chains/chains-solana/src/networks.ts: -------------------------------------------------------------------------------- 1 | import { RenNetwork } from "@renproject/utils"; 2 | 3 | export interface SolNetworkConfig { 4 | name: RenNetwork; 5 | symbol: string; 6 | chain: string; 7 | isTestnet?: boolean; 8 | chainLabel: string; 9 | 10 | nativeAsset: { 11 | name: string; 12 | symbol: string; 13 | decimals: number; 14 | }; 15 | averageConfirmationTime: number; 16 | 17 | chainExplorer: string; 18 | endpoint: string; 19 | addresses: { 20 | GatewayRegistry: string; 21 | }; 22 | // used for identifying the network (similar to chainID in eth) 23 | genesisHash: string; 24 | } 25 | 26 | const isSolNetworkConfig = (x: unknown): x is SolNetworkConfig => 27 | (x as SolNetworkConfig).genesisHash !== undefined; 28 | 29 | export const resolveNetwork = ( 30 | networkInput: RenNetwork | `${RenNetwork}` | SolNetworkConfig, 31 | ): SolNetworkConfig => { 32 | if (typeof networkInput === "string") { 33 | switch (networkInput) { 34 | case RenNetwork.Mainnet: 35 | return renMainnet; 36 | case RenNetwork.Testnet: 37 | return renTestnet; 38 | } 39 | throw new Error(`Unrecognized solana network ${networkInput}.`); 40 | } 41 | if (isSolNetworkConfig(networkInput)) { 42 | return networkInput; 43 | } 44 | // TODO: Throw better error and point out any missing fields. 45 | throw new Error( 46 | `Unrecognized solana network configuration (${String(networkInput)}).`, 47 | ); 48 | }; 49 | 50 | export const renMainnet: SolNetworkConfig = { 51 | name: RenNetwork.Mainnet, 52 | symbol: "SOL", 53 | chain: "mainnet-beta", 54 | chainLabel: "Mainnet Beta", 55 | 56 | nativeAsset: { 57 | name: "Solana", 58 | symbol: "SOL", 59 | decimals: 18, 60 | }, 61 | averageConfirmationTime: 0.5, 62 | 63 | endpoint: "https://ren.rpcpool.com/", 64 | chainExplorer: "https://explorer.solana.com", 65 | addresses: { 66 | GatewayRegistry: "REGrPFKQhRneFFdUV3e9UDdzqUJyS6SKj88GdXFCRd2", 67 | }, 68 | genesisHash: "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d", 69 | }; 70 | 71 | export const renTestnet: SolNetworkConfig = { 72 | name: RenNetwork.Testnet, 73 | symbol: "SOL", 74 | chain: "devnet", 75 | isTestnet: true, 76 | chainLabel: "Devnet", 77 | 78 | nativeAsset: { 79 | name: "Solana", 80 | symbol: "SOL", 81 | decimals: 18, 82 | }, 83 | averageConfirmationTime: 0.5, 84 | 85 | endpoint: "https://api.devnet.solana.com", 86 | chainExplorer: "https://explorer.solana.com", 87 | addresses: { 88 | GatewayRegistry: "REGrPFKQhRneFFdUV3e9UDdzqUJyS6SKj88GdXFCRd2", 89 | }, 90 | genesisHash: "EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG", 91 | }; 92 | -------------------------------------------------------------------------------- /packages/chains/chains-solana/src/types/types.ts: -------------------------------------------------------------------------------- 1 | import { ChainTransaction } from "@renproject/utils"; 2 | import { Connection } from "@solana/web3.js"; 3 | 4 | import { Wallet } from "../wallet"; 5 | 6 | export type SolanaProvider = Connection; 7 | export type SolanaSigner = Wallet; 8 | 9 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 10 | export interface SolanaPayloadInterface { 11 | chain: string; 12 | type: Name; 13 | params: T; 14 | setup?: { 15 | [name: string]: SolanaPayloadInterface; 16 | }; 17 | } 18 | 19 | export type MintToAddress = SolanaPayloadInterface< 20 | "mintToAddress", 21 | { 22 | to: string; 23 | } 24 | >; 25 | 26 | export type MintToTokenAddress = SolanaPayloadInterface< 27 | "mintToTokenAddress", 28 | { 29 | to: string; 30 | } 31 | >; 32 | 33 | export type BurnFromAddress = SolanaPayloadInterface< 34 | "burnToAddress", 35 | { 36 | amount: number | string; 37 | convertUnit?: boolean; 38 | address?: string; 39 | } 40 | >; 41 | 42 | export type BurnNonce = SolanaPayloadInterface< 43 | "burnNonce", 44 | { 45 | burnNonce: string | number; 46 | } 47 | >; 48 | 49 | export type Transaction = SolanaPayloadInterface< 50 | "transaction", 51 | { 52 | tx: ChainTransaction; 53 | } 54 | >; 55 | 56 | export type SolanaOutputPayload = MintToAddress | MintToTokenAddress; 57 | export type SolanaInputPayload = BurnFromAddress | BurnNonce | Transaction; 58 | -------------------------------------------------------------------------------- /packages/chains/chains-solana/src/wallet.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey, Transaction } from "@solana/web3.js"; 2 | 3 | // See @project-serum/sol-wallet-adapter 4 | export type Wallet = { 5 | signTransaction(transaction: Transaction): Promise; 6 | publicKey: PublicKey; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/chains/chains-solana/test/utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { Connection } from "@solana/web3.js"; 2 | import { expect } from "chai"; 3 | 4 | import { Solana } from "../src"; 5 | import { signerFromMnemonic, signerFromPrivateKey } from "../src/utils"; 6 | 7 | describe("Utils", () => { 8 | it("validateTransaction", () => { 9 | const solana = new Solana({ 10 | network: "testnet", 11 | provider: {} as unknown as Connection, 12 | }); 13 | 14 | expect( 15 | solana.validateTransaction({ 16 | txHash: "3mabcf8u7eduVN3GfM8nyGwJ3g3GqApqbGq8m2CtoakgeEVHsw1ZgqSL7KWCRaEdK9rcHUwWNfpkGAb17ewC6XwV", 17 | }), 18 | ).to.be.true; 19 | 20 | expect( 21 | solana.validateTransaction({ 22 | txHash: "3mabcf8u7eduVN3GfM8nyGwJ3g3GqApqbGq8m2CtoakgeEVHsw1ZgqSL7KWCRaEdK9rcHUwWNfpkGAb17ewC6XwV", 23 | txid: "ino6crZYCRm5Lm6kMlt9hZo68stwCZywdXZdsttSXoB_tDfB7cB4fDdeBX-xodXoFwZl3MfKpwDj0_tKDogfCA", 24 | txindex: "0", 25 | }), 26 | ).to.be.true; 27 | }); 28 | 29 | it("signerFromMnemonic", () => { 30 | // Test mnemonic - DO NOT USE. 31 | const mnemonic = 32 | "fiber quarter possible fluid fatal harvest layer harsh east neck jewel marine"; 33 | 34 | const signer1 = signerFromMnemonic(mnemonic); 35 | expect(signer1.publicKey.toBase58()).to.equal( 36 | "GCQcNnHZ712nkkNeGFhHRj22qbps3tmvesSu2bhb3U4f", 37 | ); 38 | 39 | const signer2 = signerFromMnemonic(mnemonic, "m/44'/501'/0'"); 40 | expect(signer2.publicKey.toBase58()).to.equal( 41 | "8dMCt1MtKNaFrBJeb6Bp5FETSqQPqB4gGsAFqWpsNvoc", 42 | ); 43 | }); 44 | 45 | it("signerFromPrivateKey", () => { 46 | // Test private keys - DO NOT USE. 47 | 48 | // From hex. 49 | const signer1 = signerFromPrivateKey( 50 | "1cd9ae6e2b1ba34523096765bae7f0f95563254469934e97c3c282171748f57ae1cb637c9b36af38f20615450a15d45278825cad9dc2c59e2a2e4e77fad57210", 51 | ); 52 | expect(signer1.publicKey.toBase58()).to.equal( 53 | "GCQcNnHZ712nkkNeGFhHRj22qbps3tmvesSu2bhb3U4f", 54 | ); 55 | 56 | // From base58. 57 | const signer2 = signerFromPrivateKey( 58 | "aTPc1419CrWBNz95E5YNpaR6Tq1D1Jnq2XiyoGy9TdyrFSmYJRmZ8DBcETrWWhJg6s5g9Q6Xss9GstKntEUdVGB", 59 | ); 60 | expect(signer2.publicKey.toBase58()).to.equal( 61 | "GCQcNnHZ712nkkNeGFhHRj22qbps3tmvesSu2bhb3U4f", 62 | ); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /packages/chains/chains-solana/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "outDir": "build", 5 | "downlevelIteration": true, 6 | "rootDir": "src", 7 | "moduleResolution": "node", 8 | "module": "commonjs", 9 | "declaration": true, 10 | "removeComments": false, 11 | "esModuleInterop": true, 12 | "strict": true, 13 | "noUnusedLocals": false, 14 | "noUnusedParameters": true, 15 | "noImplicitReturns": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "traceResolution": false, 18 | "listEmittedFiles": false, 19 | "listFiles": false, 20 | "pretty": true, 21 | "lib": ["es2017", "dom"], 22 | "types": ["node"], 23 | "typeRoots": ["node_modules/@types", "src/types"], 24 | "resolveJsonModule": true, 25 | "forceConsistentCasingInFileNames": true, 26 | "noImplicitThis": true, 27 | "noImplicitAny": true, 28 | "strictNullChecks": true, 29 | "suppressImplicitAnyIndexErrors": true, 30 | "strictPropertyInitialization": true, 31 | "alwaysStrict": true, 32 | "strictFunctionTypes": true, 33 | "sourceMap": true, 34 | "declarationMap": true, 35 | "skipLibCheck": true 36 | }, 37 | "include": ["src/**/*.ts"], 38 | "exclude": ["node_modules/**"], 39 | "compileOnSave": false 40 | } 41 | -------------------------------------------------------------------------------- /packages/chains/chains-solana/tsconfig.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "target": "es2020", 5 | "outDir": "build/module", 6 | "module": "es2020" 7 | }, 8 | "exclude": ["node_modules/**"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/chains/chains-terra/README.md: -------------------------------------------------------------------------------- 1 | # `@renproject/chains-terra` 2 | 3 | This package is part of [RenJS](https://github.com/renproject.ren-js). 4 | 5 | See [`@renproject/chains-terra` docs](https://renproject.github.io/ren-js-v3-docs/modules/_renproject_chains_terra.html) 6 | -------------------------------------------------------------------------------- /packages/chains/chains-terra/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@renproject/chains-terra", 3 | "version": "3.6.0", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/renproject/ren-js.git" 7 | }, 8 | "publishConfig": { 9 | "access": "public", 10 | "directory": "build" 11 | }, 12 | "author": "Ren", 13 | "license": "MIT", 14 | "bugs": { 15 | "url": "https://github.com/renproject/ren-js/issues" 16 | }, 17 | "main": "./build/index.js", 18 | "typings": "./build/index.d.ts", 19 | "module": "./build/module/index.js", 20 | "scripts": { 21 | "clean": "yarn rimraf ./build ./node_modules", 22 | "link": "yarn build:link && cd build && yarn link", 23 | "unlink": "yarn unlink", 24 | "build": "run-s build:*", 25 | "build:main": "tsc -p tsconfig.json", 26 | "build:module": "tsc -p tsconfig.module.json", 27 | "build:link": "cp package.json build && cp README.md build && sed -i.tmp 's/\\/build\\//\\//' ./build/package.json && rm ./build/package.json.tmp", 28 | "prettier": "yarn fix:prettier", 29 | "lint": "run-s lint:*", 30 | "lint:eslint": "eslint --config ../../../.eslintrc.js src", 31 | "lint:prettier": "prettier --check \"./(src|test)/**/*.ts*\"", 32 | "fix": "run-s fix:*", 33 | "fix:eslint": "yarn lint:eslint --fix", 34 | "fix:prettier": "prettier --write './(src|test)/**/*.ts*'", 35 | "test": "run-s test:* lint", 36 | "test:unit": "nyc ../../../node_modules/ts-mocha/bin/ts-mocha --bail --sort --exit --timeout 180000 --paths -p ./tsconfig.json ./test/*.spec.ts ./test/**/*.spec.ts --ignore ./test/testutils/chai.d.ts", 37 | "watch": "run-s build:main && run-s \"build:main -- -w\"", 38 | "cov": "run-s build:main test:unit cov:html && echo \"\n\nTo see coverage, run: 'open coverage/index.html'\n\n\"", 39 | "cov:html": "nyc report --reporter=html", 40 | "cov:send": "nyc report --reporter=lcov && codecov", 41 | "cov:check": "nyc report && nyc check-coverage --lines 0 --functions 0 --branches 0", 42 | "prepare": "yarn build" 43 | }, 44 | "dependencies": { 45 | "@renproject/utils": "^3.6.0", 46 | "@terra-money/terra.js": "3.1.5", 47 | "@types/elliptic": "6.4.14", 48 | "bech32": "2.0.0", 49 | "bignumber.js": "9.0.2", 50 | "elliptic": "6.5.4" 51 | }, 52 | "nyc": { 53 | "extends": "@istanbuljs/nyc-config-typescript", 54 | "exclude": [ 55 | "**/*.d.ts", 56 | "**/*.spec.js" 57 | ], 58 | "include": [ 59 | "src" 60 | ] 61 | }, 62 | "prettier": { 63 | "printWidth": 80, 64 | "semi": true, 65 | "singleQuote": false, 66 | "tabWidth": 4, 67 | "trailingComma": "all", 68 | "endOfLine": "lf", 69 | "arrowParens": "always" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /packages/chains/chains-terra/src/api/types.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from "bignumber.js"; 2 | 3 | export interface TerraNetworkConfig { 4 | selector: string; 5 | chainId: string; 6 | addressPrefix: string; 7 | isTestnet?: boolean; 8 | 9 | nativeAsset: { 10 | name: string; 11 | symbol: string; 12 | decimals: number; 13 | }; 14 | averageConfirmationTime: number; 15 | explorer: string; 16 | apiUrl: string; 17 | } 18 | 19 | export const isTerraNetworkConfig = ( 20 | renNetwork: unknown, 21 | ): renNetwork is TerraNetworkConfig => 22 | !!(renNetwork as TerraNetworkConfig).selector && 23 | !!(renNetwork as TerraNetworkConfig).chainId && 24 | !!(renNetwork as TerraNetworkConfig).nativeAsset && 25 | !!(renNetwork as TerraNetworkConfig).explorer && 26 | !!(renNetwork as TerraNetworkConfig).apiUrl; 27 | 28 | export interface TerraTransaction { 29 | hash: string; 30 | from: string; 31 | to: string; 32 | denomination: string; 33 | amount: string; 34 | memo: string; 35 | confirmations: number; 36 | messageIndex: number; 37 | } 38 | 39 | export interface TerraAPI { 40 | fetchDeposits: ( 41 | address: string, 42 | memo?: string | undefined, 43 | page?: number, 44 | ) => Promise; 45 | 46 | fetchConfirmations: (hash: string) => Promise; 47 | } 48 | -------------------------------------------------------------------------------- /packages/chains/chains-terra/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./terra"; 2 | -------------------------------------------------------------------------------- /packages/chains/chains-terra/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { utils } from "@renproject/utils"; 2 | 3 | /** 4 | * Convert a Terra transaction hash from its standard format to the format 5 | * required by RenVM. 6 | * 7 | * @param txHash A Terra transaction hash formatted as an unprefixed 8 | * hex string. 9 | * @returns The same Terra transaction hash formatted as a base64 string. 10 | */ 11 | export const txHashToBytes = (txHash: string): Uint8Array => { 12 | return utils.fromHex(txHash); 13 | }; 14 | 15 | /** 16 | * Convert a Terra transaction hash from the format required by RenVM to its 17 | * standard format. 18 | * 19 | * @param bytes A Terra transaction hash formatted as a base64 string. 20 | * @returns The same Terra transaction hash formatted as an unprefixed hex 21 | * string. 22 | */ 23 | export const txHashFromBytes = (bytes: Uint8Array): string => { 24 | return utils.toHex(bytes).toUpperCase(); 25 | }; 26 | -------------------------------------------------------------------------------- /packages/chains/chains-terra/test/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | 3 | import { Terra } from "../src"; 4 | 5 | describe("@renproject/chains-terra", () => { 6 | it("should export Terra correctly", async () => { 7 | expect(Terra).not.to.equal(undefined); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/chains/chains-terra/test/utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | 3 | import { Terra } from "../src"; 4 | 5 | describe("Utils", () => { 6 | it("validateTransaction", () => { 7 | const terra = new Terra({ 8 | network: "testnet", 9 | }); 10 | 11 | expect( 12 | terra.validateTransaction({ 13 | txHash: "79EC7C5DBA526D3C3B7CCCFFDA1B06F16D3E2402A3D6B82D7D251F26B68C4489", 14 | }), 15 | ).to.be.true; 16 | 17 | expect( 18 | terra.validateTransaction({ 19 | txHash: "79EC7C5DBA526D3C3B7CCCFFDA1B06F16D3E2402A3D6B82D7D251F26B68C4489", 20 | txid: "eex8XbpSbTw7fMz_2hsG8W0-JAKj1rgtfSUfJraMRIk", 21 | txindex: "0", 22 | }), 23 | ).to.be.true; 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /packages/chains/chains-terra/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "outDir": "build", 5 | "rootDir": "src", 6 | "moduleResolution": "node", 7 | "module": "commonjs", 8 | "declaration": true, 9 | "removeComments": false, 10 | "esModuleInterop": true, 11 | "strict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "traceResolution": false, 17 | "listEmittedFiles": false, 18 | "listFiles": false, 19 | "pretty": true, 20 | "lib": ["es2017", "dom"], 21 | "types": ["node"], 22 | "typeRoots": ["node_modules/@types", "src/types"], 23 | "resolveJsonModule": true, 24 | "forceConsistentCasingInFileNames": true, 25 | "noImplicitThis": true, 26 | "noImplicitAny": true, 27 | "strictNullChecks": true, 28 | "suppressImplicitAnyIndexErrors": true, 29 | "strictPropertyInitialization": true, 30 | "alwaysStrict": true, 31 | "strictFunctionTypes": true, 32 | "sourceMap": true, 33 | "declarationMap": true 34 | }, 35 | "include": ["src/**/*.ts"], 36 | "exclude": ["node_modules/**"], 37 | "compileOnSave": false 38 | } 39 | -------------------------------------------------------------------------------- /packages/chains/chains-terra/tsconfig.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "outDir": "build/module", 6 | "module": "es6" 7 | }, 8 | "exclude": ["node_modules/**"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/chains/chains/README.md: -------------------------------------------------------------------------------- 1 | # `@renproject/chains` 2 | 3 | This package is part of [RenJS](https://github.com/renproject.ren-js). 4 | 5 | See [`@renproject/chains` docs](https://renproject.github.io/ren-js-v3-docs/modules/_renproject_chains.html) 6 | -------------------------------------------------------------------------------- /packages/chains/chains/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@renproject/chains", 3 | "version": "3.6.0", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/renproject/ren-js.git" 7 | }, 8 | "publishConfig": { 9 | "access": "public", 10 | "directory": "build" 11 | }, 12 | "author": "Ren", 13 | "license": "MIT", 14 | "bugs": { 15 | "url": "https://github.com/renproject/ren-js/issues" 16 | }, 17 | "main": "./build/index.js", 18 | "typings": "./build/index.d.ts", 19 | "module": "./build/module/index.js", 20 | "scripts": { 21 | "clean": "yarn rimraf ./build ./node_modules", 22 | "link": "yarn build:link && cd build && yarn link", 23 | "unlink": "yarn unlink", 24 | "build": "run-s build:*", 25 | "build:main": "tsc -p tsconfig.json", 26 | "build:module": "tsc -p tsconfig.module.json", 27 | "build:link": "cp package.json build && cp README.md build && sed -i.tmp 's/\\/build\\//\\//' ./build/package.json && rm ./build/package.json.tmp", 28 | "prettier": "yarn fix:prettier", 29 | "lint": "run-s lint:*", 30 | "lint:eslint": "eslint --config ../../../.eslintrc.js src", 31 | "lint:prettier": "prettier --check \"./(src|test)/**/*.ts*\"", 32 | "fix": "run-s fix:*", 33 | "fix:eslint": "yarn lint:eslint --fix", 34 | "fix:prettier": "prettier --write './(src|test)/**/*.ts*'", 35 | "test": "run-s test:* lint", 36 | "test:unit": "nyc ../../../node_modules/ts-mocha/bin/ts-mocha --bail --sort --exit --timeout 180000 --paths -p ./tsconfig.json ./test/*.spec.ts ./test/**/*.spec.ts --ignore ./test/testutils/chai.d.ts", 37 | "watch": "run-s build:main && run-s \"build:main -- -w\"", 38 | "cov": "run-s build:main test:unit cov:html && echo \"\n\nTo see coverage, run: 'open coverage/index.html'\n\n\"", 39 | "cov:html": "nyc report --reporter=html", 40 | "cov:send": "nyc report --reporter=lcov && codecov", 41 | "cov:check": "nyc report && nyc check-coverage --lines 0 --functions 0 --branches 0", 42 | "prepare": "yarn build" 43 | }, 44 | "dependencies": { 45 | "@renproject/chains-bitcoin": "^3.6.0", 46 | "@renproject/chains-ethereum": "^3.6.0", 47 | "@renproject/chains-filecoin": "^3.6.0", 48 | "@renproject/chains-solana": "^3.6.0", 49 | "@renproject/chains-terra": "^3.6.0", 50 | "@renproject/utils": "^3.6.0" 51 | }, 52 | "nyc": { 53 | "extends": "@istanbuljs/nyc-config-typescript", 54 | "exclude": [ 55 | "**/*.d.ts", 56 | "**/*.spec.js" 57 | ], 58 | "include": [ 59 | "src" 60 | ] 61 | }, 62 | "prettier": { 63 | "printWidth": 80, 64 | "semi": true, 65 | "singleQuote": false, 66 | "tabWidth": 4, 67 | "trailingComma": "all", 68 | "endOfLine": "lf", 69 | "arrowParens": "always" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /packages/chains/chains/src/declarations/declarations.d.ts: -------------------------------------------------------------------------------- 1 | // declare module "wallet-address-validator"; 2 | // declare module "wallet-address-validator/src/bitcoin_validator"; 3 | // declare module "blakejs"; 4 | declare module "buffer-layout"; 5 | -------------------------------------------------------------------------------- /packages/chains/chains/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "@renproject/chains-bitcoin"; 2 | export * from "@renproject/chains-ethereum"; 3 | export * from "@renproject/chains-filecoin"; 4 | export * from "@renproject/chains-terra"; 5 | export * from "@renproject/chains-solana"; 6 | 7 | import { 8 | Bitcoin, 9 | BitcoinCash, 10 | DigiByte, 11 | Dogecoin, 12 | Zcash, 13 | } from "@renproject/chains-bitcoin"; 14 | import { 15 | Arbitrum, 16 | Avalanche, 17 | BinanceSmartChain, 18 | Catalog, 19 | Ethereum, 20 | Fantom, 21 | Goerli, 22 | Kava, 23 | Moonbeam, 24 | Optimism, 25 | Polygon, 26 | } from "@renproject/chains-ethereum"; 27 | import { Filecoin } from "@renproject/chains-filecoin"; 28 | import { Solana } from "@renproject/chains-solana"; 29 | import { Terra } from "@renproject/chains-terra"; 30 | import { RenNetwork } from "@renproject/utils"; 31 | 32 | export const chains = { 33 | Arbitrum, 34 | Avalanche, 35 | BinanceSmartChain, 36 | Bitcoin, 37 | BitcoinCash, 38 | Catalog, 39 | DigiByte, 40 | Dogecoin, 41 | Ethereum, 42 | Fantom, 43 | Filecoin, 44 | Goerli, 45 | Kava, 46 | Moonbeam, 47 | Optimism, 48 | Polygon, 49 | Solana, 50 | Terra, 51 | Zcash, 52 | }; 53 | 54 | export enum Asset { 55 | ArbETH = "ArbETH", 56 | AVAX = "AVAX", 57 | BADGER = "BADGER", 58 | BCH = "BCH", 59 | BNB = "BNB", 60 | BTC = "BTC", 61 | BUSD = "BUSD", 62 | CRV = "CRV", 63 | DAI = "DAI", 64 | DGB = "DGB", 65 | DOGE = "DOGE", 66 | ETH = "ETH", 67 | EURT = "EURT", 68 | FIL = "FIL", 69 | FTM = "FTM", 70 | FTT = "FTT", 71 | gETH = "gETH", 72 | GLMR = "GLMR", 73 | KAVA = "KAVA", 74 | KNC = "KNC", 75 | LINK = "LINK", 76 | LUNA = "LUNA", 77 | MATIC = "MATIC", 78 | MIM = "MIM", 79 | oETH = "oETH", 80 | REN = "REN", 81 | ROOK = "ROOK", 82 | SOL = "SOL", 83 | SUSHI = "SUSHI", 84 | UNI = "UNI", 85 | USDC = "USDC", 86 | USDT = "USDT", 87 | ZEC = "ZEC", 88 | } 89 | 90 | export const assets = Object.values(chains).reduce( 91 | (acc, chain) => 92 | acc.concat( 93 | Object.values( 94 | chain.assets[RenNetwork.Mainnet] || 95 | chain.assets[RenNetwork.Testnet], 96 | ), 97 | ), 98 | [], 99 | ); 100 | 101 | /* eslint-disable @typescript-eslint/no-shadow */ 102 | export enum Chain { 103 | Arbitrum = "Arbitrum", 104 | Avalanche = "Avalanche", 105 | BinanceSmartChain = "BinanceSmartChain", 106 | Bitcoin = "Bitcoin", 107 | BitcoinCash = "BitcoinCash", 108 | DigiByte = "DigiByte", 109 | Dogecoin = "Dogecoin", 110 | Ethereum = "Ethereum", 111 | Fantom = "Fantom", 112 | Filecoin = "Filecoin", 113 | Goerli = "Goerli", 114 | Kava = "Kava", 115 | Moonbeam = "Moonbeam", 116 | Optimism = "Optimism", 117 | Polygon = "Polygon", 118 | Catalog = "Catalog", 119 | Solana = "Solana", 120 | Terra = "Terra", 121 | Zcash = "Zcash", 122 | } 123 | 124 | export default chains; 125 | -------------------------------------------------------------------------------- /packages/chains/chains/test/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | 3 | import * as Chains from "../src"; 4 | 5 | describe("@renproject/chains", () => { 6 | it("should export chains correctly", async () => { 7 | expect(Chains.Ethereum).not.to.equal(undefined); 8 | expect(Chains.Bitcoin).not.to.equal(undefined); 9 | expect(Chains.BitcoinCash).not.to.equal(undefined); 10 | expect(Chains.Zcash).not.to.equal(undefined); 11 | expect(Chains.BinanceSmartChain).not.to.equal(undefined); 12 | expect(Chains.Solana).not.to.equal(undefined); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/chains/chains/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "outDir": "build", 5 | "rootDir": "src", 6 | "moduleResolution": "node", 7 | "module": "commonjs", 8 | "declaration": true, 9 | "removeComments": false, 10 | "esModuleInterop": true, 11 | "strict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "traceResolution": false, 17 | "listEmittedFiles": false, 18 | "listFiles": false, 19 | "pretty": true, 20 | "lib": ["es2017", "dom"], 21 | "types": ["node"], 22 | "typeRoots": ["node_modules/@types", "src/types"], 23 | "resolveJsonModule": true, 24 | "forceConsistentCasingInFileNames": true, 25 | "noImplicitThis": true, 26 | "noImplicitAny": true, 27 | "strictNullChecks": true, 28 | "suppressImplicitAnyIndexErrors": true, 29 | "strictPropertyInitialization": true, 30 | "alwaysStrict": true, 31 | "strictFunctionTypes": true, 32 | "sourceMap": true, 33 | "declarationMap": true 34 | }, 35 | "include": ["src/**/*.ts"], 36 | "exclude": ["node_modules/**"], 37 | "compileOnSave": false 38 | } 39 | -------------------------------------------------------------------------------- /packages/chains/chains/tsconfig.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "outDir": "build/module", 6 | "module": "es6" 7 | }, 8 | "exclude": ["node_modules/**"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/mock-provider/README.md: -------------------------------------------------------------------------------- 1 | # `@renproject/mock-provider` 2 | 3 | This package is part of [RenJS](https://github.com/renproject.ren-js). 4 | 5 | See [`@renproject/mock-provider` docs](https://renproject.github.io/ren-js-v3-docs/modules/_renproject_mock_provider.html) 6 | -------------------------------------------------------------------------------- /packages/mock-provider/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@renproject/mock-provider", 3 | "version": "3.6.0", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/renproject/ren-js.git" 7 | }, 8 | "publishConfig": { 9 | "access": "public", 10 | "directory": "build" 11 | }, 12 | "author": "Ren", 13 | "license": "MIT", 14 | "bugs": { 15 | "url": "https://github.com/renproject/ren-js/issues" 16 | }, 17 | "main": "./build/index.js", 18 | "typings": "./build/index.d.ts", 19 | "module": "./build/module/index.js", 20 | "scripts": { 21 | "clean": "yarn rimraf ./build ./node_modules", 22 | "link": "yarn build:link && cd build && yarn link", 23 | "unlink": "yarn unlink", 24 | "build": "run-s build:*", 25 | "build:main": "tsc -p tsconfig.json", 26 | "build:module": "tsc -p tsconfig.module.json", 27 | "build:link": "cp package.json build && cp README.md build && sed -i.tmp 's/\\/build\\//\\//' ./build/package.json && rm ./build/package.json.tmp", 28 | "prettier": "yarn fix:prettier", 29 | "lint": "run-s lint:*", 30 | "lint:eslint": "eslint --config ../../.eslintrc.js src", 31 | "lint:prettier": "prettier --check \"./(src|test)/**/*.ts*\"", 32 | "fix": "run-s fix:*", 33 | "fix:eslint": "yarn lint:eslint --fix", 34 | "fix:prettier": "prettier --write './(src|test)/**/*.ts*'", 35 | "test": "run-s build:main test:* lint", 36 | "test:unit": "nyc ../../node_modules/ts-mocha/bin/ts-mocha --bail --sort --exit --timeout 180000 --paths -p ./tsconfig.json ./test/*.spec.ts ./test/**/*.spec.ts --ignore ./test/testutils/chai.d.ts", 37 | "watch": "run-s build:main && run-s \"build:main -- -w\"", 38 | "cov": "run-s build:main test:unit cov:html && echo \"\n\nTo see coverage, run: 'open coverage/index.html'\n\n\"", 39 | "cov:html": "nyc report --reporter=html", 40 | "cov:send": "nyc report --reporter=lcov && codecov", 41 | "cov:check": "nyc report && nyc check-coverage --lines 0 --functions 0 --branches 0", 42 | "prepare": "yarn build" 43 | }, 44 | "dependencies": { 45 | "@renproject/chains-bitcoin": "^3.6.0", 46 | "@renproject/provider": "^3.6.0", 47 | "@renproject/utils": "^3.6.0", 48 | "@types/elliptic": "6.4.14", 49 | "bignumber.js": "9.0.2", 50 | "elliptic": "6.5.4", 51 | "ethereumjs-util": "7.1.5", 52 | "immutable": "4.1.0" 53 | }, 54 | "nyc": { 55 | "extends": "@istanbuljs/nyc-config-typescript", 56 | "exclude": [ 57 | "**/*.d.ts", 58 | "**/*.spec.js" 59 | ], 60 | "include": [ 61 | "src" 62 | ] 63 | }, 64 | "prettier": { 65 | "printWidth": 80, 66 | "semi": true, 67 | "singleQuote": false, 68 | "tabWidth": 4, 69 | "trailingComma": "all", 70 | "endOfLine": "lf", 71 | "arrowParens": "always" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /packages/mock-provider/src/MockChain.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BitcoinBaseChain, 3 | BitcoinInputPayload, 4 | BitcoinOutputPayload, 5 | } from "@renproject/chains-bitcoin"; 6 | import { UTXO } from "@renproject/chains-bitcoin/APIs/API"; 7 | import { DepositChain, utils } from "@renproject/utils"; 8 | import BigNumber from "bignumber.js"; 9 | 10 | import { randomBytes } from "./utils"; 11 | 12 | export class MockChain 13 | extends BitcoinBaseChain 14 | implements DepositChain 15 | { 16 | public mempool: Array; 17 | 18 | public assets: { 19 | default: string; 20 | }; 21 | 22 | public constructor({ chain, asset }: { chain: string; asset: string }) { 23 | super({ 24 | network: { 25 | label: chain, 26 | selector: chain, 27 | 28 | nativeAsset: { 29 | name: asset, 30 | symbol: asset, 31 | decimals: 8, 32 | }, 33 | averageConfirmationTime: 1, 34 | 35 | isTestnet: true, 36 | p2shPrefix: new Uint8Array([0xc4]), 37 | explorer: { 38 | url: "", 39 | address: (_address: string) => "", 40 | transaction: (_txid: string) => "", 41 | }, 42 | providers: [ 43 | { 44 | fetchHeight: async () => Promise.resolve("6"), 45 | fetchUTXO: async (txid: string, txindex: string) => 46 | this.fetchUTXO(txid, txindex), 47 | fetchUTXOs: async (address: string) => 48 | this.fetchUTXOs(address), 49 | fetchTXs: (_address: string) => Promise.resolve([]), 50 | }, 51 | ], 52 | }, 53 | }); 54 | this.mempool = []; 55 | this.chain = chain; 56 | this.assets = { 57 | default: asset, 58 | }; 59 | } 60 | 61 | // eslint-disable-next-line @typescript-eslint/require-await 62 | public fetchUTXO = async (txid: string, txindex: string): Promise => { 63 | const utxo = this.mempool.find( 64 | (x) => x.txid === txid && x.txindex === txindex, 65 | ); 66 | if (utxo) { 67 | return utxo; 68 | } 69 | throw new Error(`UTXO ${txid}, ${txindex} not found`); 70 | }; 71 | // eslint-disable-next-line @typescript-eslint/require-await 72 | public fetchUTXOs = async (address: string): Promise => 73 | this.mempool.filter((x) => x.to === address); 74 | 75 | public addUTXO = (to: string, amount: BigNumber | number): UTXO => { 76 | const tx: UTXO & { to: string } = { 77 | to, 78 | txid: utils.toHex(randomBytes(32)), 79 | txindex: "0", 80 | amount: amount.toString(), 81 | height: "0", 82 | }; 83 | this.mempool.push(tx); 84 | return tx; 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /packages/mock-provider/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./MockProvider"; 2 | export * from "./MockChain"; 3 | -------------------------------------------------------------------------------- /packages/mock-provider/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { utils } from "@renproject/utils"; 2 | 3 | /** 4 | * Generates a random hex string (prefixed with '0x'). 5 | * 6 | * @param bytes The number of bytes to generate. 7 | */ 8 | export const randomBytes = (bytes: number): Uint8Array => { 9 | try { 10 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 11 | // @ts-ignore 12 | if (window) { 13 | const uints = new Uint32Array(bytes / 4); // 4 bytes (32 bits) 14 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 15 | // @ts-ignore 16 | window.crypto.getRandomValues(uints); 17 | let str = ""; 18 | for (const uint of uints) { 19 | str += 20 | "0".repeat(8 - uint.toString(16).length) + 21 | String(uint.toString(16)); 22 | } 23 | return utils.fromHex(str); 24 | } 25 | } catch (error: unknown) { 26 | // Ignore error 27 | } 28 | // eslint-disable-next-line @typescript-eslint/no-var-requires 29 | const crypto = require("crypto") as { 30 | randomBytes: (length: number) => Uint8Array; 31 | }; 32 | return crypto.randomBytes(bytes); 33 | }; 34 | 35 | // context("randomBytes", () => { 36 | // // Restore global window state afterwards incase this is being run in 37 | // // a browser environment. 38 | // let previousWindow: unknown; 39 | // before(() => { 40 | // previousWindow = (global as { window: unknown }).window; 41 | // }); 42 | // after(() => { 43 | // (global as { window: unknown }).window = previousWindow; 44 | // }); 45 | 46 | // it("returns random bytes of the correct length", () => { 47 | // expect(randomBytes(32).length).to.equal(32); 48 | // expect(randomBytes(32)).not.to.equal(randomBytes(32)); 49 | // (global as { window: unknown }).window = { 50 | // crypto: { 51 | // getRandomValues: (uints: Uint32Array) => { 52 | // for (let i = 0; i < uints.length; i++) { 53 | // uints[i] = 0; 54 | // } 55 | // }, 56 | // }, 57 | // }; 58 | // expect(randomBytes(32).length).to.equal(32); 59 | // }); 60 | // }); 61 | -------------------------------------------------------------------------------- /packages/mock-provider/test/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { RPCMethod } from "@renproject/provider/methods"; 2 | import { expect } from "chai"; 3 | 4 | import { MockChain, MockProvider } from "../src"; 5 | 6 | describe("@renproject/mock-provider", () => { 7 | it("should export MockProvider and MockChain correctly", async () => { 8 | expect(MockProvider).not.to.equal(undefined); 9 | expect(MockChain).not.to.equal(undefined); 10 | }); 11 | 12 | it("can provide a gPubKey", async () => { 13 | const gPubKey = "Aw3WX32ykguyKZEuP0IT3RUOX5csm3PpvnFNhEVhrDVc"; 14 | const provider = new MockProvider({ 15 | gPubKey, 16 | }); 17 | const blockState = await provider.sendMessage( 18 | RPCMethod.QueryBlockState, 19 | { 20 | contract: "BTC", 21 | }, 22 | ); 23 | expect(blockState.state.v["BTC"].shards[0].pubKey).to.equal(gPubKey); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /packages/mock-provider/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "outDir": "build", 5 | "rootDir": "src", 6 | "moduleResolution": "node", 7 | "module": "commonjs", 8 | "declaration": true, 9 | "removeComments": false, 10 | "esModuleInterop": true, 11 | "strict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "traceResolution": false, 17 | "listEmittedFiles": false, 18 | "listFiles": false, 19 | "pretty": true, 20 | "lib": ["es2017", "dom"], 21 | "types": ["node"], 22 | "typeRoots": ["node_modules/@types", "src/types"], 23 | "resolveJsonModule": true, 24 | "forceConsistentCasingInFileNames": true, 25 | "noImplicitThis": true, 26 | "noImplicitAny": true, 27 | "strictNullChecks": true, 28 | "suppressImplicitAnyIndexErrors": true, 29 | "strictPropertyInitialization": true, 30 | "alwaysStrict": true, 31 | "strictFunctionTypes": true, 32 | "sourceMap": true, 33 | "declarationMap": true 34 | }, 35 | "include": ["src/**/*.ts"], 36 | "exclude": ["node_modules/**"], 37 | "compileOnSave": false 38 | } 39 | -------------------------------------------------------------------------------- /packages/mock-provider/tsconfig.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "outDir": "build/module", 6 | "module": "esnext" 7 | }, 8 | "exclude": [ 9 | "node_modules/**" 10 | ] 11 | } -------------------------------------------------------------------------------- /packages/provider/README.md: -------------------------------------------------------------------------------- 1 | # `@renproject/provider` 2 | 3 | This package is part of [RenJS](https://github.com/renproject.ren-js). 4 | 5 | See [`@renproject/provider` docs](https://renproject.github.io/ren-js-v3-docs/modules/_renproject_provider.html) 6 | -------------------------------------------------------------------------------- /packages/provider/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@renproject/provider", 3 | "version": "3.6.0", 4 | "description": "Official Ren JavaScript client", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/renproject/ren-js.git" 8 | }, 9 | "publishConfig": { 10 | "access": "public", 11 | "directory": "build" 12 | }, 13 | "author": "Ren", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/renproject/ren-js/issues" 17 | }, 18 | "main": "./build/index.js", 19 | "typings": "./build/index.d.ts", 20 | "module": "./build/module/index.js", 21 | "scripts": { 22 | "clean": "yarn rimraf ./build ./node_modules", 23 | "link": "yarn build:link && cd build && yarn link", 24 | "unlink": "yarn unlink", 25 | "build": "run-s build:*", 26 | "build:main": "tsc -p tsconfig.json", 27 | "build:module": "tsc -p tsconfig.module.json", 28 | "build:link": "cp package.json build && cp README.md build && sed -i.tmp 's/\\/build\\//\\//' ./build/package.json && rm ./build/package.json.tmp", 29 | "prettier": "yarn fix:prettier", 30 | "lint": "run-s lint:*", 31 | "lint:eslint": "eslint --config ../../.eslintrc.js src", 32 | "lint:prettier": "prettier --check \"./(src|test)/**/*.ts*\"", 33 | "fix": "run-s fix:*", 34 | "fix:eslint": "yarn lint:eslint --fix", 35 | "fix:prettier": "prettier --write './(src|test)/**/*.ts*'", 36 | "test": "run-s test:* lint", 37 | "test:unit": "nyc ../../node_modules/ts-mocha/bin/ts-mocha --bail --sort --exit --timeout 180000 --paths -p ./tsconfig.json ./test/*.spec.ts ./test/**/*.spec.ts --ignore ./test/testutils/chai.d.ts", 38 | "watch": "run-s build:main && run-s \"build:main -- -w\"", 39 | "cov": "run-s build:main test:unit cov:html && echo \"\n\nTo see coverage, run: 'open coverage/index.html'\n\n\"", 40 | "cov:html": "nyc report --reporter=html", 41 | "cov:send": "nyc report --reporter=lcov && codecov", 42 | "cov:check": "nyc report && nyc check-coverage --lines 0 --functions 0 --branches 0", 43 | "prepare": "yarn build" 44 | }, 45 | "dependencies": { 46 | "@renproject/utils": "^3.6.0", 47 | "axios": "0.27.2", 48 | "bignumber.js": "9.0.2" 49 | }, 50 | "nyc": { 51 | "extends": "@istanbuljs/nyc-config-typescript", 52 | "exclude": [ 53 | "**/*.d.ts", 54 | "**/*.spec.js" 55 | ], 56 | "include": [ 57 | "src" 58 | ] 59 | }, 60 | "prettier": { 61 | "printWidth": 80, 62 | "semi": true, 63 | "singleQuote": false, 64 | "tabWidth": 4, 65 | "trailingComma": "all", 66 | "endOfLine": "lf", 67 | "arrowParens": "always" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /packages/provider/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./provider"; 2 | export * from "./methods/index"; 3 | export * from "./methods/ren_queryBlockState"; 4 | export * from "./unmarshal"; 5 | export * from "./types/core"; 6 | -------------------------------------------------------------------------------- /packages/provider/src/methods/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ParamsQueryBlock, 3 | ParamsQueryBlocks, 4 | ResponseQueryBlock, 5 | ResponseQueryBlocks, 6 | } from "./ren_queryBlock"; 7 | import { 8 | ParamsQueryBlockState, 9 | ResponseQueryBlockState, 10 | } from "./ren_queryBlockState"; 11 | import { ParamsQueryConfig, ResponseQueryConfig } from "./ren_queryConfig"; 12 | import { ParamsSubmitGateway } from "./ren_submitGateway"; 13 | import { 14 | ParamsQueryTx, 15 | ParamsQueryTxs, 16 | ParamsSubmitTx, 17 | ResponseQueryTx, 18 | ResponseQueryTxs, 19 | ResponseSubmitGateway, 20 | ResponseSubmitTx, 21 | } from "./ren_submitTx"; 22 | 23 | export * from "./ren_queryBlock"; 24 | export * from "./ren_queryBlockState"; 25 | export * from "./ren_queryConfig"; 26 | export * from "./ren_submitGateway"; 27 | export * from "./ren_submitTx"; 28 | 29 | export enum RPCMethod { 30 | // MethodSubmitGateway submits the details of a gateway to the lightnode, 31 | // used for recovering mints that didn't get submitted to RenVM. 32 | SubmitGateway = "ren_submitGateway", 33 | 34 | // MethodSubmitTx submits a new transaction to the Darknode for acceptance 35 | // into the transaction pool. 36 | SubmitTx = "ren_submitTx", 37 | 38 | // MethodQueryTx returns the latest information about a transaction 39 | // identified by a transaction hash. 40 | QueryTx = "ren_queryTx", 41 | 42 | // MethodQueryTxs returns pages of transactions with optional filtering by 43 | // status and tags. 44 | QueryTxs = "ren_queryTxs", 45 | 46 | // MethodQueryBlock returns a block identified by the block height. 47 | QueryBlock = "ren_queryBlock", 48 | 49 | // MethodQueryBlocks returns recently committed blocks. 50 | QueryBlocks = "ren_queryBlocks", 51 | 52 | // MethodQueryConfig returns the node configuration. 53 | QueryConfig = "ren_queryConfig", 54 | 55 | // MethodQueryBlockState returns the contract state. 56 | QueryBlockState = "ren_queryBlockState", 57 | } 58 | 59 | // ///////////////////////////////////////////////////////////////////////////// 60 | 61 | export type RPCParams = { 62 | [RPCMethod.SubmitTx]: ParamsSubmitTx; 63 | [RPCMethod.SubmitGateway]: ParamsSubmitGateway; 64 | [RPCMethod.QueryTx]: ParamsQueryTx; 65 | [RPCMethod.QueryTxs]: ParamsQueryTxs; 66 | [RPCMethod.QueryBlock]: ParamsQueryBlock; 67 | [RPCMethod.QueryBlocks]: ParamsQueryBlocks; 68 | [RPCMethod.QueryConfig]: ParamsQueryConfig; 69 | [RPCMethod.QueryBlockState]: ParamsQueryBlockState; 70 | }; 71 | 72 | export type RPCResponses = { 73 | [RPCMethod.SubmitTx]: ResponseSubmitTx; 74 | [RPCMethod.SubmitGateway]: ResponseSubmitGateway; 75 | [RPCMethod.QueryTx]: ResponseQueryTx; 76 | [RPCMethod.QueryTxs]: ResponseQueryTxs; 77 | [RPCMethod.QueryBlock]: ResponseQueryBlock; 78 | [RPCMethod.QueryBlocks]: ResponseQueryBlocks; 79 | [RPCMethod.QueryConfig]: ResponseQueryConfig; 80 | [RPCMethod.QueryBlockState]: ResponseQueryBlockState; 81 | }; 82 | 83 | // The following lines will throw a type error if RenVMResponses or RenVMParams 84 | // aren't defined for all RPC methods. 85 | (): RPCParams[RPCMethod] | void => {}; 86 | (): RPCResponses[RPCMethod] | void => {}; 87 | -------------------------------------------------------------------------------- /packages/provider/src/methods/ren_queryBlock.ts: -------------------------------------------------------------------------------- 1 | import { Marshalled, PackPrimitive, PackStructType } from "@renproject/utils"; 2 | 3 | export const renVMBlockType: PackStructType = { 4 | struct: [ 5 | { height: PackPrimitive.U64 }, 6 | { hash: PackPrimitive.Bytes }, 7 | { parentHash: PackPrimitive.Bytes }, 8 | { commitment: { list: PackPrimitive.Bytes } }, 9 | { timestamp: PackPrimitive.U64 }, 10 | { round: PackPrimitive.U64 }, 11 | { stateRoot: PackPrimitive.Bytes }, 12 | { intrinsicTxs: { list: PackPrimitive.Bytes } }, 13 | { extrinsicTxs: { list: PackPrimitive.Bytes } }, 14 | ], 15 | }; 16 | 17 | export interface MarshalledRenVMBlock { 18 | height: Marshalled; 19 | hash: Marshalled; 20 | parentHash: Marshalled; 21 | commitment: Array>; 22 | timestamp: Marshalled; 23 | round: Marshalled; 24 | stateRoot: Marshalled; 25 | intrinsicTxs: Array>; 26 | extrinsicTxs: Array>; 27 | } 28 | 29 | // ParamsQueryBlock defines the parameters of the MethodQueryBlock. 30 | export interface ParamsQueryBlock { 31 | // BlockHeight of the block that will be returned. A nil value can be used 32 | // to request the latest block. 33 | blockHeight?: Marshalled; 34 | } 35 | 36 | // ParamsQueryBlocks defines the parameters of the MethodQueryBlocks. 37 | export interface ParamsQueryBlocks { 38 | // BlockHeight of the youngest block that will be returned in the list. A 39 | // nil value can be used to request a list of the latest blocks. 40 | blockHeight?: Marshalled; 41 | // N defines the maximum number of ancestor blocks that will be returned. A 42 | // nil value can be used to request the maximum allowed number of blocks. 43 | n?: Marshalled; 44 | } 45 | 46 | // ResponseQueryBlock defines the response of the MethodQueryBlock. 47 | export interface ResponseQueryBlock { 48 | block: MarshalledRenVMBlock; // Block json.RawMessage`json:"block"` 49 | } 50 | 51 | // ResponseQueryBlocks defines the response of the MethodQueryBlocks. 52 | export interface ResponseQueryBlocks { 53 | blocks: MarshalledRenVMBlock[]; // Blocks json.RawMessage`json:"blocks"` 54 | } 55 | -------------------------------------------------------------------------------- /packages/provider/src/methods/ren_queryConfig.ts: -------------------------------------------------------------------------------- 1 | import { Marshalled, PackPrimitive } from "@renproject/utils"; 2 | 3 | // ParamsQueryConfig defines the parameters of the MethodQueryConfig. 4 | export interface ParamsQueryConfig { 5 | // No parameters. 6 | } 7 | 8 | // Responses /////////////////////////////////////////////////////////////////// 9 | 10 | // ResponseQueryConfig defines the response of the MethodQueryConfig. 11 | export interface ResponseQueryConfig { 12 | confirmations: { 13 | [chain: string]: Marshalled; 14 | }; 15 | maxConfirmations: { 16 | [chain: string]: Marshalled; 17 | }; 18 | network: string; 19 | registries: { 20 | [chain: string]: string; 21 | }; 22 | whitelist: string[]; 23 | } 24 | -------------------------------------------------------------------------------- /packages/provider/src/methods/ren_submitGateway.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Marshalled, 3 | PackPrimitive, 4 | PackTypeDefinition, 5 | TypedPackValue, 6 | } from "@renproject/utils"; 7 | 8 | export interface SubmitGatewayInput { 9 | version: string; 10 | selector: string; 11 | in: SubmitGateway; 12 | } 13 | 14 | export const submitGatewayType: PackTypeDefinition = { 15 | struct: [ 16 | { 17 | payload: PackPrimitive.Bytes, 18 | }, 19 | { 20 | phash: PackPrimitive.Bytes32, 21 | }, 22 | { 23 | to: PackPrimitive.Str, 24 | }, 25 | { 26 | nonce: PackPrimitive.Bytes32, 27 | }, 28 | { 29 | nhash: PackPrimitive.Bytes32, 30 | }, 31 | { 32 | gpubkey: PackPrimitive.Bytes, 33 | }, 34 | { 35 | ghash: PackPrimitive.Bytes32, 36 | }, 37 | ], 38 | }; 39 | 40 | export type SubmitGateway = TypedPackValue< 41 | // Types 42 | typeof submitGatewayType, 43 | // Values 44 | { 45 | amount: Marshalled; 46 | ghash: Marshalled; // "x0gTBzbXmM1Xdwk-B8PHJ4sgY2T_NcrWsxK6MJ2xYos", 47 | gpubkey: Marshalled; // "8Qnq", 48 | nhash: Marshalled; // "a_46LkThVhVYlkIxBXaInubuEmYcfDNk45EBl60prhA", 49 | nonce: Marshalled; // "vPIiF6apzdJ4Rr8IMpT2uywo8LbuHOcaEXQ21ydXFBA", 50 | payload: Marshalled; // "I_9MVtYiO4NlH7lwIx8", 51 | phash: Marshalled; // "ibSvPHswcsI3o3nkQRpHp23ANg3tf9L5ivk5kKwnGTQ", 52 | to: Marshalled; // "򝊞􋄛𧚞󥫨򨚘󳽈򤙳񙓻򳳱􎖫򗣌𻄭񑦁򏬰񆆅򒒛􊗓𧜿򇞣􁓹", 53 | txid: Marshalled; 54 | txindex: Marshalled; 55 | } 56 | >; 57 | 58 | export type ParamsSubmitGateway = { 59 | gateway: string; 60 | tx: SubmitGatewayInput; 61 | }; 62 | -------------------------------------------------------------------------------- /packages/provider/src/rpcUrls.ts: -------------------------------------------------------------------------------- 1 | import { RenNetwork } from "@renproject/utils"; 2 | 3 | export const renRpcUrls = { 4 | [RenNetwork.Mainnet]: "https://rpc.renproject.io", 5 | [RenNetwork.Testnet]: "https://rpc-testnet.renproject.io", 6 | }; 7 | 8 | export const renExplorerUrls = { 9 | [RenNetwork.Mainnet]: "https://explorer.renproject.io", 10 | [RenNetwork.Testnet]: "https://explorer-testnet.renproject.io", 11 | }; 12 | -------------------------------------------------------------------------------- /packages/provider/src/types/core.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from "bignumber.js"; 2 | 3 | import { TxStatus, UrlBase64String } from "@renproject/utils"; 4 | 5 | export interface RenVMBlock { 6 | height: BigNumber; 7 | hash: Uint8Array; 8 | parentHash: Uint8Array; 9 | commitment: Uint8Array; 10 | timestamp: BigNumber; 11 | round: BigNumber; 12 | stateRoot: Uint8Array; 13 | intrinsicTxs: Uint8Array[]; 14 | extrinsicTxs: Uint8Array[]; 15 | } 16 | 17 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 18 | export interface RenVMTransaction { 19 | hash: UrlBase64String; 20 | version: number; 21 | selector: string; // "BTC/fromEthereum", 22 | in: Input; 23 | out?: Output; 24 | } 25 | 26 | export interface RenVMTransactionWithStatus< 27 | Transaction extends RenVMTransaction = RenVMTransaction, 28 | > { 29 | tx: Transaction; 30 | txStatus: TxStatus; 31 | } 32 | 33 | export type RenVMCrossChainTransaction = RenVMTransaction< 34 | // Input 35 | { 36 | txid: Uint8Array; 37 | txindex: BigNumber; 38 | amount: BigNumber; 39 | payload: Uint8Array; 40 | phash: Uint8Array; 41 | to: string; 42 | nonce: Uint8Array; 43 | nhash: Uint8Array; 44 | gpubkey: Uint8Array; 45 | ghash: Uint8Array; 46 | }, 47 | // Output 48 | { 49 | amount: BigNumber; 50 | fees: BigNumber; 51 | hash: Uint8Array; 52 | revert: string; 53 | sig: Uint8Array; 54 | sighash: Uint8Array; 55 | txid: Uint8Array; 56 | txindex: BigNumber; 57 | } 58 | >; 59 | -------------------------------------------------------------------------------- /packages/provider/src/unmarshal.ts: -------------------------------------------------------------------------------- 1 | import { normalizeSignature, pack, TypedPackValue } from "@renproject/utils"; 2 | 3 | import { ResponseQueryTx } from "./methods"; 4 | import { RenVMTransaction } from "./types/core"; 5 | 6 | export const unmarshalRenVMTransaction = < 7 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 8 | Input = any, 9 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 10 | Output = any, 11 | TypedInput extends TypedPackValue = TypedPackValue, 12 | TypedOutput extends TypedPackValue = TypedPackValue, 13 | >( 14 | tx: ResponseQueryTx["tx"], 15 | ): RenVMTransaction => { 16 | // If the transaction has a signature output, apply standard signature fixes. 17 | const out = pack.unmarshal.unmarshalTypedPackValue(tx.out); 18 | if (out && out.sig && out.sig instanceof Uint8Array && out.sig.length > 0) { 19 | out.sig = normalizeSignature(out.sig); 20 | } 21 | 22 | return { 23 | version: parseInt(tx.version), 24 | hash: tx.hash, 25 | selector: tx.selector, 26 | in: pack.unmarshal.unmarshalTypedPackValue(tx.in), 27 | out, 28 | }; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/provider/test/pack.spec.ts: -------------------------------------------------------------------------------- 1 | import { utils } from "@renproject/utils"; 2 | import BigNumber from "bignumber.js"; 3 | import { expect } from "chai"; 4 | import { describe, it } from "mocha"; 5 | 6 | import { unmarshalPackValue } from "../../utils/src/libraries/pack/unmarshal"; 7 | import { burnParamsType, crossChainParamsType } from "../src"; 8 | 9 | describe("Pack", () => { 10 | it("Unmarshal burn - 1", () => { 11 | const amount = 12 | "51423850459342719531259112406474019285406140697150570331000675381551947991775"; 13 | const nonce = "H8AmOgjiSt8ULnuw1mDzPMJogHDOS2J1uNELrDma0xg"; 14 | const to = "1234"; 15 | 16 | const result = unmarshalPackValue(burnParamsType, { 17 | amount, 18 | nonce, 19 | to, 20 | }); 21 | 22 | expect(result).to.deep.equal({ 23 | amount: new BigNumber(amount), 24 | nonce: utils.fromBase64(nonce), 25 | to, 26 | }); 27 | }); 28 | 29 | it("Unmarshal mint", () => { 30 | const ghash = "x0gTBzbXmM1Xdwk-B8PHJ4sgY2T_NcrWsxK6MJ2xYos"; 31 | const gpubkey = "8Qnq"; 32 | const nhash = "a_46LkThVhVYlkIxBXaInubuEmYcfDNk45EBl60prhA"; 33 | const nonce = "vPIiF6apzdJ4Rr8IMpT2uywo8LbuHOcaEXQ21ydXFBA"; 34 | const txid = "_yJG1tKIALMrvaSes9BB4dYx5eCN8OK5V_PEM4N3R10"; 35 | const txindex = "2288363171"; 36 | const amount = "503863382662879832"; 37 | const payload = "I_9MVtYiO4NlH7lwIx8"; 38 | const phash = "ibSvPHswcsI3o3nkQRpHp23ANg3tf9L5ivk5kKwnGTQ"; 39 | const to = "1234"; 40 | 41 | const result = unmarshalPackValue(crossChainParamsType, { 42 | ghash, 43 | gpubkey, 44 | nhash, 45 | nonce, 46 | txid, 47 | txindex, 48 | amount, 49 | payload, 50 | phash, 51 | to, 52 | }); 53 | 54 | expect(result).to.deep.equal({ 55 | ghash: utils.fromBase64(ghash), 56 | gpubkey: utils.fromBase64(gpubkey), 57 | nhash: utils.fromBase64(nhash), 58 | nonce: utils.fromBase64(nonce), 59 | txid: utils.fromBase64(txid), 60 | txindex: new BigNumber(txindex), 61 | amount: new BigNumber(amount), 62 | payload: utils.fromBase64(payload), 63 | phash: utils.fromBase64(phash), 64 | to: to, 65 | }); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /packages/provider/test/selectPublicKey.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | 3 | import chai from "chai"; 4 | 5 | import { utils } from "@renproject/utils"; 6 | 7 | import { RenVMProvider } from "../src"; 8 | 9 | chai.should(); 10 | 11 | describe("RenVMProvider v2", () => { 12 | it("selectShard", async () => { 13 | const renVMProvider = new RenVMProvider({ 14 | sendMessage: (method) => { 15 | switch (method) { 16 | case "ren_queryState": 17 | return require("./mockResponses/ren_queryState.json") 18 | .result; 19 | case "ren_queryBlockState": 20 | return require("./mockResponses/ren_queryBlockState.json") 21 | .result; 22 | default: 23 | return {}; 24 | } 25 | }, 26 | } as any); // eslint-disable-line @typescript-eslint/no-explicit-any 27 | utils 28 | .Ox((await renVMProvider.selectShard("BTC")).gPubKey) 29 | .should.equal("0xA6Auk8-MR7JQB1sK9h-W69EDdsCqp2NRSOiJyytRyWkn"); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /packages/provider/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "outDir": "build", 5 | "rootDir": "src", 6 | "moduleResolution": "node", 7 | "module": "commonjs", 8 | "declaration": true, 9 | "removeComments": false, 10 | "esModuleInterop": true, 11 | "strict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "traceResolution": false, 17 | "listEmittedFiles": false, 18 | "listFiles": false, 19 | "pretty": true, 20 | "lib": ["es2017", "dom"], 21 | "types": ["node"], 22 | "typeRoots": ["node_modules/@types", "src/types"], 23 | "resolveJsonModule": true, 24 | "forceConsistentCasingInFileNames": true, 25 | "noImplicitThis": true, 26 | "noImplicitAny": true, 27 | "strictNullChecks": true, 28 | "suppressImplicitAnyIndexErrors": true, 29 | "strictPropertyInitialization": true, 30 | "alwaysStrict": true, 31 | "strictFunctionTypes": true, 32 | "sourceMap": true, 33 | "declarationMap": true 34 | }, 35 | "include": ["src/**/*.ts"], 36 | "exclude": ["node_modules/**"], 37 | "compileOnSave": false 38 | } 39 | -------------------------------------------------------------------------------- /packages/provider/tsconfig.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "outDir": "build/module", 6 | "module": "es6" 7 | }, 8 | "exclude": ["node_modules/**"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/ren/README.md: -------------------------------------------------------------------------------- 1 | ../../README.md -------------------------------------------------------------------------------- /packages/ren/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@renproject/ren", 3 | "version": "3.6.0", 4 | "description": "Official Ren JavaScript SDK for bridging crypto assets cross-chain.", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/renproject/ren-js.git" 8 | }, 9 | "publishConfig": { 10 | "access": "public", 11 | "directory": "build" 12 | }, 13 | "keywords": [ 14 | "RenVM", 15 | "Ren", 16 | "Cross-Chain", 17 | "Ethereum", 18 | "Bitcoin", 19 | "Solana", 20 | "Dogecoin", 21 | "Web3", 22 | "DeFi" 23 | ], 24 | "author": "Ren", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/renproject/ren-js/issues" 28 | }, 29 | "main": "./build/index.js", 30 | "typings": "./build/index.d.ts", 31 | "module": "./build/module/index.js", 32 | "scripts": { 33 | "clean": "yarn rimraf ./build ./node_modules", 34 | "link": "yarn build:link && cd build && yarn link", 35 | "unlink": "yarn unlink", 36 | "build": "run-s build:*", 37 | "build:main": "tsc -p tsconfig.json", 38 | "build:module": "tsc -p tsconfig.module.json", 39 | "build:link": "cp package.json build && cp README.md build && sed -i.tmp 's/\\/build\\//\\//' ./build/package.json && rm ./build/package.json.tmp", 40 | "_build:bundled": "cross-env NODE_ENV=production webpack --config ../../webpack.config.js --mode production --progress --color", 41 | "prettier": "yarn fix:prettier", 42 | "lint": "run-s lint:*", 43 | "lint:eslint": "eslint --config ../../.eslintrc.js src", 44 | "lint:prettier": "prettier --check \"./(src|test)/**/*.ts*\"", 45 | "fix": "run-s fix:*", 46 | "fix:eslint": "yarn lint:eslint --fix", 47 | "fix:prettier": "prettier --write './(src|test)/**/*.ts*'", 48 | "test": "run-s test:* lint", 49 | "test-all": "ALL_TESTS=true run-s build:main test:unit lint", 50 | "test:unit": "nyc ../../node_modules/ts-mocha/bin/ts-mocha --sort --exit --timeout 180000 --paths -p ./tsconfig.json ./test/*.spec.ts ./test/**/*.spec.ts", 51 | "watch": "run-s build:main && run-s \"build:main -- -w\"", 52 | "cov": "run-s build:main test:unit cov:html && echo \"\n\nTo see coverage, run: 'open coverage/index.html'\n\n\"", 53 | "cov:html": "nyc report --reporter=html", 54 | "cov:send": "nyc report --reporter=lcov && codecov", 55 | "cov:check": "nyc report && nyc check-coverage --lines 0 --functions 0 --branches 0", 56 | "prepare": "yarn build" 57 | }, 58 | "dependencies": { 59 | "@renproject/provider": "^3.6.0", 60 | "@renproject/utils": "^3.6.0", 61 | "bignumber.js": "9.0.2", 62 | "events": "3.3.0", 63 | "immutable": "4.1.0" 64 | }, 65 | "nyc": { 66 | "extends": "@istanbuljs/nyc-config-typescript", 67 | "exclude": [ 68 | "**/*.d.ts", 69 | "**/*.spec.js" 70 | ], 71 | "include": [ 72 | "src" 73 | ] 74 | }, 75 | "prettier": { 76 | "printWidth": 80, 77 | "semi": true, 78 | "singleQuote": false, 79 | "tabWidth": 4, 80 | "trailingComma": "all", 81 | "endOfLine": "lf", 82 | "arrowParens": "always" 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /packages/ren/src/utils/config.ts: -------------------------------------------------------------------------------- 1 | import { defaultLogger, Logger, LogLevel, utils } from "@renproject/utils"; 2 | 3 | export { LogLevel } from "@renproject/utils"; 4 | 5 | export interface RenJSConfig { 6 | /** 7 | * The logger and logLevel are used to configure where RenJS sends debug 8 | * and error logs. Set the logLevel to `LogLevel.Debug` or `LogLevel.Trace` 9 | * to receive debug logs. 10 | */ 11 | logLevel?: LogLevel; 12 | logger?: Logger; 13 | 14 | /** 15 | * `networkDelay` is the timeout in ms between retrying various network 16 | * requests including 1) fetching deposits, 2) fetching confirmations and 17 | * 3) fetching a transaction's RenVM status. 18 | * 19 | * It defaults to `15000` (15 seconds). 20 | */ 21 | networkDelay?: number; 22 | 23 | /** 24 | * `loadCompletedDeposits` whether or not to detect deposits that have 25 | * already been minted. 26 | * 27 | * It defaults to false 28 | */ 29 | // loadCompletedDeposits?: boolean; 30 | } 31 | 32 | export const defaultRenJSConfig = { 33 | logLevel: LogLevel.Debug, 34 | logger: defaultLogger, 35 | networkDelay: 15 * utils.sleep.SECONDS, 36 | // loadCompletedDeposits: false as boolean, 37 | }; 38 | 39 | // Check that defaultRenJSConfig is a valid RenJSConfig object, while 40 | // still allowing typescript to infer its type from is value, so that it knows 41 | // that `defaultRenJSConfig.logger` is not potentially undefined. 42 | const _check: RenJSConfig = defaultRenJSConfig; 43 | -------------------------------------------------------------------------------- /packages/ren/src/utils/transactionEmitter.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from "events"; 2 | 3 | import { EventEmitterTyped } from "@renproject/utils"; 4 | 5 | import { GatewayTransaction } from "../gatewayTransaction"; 6 | 7 | // The TransactionEmitter extends the built-in EventEmitter, adding the ability 8 | // to retrieve previous transactions that have been emitted. 9 | export class TransactionEmitter< 10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 11 | ToPayload extends { chain: string; txConfig?: any } = any, 12 | > 13 | extends EventEmitter 14 | implements 15 | EventEmitterTyped<{ transaction: [GatewayTransaction] }> 16 | { 17 | private getTransactions: () => Array>; 18 | 19 | public constructor( 20 | getTransactions: () => Array>, 21 | ) { 22 | super(); 23 | 24 | this.getTransactions = getTransactions; 25 | } 26 | 27 | public addListener = ( 28 | event: Event, 29 | callback: Event extends "transaction" 30 | ? (deposit: GatewayTransaction) => void 31 | : never, 32 | ): this => { 33 | // Emit previous deposit events. 34 | if (event === "transaction") { 35 | this.getTransactions().map(callback); 36 | } 37 | 38 | super.on(event, callback); 39 | return this; 40 | }; 41 | 42 | /** 43 | * `on` creates a new listener to `"transaction"` events, returning 44 | * [[GatewayTransaction]] instances. 45 | * 46 | * `on` extends `EventEmitter.on`, modifying it to immediately return all 47 | * previous `"transaction"` events, in addition to new events, when a new 48 | * listener is created. 49 | * 50 | * @category Main 51 | */ 52 | public on = ( 53 | event: Event, 54 | callback: ( 55 | ...values: { transaction: [GatewayTransaction] }[Event] 56 | ) => void | Promise, 57 | ): this => 58 | this.addListener( 59 | event, 60 | callback as Event extends "transaction" 61 | ? (deposit: GatewayTransaction) => void 62 | : never, 63 | ); 64 | 65 | public once = ( 66 | event: Event, 67 | callback: ( 68 | ...values: { transaction: [GatewayTransaction] }[Event] 69 | ) => void | Promise, 70 | ): this => 71 | super.once( 72 | event, 73 | callback as Event extends "transaction" 74 | ? (deposit: GatewayTransaction) => void 75 | : never, 76 | ); 77 | } 78 | -------------------------------------------------------------------------------- /packages/ren/test/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | 3 | import RenJS from "../src"; 4 | 5 | describe("@renproject/ren", () => { 6 | it("should export RenJS correctly", async () => { 7 | expect(RenJS).not.to.equal(undefined); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/ren/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "outDir": "build", 5 | "rootDir": "src", 6 | "moduleResolution": "node", 7 | "module": "commonjs", 8 | "declaration": true, 9 | "removeComments": false, 10 | "esModuleInterop": true, 11 | "strict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "traceResolution": false, 17 | "listEmittedFiles": false, 18 | "listFiles": false, 19 | "pretty": true, 20 | "lib": ["es2017", "dom"], 21 | "types": ["node"], 22 | "typeRoots": ["node_modules/@types", "src/types"], 23 | "resolveJsonModule": true, 24 | "forceConsistentCasingInFileNames": true, 25 | "noImplicitThis": true, 26 | "noImplicitAny": true, 27 | "strictNullChecks": true, 28 | "suppressImplicitAnyIndexErrors": true, 29 | "strictPropertyInitialization": true, 30 | "alwaysStrict": true, 31 | "strictFunctionTypes": true, 32 | "sourceMap": true, 33 | "declarationMap": true 34 | }, 35 | "include": ["src/**/*.ts"], 36 | "exclude": ["node_modules/**"], 37 | "compileOnSave": false 38 | } 39 | -------------------------------------------------------------------------------- /packages/ren/tsconfig.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "outDir": "build/module", 6 | "module": "es6" 7 | }, 8 | "exclude": ["node_modules/**"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/utils/README.md: -------------------------------------------------------------------------------- 1 | # `@renproject/utils` 2 | 3 | This package is part of [RenJS](https://github.com/renproject.ren-js). 4 | 5 | See [`@renproject/utils` docs](https://renproject.github.io/ren-js-v3-docs/modules/_renproject_utils.html) 6 | -------------------------------------------------------------------------------- /packages/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@renproject/utils", 3 | "version": "3.6.0", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/renproject/ren-js.git" 7 | }, 8 | "publishConfig": { 9 | "access": "public", 10 | "directory": "build" 11 | }, 12 | "author": "Ren", 13 | "license": "MIT", 14 | "bugs": { 15 | "url": "https://github.com/renproject/ren-js/issues" 16 | }, 17 | "main": "./build/index.js", 18 | "typings": "./build/index.d.ts", 19 | "module": "./build/module/index.js", 20 | "scripts": { 21 | "clean": "yarn rimraf ./build ./node_modules", 22 | "link": "yarn build:link && cd build && yarn link", 23 | "unlink": "yarn unlink", 24 | "build": "run-s build:*", 25 | "build:main": "tsc -p tsconfig.json", 26 | "build:module": "tsc -p tsconfig.module.json", 27 | "build:link": "cp package.json build && cp README.md build && sed -i.tmp 's/\\/build\\//\\//' ./build/package.json && rm ./build/package.json.tmp", 28 | "prettier": "yarn fix:prettier", 29 | "lint": "run-s lint:*", 30 | "lint:eslint": "eslint --config ../../.eslintrc.js src", 31 | "lint:prettier": "prettier --check \"./(src|test)/**/*.ts*\"", 32 | "fix": "run-s fix:*", 33 | "fix:eslint": "yarn lint:eslint --fix", 34 | "fix:prettier": "prettier --write './(src|test)/**/*.ts*'", 35 | "test": "run-s test:* lint", 36 | "test:unit": "nyc ../../node_modules/ts-mocha/bin/ts-mocha --bail --sort --exit --timeout 180000 --paths -p ./tsconfig.json ./src/*.spec.ts ./src/**/*.spec.ts ./test/*.spec.ts ./test/**/*.spec.ts --ignore ./test/testutils/chai.d.ts", 37 | "watch": "run-s build:main && run-s \"build:main -- -w\"", 38 | "cov": "run-s test:unit cov:html && echo \"\n\nTo see coverage, run: 'open coverage/index.html'\n\n\"", 39 | "cov:html": "nyc report --reporter=html", 40 | "cov:send": "nyc report --reporter=lcov && codecov", 41 | "cov:check": "nyc report && nyc check-coverage --lines 0 --functions 0 --branches 0", 42 | "prepare": "yarn build" 43 | }, 44 | "dependencies": { 45 | "@noble/hashes": "1.1.2", 46 | "@types/events": "3.0.0", 47 | "axios": "0.27.2", 48 | "base64-js": "1.5.1", 49 | "bignumber.js": "9.0.2", 50 | "events": "3.3.0", 51 | "immutable": "4.1.0" 52 | }, 53 | "nyc": { 54 | "extends": "@istanbuljs/nyc-config-typescript", 55 | "exclude": [ 56 | "**/*.d.ts", 57 | "**/*.spec.js" 58 | ], 59 | "include": [ 60 | "src" 61 | ] 62 | }, 63 | "prettier": { 64 | "printWidth": 80, 65 | "semi": true, 66 | "singleQuote": false, 67 | "tabWidth": 4, 68 | "trailingComma": "all", 69 | "endOfLine": "lf", 70 | "arrowParens": "always" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /packages/utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./common"; 2 | export * from "./errors"; 3 | export * from "./internal"; 4 | export * from "./internal/assert"; 5 | export * from "./libraries/pack"; 6 | export * from "./renVMHashes"; 7 | export * from "./txSubmitter"; 8 | export * from "./types"; 9 | -------------------------------------------------------------------------------- /packages/utils/src/internal/extractError.ts: -------------------------------------------------------------------------------- 1 | export const hasOwnProperty = ( 2 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 3 | object: any, 4 | property: keyof T, 5 | ): object is T => Object.prototype.hasOwnProperty.call(object, property); 6 | 7 | export const invalidError = (errorMessage: string): boolean => 8 | errorMessage === "" || 9 | errorMessage === "null" || 10 | errorMessage === "undefined"; 11 | 12 | /** 13 | * Attempt to extract a more meaningful error from a thrown error, such as 14 | * the body of a network response. 15 | */ 16 | export const extractError = (error: unknown): string => { 17 | if (error && typeof error === "object") { 18 | if (hasOwnProperty(error, "response") && error.response) { 19 | const extractedError = extractError(error.response); 20 | if (!invalidError(extractedError)) { 21 | return extractedError; 22 | } 23 | } 24 | if (hasOwnProperty(error, "data") && error.data) { 25 | const extractedError = extractError(error.data); 26 | if (!invalidError(extractedError)) { 27 | return extractedError; 28 | } 29 | } 30 | if (hasOwnProperty(error, "error") && error.error) { 31 | const extractedError = extractError(error.error); 32 | if (!invalidError(extractedError)) { 33 | return extractedError; 34 | } 35 | } 36 | if (hasOwnProperty(error, "context") && error.context) { 37 | const extractedError = extractError(error.context); 38 | if (!invalidError(extractedError)) { 39 | return extractedError; 40 | } 41 | } 42 | if (hasOwnProperty(error, "message") && error.message) { 43 | const extractedError = extractError(error.message); 44 | if (!invalidError(extractedError)) { 45 | return extractedError; 46 | } 47 | } 48 | if (hasOwnProperty(error, "statusText") && error.statusText) { 49 | const extractedError = extractError(error.statusText); 50 | if (!invalidError(extractedError)) { 51 | return extractedError; 52 | } 53 | } 54 | } 55 | try { 56 | if (typeof error === "string") { 57 | if (error.slice(0, 7) === "Error: ") { 58 | error = error.slice(7); 59 | } 60 | return String(error); 61 | } 62 | return JSON.stringify(error); 63 | } catch (innerError) { 64 | // Ignore JSON error 65 | } 66 | return String(error); 67 | }; 68 | -------------------------------------------------------------------------------- /packages/utils/src/internal/hashes.ts: -------------------------------------------------------------------------------- 1 | import { sha256 as createSha256 } from "@noble/hashes/sha256"; 2 | import { keccak_256 as createKeccak256 } from "@noble/hashes/sha3"; 3 | 4 | import { assertType } from "./assert"; 5 | import { concat } from "./common"; 6 | 7 | /** 8 | * Returns the keccak256 hash of an array of Uint8Arrays. The inputs are 9 | * concatenated before being hashed. 10 | * 11 | * @param msg One ore more Uint8Arrays to hash. 12 | * @returns The keccak256 hash of the concatenated input Uint8Arrays. 13 | */ 14 | export const keccak256 = (...msg: Uint8Array[]): Uint8Array => { 15 | assertType("Uint8Array[]", { msg }); 16 | return new Uint8Array(createKeccak256(concat(msg))); 17 | }; 18 | 19 | /** 20 | * Returns the sha256 hash of an array of Uint8Arrays. The inputs are 21 | * concatenated before being hashed. 22 | * 23 | * @param msg One ore more Uint8Arrays to hash. 24 | * @returns The sha256 hash of the concatenated input Uint8Arrays. 25 | */ 26 | export const sha256 = (...msg: Uint8Array[]): Uint8Array => { 27 | assertType("Uint8Array[]", { msg }); 28 | return new Uint8Array(createSha256(concat(msg))); 29 | }; 30 | -------------------------------------------------------------------------------- /packages/utils/src/internal/index.ts: -------------------------------------------------------------------------------- 1 | import * as asset from "./assert"; 2 | import * as common from "./common"; 3 | import * as extractError from "./extractError"; 4 | import * as hashes from "./hashes"; 5 | import * as network from "./network"; 6 | import * as sleep from "./sleep"; 7 | 8 | export const utils = { 9 | ...common, 10 | ...asset, 11 | ...hashes, 12 | ...network, 13 | ...extractError, 14 | ...sleep, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/utils/src/internal/network.ts: -------------------------------------------------------------------------------- 1 | import Axios, { AxiosRequestConfig } from "axios"; 2 | 3 | import { extractError } from "./extractError"; 4 | import { sleep } from "./sleep"; 5 | 6 | // Default timeout for network requests. 7 | export const DEFAULT_TIMEOUT = 30 * sleep.SECONDS; 8 | 9 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 10 | export const GET = async ( 11 | url: string, 12 | config?: AxiosRequestConfig, 13 | ): Promise => { 14 | try { 15 | const response = await Axios.get(url, { 16 | timeout: DEFAULT_TIMEOUT, 17 | ...config, 18 | }); 19 | 20 | return response.data; 21 | } catch (error: unknown) { 22 | throw new Error(extractError(error)); 23 | } 24 | }; 25 | 26 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 27 | export const POST = async ( 28 | url: string, 29 | data?: D, 30 | config?: AxiosRequestConfig, 31 | ): Promise => { 32 | try { 33 | const response = await Axios.post(url, data, { 34 | timeout: DEFAULT_TIMEOUT, 35 | ...config, 36 | }); 37 | 38 | return response.data; 39 | } catch (error: unknown) { 40 | throw new Error(extractError(error)); 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /packages/utils/src/internal/sleep.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Pauses the thread for the specified number of milliseconds. 3 | * 4 | * @param ms The number of milliseconds to pause for. 5 | */ 6 | export const sleep = async (ms: number): Promise => { 7 | return new Promise((resolve) => { 8 | setTimeout(resolve, ms); 9 | }); 10 | }; 11 | sleep.SECONDS = 1000; 12 | sleep.MINUTES = 60 * sleep.SECONDS; 13 | -------------------------------------------------------------------------------- /packages/utils/src/libraries/pack/README.md: -------------------------------------------------------------------------------- 1 | # `📦 pack` 2 | 3 | An interface for serializing well-typed values to binary and JSON without losing 4 | any type information. 5 | 6 | Reference implementation (Go): https://github.com/renproject/pack 7 | 8 | ## Implementation checklist 9 | 10 | - [x] JSON unmarshalling 11 | - [ ] JSON marshalling 12 | - [ ] Binary unmarshalling 13 | - [x] Binary marshalling 14 | -------------------------------------------------------------------------------- /packages/utils/src/libraries/pack/common.ts: -------------------------------------------------------------------------------- 1 | import { PackListType, PackStructType } from "./types"; 2 | 3 | /** 4 | * Check that the passed-in value is a PackStructType - i.e. an object that has 5 | * a single field called `struct` which stores an array. 6 | */ 7 | export const isPackStructType = (type: unknown): type is PackStructType => 8 | typeof type === "object" && 9 | type !== null && 10 | Object.keys(type).length === 1 && 11 | (type as PackStructType).struct !== undefined && 12 | Array.isArray((type as PackStructType).struct); 13 | 14 | /** 15 | * Check that the passed-in value is a PackListType - i.e. an object that has 16 | * a single field called `list`. 17 | */ 18 | export const isPackListType = (type: unknown): type is PackListType => 19 | typeof type === "object" && (type as PackListType).list !== undefined; 20 | -------------------------------------------------------------------------------- /packages/utils/src/libraries/pack/index.ts: -------------------------------------------------------------------------------- 1 | import * as binaryMarshal from "./binaryMarshal"; 2 | import { isPackListType, isPackStructType } from "./common"; 3 | import * as unmarshal from "./unmarshal"; 4 | 5 | export * from "./types"; 6 | 7 | /** 8 | * `pack` implements marshalling and marshalling for the pack serializing 9 | * standard. See github.com/renproject/pack 10 | */ 11 | export const pack = { 12 | isPackStructType, 13 | isPackListType, 14 | binaryMarshal, 15 | unmarshal, 16 | }; 17 | -------------------------------------------------------------------------------- /packages/utils/src/libraries/pack/types.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | 3 | import BigNumber from "bignumber.js"; 4 | 5 | export enum PackPrimitive { 6 | Bool = "bool", 7 | U8 = "u8", 8 | U16 = "u16", 9 | U32 = "u32", 10 | U64 = "u64", 11 | U128 = "u128", 12 | U256 = "u256", 13 | Str = "string", 14 | Bytes = "bytes", 15 | Bytes32 = "bytes32", 16 | Bytes65 = "bytes65", 17 | } 18 | 19 | export interface PackStructType< 20 | T extends Array<{ [name: string]: PackTypeDefinition }> = Array<{ 21 | [name: string]: PackTypeDefinition; 22 | }>, 23 | > { 24 | struct: T; 25 | } 26 | 27 | export interface PackListType< 28 | T extends PackTypeDefinition = PackTypeDefinition, 29 | > { 30 | list: T; 31 | } 32 | 33 | export type PackNilType = "nil"; 34 | 35 | export type PackTypeDefinition = 36 | | PackPrimitive 37 | | PackStructType 38 | | PackListType 39 | | PackNilType; 40 | 41 | // export type PackType = PackPrimitive | PackNilType | "list" | "struct"; 42 | 43 | export type MarshalledPackArray = T[]; 44 | export type MarshalledPackStruct = T; 45 | 46 | export type Marshalled< 47 | Type extends PackTypeDefinition, 48 | InnerType extends PackTypeDefinition = PackTypeDefinition, 49 | > = Type extends PackPrimitive.Bool 50 | ? boolean 51 | : Type extends PackPrimitive.U8 52 | ? string 53 | : Type extends PackPrimitive.U16 54 | ? string 55 | : Type extends PackPrimitive.U32 56 | ? string 57 | : Type extends PackPrimitive.U64 58 | ? string 59 | : Type extends PackPrimitive.U128 60 | ? string 61 | : Type extends PackPrimitive.U256 62 | ? string 63 | : Type extends PackPrimitive.Str 64 | ? string 65 | : Type extends PackPrimitive.Bytes 66 | ? string 67 | : Type extends PackPrimitive.Bytes32 68 | ? string 69 | : Type extends PackPrimitive.Bytes65 70 | ? string 71 | : Type extends PackNilType 72 | ? string 73 | : Type extends { list: InnerType } 74 | ? Array> 75 | : Type extends { struct: Array<{ [key: string]: PackTypeDefinition }> } 76 | ? { [k: string]: any } 77 | : never; 78 | 79 | export type Unmarshalled< 80 | Type extends PackTypeDefinition, 81 | InnerType extends PackTypeDefinition = PackTypeDefinition, 82 | > = Type extends PackPrimitive.Bool 83 | ? boolean 84 | : Type extends PackPrimitive.U8 85 | ? BigNumber 86 | : Type extends PackPrimitive.U16 87 | ? BigNumber 88 | : Type extends PackPrimitive.U32 89 | ? BigNumber 90 | : Type extends PackPrimitive.U64 91 | ? BigNumber 92 | : Type extends PackPrimitive.U128 93 | ? BigNumber 94 | : Type extends PackPrimitive.U256 95 | ? BigNumber 96 | : Type extends PackPrimitive.Str 97 | ? string 98 | : Type extends PackPrimitive.Bytes 99 | ? Uint8Array 100 | : Type extends PackPrimitive.Bytes32 101 | ? Uint8Array 102 | : Type extends PackPrimitive.Bytes65 103 | ? Uint8Array 104 | : Type extends PackNilType 105 | ? null 106 | : Type extends { list: InnerType } 107 | ? Array> 108 | : Type extends { struct: Array<{ [key: string]: PackTypeDefinition }> } 109 | ? { [k: string]: any } 110 | : never; 111 | 112 | export interface TypedPackValue< 113 | T extends PackTypeDefinition = PackTypeDefinition, 114 | V = any, 115 | > { 116 | t: T; 117 | v: V; 118 | } 119 | -------------------------------------------------------------------------------- /packages/utils/src/libraries/promiEvent/LICENSE: -------------------------------------------------------------------------------- 1 | This file is part of web3.js. 2 | 3 | web3.js is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU Lesser General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | web3.js is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU Lesser General Public License for more details. 12 | 13 | You should have received a copy of the GNU Lesser General Public License 14 | along with web3.js. If not, see . -------------------------------------------------------------------------------- /packages/utils/src/pack/README.md: -------------------------------------------------------------------------------- 1 | # `pack` 2 | 3 | An application binary interface for well-typed message passing over networks and disks. 4 | 5 | Reference implementation (Go): https://github.com/renproject/pack 6 | -------------------------------------------------------------------------------- /packages/utils/src/types/eventEmitter.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-ts-comment */ 2 | 3 | import { EventEmitter } from "events"; 4 | 5 | import { Web3PromiEvent } from "../libraries/promiEvent"; 6 | 7 | /** Interface for EventEmitter with well-typed events. */ 8 | export class EventEmitterTyped< 9 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 10 | EventTypes extends { [event: string]: any[] } = {}, 11 | > { 12 | // @ts-ignore no initializer because of proxyHandler 13 | public readonly emit: ( 14 | event: Event, 15 | ...args: EventTypes[Event] 16 | ) => boolean; // EventEmitter["emit"] 17 | // @ts-ignore no initializer because of proxyHandler 18 | public readonly removeListener: EventEmitter["removeListener"]; 19 | // @ts-ignore no initializer because of proxyHandler 20 | public readonly on: ( 21 | event: Event, 22 | callback: (...values: EventTypes[Event]) => void | Promise, 23 | ) => this; 24 | // @ts-ignore no initializer because of proxyHandler 25 | public readonly once: ( 26 | event: Event, 27 | callback: (...values: EventTypes[Event]) => void | Promise, 28 | ) => this; 29 | // @ts-ignore no initializer because of proxyHandler 30 | public readonly listenerCount: (event: string | symbol) => number; 31 | } 32 | 33 | /** Create a new EventEmitterTyped */ 34 | export const eventEmitter = < 35 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 36 | EventTypes extends { [event: string]: any[] } = {}, 37 | >(): EventEmitterTyped => 38 | new EventEmitter() as unknown as EventEmitterTyped; 39 | 40 | // Tell Typescript that Web3PromiEvent implements Promise. 41 | export type PromiEvent< 42 | T, 43 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 44 | EventTypes extends { [event: string]: any[] } = {}, 45 | > = Web3PromiEvent & Promise; 46 | -------------------------------------------------------------------------------- /packages/utils/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./chain"; 2 | export * from "./eventEmitter"; 3 | export * from "./logger"; 4 | export * from "./renNetwork"; 5 | export * from "./shard"; 6 | export * from "./types"; 7 | export * from "./types"; 8 | -------------------------------------------------------------------------------- /packages/utils/src/types/logger.ts: -------------------------------------------------------------------------------- 1 | /** Based on log levels from the `loglevel` npm package. */ 2 | export enum LogLevel { 3 | Trace = 0, 4 | Debug = 1, 5 | Log = LogLevel.Debug, 6 | Info = 2, 7 | Warn = 3, 8 | Error = 4, 9 | Silent = 5, 10 | } 11 | 12 | /** 13 | * Standard logger/console interface. 14 | */ 15 | export interface Logger { 16 | error(message?: unknown, ...optionalParams: unknown[]): void; 17 | warn(message?: unknown, ...optionalParams: unknown[]): void; 18 | info(message?: unknown, ...optionalParams: unknown[]): void; 19 | debug(message?: unknown, ...optionalParams: unknown[]): void; 20 | 21 | // Return the logging level, as a number from 0 (trace) to 5 (silent). 22 | getLevel?(): LogLevel | number; 23 | } 24 | 25 | const doNothing = (): void => {}; 26 | 27 | /** 28 | * The defaultLogger forwards info, warn and error logs to the console, and 29 | * ignores debug logs. 30 | * 31 | * @example 32 | * ``` 33 | * const logger = params.logger || defaultLogger; 34 | * logger.debug("Test."); 35 | * ``` 36 | */ 37 | export const defaultLogger: Logger = { 38 | debug: doNothing, 39 | // eslint-disable-next-line no-console 40 | info: console.info, 41 | warn: console.warn, 42 | error: console.error, 43 | }; 44 | -------------------------------------------------------------------------------- /packages/utils/src/types/renNetwork.ts: -------------------------------------------------------------------------------- 1 | export enum RenNetwork { 2 | Mainnet = "mainnet", 3 | Testnet = "testnet", 4 | } 5 | 6 | export type RenNetworkString = `${RenNetwork}`; 7 | -------------------------------------------------------------------------------- /packages/utils/src/types/shard.ts: -------------------------------------------------------------------------------- 1 | // The details for a RenVM shard. The is currently only one shard that doesn't 2 | // expire. 3 | // There will be multiple levels of expiries - the `expiry` field will refer 4 | // to the time (as seconds since Unix epoch) by which gateway transactions 5 | // have to be submitted by. For mints and for contract-based releases, RenVM 6 | // will then generate a signature which needs to be submitted by a second 7 | // deadline. 8 | export interface RenVMShard { 9 | gPubKey: string; 10 | 11 | expiry?: number; 12 | } 13 | -------------------------------------------------------------------------------- /packages/utils/src/types/types.ts: -------------------------------------------------------------------------------- 1 | export type UrlBase64String = string; 2 | export type HexString = string; 3 | 4 | export enum TxStatus { 5 | // TxStatusNil is used for transactions that have not been seen, or are 6 | // otherwise unknown. 7 | TxStatusNil = "nil", 8 | // TxStatusConfirming is used for transactions that are currently waiting 9 | // for their underlying blockchain transactions to be confirmed. 10 | TxStatusConfirming = "confirming", 11 | // TxStatusPending is used for transactions that are waiting for consensus 12 | // to be reached on when the transaction should be executed. 13 | TxStatusPending = "pending", 14 | // TxStatusExecuting is used for transactions that are currently being 15 | // executed. 16 | TxStatusExecuting = "executing", 17 | // TxStatusReverted is used for transactions that were reverted during 18 | // execution. 19 | TxStatusReverted = "reverted", 20 | // TxStatusDone is used for transactions that have been successfully 21 | // executed. 22 | TxStatusDone = "done", 23 | } 24 | 25 | export const TxStatusIndex = { 26 | [TxStatus.TxStatusNil]: 0, 27 | [TxStatus.TxStatusConfirming]: 1, 28 | [TxStatus.TxStatusPending]: 2, 29 | [TxStatus.TxStatusExecuting]: 3, 30 | [TxStatus.TxStatusReverted]: 4, 31 | [TxStatus.TxStatusDone]: 5, 32 | }; 33 | -------------------------------------------------------------------------------- /packages/utils/test/hash.spec.ts: -------------------------------------------------------------------------------- 1 | import chai, { expect } from "chai"; 2 | 3 | import { utils } from "../src"; 4 | import { keccak256 } from "../src/internal/hashes"; 5 | 6 | chai.should(); 7 | 8 | const testCases = [ 9 | { 10 | msg: Buffer.from([1, 2, 3]), 11 | hashes: { 12 | keccak256: 13 | "f1885eda54b7a053318cd41e2093220dab15d65381b1157a3633a83bfd5c9239", 14 | }, 15 | }, 16 | { 17 | msg: Buffer.from([]), 18 | hashes: { 19 | keccak256: 20 | "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", 21 | }, 22 | }, 23 | { 24 | msg: Buffer.from("00".repeat(20), "hex"), 25 | hashes: { 26 | keccak256: 27 | "5380c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312a", 28 | }, 29 | }, 30 | ]; 31 | 32 | const hashers = { keccak256 }; 33 | 34 | describe("keccak256", () => { 35 | it("returns correct result for hard-coded testcases", () => { 36 | for (const testCase of testCases) { 37 | for (const hash of Object.keys(testCase.hashes)) { 38 | const result = hashers[hash](testCase.msg); 39 | expect(result instanceof Uint8Array).to.be.true; 40 | expect(utils.toHex(result)).to.equal(testCase.hashes[hash]); 41 | } 42 | } 43 | }); 44 | }); 45 | 46 | /* 47 | * Generate new test cases: 48 | * 49 | * ```js 50 | const { hash160, keccak256, ripemd160, sha256 } = require("@renproject/utils"); 51 | let msg = Buffer.from([0]) 52 | let hashers = {keccak256, ripemd160, sha256, hash160 } 53 | let hash = (msg) => { 54 | let obj = {}; 55 | for (const hash of Object.keys(hashers)) { 56 | obj[hash] = hashers[hash](msg).toString("hex"); 57 | } 58 | console.debug(JSON.stringify(obj, null, " ")) 59 | } 60 | * ``` 61 | */ 62 | -------------------------------------------------------------------------------- /packages/utils/test/marshalPack.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import { describe, it } from "mocha"; 3 | 4 | import { Ox } from "../src/internal/common"; 5 | import { PackPrimitive, TypedPackValue } from "../src/libraries/pack"; 6 | 7 | describe("Pack", () => { 8 | it("Marshal pack value", () => { 9 | const expected = 10 | "0x140000000400000006616d6f756e740700000005746f6b656e0a00000002746f0a000000056e6f6e63650ccb6beefca4aded539a56f136a7ff24a2901fe6627233b8bf8d7d7f69c8737fc300000144f2b580a8f0ac80a2f294b3a9f1afaf86f18597b6f38186a3f1ada7aff185bc94f2908ba6f1a7afb3e4aaa2f481b0b1f29986a5f3aea7b1f488a3a1f396958aebad83f283ad81f0b2a8b5f193ada4f2b0b1b0f3a9b692f2a4a9bef2a9acb3f39d8abef189aab0f2878585f38aa1a9f18b97adf09d978cf29caabff3b099b9f2a494a5f39294a9f2b58299f393ba94f388979ae3b185f2b58fa9f294bfa2f390aa9df3ba84a1f29db093f0a1a7a4f18f939ef1a59d9df48fb0aaeb81ade49fb8e88aaaf0968aa2f1a488aaf381b6a8f0a4bdbaf3bf99aaf2a98e97f29eb486f2b294a2f1a98c86f1bab29be7babaf399bf93f285bf89f3b08996f3839b8df2b8af9af392adb6f0b58cabf2a484b3f0b6ac8af0a4808ff0aeb3a0f282949ceebfa9f2b5b48af3bb9da7f286819bf1b9b1baf39bbeb8f0baa484f18f8b8af398a691f2a39fa700000168f38285acf2bb93b7f0a0b195f0b3bfb6f1b980a7f2b4b28bf1b785b0f2a2afbef3baa99bf0b5b59cf187a6a1f3acb58ff3a5899df38cb3baf2b78f94f18bb599f29d908cf38290a3f1b2a8aef0b39785ecb1bbf0a5bb86eeac81f3a4aa8ff4858299f3bc80bef2ae80a3f1a396a8f28ca18bf3b794b5f38faaa3f0b181a5f3928a8bf2989cbaf2a9919ef296a8b5f39cb0aaf09eb5abf098abb0f2a382b1f1b3b1a8f1acb5aaf1b2bb98efb1bbf2b580adf1849facf39d8cbcf19bb5b9f09a8aa9f39f88bbe5b2b3f29c80a3f39fb596f1a7af97f48f87a6f0bb91b3f398a9a2f28d82a6f0a5a394f2999e93f0a5bc92f3a48b8af3bda295f482adb6f3a9a3a5f3bc89b5f195a1baf2a18db4f2969b9bf1a5bcb1f2b1b19bf39ea5abef9e9ff1b68d91f0b895b9f18db590f3b691baf399a9abe8afbbf094a9b2e98f8cf295b0b8f18eafb0f2868cbbf2a48e9bf3bdadaef394a9b8f1acb3a3f4878a8de7b0acf3b59495f48a8ba6df46480fdfbf78dfc7f1fea5dfd3a5b4668f5c48e16e086baf28852beb01a9d4"; 11 | 12 | const packValue: TypedPackValue = { 13 | t: { 14 | struct: [ 15 | { amount: PackPrimitive.U256 }, 16 | { token: PackPrimitive.Str }, 17 | { to: PackPrimitive.Str }, 18 | { nonce: PackPrimitive.Bytes32 }, 19 | ], 20 | }, 21 | v: { 22 | amount: "92010210325214225514040705701652972196351460568772244563366741439829733769155", 23 | nonce: "30ZID9-_eN_H8f6l39OltGaPXEjhbghrryiFK-sBqdQ", 24 | to: "󂅬򻓷𠱕𳿶񹀧򴲋񷅰򢯾󺩛𵵜񇦡󬵏󥉝󌳺򷏔񋵙򝐌󂐣񲨮𳗅챻𥻆󤪏􅂙󼀾򮀣񣖨򌡋󷔵󏪣𱁥󒊋򘜺򩑞򖨵󜰪𞵫𘫰򣂱񳱨񬵪񲻘ﱻ򵀭񄟬󝌼񛵹𚊩󟈻岳򜀣󟵖񧯗􏇦𻑳󘩢򍂦𥣔򙞓𥼒󤋊󽢕􂭶󩣥󼉵񕡺򡍴򖛛񥼱򱱛󞥫񶍑𸕹񍵐󶑺󙩫读𔩲鏌򕰸񎯰򆌻򤎛󽭮󔩸񬳣􇊍簬󵔕􊋦", 25 | token: "򵀨𬀢򔳩񯯆񅗶󁆣񭧯񅼔򐋦񧯳䪢􁰱򙆥󮧱􈣡󖕊뭃򃭁𲨵񓭤򰱰󩶒򤩾򩬳󝊾񉪰򇅅󊡩񋗭𝗌򜪿󰙹򤔥󒔩򵂙󓺔󈗚㱅򵏩򔿢󐪝󺄡򝰓𡧤񏓞񥝝􏰪끭䟸芪𖊢񤈪󁶨𤽺󿙪򩎗򞴆򲔢񩌆񺲛纺󙿓򅿉󰉖󃛍򸯚󒭶𵌫򤄳𶬊𤀏𮳠򂔜򵴊󻝧򆁛񹱺󛾸𺤄񏋊󘦑򣟧", 26 | }, 27 | }; 28 | 29 | // const data = `0000000130000000104254432f66726f6d457468657265756d` + expected; 30 | // const hash = "c4e423c339ffb1c1bd37b6493a4f209391fb498466bb257fc565ba904804af5a"; 31 | 32 | // expect(Ox(marshalTypedPackValue(packValue))).to.equal(expected); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/utils/test/renVMHashes.spec.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from "bignumber.js"; 2 | import { expect } from "chai"; 3 | 4 | import { fromHex, Ox, toNBytes } from "../src/internal/common"; 5 | import { 6 | generateGHash, 7 | generateNHash, 8 | generatePHash, 9 | generateSHash, 10 | generateSighash, 11 | } from "../src/renVMHashes"; 12 | 13 | describe("renVMHashes", () => { 14 | const payload: Uint8Array = toNBytes(1, 32); 15 | 16 | context("generateSHash", () => { 17 | it("hashes correctly", () => { 18 | expect(Ox(generateSHash("BTC/toEthereum"))).to.equal( 19 | "0x1fb79ec5bb04cf1aa8eb8fdeda8d3f986e5ebaba72d0e12048cec0a95188fe5e", 20 | ); 21 | expect(Ox(generateSHash("ZEC/toFantom"))).to.equal( 22 | "0x2cb58c03e9b6bb1f395dd8a458fc8e76767253ae17b364c817871899e2cf48ad", 23 | ); 24 | }); 25 | 26 | it("removes from chain for host-to-host", () => { 27 | expect(Ox(generateSHash("BTC/fromFantomToEthereum"))).to.equal( 28 | Ox(generateSHash("BTC/toEthereum")), 29 | ); 30 | }); 31 | }); 32 | 33 | it("generatePHash", () => { 34 | expect(Ox(generatePHash(payload))).to.equal( 35 | "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6", 36 | ); 37 | expect(Ox(generatePHash(payload))).to.equal( 38 | "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6", 39 | ); 40 | }); 41 | 42 | it("generateGHash", () => { 43 | const to = fromHex("00".repeat(20)); 44 | const sHash = fromHex("00".repeat(20)); 45 | const nonce = fromHex("00".repeat(32)); 46 | 47 | expect( 48 | Ox(generateGHash(generatePHash(payload), to, sHash, nonce)), 49 | ).to.equal( 50 | "0x4b606c6a759e54ae3332637bd88050fff7be648b58d03f36491e277f94062ea9", 51 | ); 52 | }); 53 | 54 | it("generateNHash", () => { 55 | const nonce = fromHex("00".repeat(32)); 56 | const txid = fromHex("00".repeat(32)); 57 | const txindex = "1"; 58 | expect(Ox(generateNHash(nonce, txid, txindex))).to.equal( 59 | "0xb92afca8929110484eee9b91373c9ed41205b90ce83867e5e9363041a70cfe3e", 60 | ); 61 | }); 62 | 63 | it("generateSighash", () => { 64 | const pHash = fromHex("12".repeat(32)); 65 | const amount = new BigNumber(102); 66 | const to = fromHex("34".repeat(20)); 67 | const selectorHash = fromHex("56".repeat(32)); 68 | const nHash = fromHex("78".repeat(32)); 69 | 70 | expect( 71 | Ox(generateSighash(pHash, amount, to, selectorHash, nHash)), 72 | ).to.equal( 73 | "0xcc6eacb85506fcb76a1951e79dfcc42a10751ff04bbfe5377fb06a1ecbe76e54", 74 | ); 75 | }); 76 | }); 77 | -------------------------------------------------------------------------------- /packages/utils/test/signatureUtils.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import { concat } from "ethers/lib/utils"; 3 | 4 | import { utils } from "../src"; 5 | import { normalizeSignature } from "../src/common"; 6 | import { fromHex } from "../src/internal/common"; 7 | 8 | const secp256k1nBuffer = fromHex( 9 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 10 | ); 11 | 12 | describe("signatureUtils", () => { 13 | context("normalizeSignature", () => { 14 | it("should return fixed signatures", () => { 15 | expect( 16 | utils.toHex( 17 | normalizeSignature( 18 | concat([ 19 | fromHex("11".repeat(32)), 20 | fromHex("00".repeat(32)), 21 | new Uint8Array([0]), 22 | ]), 23 | ), 24 | ), 25 | ).to.deep.equal( 26 | utils.toHex( 27 | concat([ 28 | fromHex("11".repeat(32)), 29 | fromHex("00".repeat(32)), 30 | new Uint8Array([27]), 31 | ]), 32 | ), 33 | ); 34 | expect( 35 | utils.toHex( 36 | normalizeSignature( 37 | concat([ 38 | fromHex("00".repeat(32)), 39 | fromHex("00".repeat(32)), 40 | new Uint8Array([0]), 41 | ]), 42 | ), 43 | ), 44 | ).to.deep.equal( 45 | utils.toHex( 46 | concat([ 47 | fromHex("00".repeat(32)), 48 | fromHex("00".repeat(32)), 49 | new Uint8Array([0]), 50 | ]), 51 | ), 52 | ); 53 | expect( 54 | utils.toHex( 55 | normalizeSignature( 56 | concat([ 57 | fromHex("00".repeat(32)), 58 | secp256k1nBuffer, 59 | new Uint8Array([0]), 60 | ]), 61 | ), 62 | ), 63 | ).to.deep.equal( 64 | utils.toHex( 65 | concat([ 66 | fromHex("00".repeat(32)), 67 | fromHex("00".repeat(32)), 68 | new Uint8Array([28]), 69 | ]), 70 | ), 71 | ); 72 | expect( 73 | utils.toHex( 74 | normalizeSignature( 75 | concat([ 76 | fromHex("00".repeat(32)), 77 | secp256k1nBuffer, 78 | new Uint8Array([1]), 79 | ]), 80 | ), 81 | ), 82 | ).to.deep.equal( 83 | utils.toHex( 84 | concat([ 85 | fromHex("00".repeat(32)), 86 | fromHex("00".repeat(32)), 87 | new Uint8Array([27]), 88 | ]), 89 | ), 90 | ); 91 | }); 92 | }); 93 | }); 94 | -------------------------------------------------------------------------------- /packages/utils/test/txHash.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import { describe, it } from "mocha"; 3 | 4 | import { Ox } from "../src/internal/common"; 5 | import { PackPrimitive, TypedPackValue } from "../src/libraries/pack"; 6 | import { generateTransactionHash } from "../src/renVMHashes"; 7 | 8 | describe("txHash", () => { 9 | it("Hash transaction", () => { 10 | const expected = 11 | "0xc4e423c339ffb1c1bd37b6493a4f209391fb498466bb257fc565ba904804af5a"; 12 | 13 | const packValue: TypedPackValue = { 14 | t: { 15 | struct: [ 16 | { amount: PackPrimitive.U256 }, 17 | { token: PackPrimitive.Str }, 18 | { to: PackPrimitive.Str }, 19 | { nonce: PackPrimitive.Bytes32 }, 20 | ], 21 | }, 22 | v: { 23 | amount: "92010210325214225514040705701652972196351460568772244563366741439829733769155", 24 | nonce: "30ZID9-_eN_H8f6l39OltGaPXEjhbghrryiFK-sBqdQ", 25 | to: "󂅬򻓷𠱕𳿶񹀧򴲋񷅰򢯾󺩛𵵜񇦡󬵏󥉝󌳺򷏔񋵙򝐌󂐣񲨮𳗅챻𥻆󤪏􅂙󼀾򮀣񣖨򌡋󷔵󏪣𱁥󒊋򘜺򩑞򖨵󜰪𞵫𘫰򣂱񳱨񬵪񲻘ﱻ򵀭񄟬󝌼񛵹𚊩󟈻岳򜀣󟵖񧯗􏇦𻑳󘩢򍂦𥣔򙞓𥼒󤋊󽢕􂭶󩣥󼉵񕡺򡍴򖛛񥼱򱱛󞥫񶍑𸕹񍵐󶑺󙩫读𔩲鏌򕰸񎯰򆌻򤎛󽭮󔩸񬳣􇊍簬󵔕􊋦", 26 | token: "򵀨𬀢򔳩񯯆񅗶󁆣񭧯񅼔򐋦񧯳䪢􁰱򙆥󮧱􈣡󖕊뭃򃭁𲨵񓭤򰱰󩶒򤩾򩬳󝊾񉪰򇅅󊡩񋗭𝗌򜪿󰙹򤔥󒔩򵂙󓺔󈗚㱅򵏩򔿢󐪝󺄡򝰓𡧤񏓞񥝝􏰪끭䟸芪𖊢񤈪󁶨𤽺󿙪򩎗򞴆򲔢񩌆񺲛纺󙿓򅿉󰉖󃛍򸯚󒭶𵌫򤄳𶬊𤀏𮳠򂔜򵴊󻝧򆁛񹱺󛾸𺤄񏋊󘦑򣟧", 27 | }, 28 | }; 29 | 30 | // const data = `0000000130000000104254432f66726f6d457468657265756d` + expected; 31 | // const hash = ""; 32 | 33 | // 0000000131000000104254432f66726f6d457468657265756d140000000400000006616d6f756e740700000005746f6b656e0a00000002746f0a000000056e6f6e63650ccb6beefca4aded539a56f136a7ff24a2901fe6627233b8bf8d7d7f69c8737fc300000144f2b580a8f0ac80a2f294b3a9f1afaf86f18597b6f38186a3f1ada7aff185bc94f2908ba6f1a7afb3e4aaa2f481b0b1f29986a5f3aea7b1f488a3a1f396958aebad83f283ad81f0b2a8b5f193ada4f2b0b1b0f3a9b692f2a4a9bef2a9acb3f39d8abef189aab0f2878585f38aa1a9f18b97adf09d978cf29caabff3b099b9f2a494a5f39294a9f2b58299f393ba94f388979ae3b185f2b58fa9f294bfa2f390aa9df3ba84a1f29db093f0a1a7a4f18f939ef1a59d9df48fb0aaeb81ade49fb8e88aaaf0968aa2f1a488aaf381b6a8f0a4bdbaf3bf99aaf2a98e97f29eb486f2b294a2f1a98c86f1bab29be7babaf399bf93f285bf89f3b08996f3839b8df2b8af9af392adb6f0b58cabf2a484b3f0b6ac8af0a4808ff0aeb3a0f282949ceebfa9f2b5b48af3bb9da7f286819bf1b9b1baf39bbeb8f0baa484f18f8b8af398a691f2a39fa700000168f38285acf2bb93b7f0a0b195f0b3bfb6f1b980a7f2b4b28bf1b785b0f2a2afbef3baa99bf0b5b59cf187a6a1f3acb58ff3a5899df38cb3baf2b78f94f18bb599f29d908cf38290a3f1b2a8aef0b39785ecb1bbf0a5bb86eeac81f3a4aa8ff4858299f3bc80bef2ae80a3f1a396a8f28ca18bf3b794b5f38faaa3f0b181a5f3928a8bf2989cbaf2a9919ef296a8b5f39cb0aaf09eb5abf098abb0f2a382b1f1b3b1a8f1acb5aaf1b2bb98efb1bbf2b580adf1849facf39d8cbcf19bb5b9f09a8aa9f39f88bbe5b2b3f29c80a3f39fb596f1a7af97f48f87a6f0bb91b3f398a9a2f28d82a6f0a5a394f2999e93f0a5bc92f3a48b8af3bda295f482adb6f3a9a3a5f3bc89b5f195a1baf2a18db4f2969b9bf1a5bcb1f2b1b19bf39ea5abef9e9ff1b68d91f0b895b9f18db590f3b691baf399a9abe8afbbf094a9b2e98f8cf295b0b8f18eafb0f2868cbbf2a48e9bf3bdadaef394a9b8f1acb3a3f4878a8de7b0acf3b59495f48a8ba6df46480fdfbf78dfc7f1fea5dfd3a5b4668f5c48e16e086baf28852beb01a9d4 34 | 35 | expect( 36 | Ox(generateTransactionHash("0", "BTC/fromEthereum", packValue)), 37 | ).to.equal(expected); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /packages/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "outDir": "build", 5 | "rootDir": "src", 6 | "moduleResolution": "node", 7 | "module": "commonjs", 8 | "declaration": true, 9 | "removeComments": false, 10 | "esModuleInterop": true, 11 | "strict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "traceResolution": false, 17 | "listEmittedFiles": false, 18 | "listFiles": false, 19 | "pretty": true, 20 | "lib": ["es2017", "dom"], 21 | "types": ["mocha"], 22 | "typeRoots": ["node_modules/@types", "src/types"], 23 | "resolveJsonModule": true, 24 | "forceConsistentCasingInFileNames": true, 25 | "noImplicitThis": true, 26 | "noImplicitAny": true, 27 | "strictNullChecks": true, 28 | "suppressImplicitAnyIndexErrors": true, 29 | "strictPropertyInitialization": true, 30 | "alwaysStrict": true, 31 | "strictFunctionTypes": true, 32 | "sourceMap": true, 33 | "declarationMap": true 34 | }, 35 | "include": ["src/**/*.ts"], 36 | "exclude": ["node_modules/**"], 37 | "compileOnSave": false 38 | } 39 | -------------------------------------------------------------------------------- /packages/utils/tsconfig.module.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "outDir": "build/module", 6 | "module": "es6" 7 | }, 8 | "exclude": ["node_modules/**"] 9 | } 10 | -------------------------------------------------------------------------------- /test/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { Ethereum } from "packages/chains/chains-ethereum/src"; 4 | import { BinanceSmartChain } from "packages/chains/chains/src"; 5 | import RenJS from "packages/ren/src"; 6 | import { RenNetwork } from "packages/utils"; 7 | 8 | import { initializeChain } from "./utils/testUtils"; 9 | 10 | const network = RenNetwork.Testnet; 11 | 12 | const main = async () => { 13 | // Initialize Ethereum and BSC chains. 14 | const ethereum = initializeChain(Ethereum, network); 15 | const bsc = initializeChain(BinanceSmartChain, network); 16 | 17 | // Create RenJS instance. NOTE - chains must now be linked to RenJS using 18 | // `withChains`. 19 | const renJS = new RenJS(network).withChains(ethereum, bsc); 20 | 21 | // Create gateway. Gateway parameters are serializable. 22 | const gateway = await renJS.gateway({ 23 | asset: ethereum.assets.DAI, 24 | from: ethereum.Account({ amount: 2, convertUnit: true }), 25 | to: bsc.Account(), 26 | }); 27 | 28 | // `gateway.fees` exposes values and helpers for calculating fees. 29 | console.debug("Fees", gateway.fees); 30 | 31 | // `gateway.inSetup` may contain multiple transactions. 32 | await gateway.inSetup.approval.submit({ 33 | txConfig: { 34 | gasLimit: 1000000, 35 | }, 36 | }); 37 | // All transactions now follow a submit/wait pattern - see TxSubmitter 38 | // interface. 39 | await gateway.inSetup.approval.wait(); 40 | 41 | // Transactions emit a `status` 42 | await gateway.in.submit().on("progress", console.debug); 43 | await gateway.in.wait(1); 44 | 45 | await new Promise((resolve, reject) => { 46 | gateway.on("transaction", (tx) => { 47 | (async () => { 48 | // GatewayTransaction parameters are serializable. To re-create 49 | // the transaction, call `renJS.gatewayTransaction`. 50 | console.debug(tx.params); 51 | 52 | // Wait for remaining confirmations for input transaction. 53 | await tx.in.wait(); 54 | 55 | // RenVM transaction also follows the submit/wait pattern. 56 | await tx.renVM.submit().on("progress", console.debug); 57 | await tx.renVM.wait(); 58 | 59 | // `submit` accepts a `txConfig` parameter for overriding 60 | // transaction config. 61 | await tx.out.submit({ 62 | txConfig: { 63 | gasLimit: 1000000, 64 | }, 65 | }); 66 | await tx.out.wait(); 67 | 68 | // All transactions return a `ChainTransaction` object in the 69 | // progress, with a `txid` field (base64) and a `txHash` 70 | // field (chain-dependent) 71 | const outTx = tx.out.progress.transaction; 72 | console.debug("Done:", outTx.txHash); 73 | 74 | resolve(); 75 | })().catch(reject); 76 | }); 77 | }); 78 | }; 79 | 80 | main().catch((error) => { 81 | console.error(error); 82 | process.exit(1); 83 | }); 84 | -------------------------------------------------------------------------------- /test/quickstart.spec.ts: -------------------------------------------------------------------------------- 1 | // import { providers, Wallet } from "ethers"; 2 | 3 | // import { Bitcoin, Ethereum } from "@renproject/chains"; 4 | // import RenJS from "@renproject/ren"; 5 | 6 | // // Test account - do not send real funds. 7 | // const mnemonic = 8 | // "black magic humor turtle symptom liar salmon rally hurt concert tower run"; 9 | 10 | // const main = async () => { 11 | // const network = "testnet"; 12 | 13 | // // Initialize Bitcoin and Ethereum. 14 | // const bitcoin = new Bitcoin({ network }); 15 | // const ethereum = new Ethereum({ 16 | // network, 17 | // provider: new providers.JsonRpcProvider( 18 | // Ethereum.configMap[network].config.rpcUrls[0], 19 | // ), 20 | // signer: Wallet.fromMnemonic(mnemonic), 21 | // }); 22 | 23 | // // Create RenJS instance. NOTE - chains must now be linked to RenJS using 24 | // // `withChains`. 25 | // const renJS = new RenJS(network).withChains(bitcoin, ethereum); 26 | 27 | // // Create gateway - mints and burns are both initialized with `gateway`. 28 | // // Gateway parameters are serializable. 29 | // const gateway = await renJS.gateway({ 30 | // asset: ethereum.assets.DAI, // "DAI" 31 | // from: bitcoin.GatewayAddress(), 32 | // to: ethereum.Account(), 33 | // }); 34 | 35 | // // `gateway.fees` exposes values and helpers for calculating fees. 36 | // console.info(gateway.fees); 37 | 38 | // console.info(`Deposit ${gateway.params.asset} to ${gateway.gatewayAddress}`); 39 | 40 | // // NOTE: Event has been renamed from "deposit" to "transaction". 41 | // gateway.on("transaction", (tx) => { 42 | // (async () => { 43 | // // GatewayTransaction parameters are serializable. To re-create 44 | // // the transaction, call `renJS.gatewayTransaction`. 45 | // console.info(tx.params); 46 | 47 | // // Wait for remaining confirmations for input transaction. 48 | // await tx.in.wait(); 49 | 50 | // // RenVM transaction also follows the submit/wait pattern. 51 | // await tx.renVM.submit().on("progress", console.info); 52 | // await tx.renVM.wait(); 53 | 54 | // // `submit` accepts a `txConfig` parameter for overriding 55 | // // transaction config. 56 | // await tx.out.submit({ 57 | // txConfig: { 58 | // gasLimit: 1000000, 59 | // }, 60 | // }); 61 | // await tx.out.wait(); 62 | 63 | // // All transactions return a `ChainTransaction` object in the 64 | // // progress, with a `txid` field (base64) and a `txHash` 65 | // // field (chain-dependent). 66 | // const outTx = tx.out.progress.transaction; 67 | // console.info("Done:", outTx.txHash); 68 | 69 | // // All chain classes expose a common set of helper functions (see 70 | // // `Chain` class.) 71 | // console.info(tx.toChain.transactionExplorerLink(outTx)); 72 | // })().catch(console.error); 73 | // }); 74 | // }; 75 | 76 | // main().catch((error) => { 77 | // console.error(error); 78 | // process.exit(1); 79 | // }); 80 | -------------------------------------------------------------------------------- /test/simple.spec.ts: -------------------------------------------------------------------------------- 1 | import { Ethereum } from "@renproject/chains-ethereum/src"; 2 | import { RenNetwork } from "@renproject/utils"; 3 | /* eslint-disable no-console */ 4 | import chalk from "chalk"; 5 | import { BinanceSmartChain } from "packages/chains/chains/src"; 6 | import RenJS from "packages/ren/src"; 7 | 8 | import { initializeChain } from "./utils/testUtils"; 9 | 10 | const network = RenNetwork.Testnet; 11 | 12 | /** 13 | * Same as daiToBsc except: 14 | * - calls `gateway.inSetup.approval` directly instead of looping through `setup` 15 | * - no retrying on errors 16 | * - less logs 17 | */ 18 | 19 | describe("DAI/toBinanceSmartChain - simpler", () => { 20 | it("DAI/toBinanceSmartChain - simpler", async () => { 21 | const ethereum = initializeChain(Ethereum, network); 22 | const bsc = initializeChain(BinanceSmartChain, network); 23 | 24 | const renJS = new RenJS(network).withChains(ethereum, bsc); 25 | 26 | const gateway = await renJS.gateway({ 27 | asset: ethereum.assets.DAI, 28 | from: ethereum.Account({ amount: 2, convertUnit: true }), 29 | to: bsc.Account(), 30 | }); 31 | 32 | console.debug(chalk.cyan("gateway parameters"), gateway.params); 33 | 34 | console.debug(chalk.cyan("calling setup.approval.submit()")); 35 | await gateway.inSetup.approval.submit({ 36 | txConfig: { 37 | gasLimit: 1000000, 38 | }, 39 | }); 40 | await gateway.inSetup.approval.wait(); 41 | 42 | console.debug(chalk.cyan("calling in.submit()")); 43 | await gateway.in.submit().on("progress", console.debug); 44 | await gateway.in.wait(1); 45 | 46 | await new Promise((resolve, reject) => { 47 | gateway.on("transaction", (tx) => { 48 | (async () => { 49 | console.debug(chalk.cyan("tx parameters"), tx.params); 50 | 51 | await tx.in.wait(); 52 | 53 | console.debug(chalk.cyan("calling renVM.submit()")); 54 | await tx.renVM.submit().on("progress", console.debug); 55 | await tx.renVM.wait(); 56 | 57 | console.debug(chalk.cyan("calling out.submit()")); 58 | await tx.out 59 | .submit({ 60 | txConfig: { 61 | gasLimit: 1000000, 62 | }, 63 | }) 64 | .on("progress", console.debug); 65 | await tx.out.wait(); 66 | 67 | console.debug( 68 | chalk.cyan("Done"), 69 | tx.out.progress.transaction, 70 | ); 71 | 72 | resolve(); 73 | })().catch(reject); 74 | }); 75 | }); 76 | }).timeout(100000000000); 77 | }); 78 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "esModuleInterop": true 5 | }, 6 | "exclude": ["node_modules/**"] 7 | } 8 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require("path"); 2 | var nodeExternals = require("webpack-node-externals"); 3 | 4 | let common = { 5 | entry: "./src/index.ts", 6 | devtool: "source-map", 7 | module: { 8 | rules: [ 9 | { 10 | test: /\.tsx?$/, 11 | use: ["babel-loader", "ts-loader"], 12 | exclude: /node_modules/, 13 | }, 14 | ], 15 | }, 16 | plugins: [], 17 | resolve: { 18 | extensions: [".ts", ".tsx", ".js"], 19 | }, 20 | }; 21 | 22 | module.exports = [ 23 | Object.assign({}, common, { 24 | target: "web", 25 | entry: ["babel-polyfill", "./src/index.ts"], 26 | output: { 27 | path: path.resolve(/* __dirname */ "./", "build/bundled"), 28 | filename: "browser.js", 29 | libraryTarget: "var", 30 | library: "RenVM", // This is the var name in browser 31 | libraryExport: "default", 32 | }, 33 | resolve: { 34 | ...common.resolve, 35 | fallback: { 36 | fs: "empty", 37 | child_process: "empty", 38 | }, 39 | }, 40 | }), 41 | Object.assign({}, common, { 42 | target: "node", 43 | output: { 44 | path: path.resolve(/* __dirname */ "./", "build/bundled"), 45 | filename: "index.js", 46 | libraryTarget: "commonjs2", 47 | // libraryExport: 'default' 48 | }, 49 | externals: [nodeExternals()], 50 | }), 51 | ]; 52 | --------------------------------------------------------------------------------