diff --git a/.codecov.yml b/.codecov.yml index d9384014fa..e718872ed2 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -3,7 +3,7 @@ coverage: project: off patch: off comment: - layout: "diff, flags, files" + layout: 'diff, flags, files' require_changes: true flags: bitgo: diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index cf5bd027a2..5dc1576f4b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,7 +2,6 @@ name: Bug Report about: Report any bugs you find to help us improve the library. labels: 'bug' - --- ## Environment Details -* **OS:** -* **Node Version:** -* **Yarn Version:** -* **BitGoJS Version:** -* **BitGo Environment:** + +- **OS:** +- **Node Version:** +- **Yarn Version:** +- **BitGoJS Version:** +- **BitGo Environment:** ## Expected Behavior + ## Current Behavior + ## Possible Solution + ## Steps to Reproduce + + 1. 2. 3. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 50f061014d..9c3468a6f3 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,6 @@ name: Feature Request about: Suggest an idea for this project. labels: 'feature' - --- ## Feature Description + ## Motivation + ## Context + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 888fe4624d..901a0a4b6e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -34,4 +34,4 @@ Please describe the tests that you ran to verify your changes. Provide instructi - [ ] I have made corresponding changes to the documentation and on any new/updated functions and/or methods - [jsdoc](https://jsdoc.app/) - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes ---> \ No newline at end of file +--> diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97d3e9ca72..9b1f47f411 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: id: lerna-cache uses: actions/cache@v3 with: - path: | + path: | node_modules modules/*/node_modules key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }}-${{ hashFiles('tsconfig.packages.json')}} @@ -166,7 +166,7 @@ jobs: id: lerna-cache uses: actions/cache@v3 with: - path: | + path: | node_modules modules/*/node_modules /home/runner/.cache/Cypress diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 15a03a7a47..24dd5461f8 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -29,7 +29,7 @@ jobs: if: github.ref != 'refs/heads/master' # only publish changes if on feature branches run: | echo "preid=alpha" >> $GITHUB_ENV - + - name: Set Environment Variable for Beta if: github.ref == 'refs/heads/master' # only publish changes if on master branches run: | @@ -45,20 +45,20 @@ jobs: echo "@bitgo-beta:registry=https://registry.npmjs.org" >> .npmrc echo "//registry.npmjs.org/:_authToken=${{ secrets.BETA_TOKEN }}" >> .npmrc echo "//registry.npmjs.org/:always-auth=true" >> .npmrc - + - name: Prepare Release run: | rm -rfd ./modules/web-demo rm -rfd ./modules/express npx ts-node ./scripts/prepare-release.ts ${{ env.preid }} - + - name: Rebuild packages run: yarn - name: Commit Local Changes run: git commit -am "Auto updated ${{ env.preid }} branch" --no-verify || echo "No changes to commit" - - name: Lerna Publish + - name: Lerna Publish run: yarn lerna publish from-package --preid ${{ env.preid }} --dist-tag ${{ env.preid }} --force-publish --yes --loglevel silly - name: Verify Publish diff --git a/.github/workflows/test_package_updates.yml b/.github/workflows/test_package_updates.yml index 3a09966664..2a6035616c 100644 --- a/.github/workflows/test_package_updates.yml +++ b/.github/workflows/test_package_updates.yml @@ -5,19 +5,19 @@ on: branches: - master paths: - - "*/**/package.json" - - "!*/**/node_modules/package.json" - - "package.json" - - "!node_modules/package.json" + - '*/**/package.json' + - '!*/**/node_modules/package.json' + - 'package.json' + - '!node_modules/package.json' pull_request: branches: - master - rel/** paths: - - "*/**/package.json" - - "!*/**/node_modules/package.json" - - "package.json" - - "!node_modules/package.json" + - '*/**/package.json' + - '!*/**/node_modules/package.json' + - 'package.json' + - '!node_modules/package.json' jobs: unit-test-all: diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..c889d1d513 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,7 @@ +.nyc_output/ +dist/ +scripts/sdk-coin-generator/template/ +protobuf/ +*.json +*.min.js +CHANGELOG.md diff --git a/.prettierrc.yml b/.prettierrc.yml index 3b75922a53..7c3d8dd32a 100644 --- a/.prettierrc.yml +++ b/.prettierrc.yml @@ -1,5 +1,3 @@ printWidth: 120 singleQuote: true -trailingComma: "es5" -requirePragma: true -insertPragma: true +trailingComma: 'es5' diff --git a/DEVELOPERS.md b/DEVELOPERS.md index 2ded87bf6d..35076fe299 100644 --- a/DEVELOPERS.md +++ b/DEVELOPERS.md @@ -1,10 +1,11 @@ # Requirements -* yarn version 1 (classic) -* node version >=14.18.0 and <17 + +- yarn version 1 (classic) +- node version >=14.18.0 and <17 # Installing -In the BitGoJS/ directory: +In the BitGoJS/ directory: ```bash $ yarn install @@ -51,6 +52,7 @@ Modules typically provide both unit and integration tests. The rule of thumb for whether a test is a unit test or an integration test is whether or not the test makes a real network request to another system. If it does, it's probably an integration test, otherwise it's a unit test. You can run unit tests for each individual module: + ```bash $ yarn run unit-test --scope bitgo ``` @@ -62,22 +64,25 @@ $ yarn run unit-test ``` Or just the modules which have changed since master: + ```bash $ yarn run unit-test-changed ``` Or the file that contains a specific string - - if you are a specific module: + +- if you are a specific module: ```bash $ yarn run unit-test --grep"keyword" ``` - if you are in the BitGoJs/ top-level directory - + ```bash $ yarn run unit-test -- -- --grep "keyword" -``` +``` + **Note:** Each module's output will be prefixed with it's name, but it may be difficult to unmangle the test output. To aid with evaluating test results, and especially test failures, a fancy test report is generated by the CI system and uploaded to S3. @@ -127,19 +132,19 @@ Each module should have the following basic file structure: ### `package.json` -* #### `name` -For a binary application module named "fooapp", this should be set to `@bitgo/fooapp`. +- #### `name` + For a binary application module named "fooapp", this should be set to `@bitgo/fooapp`. For a generic library module named "bar", this should be set to `@bitgo/sdk-lib-bar`. For a coin library module which supports a coin with ticker "BAZ", this should be set to `@bitgo/sdk-coin-baz`. -* #### `scripts` +- #### `scripts` These npm scripts may be run during lifecycle events and by lerna across all modules. If a script is not present in a module, that module will be skipped. | Name | Description | Required? | -|----------------------|--------------------------------------------------------------------------------------------|-----------| +| -------------------- | ------------------------------------------------------------------------------------------ | --------- | | `test` / `unit-test` | Run module unit tests | Yes | | `integration-test` | Run module integration tests. These are run when a PR is targeted to merge against master. | No | | `prepare` / `build` | Compile typescript sources | No | @@ -151,9 +156,10 @@ These npm scripts may be run during lifecycle events and by lerna across all mod Additional scripts which are too large for the package.json file should be placed in `scripts/` and should be plain javascript or bash. -* #### `repository` +- #### `repository` This shall always be set for all modules to: + ```json { "repository": { @@ -163,13 +169,14 @@ This shall always be set for all modules to: } ``` -* #### `license` +- #### `license` License shall be `Apache-2.0`. -* #### `engines` +- #### `engines` Engines should be set to the following: + ```json { "engines": { @@ -182,13 +189,15 @@ Engines should be set to the following: ### `tsconfig.json` There are a few things each module's `tsconfig.json` must do: -* Extend the root tsconfig.json -* Set the `outDir` and `rootDir` compiler options -* Set the `include` property to the correct module source directories (`package.json` should also be included if it is read at runtime) -* Include references to other packages within the repo already added to the `package.json` + +- Extend the root tsconfig.json +- Set the `outDir` and `rootDir` compiler options +- Set the `include` property to the correct module source directories (`package.json` should also be included if it is read at runtime) +- Include references to other packages within the repo already added to the `package.json` Here is a template to help get started:
Note: you only need to add references to other modules in the repo you actually use. + ```json { "extends": "../../tsconfig.json", @@ -196,10 +205,7 @@ Here is a template to help get started:
"outDir": "./dist", "rootDir": "." }, - "include": [ - "src/**/*", - "package.json" - ], + "include": ["src/**/*", "package.json"], "references": [ { "path": "../sdk-core" @@ -212,7 +218,8 @@ Here is a template to help get started:
``` ### `tsconfig.packages.json` -Each package should also be listed in the root level `tsconfig.packages.json` as well. + +Each package should also be listed in the root level `tsconfig.packages.json` as well. ## Package Installation @@ -241,6 +248,7 @@ Make sure to run `yarn install` after adding a new dependency to a module. This - Standalone packages that do not rely on direct SDK development but rather depend on SDK modules as installed from `npm` should keep all used dependencies within their module. They should not depend on any single dependency as defined at the root `package.json` or `node_modules`. Examples of exceptions include: + - `express` - `web-demo` @@ -265,10 +273,10 @@ This will prompt you for both the coin's name (mainnet and testnet), symbol, and Additional information about coin development can be found in the newly created coin's README.md file. Due to supporting legacy versions of registering coins to `bitgo`, you will continue to add new coin definitions to: -| Module | Notes | +| Module | Notes | |---------------|----------------------------------------------------------------------------------------------------------------------| -| `statics` | | -| `bitgo` | Coin registration in the `CoinFactory` class | +| `statics` | | +| `bitgo` | Coin registration in the `CoinFactory` class | | `account-lib` | For account based coins that are converting from `account-lib`, the import/export at `account-lib`'s root `index.ts` | ### Coin Creation Options @@ -278,8 +286,7 @@ Upon creating coins, you are given different options to choose from to create yo > Do not install coin packages in the root of BitGoJS. They must be scoped to their respective package. | Option | Description | -|---------|--------------------------------------------------------| +| ------- | ------------------------------------------------------ | | Account | Used for account based coins. Eth based or "Eth like". | | Utxo | Used for utxo based coins. Bitcoin, Litecoin, etc... | | Simple | Base implementation extending BaseCoin. | - diff --git a/README.md b/README.md index b7710565f0..a98430dcac 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Please email us at support@bitgo.com if you have questions or comments about thi The BitGo SDK repository is a monorepo composed of separate modules, each of which implement some subset of the features of the SDK. | Package Name | Module | Description | | -|---------------------|----------------|-----------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------| +| ------------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | | bitgo | `bitgo` | Authentication, wallet management, user authentication, cryptographic primitives, abstract coin interfaces, coin implementations. | [Link](https://github.com/BitGo/BitGoJS/tree/master/modules/bitgo) | | @bitgo/account-lib | `account-lib` | Build and sign transactions for account-based coins. | [Link](https://github.com/BitGo/BitGoJS/tree/master/modules/account-lib) | | @bitgo/blake2b | `blake2b` | Blake2b (64-bit version) in pure JavaScript. | [Link](https://github.com/BitGo/BitGoJS/tree/master/modules/blake2b) | @@ -35,9 +35,9 @@ The release notes for the `bitgo` module are [here](https://github.com/BitGo/Bit The BitGoJS SDK use a number of branches to control the development of various packages throughout the deployment lifecycle. Provided below is an overview to how branches relate to one another. -| Branch | Status | NPM | Description | -|--------------|----------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `master` | Unstable | N/A | Ongoing development of SDK packages | +| Branch | Status | NPM | Description | +| ------------ | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `master` | Unstable | N/A | Ongoing development of SDK packages | | `rel/latest` | Stable | `latest` | Deployed packages from `master` to `rel/latest`. This includes Express and is recommended to use `rel/latest` when not using Docker images for Express. | Other tags may be released to npm (e.g. `hotfix`, `dev`, etc...), but are not considered critical to the common path for consumers usage of SDK packages unless otherwise stated. @@ -49,6 +49,7 @@ Examples can be found in each of the modules specific to the module use cases. S # NodeJS Version Support Policy BitGoJS currently provides support for the following Node versions per package.json engines policy: + ``` "engines": { "node": ">=14.18.0 <17", @@ -60,12 +61,13 @@ We specifically limit our support to these versions of Node, not because this pa As each Node LTS version reaches its end-of-life we will exclude that version from the node engines property of our package's package.json file. Removing a Node version is considered a breaking change and will entail the publishing of a new major version of this package. We will not accept any requests to support an end-of-life version of Node, and any pull requests or issues regarding support for an end-of-life version of Node will be closed. We will accept code that allows this package to run on newer, non-LTS, versions of Node. Furthermore, we will attempt to ensure our own changes work on the latest version of Node. To help in that commitment, our continuous integration setup runs the full test suite on the latest release of the following versions of node: -* `>=14.18.0` -* `16` +- `>=14.18.0` +- `16` JavaScript package managers should allow you to install this package with any version of Node, with, at most, a warning if your version of Node does not fall within the range specified by our node engines property. If you encounter issues installing this package on a supported version of Node, please report the issue to us. -> **_NOTE:_** Users that would like to use ecdsa tss coins with node v14 must enable `--experimental-wasm-bigint` to initialize wallets +> **_NOTE:_** Users that would like to use ecdsa tss coins with node v14 must enable `--experimental-wasm-bigint` to initialize wallets + # Notes for Developers See [DEVELOPERS.md](https://github.com/BitGo/BitGoJS/blob/master/DEVELOPERS.md) diff --git a/check-package-versions.js b/check-package-versions.js index d0fcfb52b8..9354a5ec33 100755 --- a/check-package-versions.js +++ b/check-package-versions.js @@ -14,11 +14,7 @@ const path = require('path'); */ function getLernaRunner(lernaPath) { return async (command, args = [], options = {}) => { - const { stdout } = await execa( - lernaPath, - [command, ...args], - options, - ); + const { stdout } = await execa(lernaPath, [command, ...args], options); return stdout; }; } @@ -91,7 +87,9 @@ async function main() { for (const dep of mod.deps) { const depVersion = getDependencyVersion(mod.path, dep); if (depVersion && depVersion !== expectedVersions[dep]) { - console.log(`error: expected lerna-managed module ${mod.name} to depend on package ${dep} using version ${expectedVersions[dep]}, but found version ${depVersion} instead`); + console.log( + `error: expected lerna-managed module ${mod.name} to depend on package ${dep} using version ${expectedVersions[dep]}, but found version ${depVersion} instead` + ); exitCode = 1; } } @@ -100,4 +98,6 @@ async function main() { return exitCode; } -main().then(process.exit).catch((e) => console.error(e)); +main() + .then(process.exit) + .catch((e) => console.error(e)); diff --git a/commitlint.config.js b/commitlint.config.js index a86881d288..744ed7dfae 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -2,16 +2,11 @@ const { readdir } = require('fs').promises; module.exports = { extends: ['@commitlint/config-conventional'], - ignores: [ - (commit) => /^Merge commit '[a-f0-9]{40}'$/m.test(commit), - ], + ignores: [(commit) => /^Merge commit '[a-f0-9]{40}'$/m.test(commit)], rules: { 'scope-enum': async () => [2, 'always', (await readdir('modules')).concat('root')], 'footer-max-line-length': [0, 'always', Infinity], - 'references-empty': [ - 2, - 'never', - ], + 'references-empty': [2, 'never'], }, parserPreset: { parserOpts: { diff --git a/examples/README.md b/examples/README.md index 4a4caae290..d713af50ac 100644 --- a/examples/README.md +++ b/examples/README.md @@ -6,62 +6,62 @@ In this directory, you can find examples on how to use the BitGoJS SDK with Type ### Wallet -* [Backup Key Creation](./ts/backup-key-creation.ts) -* [Create Policy](./ts/create-policy.ts) -* [Create Wallet Address](./ts/create-wallet-address.ts) -* [Create Wallet Addresses](./ts/create-wallet-addresses.ts) -* [Create Wallet](./ts/create-wallet.ts) -* [Get Maximum Spendable](./ts/get-maximum-spendable.ts) -* [Get Wallet Balance](./ts/get-wallet-balance.ts) -* [Get Wallet](./ts/get-wallet.ts) -* [List Wallet Shares](./ts/list-wallet-shares.ts) -* [List Wallet Transfers](./ts/list-wallet-transfers.ts) -* [List Wallets](./ts/list-wallets.ts) -* [Recover XRP](./ts/recover-xrp.ts) -* [Resend Wallet Share Invite](./ts/resend-wallet-share-invite.ts) -* [Send Wallet Transaction](./ts/send-wallet-transaction.ts) -* [Send With Provided Public Key](./ts/send-with-provided-public-keys.ts) -* [Share Wallet](./ts/share-wallet.ts) -* [Update Wallet Forwarders](./ts/update-wallet-forwarders.ts) +- [Backup Key Creation](./ts/backup-key-creation.ts) +- [Create Policy](./ts/create-policy.ts) +- [Create Wallet Address](./ts/create-wallet-address.ts) +- [Create Wallet Addresses](./ts/create-wallet-addresses.ts) +- [Create Wallet](./ts/create-wallet.ts) +- [Get Maximum Spendable](./ts/get-maximum-spendable.ts) +- [Get Wallet Balance](./ts/get-wallet-balance.ts) +- [Get Wallet](./ts/get-wallet.ts) +- [List Wallet Shares](./ts/list-wallet-shares.ts) +- [List Wallet Transfers](./ts/list-wallet-transfers.ts) +- [List Wallets](./ts/list-wallets.ts) +- [Recover XRP](./ts/recover-xrp.ts) +- [Resend Wallet Share Invite](./ts/resend-wallet-share-invite.ts) +- [Send Wallet Transaction](./ts/send-wallet-transaction.ts) +- [Send With Provided Public Key](./ts/send-with-provided-public-keys.ts) +- [Share Wallet](./ts/share-wallet.ts) +- [Update Wallet Forwarders](./ts/update-wallet-forwarders.ts) ### Webhooks -* [Webhooks - Add (Block)](./ts/webhooks-block-add.ts) -* Webhooks - Add (Wallet) - Coming Soon -* [Webhooks - List](./ts/webhooks-list.ts) -* [Webhooks - Remove](./ts/webhooks-remove.ts) -* [Webhooks - List Notifications](./ts/webhooks-list-notifications.ts) -* [Webhooks - Simulate](./ts/webhooks-simulate.ts) +- [Webhooks - Add (Block)](./ts/webhooks-block-add.ts) +- Webhooks - Add (Wallet) - Coming Soon +- [Webhooks - List](./ts/webhooks-list.ts) +- [Webhooks - Remove](./ts/webhooks-remove.ts) +- [Webhooks - List Notifications](./ts/webhooks-list-notifications.ts) +- [Webhooks - Simulate](./ts/webhooks-simulate.ts) ### Algorand (ALGO) -* [Account Consolidation Build](./ts/algo/account-consolidation-build.ts) -* [Account Consolidation Send](./ts/algo/account-consolidation-send.ts) -* [Disable Token](./ts/algo/disable-token.ts) -* [Enable Token](./ts/algo/enable-token.ts) -* [Transaction with emergency param](./ts/algo/transaction-with-emergency-param.ts) +- [Account Consolidation Build](./ts/algo/account-consolidation-build.ts) +- [Account Consolidation Send](./ts/algo/account-consolidation-send.ts) +- [Disable Token](./ts/algo/disable-token.ts) +- [Enable Token](./ts/algo/enable-token.ts) +- [Transaction with emergency param](./ts/algo/transaction-with-emergency-param.ts) ### Bitcoin Lightning (BTC) -* [Check Lightning Balance](./ts/btc/check-lightning-balance.ts) -* [Create Lightning Invoice](./ts/btc/create-lightning-invoice.ts) -* [Withdraw Lightning Balance](./ts/btc/withdraw-lightning-balance.ts) -* [Make Lightning Deposit](./ts/btc/make-lightning-deposit.ts) -* [Make Lightning Payment](./ts/btc/make-lightning-payment.ts) -* [Pay LNURL Request](./ts/btc/pay-lnurl-request.ts) +- [Check Lightning Balance](./ts/btc/check-lightning-balance.ts) +- [Create Lightning Invoice](./ts/btc/create-lightning-invoice.ts) +- [Withdraw Lightning Balance](./ts/btc/withdraw-lightning-balance.ts) +- [Make Lightning Deposit](./ts/btc/make-lightning-deposit.ts) +- [Make Lightning Payment](./ts/btc/make-lightning-payment.ts) +- [Pay LNURL Request](./ts/btc/pay-lnurl-request.ts) ### Ethereum (ETH) -* [Create Wallet Address](./ts/eth/create-wallet-address.ts) -* [Create Wallet](./ts/eth/create-wallet.ts) -* [Deploy Forwarder](./ts/eth/deployForwarder.ts) -* [Flush Forwarder Token](./ts/eth/flushForwarderToken.ts) -* [Set Flush Threshold](./ts/eth/set-flush-threshold.ts) +- [Create Wallet Address](./ts/eth/create-wallet-address.ts) +- [Create Wallet](./ts/eth/create-wallet.ts) +- [Deploy Forwarder](./ts/eth/deployForwarder.ts) +- [Flush Forwarder Token](./ts/eth/flushForwarderToken.ts) +- [Set Flush Threshold](./ts/eth/set-flush-threshold.ts) ### Tezos (XTZ) -* [Consolidate Account Balances](./ts/xtz/consolidate-account-balances.ts) -* [Create Address](./ts/xtz/create-address.ts) +- [Consolidate Account Balances](./ts/xtz/consolidate-account-balances.ts) +- [Create Address](./ts/xtz/create-address.ts) ## `js` directory (JavaScript) diff --git a/examples/js/ada/send-pledge-transaction.js b/examples/js/ada/send-pledge-transaction.js index f396ff7f3f..13030c0e81 100644 --- a/examples/js/ada/send-pledge-transaction.js +++ b/examples/js/ada/send-pledge-transaction.js @@ -16,44 +16,43 @@ const pledgingRawTxHex = ''; const pledgingNodePubKey = ''; const pledgingNodeKeySignature = ''; -Promise.coroutine(function *() { - // generating address w/ same staking key and same payment key - bitgo.authenticateWithAccessToken({ accessToken: accessToken }); - yield bitgo.unlock({ otp: '000000', duration: 3600 }); - const walletInstance = yield basecoin.wallets().get({ id: walletId }); - - const whitelistedParams = { - intent: { - intentType: 'pledge', - rawTx: pledgingRawTxHex, - nodePublicKey: pledgingNodePubKey, - nodeKeySignature: pledgingNodeKeySignature, - }, - apiVersion: 'lite', - preview: undefined, - }; - - const unsignedTx = (yield bitgo - .post(bitgo.url('/wallet/' + walletId + '/txrequests', 2)) - .send(whitelistedParams) - .result()); - - // sign tx - const keychains = yield basecoin.keychains().getKeysForSigning({ wallet: walletInstance }); - const signedStakingTransaction = yield walletInstance.signTransaction({ - txPrebuild: unsignedTx, - keychain: keychains[0], - walletPassphrase: walletPassphrase, - pubs: keychains.map((k) => k.pub), - reqId: unsignedTx.txRequestId, - }); - - // submit tx - const submittedTx = yield bitgo - .post(basecoin.url('/wallet/' + walletId + '/tx/send')) - .send({ txRequestId: signedStakingTransaction.txRequestId }) - .result(); - - console.log('New Transaction:', JSON.stringify(submittedTx, null, 4)); - +Promise.coroutine(function* () { + // generating address w/ same staking key and same payment key + bitgo.authenticateWithAccessToken({ accessToken: accessToken }); + yield bitgo.unlock({ otp: '000000', duration: 3600 }); + const walletInstance = yield basecoin.wallets().get({ id: walletId }); + + const whitelistedParams = { + intent: { + intentType: 'pledge', + rawTx: pledgingRawTxHex, + nodePublicKey: pledgingNodePubKey, + nodeKeySignature: pledgingNodeKeySignature, + }, + apiVersion: 'lite', + preview: undefined, + }; + + const unsignedTx = yield bitgo + .post(bitgo.url('/wallet/' + walletId + '/txrequests', 2)) + .send(whitelistedParams) + .result(); + + // sign tx + const keychains = yield basecoin.keychains().getKeysForSigning({ wallet: walletInstance }); + const signedStakingTransaction = yield walletInstance.signTransaction({ + txPrebuild: unsignedTx, + keychain: keychains[0], + walletPassphrase: walletPassphrase, + pubs: keychains.map((k) => k.pub), + reqId: unsignedTx.txRequestId, + }); + + // submit tx + const submittedTx = yield bitgo + .post(basecoin.url('/wallet/' + walletId + '/tx/send')) + .send({ txRequestId: signedStakingTransaction.txRequestId }) + .result(); + + console.log('New Transaction:', JSON.stringify(submittedTx, null, 4)); })(); diff --git a/examples/js/ada/send-staking-transaction.js b/examples/js/ada/send-staking-transaction.js index 22dffa0b3e..f6ecfa1d84 100644 --- a/examples/js/ada/send-staking-transaction.js +++ b/examples/js/ada/send-staking-transaction.js @@ -16,7 +16,7 @@ const walletId = '631b73c2bf01c90007f9154194486da3'; // TODO: set your passphrase here const walletPassphrase = null; -Promise.coroutine(function *() { +Promise.coroutine(function* () { // generating address w/ same staking key and same payment key bitgo.authenticateWithAccessToken({ accessToken: accessToken }); yield bitgo.unlock({ otp: '000000', duration: 3600 }); @@ -34,10 +34,10 @@ Promise.coroutine(function *() { preview: undefined, }; - const unsignedTx = (yield bitgo + const unsignedTx = yield bitgo .post(bitgo.url('/wallet/' + walletId + '/txrequests', 2)) .send(whitelistedParams) - .result()); + .result(); // sign tx const keychains = yield basecoin.keychains().getKeysForSigning({ wallet: walletInstance }); @@ -56,5 +56,4 @@ Promise.coroutine(function *() { .result(); console.log('New Transaction:', JSON.stringify(submittedTx, null, 4)); - })(); diff --git a/examples/js/ada/send-unstaking-transaction.js b/examples/js/ada/send-unstaking-transaction.js index 31c0570032..51b72fcadf 100644 --- a/examples/js/ada/send-unstaking-transaction.js +++ b/examples/js/ada/send-unstaking-transaction.js @@ -16,7 +16,7 @@ const walletId = '631b73c2bf01c90007f9154194486da3'; // TODO: set your passphrase here const walletPassphrase = null; -Promise.coroutine(function *() { +Promise.coroutine(function* () { // generating address w/ same staking key and same payment key bitgo.authenticateWithAccessToken({ accessToken: accessToken }); yield bitgo.unlock({ otp: '000000', duration: 3600 }); @@ -31,10 +31,10 @@ Promise.coroutine(function *() { preview: undefined, }; // build tx - const unsignedTx = (yield bitgo + const unsignedTx = yield bitgo .post(bitgo.url('/wallet/' + walletId + '/txrequests', 2)) .send(whitelistedParams) - .result()); + .result(); // sign tx const keychains = yield basecoin.keychains().getKeysForSigning({ wallet: walletInstance }); @@ -53,5 +53,4 @@ Promise.coroutine(function *() { .result(); console.log('New Transaction:', JSON.stringify(submittedTx, null, 4)); - })(); diff --git a/examples/js/ada/send-withdraw-rewards-transaction.js b/examples/js/ada/send-withdraw-rewards-transaction.js index 11660e881b..924d3ec014 100644 --- a/examples/js/ada/send-withdraw-rewards-transaction.js +++ b/examples/js/ada/send-withdraw-rewards-transaction.js @@ -59,7 +59,6 @@ async function main() { .result(); console.log('New Transaction:', JSON.stringify(submittedTx, null, 4)); - } main().catch((e) => console.error(e)); diff --git a/examples/js/algo/account-consolidation-build.js b/examples/js/algo/account-consolidation-build.js index af73365480..de941719ab 100644 --- a/examples/js/algo/account-consolidation-build.js +++ b/examples/js/algo/account-consolidation-build.js @@ -30,7 +30,7 @@ const otp = '000000'; // the token will need Spender permission for ALGO const accessToken = 'insert access token string here'; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const wallet = yield bitgo.coin(coin).wallets().get({ id: walletId }); @@ -71,9 +71,12 @@ Promise.coroutine(function *() { try { // this is one example of how you might send only the first consolidation from this group const unsignedConsolidation = consolidationTxes[0]; - const sendConsolidations = yield wallet.sendAccountConsolidation({ walletPassphrase, prebuildTx: unsignedConsolidation }); + const sendConsolidations = yield wallet.sendAccountConsolidation({ + walletPassphrase, + prebuildTx: unsignedConsolidation, + }); console.dir(sendConsolidations, { depth: 6 }); } catch (e) { console.error(e); } -})().catch(e => console.error(e)); +})().catch((e) => console.error(e)); diff --git a/examples/js/algo/account-consolidation-send.js b/examples/js/algo/account-consolidation-send.js index 1dabc8d1d8..e12562e2df 100644 --- a/examples/js/algo/account-consolidation-send.js +++ b/examples/js/algo/account-consolidation-send.js @@ -27,7 +27,7 @@ const otp = '000000'; // the token will need Spender permission for ALGO const accessToken = 'insert access token string here'; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const wallet = yield bitgo.coin(coin).wallets().get({ id: walletId }); @@ -62,4 +62,4 @@ Promise.coroutine(function *() { } catch (e) { console.error(e); } -})().catch(e => console.error(e)); +})().catch((e) => console.error(e)); diff --git a/examples/js/algo/disable-token.js b/examples/js/algo/disable-token.js index 17f01d8b89..62f5dc81b6 100644 --- a/examples/js/algo/disable-token.js +++ b/examples/js/algo/disable-token.js @@ -1,6 +1,6 @@ /** - * Currently, assets on algorand network need to be enabled and disabled in order to be used or not. - * Please note that enable/disable transactions have a fee associated, and increase the minimum balance wallet must have by 0.1 Algos for each enable token as well. In example : + * Currently, assets on algorand network need to be enabled and disabled in order to be used or not. + * Please note that enable/disable transactions have a fee associated, and increase the minimum balance wallet must have by 0.1 Algos for each enable token as well. In example : * Wallet without enabled token has minimum balance of 0.1 Algos * Wallet with 1 enabled token has minimum balance of 0.2 Algos * Wallet with 2 enabled token has minimum balance of 0.3 Algos @@ -9,52 +9,51 @@ const BitGoJS = require('bitgo'); const Promise = require('bluebird'); - + // change this to env: 'production' when you are ready for production const bitgo = new BitGoJS.BitGo({ env: 'test' }); - + // change this to 'algo:16026733' when you are ready for production const coin = 'talgo:KAL-16026733'; - + // this can be found on test.bitgo.com in the URL after clicking on a wallet // https://test.bitgo.com/enterprise/XXXXXXXXX/coin/talgo/YYYYY/transactions const walletId = 'your wallet id'; - + // this is your wallet passphrase, which could be different than your login credentials const walletPassphrase = 'set your wallet passphrase here'; - + // this will need to be a real OTP code on production const otp = '000000'; - + // this can be retrieved by logging into app.bitgo-test.com (app.bitgo.com for production) // and going to: User > User Settings > Access Tokens > (+ icon) // the token will need Spender permission for ALGO const accessToken = 'insert access token string here'; - + const address = 'your root address or address of same wallet'; const closeRemainderTo = 'your address where send token balance once you disable it'; - - -Promise.coroutine(function *() { + +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); - + const wallet = yield bitgo.coin(coin).wallets().get({ id: walletId }); - + console.log('Wallet ID:', wallet.id()); - + // this is your wallet's root address - this is where spendable funds come from console.log('Root Address:', wallet.coinSpecific().rootAddress); - + // your balance or confirmed balance will be sum of the amounts // across all addresses and your wallet's root address console.log('Balance:', wallet.balanceString()); console.log('Confirmed Balance:', wallet.confirmedBalanceString()); - + // your spendable balance will be the balance on the wallet root address // and should differ from your confirmed balance console.log('Spendable Balance:', wallet.spendableBalanceString()); - + // we have to unlock this session since we're sending funds const unlock = yield bitgo.unlock({ otp, duration: 3600 }); if (!unlock) { @@ -77,5 +76,4 @@ Promise.coroutine(function *() { } catch (e) { console.error(e); } -})().catch(e => console.error(e)); - +})().catch((e) => console.error(e)); diff --git a/examples/js/algo/enable-token.js b/examples/js/algo/enable-token.js index 694ecb8331..9799257363 100644 --- a/examples/js/algo/enable-token.js +++ b/examples/js/algo/enable-token.js @@ -1,6 +1,6 @@ /** - * Currently, assets on algorand network need to be enabled and disabled in order to be used or not. - * Please note that enable/disable transactions have a fee associated, and increase the minimum balance wallet must have by 0.1 Algos for each enable token as well. In example : + * Currently, assets on algorand network need to be enabled and disabled in order to be used or not. + * Please note that enable/disable transactions have a fee associated, and increase the minimum balance wallet must have by 0.1 Algos for each enable token as well. In example : * Wallet without tokens enabled has minimum balance of 0.1 Algos * Wallet with 1 token enabled has minimum balance of 0.2 Algos * Wallet with 2 token enabled has minimum balance of 0.3 Algos @@ -9,23 +9,23 @@ const BitGoJS = require('bitgo'); const Promise = require('bluebird'); - + // change this to env: 'production' when you are ready for production const bitgo = new BitGoJS.BitGo({ env: 'test' }); - + // change this to 'algo:16026733' when you are ready for production const coin = 'talgo:KAL-16026733'; - + // this can be found on test.bitgo.com in the URL after clicking on a wallet // https://test.bitgo.com/enterprise/XXXXXXXXX/coin/talgo/YYYYY/transactions const walletId = 'your wallet id'; - + // this is your wallet passphrase, which could be different than your login credentials const walletPassphrase = 'set your wallet passphrase here'; - + // this will need to be a real OTP code on production const otp = '000000'; - + // this can be retrieved by logging into app.bitgo-test.com (app.bitgo.com for production) // and going to: User > User Settings > Access Tokens > (+ icon) // the token will need Spender permission for ALGO @@ -33,8 +33,7 @@ const accessToken = 'insert access token string here'; const address = 'your root address or address of same wallet'; - -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const wallet = yield bitgo.coin(coin).wallets().get({ id: walletId }); @@ -74,5 +73,4 @@ Promise.coroutine(function *() { } catch (e) { console.error(e); } -})().catch(e => console.error(e)); - +})().catch((e) => console.error(e)); diff --git a/examples/js/atom/create-wallet.js b/examples/js/atom/create-wallet.js index 057bdc86c4..cb5ace250d 100644 --- a/examples/js/atom/create-wallet.js +++ b/examples/js/atom/create-wallet.js @@ -54,4 +54,3 @@ async function main() { } main().catch((e) => console.error(e)); - diff --git a/examples/js/atom/send-wallet-transaction.js b/examples/js/atom/send-wallet-transaction.js index 7f41b85928..4a3b9b6baf 100644 --- a/examples/js/atom/send-wallet-transaction.js +++ b/examples/js/atom/send-wallet-transaction.js @@ -53,10 +53,10 @@ async function main() { preview: false, }; - const unsignedTx = (await bitgo + const unsignedTx = await bitgo .post(bitgo.url('/wallet/' + id + '/txrequests', 2)) .send(whitelistedParams) - .result()); + .result(); // sign tx const keychains = await bitgo.coin(coin).keychains().getKeysForSigning({ wallet: wallet }); @@ -69,8 +69,6 @@ async function main() { }); console.log('signedTransaction:', JSON.stringify(signedTransaction, null, 4)); - } main().catch((e) => console.error(e)); - diff --git a/examples/js/backup-key-creation.js b/examples/js/backup-key-creation.js index 40231196af..92030512ec 100644 --- a/examples/js/backup-key-creation.js +++ b/examples/js/backup-key-creation.js @@ -19,8 +19,7 @@ const bitgo = new BitGoJS.BitGo({ env: 'prod' }); const coin = 'btc'; // Create the wallet -Promise.coroutine(function *() { - +Promise.coroutine(function* () { // this function takes one parameter - seed - if you want to create from your own entropy (recommended) const backupKey = bitgo.coin(coin).keychains().create(); diff --git a/examples/js/build-transaction.js b/examples/js/build-transaction.js index 7d5510c0e5..60f4c62675 100644 --- a/examples/js/build-transaction.js +++ b/examples/js/build-transaction.js @@ -23,7 +23,7 @@ const coin = 'tdoge'; const amount = ''; const toAddress = ''; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const wallet = yield bitgo.coin(coin).wallets().get({ id }); @@ -38,9 +38,11 @@ Promise.coroutine(function *() { }, ], }; - wallet.prebuildTransaction(buildTxParams).then(function (transaction) { - // print transaction details - console.dir(transaction); - }).catch(err => console.log('Error: ', err)); - + wallet + .prebuildTransaction(buildTxParams) + .then(function (transaction) { + // print transaction details + console.dir(transaction); + }) + .catch((err) => console.log('Error: ', err)); })(); diff --git a/examples/js/create-policy.js b/examples/js/create-policy.js index e255262b4e..16f4ee7a19 100644 --- a/examples/js/create-policy.js +++ b/examples/js/create-policy.js @@ -19,7 +19,7 @@ const id = null; const coin = 'tltc'; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const wallet = yield bitgo.coin(coin).wallets().get({ id }); diff --git a/examples/js/create-wallet-address.js b/examples/js/create-wallet-address.js index 520a01f1f5..acccfbf2d8 100644 --- a/examples/js/create-wallet-address.js +++ b/examples/js/create-wallet-address.js @@ -17,7 +17,7 @@ const accessToken = ''; // https://test.bitgo.com/enterprise/XXXXXXXXX/coin/talgo/YYYYY/transactions const walletId = ''; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken: accessToken }); const wallet = yield bitgo.coin(coin).wallets().get({ id: walletId }); @@ -27,4 +27,4 @@ Promise.coroutine(function *() { console.log('Wallet ID:', wallet.id()); console.log('First Receive Address:', wallet.receiveAddress()); console.log('Second Receive Address:', newReceiveAddress); -})().catch(e => console.error(e)); +})().catch((e) => console.error(e)); diff --git a/examples/js/create-wallet-addresses.js b/examples/js/create-wallet-addresses.js index 324c62c838..394cff3d92 100644 --- a/examples/js/create-wallet-addresses.js +++ b/examples/js/create-wallet-addresses.js @@ -14,15 +14,14 @@ const accessToken = null; // TODO: set your passphrase here const walletPassphrase = null; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken: accessToken }); - const wallet = yield basecoin.wallets() - .generateWallet({ - label: `Test Wallet Example`, - passphrase: walletPassphrase, - backupXpubProvider: 'keyternal', - }); + const wallet = yield basecoin.wallets().generateWallet({ + label: `Test Wallet Example`, + passphrase: walletPassphrase, + backupXpubProvider: 'keyternal', + }); const walletInstance = wallet.wallet; const newReceiveAddress = yield walletInstance.createAddress(); diff --git a/examples/js/create-wallet.js b/examples/js/create-wallet.js index 5be585be93..4d224659a4 100644 --- a/examples/js/create-wallet.js +++ b/examples/js/create-wallet.js @@ -27,7 +27,7 @@ const passphrase = 'test_wallet_passphrase'; const coin = 'tltc'; // Create the wallet -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const walletOptions = { diff --git a/examples/js/eth/list-wallet-addresses.js b/examples/js/eth/list-wallet-addresses.js index fc816da99a..6949caaa1d 100644 --- a/examples/js/eth/list-wallet-addresses.js +++ b/examples/js/eth/list-wallet-addresses.js @@ -16,7 +16,11 @@ async function main() { bitgo.authenticateWithAccessToken({ accessToken }); const walletInstance = await basecoin.wallets().get({ id: walletId }); - const addresses = await walletInstance.addresses({ includeBalances: true, returnBalancesForToken: 'gterc6dp', pendingDeployment: false }); + const addresses = await walletInstance.addresses({ + includeBalances: true, + returnBalancesForToken: 'gterc6dp', + pendingDeployment: false, + }); console.log('Wallet ID:', walletInstance.id()); for (const address of addresses.addresses) { diff --git a/examples/js/get-maximum-spendable.js b/examples/js/get-maximum-spendable.js index 47fb437b59..1a0dfd64ec 100644 --- a/examples/js/get-maximum-spendable.js +++ b/examples/js/get-maximum-spendable.js @@ -25,8 +25,7 @@ const id = null; const coin = 'tbtc'; const basecoin = bitgo.coin(coin); -Promise.coroutine(function *() { - +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const walletInstance = yield basecoin.wallets().get({ id: id }); @@ -65,6 +64,4 @@ Promise.coroutine(function *() { console.log('Wallet ID:', id); console.log('Coin:', response.coin); console.log('Maximum Spendable:', response.maximumSpendable); - })(); - diff --git a/examples/js/get-wallet-balance.js b/examples/js/get-wallet-balance.js index 5cf9c02126..66ed177f89 100644 --- a/examples/js/get-wallet-balance.js +++ b/examples/js/get-wallet-balance.js @@ -17,7 +17,7 @@ const basecoin = bitgo.coin(coin); const accessToken = null; const walletId = '5941ce2db42fcbc70717e5a898fd1595'; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken: accessToken }); const walletInstance = yield basecoin.wallets().get({ id: walletId }); diff --git a/examples/js/get-wallet-token-balance.js b/examples/js/get-wallet-token-balance.js index 9f1397b489..01766a210b 100644 --- a/examples/js/get-wallet-token-balance.js +++ b/examples/js/get-wallet-token-balance.js @@ -18,7 +18,7 @@ const basecoin = bitgo.coin(coin); const accessToken = ''; const walletId = '624ef521e876e800073b865e31b6d7e9'; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken: accessToken }); const walletInstance = yield basecoin.wallets().get({ id: walletId, allTokens: true }); diff --git a/examples/js/get-wallet.js b/examples/js/get-wallet.js index 4c42a99bc2..a952b4b2bc 100644 --- a/examples/js/get-wallet.js +++ b/examples/js/get-wallet.js @@ -22,7 +22,7 @@ const id = null; const coin = 'tltc'; // Create the wallet with Bluebird coroutines -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const wallet = yield bitgo.coin(coin).wallets().get({ id }); diff --git a/examples/js/list-wallet-shares.js b/examples/js/list-wallet-shares.js index 4613197e2c..736327ce5b 100644 --- a/examples/js/list-wallet-shares.js +++ b/examples/js/list-wallet-shares.js @@ -17,7 +17,7 @@ const accessToken = null; const coin = 'tltc'; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const shares = yield bitgo.coin(coin).wallets().listShares({}); diff --git a/examples/js/list-wallet-transfers.js b/examples/js/list-wallet-transfers.js index f720df2266..f8bcbbc386 100644 --- a/examples/js/list-wallet-transfers.js +++ b/examples/js/list-wallet-transfers.js @@ -16,7 +16,7 @@ const basecoin = bitgo.coin(coin); const accessToken = null; const walletId = '5941ce2db42fcbc70717e5a898fd1595'; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken: accessToken }); const walletInstance = yield basecoin.wallets().get({ id: walletId }); diff --git a/examples/js/list-wallets.js b/examples/js/list-wallets.js index fc9ef65af5..da720a2038 100644 --- a/examples/js/list-wallets.js +++ b/examples/js/list-wallets.js @@ -17,7 +17,7 @@ const accessToken = null; const coin = 'tltc'; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const wallets = yield bitgo.coin(coin).wallets().list({}); diff --git a/examples/js/recover-xrp.js b/examples/js/recover-xrp.js index a8a925b558..25c63ddf4d 100644 --- a/examples/js/recover-xrp.js +++ b/examples/js/recover-xrp.js @@ -10,14 +10,15 @@ const bitgo = new BitGoJS.BitGo({ env: 'prod' }); const coin = 'xrp'; const basecoin = bitgo.coin(coin); -Promise.coroutine(function *() { - +Promise.coroutine(function* () { const response = yield basecoin.recover({ // BOX A - userKey: '{"iv":"UgFBAnCOYhGpySRGlaLSrA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"vMawLQuCAZI=","ct":"RTAgWQSJOroRfWF9GT8mxsTeFwXPBYuRf9k7UeDAHSao5EZH0E5EUo0dKm2gyogpc64HYfQhmkiQgKElDYq2/EdH+PXkSZxAzWrfFNVkgmM6CyWN1IMR8vvjLnBjNSlpYHQOLR733szlP5OFntf01soVsUZHb5A="}', + userKey: + '{"iv":"UgFBAnCOYhGpySRGlaLSrA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"vMawLQuCAZI=","ct":"RTAgWQSJOroRfWF9GT8mxsTeFwXPBYuRf9k7UeDAHSao5EZH0E5EUo0dKm2gyogpc64HYfQhmkiQgKElDYq2/EdH+PXkSZxAzWrfFNVkgmM6CyWN1IMR8vvjLnBjNSlpYHQOLR733szlP5OFntf01soVsUZHb5A="}', // BOX B - backupKey: '{"iv":"SS/5vfzJx8Nr+YIUVENZ4Q==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"8VP7bl5uSVM=","ct":"vITKMhfemxW6lrai1TXHpGFJhyksHXBIhZ5x3bQwDGeURyLrOiVRfvIuAk5vptSQOSwU8gmfMHOSweRMjEFkw8j0RwuYp79vrDY4pu47oo/iR6uiiZ1grCLjd27hO68SULPWXrMvzLvRb8ELh9EvuoByWnujyvM="}', + backupKey: + '{"iv":"SS/5vfzJx8Nr+YIUVENZ4Q==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"8VP7bl5uSVM=","ct":"vITKMhfemxW6lrai1TXHpGFJhyksHXBIhZ5x3bQwDGeURyLrOiVRfvIuAk5vptSQOSwU8gmfMHOSweRMjEFkw8j0RwuYp79vrDY4pu47oo/iR6uiiZ1grCLjd27hO68SULPWXrMvzLvRb8ELh9EvuoByWnujyvM="}', // BOX C rootAddress: 'rB651yVavQSCEd6xi9pzg8QkHkPrR8gR4i', @@ -30,14 +31,14 @@ Promise.coroutine(function *() { console.log(JSON.stringify(response, null, 4)); - const submittedTx = yield bitgo.post(basecoin.getRippledUrl()) - .send({ - method: 'submit', - params: [{ + const submittedTx = yield bitgo.post(basecoin.getRippledUrl()).send({ + method: 'submit', + params: [ + { tx_blob: response.txHex, - }], - }); + }, + ], + }); console.log(JSON.stringify(submittedTx, null, 4)); - })(); diff --git a/examples/js/resend-wallet-share-invite.js b/examples/js/resend-wallet-share-invite.js index 6ade76b848..a4af92cd1f 100644 --- a/examples/js/resend-wallet-share-invite.js +++ b/examples/js/resend-wallet-share-invite.js @@ -17,7 +17,7 @@ const walletShareId = null; const coin = 'tltc'; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const shareResult = yield bitgo.coin(coin).wallets().resendShareInvite({ walletShareId }); diff --git a/examples/js/send-wallet-transaction.js b/examples/js/send-wallet-transaction.js index 1c6eb9f5c5..d12ae6bd94 100644 --- a/examples/js/send-wallet-transaction.js +++ b/examples/js/send-wallet-transaction.js @@ -15,7 +15,7 @@ const walletId = '5941ce2db42fcbc70717e5a898fd1595'; // TODO: set your passphrase here const walletPassphrase = null; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken: accessToken }); const walletInstance = yield basecoin.wallets().get({ id: walletId }); diff --git a/examples/js/share-wallet.js b/examples/js/share-wallet.js index 16293d4553..17d2e41cf5 100644 --- a/examples/js/share-wallet.js +++ b/examples/js/share-wallet.js @@ -29,7 +29,7 @@ const passphrase = null; const coin = 'tltc'; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const wallet = yield bitgo.coin(coin).wallets().get({ id: walletId }); diff --git a/examples/js/webhooks-add.js b/examples/js/webhooks-add.js index b0a272e800..38adc6b955 100644 --- a/examples/js/webhooks-add.js +++ b/examples/js/webhooks-add.js @@ -1,6 +1,6 @@ /** * Add a new webhook for a coin type for a user defined notification url - * + * * Copyright 2022, BitGo, Inc. All Rights Reserved. */ diff --git a/examples/js/webhooks-list-notifications.js b/examples/js/webhooks-list-notifications.js index bba53f876f..7fc31725c9 100644 --- a/examples/js/webhooks-list-notifications.js +++ b/examples/js/webhooks-list-notifications.js @@ -1,6 +1,6 @@ /** * Fetch a list of block notifications triggered by a webhook for a given coin type - * + * * Copyright 2022, BitGo, Inc. All Rights Reserved. */ diff --git a/examples/js/webhooks-list.js b/examples/js/webhooks-list.js index 9a2a97482c..b6a6114961 100644 --- a/examples/js/webhooks-list.js +++ b/examples/js/webhooks-list.js @@ -1,6 +1,6 @@ /** * Fetch a list of webhooks for wallet's coin type - * + * * Copyright 2022, BitGo, Inc. All Rights Reserved. */ diff --git a/examples/js/webhooks-remove.js b/examples/js/webhooks-remove.js index 46f3aa6870..fce4e88440 100644 --- a/examples/js/webhooks-remove.js +++ b/examples/js/webhooks-remove.js @@ -1,6 +1,6 @@ /** * Remove a webhook from a BitGo account wallet - * + * * Copyright 2022, BitGo, Inc. All Rights Reserved. */ diff --git a/examples/js/webhooks-simulate.js b/examples/js/webhooks-simulate.js index 1db2be0009..6c731b2941 100644 --- a/examples/js/webhooks-simulate.js +++ b/examples/js/webhooks-simulate.js @@ -1,6 +1,6 @@ /** * Simulate a webhook trigger for a wallet's coin type - * + * * Copyright 2022, BitGo, Inc. All Rights Reserved. */ diff --git a/examples/js/xtz/consolidate-account-balances.js b/examples/js/xtz/consolidate-account-balances.js index 7d9b53c91a..53bf656fd1 100644 --- a/examples/js/xtz/consolidate-account-balances.js +++ b/examples/js/xtz/consolidate-account-balances.js @@ -26,7 +26,7 @@ const otp = '000000'; // You can get this from User Settings > Developer Options > Add Access Token const accessToken = ''; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const wallet = yield bitgo.coin(coin).wallets().get({ id: walletId }); diff --git a/examples/js/xtz/create-address.js b/examples/js/xtz/create-address.js index 315a79f9f8..a348724ec3 100644 --- a/examples/js/xtz/create-address.js +++ b/examples/js/xtz/create-address.js @@ -15,7 +15,7 @@ const walletId = ''; // You can get this from User Settings > Developer Options > Add Access Token const accessToken = ''; -Promise.coroutine(function *() { +Promise.coroutine(function* () { bitgo.authenticateWithAccessToken({ accessToken }); const wallet = yield bitgo.coin(coin).wallets().getWallet({ id: walletId }); diff --git a/examples/ts/add-webhook.ts b/examples/ts/add-webhook.ts index b2088ab1ae..44d33b4023 100644 --- a/examples/ts/add-webhook.ts +++ b/examples/ts/add-webhook.ts @@ -35,4 +35,4 @@ async function main() { console.log(`Wallet Webhooks: ${webhooks}`); } -main().catch(e => console.log(e)); +main().catch((e) => console.log(e)); diff --git a/examples/ts/algo/account-consolidation-build.ts b/examples/ts/algo/account-consolidation-build.ts index 3f40961ed5..89955480a2 100644 --- a/examples/ts/algo/account-consolidation-build.ts +++ b/examples/ts/algo/account-consolidation-build.ts @@ -77,7 +77,10 @@ async function main() { // this is one example of how you might send only the first consolidation from this group const unsignedConsolidation = consolidationTxes[0]; - const sendConsolidations = await wallet.sendAccountConsolidation({ walletPassphrase, prebuildTx: unsignedConsolidation }); + const sendConsolidations = await wallet.sendAccountConsolidation({ + walletPassphrase, + prebuildTx: unsignedConsolidation, + }); console.dir(sendConsolidations, { depth: 6 }); } diff --git a/examples/ts/algo/disable-token.ts b/examples/ts/algo/disable-token.ts index dcff813c0a..4cbabab0b9 100644 --- a/examples/ts/algo/disable-token.ts +++ b/examples/ts/algo/disable-token.ts @@ -1,6 +1,6 @@ /** - * Currently, assets on algorand network need to be enabled and disabled in order to be used or not. - * Please note that enable/disable transactions have a fee associated, and increase the minimum balance wallet must have by 0.1 Algos for each enable token as well. In example : + * Currently, assets on algorand network need to be enabled and disabled in order to be used or not. + * Please note that enable/disable transactions have a fee associated, and increase the minimum balance wallet must have by 0.1 Algos for each enable token as well. In example : * Wallet without tokens enabled has minimum balance of 0.1 Algos * Wallet with 1 token enabled has minimum balance of 0.2 Algos * Wallet with 2 token enabled has minimum balance of 0.3 Algos @@ -9,60 +9,60 @@ import { BitGo, Wallet } from 'bitgo'; import { WalletCoinSpecific } from '../../../src/v2/wallet'; - + // change this to env: 'production' when you are ready for production const bitgo = new BitGo({ env: 'test' }); - + // change this to 'algo:16026733' when you are ready for production const coin = 'talgo:KAL-16026733'; - + // this can be found on test.bitgo.com in the URL after clicking on a wallet // https://test.bitgo.com/enterprise/XXXXXXXXX/coin/talgo/YYYYY/transactions const walletId = 'your wallet id'; - + // this is your wallet passphrase, which could be different than your login credentials const walletPassphrase = 'set your wallet passphrase here'; - + // this will need to be a real OTP code on production const otp = '000000'; - + // this can be retrieved by logging into app.bitgo-test.com (app.bitgo.com for production) // and going to: User > User Settings > Access Tokens > (+ icon) // the token will need Spender permission for ALGO const accessToken = 'insert access token string here'; - + const address = 'your root address or address of same wallet'; const closeRemainderTo = 'your address where send token balance once you disable it'; - + async function main(): Promise { bitgo.authenticateWithAccessToken({ accessToken }); - + const wallet: Wallet = await bitgo.coin(coin).wallets().get({ id: walletId }); - + console.log('Wallet ID:', wallet.id()); - + if (!wallet || !wallet.coinSpecific()) { throw new Error('Failed to retrieve wallet'); } - + const coinSpecific = wallet.coinSpecific() as WalletCoinSpecific; if (!coinSpecific) { throw new Error('Coin specific area not found - aborting.'); } - + // this is your wallet's root address - this is where spendable funds come from console.log('Root Address:', wallet.coinSpecific()?.rootAddress); - + // your balance or confirmed balance will be sum of the amounts // across all addresses and your wallet's root address console.log('Balance:', wallet.balanceString()); console.log('Confirmed Balance:', wallet.confirmedBalanceString()); - + // your spendable balance will be the balance on the wallet root address // and should differ from your confirmed balance console.log('Spendable Balance:', wallet.spendableBalanceString()); - + // we have to unlock this session since we're sending funds const unlock = await bitgo.unlock({ otp, duration: 3600 }); if (!unlock) { @@ -82,6 +82,5 @@ async function main(): Promise { }); console.dir(txDisableToken, { depth: 6 }); } - + main().catch((e) => console.error(e)); - diff --git a/examples/ts/algo/enable-token.ts b/examples/ts/algo/enable-token.ts index 1d52f65c33..b05289b6e6 100644 --- a/examples/ts/algo/enable-token.ts +++ b/examples/ts/algo/enable-token.ts @@ -1,45 +1,43 @@ /** - * Currently, assets on algorand network need to be enabled and disabled in order to be used or not. - * Please note that enable/disable transactions have a fee associated, and increase the minimum balance wallet must have by 0.1 Algos for each enable token as well. In example : + * Currently, assets on algorand network need to be enabled and disabled in order to be used or not. + * Please note that enable/disable transactions have a fee associated, and increase the minimum balance wallet must have by 0.1 Algos for each enable token as well. In example : * Wallet without tokens enabled has minimum balance of 0.1 Algos * Wallet with 1 token enabled has minimum balance of 0.2 Algos * Wallet with 2 token enabled has minimum balance of 0.3 Algos * And so */ - import { BitGo, Wallet } from 'bitgo'; import { WalletCoinSpecific } from '../../../src/v2/wallet'; - + // change this to env: 'production' when you are ready for production const bitgo = new BitGo({ env: 'test' }); - + // change this to 'algo:16026733' when you are ready for production const coin = 'talgo:KAL-16026733'; - + // this can be found on test.bitgo.com in the URL after clicking on a wallet // https://test.bitgo.com/enterprise/XXXXXXXXX/coin/talgo/YYYYY/transactions const walletId = 'your wallet id'; - + // this is your wallet passphrase, which could be different than your login credentials const walletPassphrase = 'set your wallet passphrase here'; - + // this will need to be a real OTP code on production const otp = '000000'; - + // this can be retrieved by logging into app.bitgo-test.com (app.bitgo.com for production) // and going to: User > User Settings > Access Tokens > (+ icon) // the token will need Spender permission for ALGO const accessToken = 'insert access token string here'; - + const address = 'your root address or address of same wallet'; - - + async function main(): Promise { bitgo.authenticateWithAccessToken({ accessToken }); - + const wallet: Wallet = await bitgo.coin(coin).wallets().get({ id: walletId }); - + console.log('Wallet ID:', wallet.id()); if (!wallet || !wallet.coinSpecific()) { @@ -50,19 +48,19 @@ async function main(): Promise { if (!coinSpecific) { throw new Error('Coin specific area not found - aborting.'); } - + // this is your wallet's root address - this is where spendable funds come from console.log('Root Address:', wallet.coinSpecific()?.rootAddress); - + // your balance or confirmed balance will be sum of the amounts // across all addresses and your wallet's root address console.log('Balance:', wallet.balanceString()); console.log('Confirmed Balance:', wallet.confirmedBalanceString()); - + // your spendable balance will be the balance on the wallet root address // and should differ from your confirmed balance console.log('Spendable Balance:', wallet.spendableBalanceString()); - + // we have to unlock this session since we're sending funds const unlock = await bitgo.unlock({ otp, duration: 3600 }); if (!unlock) { diff --git a/examples/ts/algo/transaction-with-emergency-param.ts b/examples/ts/algo/transaction-with-emergency-param.ts index 49021cc4a2..e7144361d9 100644 --- a/examples/ts/algo/transaction-with-emergency-param.ts +++ b/examples/ts/algo/transaction-with-emergency-param.ts @@ -1,76 +1,75 @@ /** * Build and send Transaction with emergency param * - * Transaction broadcast in algorand currently last 2 hours. - * For reducing this delay, we have implemented this emergency flag. + * Transaction broadcast in algorand currently last 2 hours. + * For reducing this delay, we have implemented this emergency flag. * This will set this broadcast time in 1 hour. - * + * * Copyright 2020, BitGo, Inc. All Rights Reserved. */ import { BitGo, Wallet } from 'bitgo'; import { WalletCoinSpecific } from '../../../src/v2/wallet'; - + // change this to env: 'production' when you are ready for production const bitgo = new BitGo({ env: 'test' }); // since talgo means test-algo put algo:tokenID when you are ready for production const coin = 'talgo:16026733'; - + // this can be found on test.bitgo.com in the URL after clicking on a wallet // https://test.bitgo.com/enterprise/XXXXXXXXX/coin/talgo/YYYYY/transactions const walletId = 'your wallet id'; - + // this is your wallet passphrase, which could be different than your login credentials const walletPassphrase = 'set your wallet passphrase here'; - + // this will need to be a real OTP code on production const otp = '000000'; - + // this can be retrieved by logging into app.bitgo-test.com (app.bitgo.com for production) // and going to: User > User Settings > Access Tokens > (+ icon) // the token will need at least Spender permission for ALGO const accessToken = 'insert access token string here'; - + const address = 'your root address or address of same wallet'; async function main(): Promise { - bitgo.authenticateWithAccessToken({ accessToken }); - + const wallet: Wallet = await bitgo.coin(coin).wallets().get({ id: walletId }); - + console.log('Wallet ID:', wallet.id()); - + if (!wallet || !wallet.coinSpecific()) { throw new Error('Failed to retrieve wallet'); } - + const coinSpecific = wallet.coinSpecific() as WalletCoinSpecific; if (!coinSpecific) { throw new Error('Coin specific area not found - aborting.'); } - + // this is your wallet's root address - this is where spendable funds come from console.log('Root Address:', wallet.coinSpecific()?.rootAddress); - + // your balance or confirmed balance will be sum of the amounts // across all addresses and your wallet's root address console.log('Balance:', wallet.balanceString()); console.log('Confirmed Balance:', wallet.confirmedBalanceString()); - + // your spendable balance will be the balance on the wallet root address // and should differ from your confirmed balance console.log('Spendable Balance:', wallet.spendableBalanceString()); - + // we have to unlock this session since we're sending funds const unlock = await bitgo.unlock({ otp, duration: 3600 }); if (!unlock) { throw new Error('We did not unlock.'); } - // Here you can set the optional emergency param - // as true which will lower the broadcast time to 1 hour. + // Here you can set the optional emergency param + // as true which will lower the broadcast time to 1 hour. // If this is flag is not set, transaction will broadcast in 2 hours. const txSetAccountOffline = await wallet.sendMany({ type: 'keyreg', @@ -78,7 +77,6 @@ async function main(): Promise { { amount: '0', address: address, - }, ], feeRate: 1, @@ -88,6 +86,5 @@ async function main(): Promise { console.dir(txSetAccountOffline, { depth: 6 }); } - + main().catch((e) => console.error(e)); - diff --git a/examples/ts/atom/create-wallet.ts b/examples/ts/atom/create-wallet.ts index 2bee434b5a..02b702f3c4 100644 --- a/examples/ts/atom/create-wallet.ts +++ b/examples/ts/atom/create-wallet.ts @@ -16,7 +16,7 @@ const coin = 'tatom'; const accessToken = ''; // TODO: set a label for your new wallet here -const label = 'Test ' + coin + ' V2 Wallet - ' + (new Date()).getTime(); +const label = 'Test ' + coin + ' V2 Wallet - ' + new Date().getTime(); // TODO: set your passphrase for your new wallet here const passphrase = ''; @@ -33,7 +33,7 @@ async function createWallet() { passphrase, passcodeEncryptionCode: passphrase, multisigType: 'tss', - enterprise + enterprise, }; const wallet = await bitgo.coin(coin).wallets().generateWallet(walletOptions); @@ -73,8 +73,6 @@ async function createWallet() { console.log('-----------------------------------------'); const bitgoKeychain = wallet.bitgoKeychain; console.log(`Bitgo commonKeychain xPrv: ${bitgoKeychain.commonKeychain}`); - } - createWallet().catch((e) => console.error(e)); diff --git a/examples/ts/atom/send-transfer.ts b/examples/ts/atom/send-transfer.ts index bb160f53d6..cfc1a94fdc 100644 --- a/examples/ts/atom/send-transfer.ts +++ b/examples/ts/atom/send-transfer.ts @@ -29,7 +29,7 @@ async function sendTx() { const bitgo = new BitGo({ env: env, - accessToken + accessToken, }); const basecoin = bitgo.coin(coin); @@ -43,7 +43,7 @@ async function sendTx() { { amount: atomAmount, address: receiveAddress, - } + }, ], walletPassphrase, type: 'transfer', @@ -52,4 +52,4 @@ async function sendTx() { console.log(`${JSON.stringify(sendDetail)}`); } -sendTx().catch(e => console.error(e)); +sendTx().catch((e) => console.error(e)); diff --git a/examples/ts/avaxp/multisig-crosschain-export-import.ts b/examples/ts/avaxp/multisig-crosschain-export-import.ts index 908c3cc5aa..8a10a8d13d 100644 --- a/examples/ts/avaxp/multisig-crosschain-export-import.ts +++ b/examples/ts/avaxp/multisig-crosschain-export-import.ts @@ -14,7 +14,8 @@ import { TransferableInput, Tx as AVMTx, } from 'avalanche/dist/apis/avm'; -import { PlatformVMAPI, +import { + PlatformVMAPI, SECPTransferOutput, SECPTransferInput, UTXOSet, @@ -23,10 +24,7 @@ import { PlatformVMAPI, KeyChain as PlatformVMKeyChain, Tx as PlatformVMTx, } from 'avalanche/dist/apis/platformvm'; -import { - Defaults, - UnixNow, -} from 'avalanche/dist/utils'; +import { Defaults, UnixNow } from 'avalanche/dist/utils'; type ChainConfig = { NODE_HOST: string; @@ -65,14 +63,17 @@ const avaxPrivateKey = ''; const pMultisigReceiveAddresses = []; // amount to transfer cross-chain plus fees -const transferAmountVal = (1 + 0.002 ) * 1e9; // 1 AVAX + 0.002 AVAX fee - +const transferAmountVal = (1 + 0.002) * 1e9; // 1 AVAX + 0.002 AVAX fee /* -* This function transfers funds from a single X-chain wallet to a P-chain multisig wallet -*/ -export async function crossChainTransfer(conf: ChainConfig, avaxPrivateKey: string, pMultisigReceiveAddresses: string[], transferAmountVal: number): Promise { - + * This function transfers funds from a single X-chain wallet to a P-chain multisig wallet + */ +export async function crossChainTransfer( + conf: ChainConfig, + avaxPrivateKey: string, + pMultisigReceiveAddresses: string[], + transferAmountVal: number +): Promise { // connect to network and get info console.log('Connecting to network...'); const avalanche = new Avalanche(conf.NODE_HOST, conf.NODE_PORT, conf.NODE_PROTOCOL, conf.NODE_NETWORK_ID); @@ -85,12 +86,9 @@ export async function crossChainTransfer(conf: ChainConfig, avaxPrivateKey: stri const avaxAssetID: string = Defaults.network[networkID].P.avaxAssetID as string; const avaxAssetIDBuf = bintools.cb58Decode(avaxAssetID); const locktime: BN = new BN(0); - const memo: Buffer = Buffer.from( - 'Manually Export AVAX from single-sig X-Chain to multi-sig P-Chain' - ); + const memo: Buffer = Buffer.from('Manually Export AVAX from single-sig X-Chain to multi-sig P-Chain'); const xBlockchainID: string = Defaults.network[networkID].X.blockchainID; const pBlockchainID: string = Defaults.network[networkID].P.blockchainID; - // import the key into keychains const pchain: PlatformVMAPI = avalanche.PChain(); @@ -120,11 +118,10 @@ export async function crossChainTransfer(conf: ChainConfig, avaxPrivateKey: stri let totalInputsAmount: BN = new BN(0); const transferAmount: BN = new BN(transferAmountVal); - + utxos.forEach((utxo: UTXO) => { // type 7 is transferable output if (utxo.getOutput().getTypeID() === 7 && totalInputsAmount.lt(transferAmount.add(fee).add(fee))) { - console.log('\nSelected utxo:'); // get amount and asset @@ -132,7 +129,7 @@ export async function crossChainTransfer(conf: ChainConfig, avaxPrivateKey: stri const amount: BN = amountOutput.getAmount().clone(); const assetID: Buffer = utxo.getAssetID(); console.log(`utxo asset:amount = ${bintools.bufferToB58(assetID)}:${amount.toString()}`); - + // get utxo txid const txid: Buffer = utxo.getTxID(); const outputidx: Buffer = utxo.getOutputIdx(); @@ -144,13 +141,8 @@ export async function crossChainTransfer(conf: ChainConfig, avaxPrivateKey: stri throw Error('Exported UTXO should have only one address'); } secpTransferInput.addSignatureIdx(0, xAddressesBufs[0]); - - const input: TransferableInput = new TransferableInput( - txid, - outputidx, - assetID, - secpTransferInput - ); + + const input: TransferableInput = new TransferableInput(txid, outputidx, assetID, secpTransferInput); inputs.push(input); totalInputsAmount = totalInputsAmount.add(amount); } else { @@ -161,21 +153,12 @@ export async function crossChainTransfer(conf: ChainConfig, avaxPrivateKey: stri // cross chain export output let secpTransferOutput: SECPTransferOutput = new SECPTransferOutput(); - secpTransferOutput = new SECPTransferOutput( - transferAmount.sub(fee), - xAddressesBufs, - locktime, - 1 - ); + secpTransferOutput = new SECPTransferOutput(transferAmount.sub(fee), xAddressesBufs, locktime, 1); // push exported output - exportedOuts.push(new TransferableOutput( - avaxAssetIDBuf, - secpTransferOutput - )); + exportedOuts.push(new TransferableOutput(avaxAssetIDBuf, secpTransferOutput)); console.log(`exported utxo: amount = ${secpTransferOutput.getAmount()}\n`); - // create change const secpTransferOutputChange = new SECPTransferOutput( totalInputsAmount.sub(secpTransferOutput.getAmount().add(fee)), @@ -185,10 +168,7 @@ export async function crossChainTransfer(conf: ChainConfig, avaxPrivateKey: stri ); // push change output - outputs.push(new TransferableOutput( - avaxAssetIDBuf, - secpTransferOutputChange - )); + outputs.push(new TransferableOutput(avaxAssetIDBuf, secpTransferOutputChange)); console.log(`change utxo: amount = ${secpTransferOutputChange.getAmount()}\n`); // create export tx @@ -201,37 +181,31 @@ export async function crossChainTransfer(conf: ChainConfig, avaxPrivateKey: stri bintools.cb58Decode(pBlockchainID), exportedOuts ); - const unsignedExportTx: UnsignedTx = new UnsignedTx(exportTx); const signedExportTx: AVMTx = unsignedExportTx.sign(xKeychain); - + console.log('Issuing Export...'); const exportTxid: string = await xchain.issueTx(signedExportTx); console.log(`Export success! TXID: https://explorer-xp.avax-test.network/tx/${exportTxid}`); // sleep for 5 seconds console.log('Wait 5 seconds for export to confirm...'); - - await new Promise(resolve => setTimeout(resolve, 5000)); + await new Promise((resolve) => setTimeout(resolve, 5000)); // create import tx - // X-chain exported out address strings const pxAddressStrings = xAddressesStrings.map((address) => { return 'P-' + address.slice(2); }); // get the exported p utxos - const platformVMUTXOResponse: any = await pchain.getUTXOs( - pxAddressStrings, - pBlockchainID - ); + const platformVMUTXOResponse: any = await pchain.getUTXOs(pxAddressStrings, pBlockchainID); const pvmUtxoSet: UTXOSet = platformVMUTXOResponse.utxos; console.log(`pvmUtxoSet length = ${pvmUtxoSet.getAllUTXOs().length}`); - + // create import tx const unsignedImportTx: PVMUnsignedTx = await pchain.buildImportTx( pvmUtxoSet, @@ -243,7 +217,7 @@ export async function crossChainTransfer(conf: ChainConfig, avaxPrivateKey: stri memo, UnixNow(), locktime, - 2, // threshold of 2 in the resulting utxo + 2 // threshold of 2 in the resulting utxo ); const signedImportTx: PlatformVMTx = unsignedImportTx.sign(pKeychain); @@ -251,7 +225,7 @@ export async function crossChainTransfer(conf: ChainConfig, avaxPrivateKey: stri const txid: string = await pchain.issueTx(signedImportTx); console.log(`Import Success! TXID: https://explorer-xp.avax-test.network/tx/${txid}`); - await new Promise(resolve => setTimeout(resolve, 5000)); + await new Promise((resolve) => setTimeout(resolve, 5000)); } crossChainTransfer(conf, avaxPrivateKey, pMultisigReceiveAddresses, transferAmountVal); diff --git a/examples/ts/backup-key-creation.ts b/examples/ts/backup-key-creation.ts index fb9c139832..a53e45cdc8 100644 --- a/examples/ts/backup-key-creation.ts +++ b/examples/ts/backup-key-creation.ts @@ -24,7 +24,6 @@ bitgo.register(coin, Tbtc.createInstance); // Create the wallet async function main() { - // this function takes one parameter - seed - if you want to create from your own entropy (recommended) const backupKey = bitgo.coin(coin).keychains().create(); diff --git a/examples/ts/build-transaction.ts b/examples/ts/build-transaction.ts index 705904726e..90e8d881f0 100644 --- a/examples/ts/build-transaction.ts +++ b/examples/ts/build-transaction.ts @@ -41,7 +41,6 @@ async function main() { }; const transaction = wallet.prebuildTransaction(buildTxParams); console.dir(transaction); - } main().catch((e) => console.log(e)); diff --git a/examples/ts/create-wallet-addresses.ts b/examples/ts/create-wallet-addresses.ts index a3436e9eb2..58206e6198 100644 --- a/examples/ts/create-wallet-addresses.ts +++ b/examples/ts/create-wallet-addresses.ts @@ -18,12 +18,11 @@ bitgo.register(coin, Tbtc.createInstance); const walletPassphrase = ''; async function main() { - const { wallet } = await bitgo.coin(coin).wallets() - .generateWallet({ - label: `Test Wallet Example`, - passphrase: walletPassphrase, - backupXpubProvider: 'keyternal', - }); + const { wallet } = await bitgo.coin(coin).wallets().generateWallet({ + label: `Test Wallet Example`, + passphrase: walletPassphrase, + backupXpubProvider: 'keyternal', + }); const newReceiveAddress = await wallet.createAddress(); diff --git a/examples/ts/create-wallet.ts b/examples/ts/create-wallet.ts index a3d2979290..38d23f48f6 100644 --- a/examples/ts/create-wallet.ts +++ b/examples/ts/create-wallet.ts @@ -53,5 +53,4 @@ async function main() { console.log(`Backup keychain xPrv: ${response.backupKeychain.prv}`); } -main().catch(e => console.log(e)); - +main().catch((e) => console.log(e)); diff --git a/examples/ts/eth/deployForwarder.ts b/examples/ts/eth/deployForwarder.ts index 33ada47f78..01c198a615 100644 --- a/examples/ts/eth/deployForwarder.ts +++ b/examples/ts/eth/deployForwarder.ts @@ -7,31 +7,29 @@ const BitGoJS = require('bitgo'); // change this to env: 'production' when you are ready for production const bitgo = new BitGoJS.BitGo({ env: 'test' }); - + // Change coin to 'eth' when working with production const coin = ''; - + // TODO: set your access token here const accessToken = ''; - + // set your wallet from the YYYYY parameter here in the URL on app.bitgo-test.com // https://test.bitgo.com/enterprise/XXXXXXXXX/coin/teth/YYYYY/transactions const walletId = ''; // set your address from wallet dashboard on app.bitgo-test.com or using the get-wallet example from this repo const addressId = ''; - + async function deployForwarders() { bitgo.authenticateWithAccessToken({ accessToken }); const wallet = await bitgo.coin(coin).wallets().get({ id: walletId }); - + const deployForwarderOptions = { address: addressId, }; - + const response = await wallet.deployForwarders(deployForwarderOptions); console.log('Response', response); - } - + deployForwarders().catch((e) => console.error(e)); - diff --git a/examples/ts/eth/flushForwarderToken.ts b/examples/ts/eth/flushForwarderToken.ts index 61e6e3ba73..cf7f4e3419 100644 --- a/examples/ts/eth/flushForwarderToken.ts +++ b/examples/ts/eth/flushForwarderToken.ts @@ -7,36 +7,35 @@ const BitGoJS = require('bitgo'); // change this to env: 'production' when you are ready for production const bitgo = new BitGoJS.BitGo({ env: 'test' }); - + // Change coin to 'eth' when working with production const coin = ''; - + // TODO: set your access token here const accessToken = ''; - + // set your wallet from the YYYYY parameter here in the URL on app.bitgo-test.com // https://test.bitgo.com/enterprise/XXXXXXXXX/coin/teth/YYYYY/transactions const walletId = ''; // set your address from wallet dashboard on app.bitgo-test.com or using the get-wallet example from this repo const addressId = ''; - + async function flushForwarderTokenManually() { bitgo.authenticateWithAccessToken({ accessToken }); const wallet = await bitgo.coin(coin).wallets().get({ id: walletId }); - + const flushForwarderOptions = { address: addressId, tokenName: coin, // required gasPrice: 0, // optional - eip1559: { // optional + eip1559: { + // optional maxPriorityFeePerGas: 0, maxFeePerGas: 0, }, }; const response = await wallet.flushForwarderToken(flushForwarderOptions); console.log('Response', response); - } - + flushForwarderTokenManually().catch((e) => console.error(e)); - diff --git a/examples/ts/eth/fund-forwarder.ts b/examples/ts/eth/fund-forwarder.ts index 5720d64ce8..e99f0e54fb 100644 --- a/examples/ts/eth/fund-forwarder.ts +++ b/examples/ts/eth/fund-forwarder.ts @@ -30,12 +30,11 @@ async function fundForwarder() { const fundForwarderOptions = { forwarderAddress: forwarderAddress, - amount: amount + amount: amount, }; const response = await wallet.fundForwarder(fundForwarderOptions); console.log('Response', response); - } -fundForwarder().catch((e) => console.error(e)); \ No newline at end of file +fundForwarder().catch((e) => console.error(e)); diff --git a/examples/ts/eth/list-wallet-addresses.ts b/examples/ts/eth/list-wallet-addresses.ts index fc816da99a..6949caaa1d 100644 --- a/examples/ts/eth/list-wallet-addresses.ts +++ b/examples/ts/eth/list-wallet-addresses.ts @@ -16,7 +16,11 @@ async function main() { bitgo.authenticateWithAccessToken({ accessToken }); const walletInstance = await basecoin.wallets().get({ id: walletId }); - const addresses = await walletInstance.addresses({ includeBalances: true, returnBalancesForToken: 'gterc6dp', pendingDeployment: false }); + const addresses = await walletInstance.addresses({ + includeBalances: true, + returnBalancesForToken: 'gterc6dp', + pendingDeployment: false, + }); console.log('Wallet ID:', walletInstance.id()); for (const address of addresses.addresses) { diff --git a/examples/ts/get-maximum-spendable.ts b/examples/ts/get-maximum-spendable.ts index 304cc685b9..aa6b89c5c4 100644 --- a/examples/ts/get-maximum-spendable.ts +++ b/examples/ts/get-maximum-spendable.ts @@ -27,7 +27,6 @@ const walletId = ''; const basecoin = bitgo.coin(coin); async function main() { - const wallet = await basecoin.wallets().get({ id: walletId }); // You may include any, all, or none of these optional parameters diff --git a/examples/ts/list-wallet-addresses.ts b/examples/ts/list-wallet-addresses.ts index a4489fe139..bf5028affb 100644 --- a/examples/ts/list-wallet-addresses.ts +++ b/examples/ts/list-wallet-addresses.ts @@ -18,7 +18,6 @@ bitgo.register(coin, Tbtc.createInstance); const walletId = ''; async function main() { - const wallet = await bitgo.coin(coin).wallets().get({ id: walletId }); const addresses = await wallet.addresses(); diff --git a/examples/ts/list-wallet-shares.ts b/examples/ts/list-wallet-shares.ts index c2c8569943..7de0541bad 100644 --- a/examples/ts/list-wallet-shares.ts +++ b/examples/ts/list-wallet-shares.ts @@ -20,7 +20,6 @@ const coin = 'tltc'; bitgo.register(coin, Tltc.createInstance); async function main() { - const shares = await bitgo.coin(coin).wallets().listShares({}); console.dir(shares); diff --git a/examples/ts/proxy/README.md b/examples/ts/proxy/README.md index be75cdb92b..07f5ce7eb7 100644 --- a/examples/ts/proxy/README.md +++ b/examples/ts/proxy/README.md @@ -3,6 +3,7 @@ This is in contrast to the [BitGo Express module](https://github.com/BitGo/BitGo Please take the time to review your use case as you choose between these options. ## Setup + Usage + - Acquire a test environment account, enterprise and access token - Fill in the `TODO` sections with the relevant credentials - `npm install` diff --git a/examples/ts/proxy/server.ts b/examples/ts/proxy/server.ts index 3c137539c4..d84f4fd4f5 100644 --- a/examples/ts/proxy/server.ts +++ b/examples/ts/proxy/server.ts @@ -8,7 +8,7 @@ const bitgoApi = 'https://app.bitgo-test.com'; // TODO: replace with your access token const secretAccessToken = 'yourAccessToken'; -app.all('*', function(req: Request, res: Response, next: NextFunction) { +app.all('*', function (req: Request, res: Response, next: NextFunction) { console.log(`received: ${req.method} ${req.url} ${JSON.stringify(req.body)}`); console.log(`headers: ${JSON.stringify(req.headers)}`); req.headers.authorization = `Bearer ${secretAccessToken}`; @@ -27,4 +27,3 @@ const port = 3000; app.listen(port, function () { console.log(`Proxy POC listening at http://localhost:${port}`); }); - diff --git a/examples/ts/recover-xrp.ts b/examples/ts/recover-xrp.ts index 56cbeeff6a..5b831cbef9 100644 --- a/examples/ts/recover-xrp.ts +++ b/examples/ts/recover-xrp.ts @@ -12,10 +12,12 @@ const basecoin = bitgo.coin(coin) as Coin.Xrp; async function main() { const response = await basecoin.recover({ // BOX A - userKey: '{"iv":"UgFBAnCOYhGpySRGlaLSrA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"vMawLQuCAZI=","ct":"RTAgWQSJOroRfWF9GT8mxsTeFwXPBYuRf9k7UeDAHSao5EZH0E5EUo0dKm2gyogpc64HYfQhmkiQgKElDYq2/EdH+PXkSZxAzWrfFNVkgmM6CyWN1IMR8vvjLnBjNSlpYHQOLR733szlP5OFntf01soVsUZHb5A="}', + userKey: + '{"iv":"UgFBAnCOYhGpySRGlaLSrA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"vMawLQuCAZI=","ct":"RTAgWQSJOroRfWF9GT8mxsTeFwXPBYuRf9k7UeDAHSao5EZH0E5EUo0dKm2gyogpc64HYfQhmkiQgKElDYq2/EdH+PXkSZxAzWrfFNVkgmM6CyWN1IMR8vvjLnBjNSlpYHQOLR733szlP5OFntf01soVsUZHb5A="}', // BOX B - backupKey: '{"iv":"SS/5vfzJx8Nr+YIUVENZ4Q==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"8VP7bl5uSVM=","ct":"vITKMhfemxW6lrai1TXHpGFJhyksHXBIhZ5x3bQwDGeURyLrOiVRfvIuAk5vptSQOSwU8gmfMHOSweRMjEFkw8j0RwuYp79vrDY4pu47oo/iR6uiiZ1grCLjd27hO68SULPWXrMvzLvRb8ELh9EvuoByWnujyvM="}', + backupKey: + '{"iv":"SS/5vfzJx8Nr+YIUVENZ4Q==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"8VP7bl5uSVM=","ct":"vITKMhfemxW6lrai1TXHpGFJhyksHXBIhZ5x3bQwDGeURyLrOiVRfvIuAk5vptSQOSwU8gmfMHOSweRMjEFkw8j0RwuYp79vrDY4pu47oo/iR6uiiZ1grCLjd27hO68SULPWXrMvzLvRb8ELh9EvuoByWnujyvM="}', // BOX C rootAddress: 'rB651yVavQSCEd6xi9pzg8QkHkPrR8gR4i', @@ -28,15 +30,14 @@ async function main() { console.log(JSON.stringify(response, null, 4)); - const submittedTx = await bitgo.post(basecoin.getRippledUrl()) - .send({ - method: 'submit', - params: [{ - tx_blob: typeof response === 'string' ? - response : - response.txHex, - }], - }); + const submittedTx = await bitgo.post(basecoin.getRippledUrl()).send({ + method: 'submit', + params: [ + { + tx_blob: typeof response === 'string' ? response : response.txHex, + }, + ], + }); console.log(JSON.stringify(submittedTx, null, 4)); } diff --git a/examples/ts/send-hop-transaction.ts b/examples/ts/send-hop-transaction.ts index ddffc7e132..0d1405f858 100644 --- a/examples/ts/send-hop-transaction.ts +++ b/examples/ts/send-hop-transaction.ts @@ -23,10 +23,12 @@ async function sendTxWithHop() { const wallet = await bitgo.coin(coin).wallets().getWallet({ id: walletId }); const res = await wallet.sendMany({ - recipients: [{ - amount: '', - address: '', - }], + recipients: [ + { + amount: '', + address: '', + }, + ], walletPassphrase: walletPassphrase, hop: true, }); diff --git a/examples/ts/send-with-provided-public-keys.ts b/examples/ts/send-with-provided-public-keys.ts index a90a96ec66..2905be2fe8 100644 --- a/examples/ts/send-with-provided-public-keys.ts +++ b/examples/ts/send-with-provided-public-keys.ts @@ -39,9 +39,15 @@ const recipients = [ // TODO: these are example public keys, please substitute them with the correct keys for your wallet const keychains = { - user: { pub: 'xpub661MyMwAqRbcG9jW7yGH5q3gniFXRiVm6eNodEXmGrUnE5k1gnFCfivEzL8PEkiYyMLiHx3mGdJk8ABZ4Aw1pthkEQbfnJjehxdZpaHb4AE' }, - backup: { pub: 'xpub661MyMwAqRbcF47eVHSVcpnPwjvf4xnfH2PpnS9sPsjUwMBxYxqDbyJEYZ2Xpi5cyEirTpYc32GBXG8DRkU8DkAYUi6vCYTy5krvve5ZwVY' }, - bitgo: { pub: 'xpub661MyMwAqRbcGt7gRtUMbV3K5f9wJjputbhCY4BM4BDEPpRyixAtiWCqNFsLeBdbStcKTGMgeX3pjvazz58r4WVFH1dXrUq7DfVmQSijgGL' }, + user: { + pub: 'xpub661MyMwAqRbcG9jW7yGH5q3gniFXRiVm6eNodEXmGrUnE5k1gnFCfivEzL8PEkiYyMLiHx3mGdJk8ABZ4Aw1pthkEQbfnJjehxdZpaHb4AE', + }, + backup: { + pub: 'xpub661MyMwAqRbcF47eVHSVcpnPwjvf4xnfH2PpnS9sPsjUwMBxYxqDbyJEYZ2Xpi5cyEirTpYc32GBXG8DRkU8DkAYUi6vCYTy5krvve5ZwVY', + }, + bitgo: { + pub: 'xpub661MyMwAqRbcGt7gRtUMbV3K5f9wJjputbhCY4BM4BDEPpRyixAtiWCqNFsLeBdbStcKTGMgeX3pjvazz58r4WVFH1dXrUq7DfVmQSijgGL', + }, }; async function main() { diff --git a/examples/ts/sui/build-pay-transaction.ts b/examples/ts/sui/build-pay-transaction.ts index 35bebc02f7..e49c2f9dcd 100644 --- a/examples/ts/sui/build-pay-transaction.ts +++ b/examples/ts/sui/build-pay-transaction.ts @@ -33,7 +33,7 @@ async function buildPayTx() { passphrase, passcodeEncryptionCode: passphrase, multisigType: 'tss', - enterprise + enterprise, }; const wallet = await bitgo.coin(coin).wallets().generateWallet(walletOptions); diff --git a/examples/ts/sui/create-wallet.ts b/examples/ts/sui/create-wallet.ts index 85f4ba8874..169b619f9f 100644 --- a/examples/ts/sui/create-wallet.ts +++ b/examples/ts/sui/create-wallet.ts @@ -16,7 +16,7 @@ const coin = 'tsui'; const accessToken = ''; // TODO: set a label for your new wallet here -const label = 'Test ' + coin + ' V2 Wallet - ' + (new Date()).getTime(); +const label = 'Test ' + coin + ' V2 Wallet - ' + new Date().getTime(); // TODO: set your passphrase for your new wallet here const passphrase = ''; @@ -33,7 +33,7 @@ async function createWallet() { passphrase, passcodeEncryptionCode: passphrase, multisigType: 'tss', - enterprise + enterprise, }; const wallet = await bitgo.coin(coin).wallets().generateWallet(walletOptions); @@ -78,8 +78,6 @@ async function createWallet() { console.log('-----------------------------------------'); const bitgoKeychain = wallet.bitgoKeychain; console.log(`Bitgo commonKeychain xPrv: ${bitgoKeychain.commonKeychain}`); - } - createWallet().catch((e) => console.error(e)); diff --git a/examples/ts/sui/multi-recipient-pay-transaction.ts b/examples/ts/sui/multi-recipient-pay-transaction.ts index 1b4b505439..e53ec3000f 100644 --- a/examples/ts/sui/multi-recipient-pay-transaction.ts +++ b/examples/ts/sui/multi-recipient-pay-transaction.ts @@ -5,11 +5,11 @@ * * Copyright 2023 BitGo, Inc. All Rights Reserved. */ -const util = require('util') +const util = require('util'); import { BitGo } from 'bitgo'; // 'prod' for prod environment -const env = 'test' +const env = 'test'; const bitgo = new BitGo({ env }); // 'sui' for production environment @@ -25,26 +25,27 @@ const walletId = ''; const passphrase = ''; // TODO: set the recipients here, each recipient is an object with address and amount. -const recipients = [{ - address: 'sui-address-1', - amount: '10000', -}, -{ - address: 'sui-address-2', - amount: '20000', -}]; +const recipients = [ + { + address: 'sui-address-1', + amount: '10000', + }, + { + address: 'sui-address-2', + amount: '20000', + }, +]; // build pay transaction async function buildPayTx() { bitgo.authenticateWithAccessToken({ accessToken }); - bitgo.unlock({otp: '000000'}) + bitgo.unlock({ otp: '000000' }); const wallet = await bitgo.coin(coin).wallets().getWallet({ id: walletId }); - const response = await wallet.sendMany({ recipients, passphrase, - type: 'transfer' + type: 'transfer', }); console.log(util.inspect(response, { showHidden: false, depth: 5, colors: true })); } diff --git a/examples/ts/webhooks-block-add.ts b/examples/ts/webhooks-block-add.ts index 07521f797f..c40f5974c9 100644 --- a/examples/ts/webhooks-block-add.ts +++ b/examples/ts/webhooks-block-add.ts @@ -1,6 +1,6 @@ /** * Add a new block webhook when a new block is seen on the network or when a wallet is initialized of a given user defined coin. - * + * * Copyright 2022, BitGo, Inc. All Rights Reserved. */ diff --git a/examples/ts/webhooks-list-notifications.ts b/examples/ts/webhooks-list-notifications.ts index 5ee1d27574..cb145e0516 100644 --- a/examples/ts/webhooks-list-notifications.ts +++ b/examples/ts/webhooks-list-notifications.ts @@ -1,6 +1,6 @@ /** * Fetch a list of block notifications triggered by a webhook for a given coin type - * + * * Copyright 2022, BitGo, Inc. All Rights Reserved. */ diff --git a/examples/ts/webhooks-list.ts b/examples/ts/webhooks-list.ts index b6634a5c04..22d88a864b 100644 --- a/examples/ts/webhooks-list.ts +++ b/examples/ts/webhooks-list.ts @@ -1,6 +1,6 @@ /** * Fetch a list of webhooks for wallet's coin type - * + * * Copyright 2022, BitGo, Inc. All Rights Reserved. */ import { BitGoAPI } from '@bitgo/sdk-api'; diff --git a/examples/ts/webhooks-remove.ts b/examples/ts/webhooks-remove.ts index c178e9d7cf..6fb40b46d7 100644 --- a/examples/ts/webhooks-remove.ts +++ b/examples/ts/webhooks-remove.ts @@ -1,6 +1,6 @@ /** * Remove a webhook from a BitGo account wallet - * + * * Copyright 2022, BitGo, Inc. All Rights Reserved. */ import { BitGoAPI } from '@bitgo/sdk-api'; diff --git a/examples/ts/webhooks-simulate.ts b/examples/ts/webhooks-simulate.ts index 98dabeacf2..de113761af 100644 --- a/examples/ts/webhooks-simulate.ts +++ b/examples/ts/webhooks-simulate.ts @@ -1,6 +1,6 @@ /** * Simulate a webhook trigger for a wallet's coin type - * + * * Copyright 2022, BitGo, Inc. All Rights Reserved. */ import { BitGoAPI } from '@bitgo/sdk-api'; diff --git a/merge-coverage-reports.js b/merge-coverage-reports.js index 828dce519d..954f1edb1d 100644 --- a/merge-coverage-reports.js +++ b/merge-coverage-reports.js @@ -11,16 +11,11 @@ process.chdir(__dirname); rimraf.sync('.nyc_output'); makeDir.sync('.nyc_output'); // Merge coverage data from each package so we can generate a complete report -glob.sync('modules/*/.nyc_output').forEach(nycOutput => { +glob.sync('modules/*/.nyc_output').forEach((nycOutput) => { const cwd = path.dirname(nycOutput); const { status, stderr } = spawnSync( 'yarn', - [ - 'nyc', - 'merge', - '.nyc_output', - path.join(__dirname, '.nyc_output', path.basename(cwd) + '.json'), - ], + ['nyc', 'merge', '.nyc_output', path.join(__dirname, '.nyc_output', path.basename(cwd) + '.json')], { encoding: 'utf8', shell: true, diff --git a/modules/account-lib/.prettierrc.js b/modules/account-lib/.prettierrc.js index 038a0e45da..b11c3022d7 100644 --- a/modules/account-lib/.prettierrc.js +++ b/modules/account-lib/.prettierrc.js @@ -1,9 +1,9 @@ -module.exports = { - semi: true, - trailingComma: 'all', - singleQuote: true, - printWidth: 120, - tabWidth: 2, +module.exports = { + semi: true, + trailingComma: 'all', + singleQuote: true, + printWidth: 120, + tabWidth: 2, bracketSpacing: true, useTabs: false, }; diff --git a/modules/account-lib/README.md b/modules/account-lib/README.md index 5136fabe93..702b58677c 100644 --- a/modules/account-lib/README.md +++ b/modules/account-lib/README.md @@ -13,7 +13,7 @@ Below is the list of coins supported by this library -- as well as those that are on the roadmap. | Coin | Mainnet Ticker | Testnet Ticker | Supported In Library | -|:-----------------|:---------------|:---------------|:---------------------| +| :--------------- | :------------- | :------------- | :------------------- | | Alogrand | algo | talgo | Yes | | CELO | celo | tcelo | Yes | | Ethereum | eth | teth | Yes | diff --git a/modules/bitgo/.mocharc.yml b/modules/bitgo/.mocharc.yml index ea7cc8f0d0..52f1b6eafb 100644 --- a/modules/bitgo/.mocharc.yml +++ b/modules/bitgo/.mocharc.yml @@ -5,9 +5,4 @@ reporter-option: - 'cdn=true' - 'json=false' exit: true -spec: [ - 'test/unit/*.ts', - 'test/unit/**/*.ts', - 'test/v2/unit/*.ts', - 'test/v2/unit/**/*.ts' -] +spec: ['test/unit/*.ts', 'test/unit/**/*.ts', 'test/v2/unit/*.ts', 'test/v2/unit/**/*.ts'] diff --git a/modules/blake2b-wasm/README.md b/modules/blake2b-wasm/README.md index 03ee1c595b..de85eda7ac 100644 --- a/modules/blake2b-wasm/README.md +++ b/modules/blake2b-wasm/README.md @@ -10,24 +10,24 @@ Works in browsers that support WASM and Node.js 8+. ## Usage -``` js -var blake2b = require('@bitgo/blake2b-wasm') +```js +var blake2b = require('@bitgo/blake2b-wasm'); if (!blake2b.SUPPORTED) { - console.log('WebAssembly not supported by your runtime') + console.log('WebAssembly not supported by your runtime'); } blake2b.ready(function (err) { - if (err) throw err + if (err) throw err; var hash = blake2b() .update(Buffer.from('hello')) // pass in a buffer or uint8array .update(Buffer.from(' ')) .update(Buffer.from('world')) - .digest('hex') + .digest('hex'); - console.log('Blake2b hash of "hello world" is %s', hash) -}) + console.log('Blake2b hash of "hello world" is %s', hash); +}); ``` ## API diff --git a/modules/blake2b-wasm/blake2b.js b/modules/blake2b-wasm/blake2b.js index 9cbe07b2c1..db63f4cd1c 100644 --- a/modules/blake2b-wasm/blake2b.js +++ b/modules/blake2b-wasm/blake2b.js @@ -1,63 +1,64 @@ +module.exports = loadWebAssembly; -module.exports = loadWebAssembly - -// turning off support for WebAssembly, +// turning off support for WebAssembly, // chrome 69 has issues with loading webassembly in the main thread if the module size >4k -loadWebAssembly.supported = false +loadWebAssembly.supported = false; -function loadWebAssembly (opts) { - if (!loadWebAssembly.supported) return null +function loadWebAssembly(opts) { + if (!loadWebAssembly.supported) return null; - var imp = opts && opts.imports - var wasm = toUint8Array('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') - var ready = null + var imp = opts && opts.imports; + var wasm = toUint8Array( + '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' + ); + var ready = null; var mod = { buffer: wasm, memory: null, exports: null, realloc: realloc, - onload: onload - } + onload: onload, + }; - onload(function () {}) + onload(function () {}); - return mod + return mod; - function realloc (size) { - mod.exports.memory.grow(Math.max(0, Math.ceil(Math.abs(size - mod.memory.length) / 65536))) - mod.memory = new Uint8Array(mod.exports.memory.buffer) + function realloc(size) { + mod.exports.memory.grow(Math.max(0, Math.ceil(Math.abs(size - mod.memory.length) / 65536))); + mod.memory = new Uint8Array(mod.exports.memory.buffer); } - function onload (cb) { - if (mod.exports) return cb() + function onload(cb) { + if (mod.exports) return cb(); if (ready) { - ready.then(cb.bind(null, null)).catch(cb) - return + ready.then(cb.bind(null, null)).catch(cb); + return; } try { - if (opts && opts.async) throw new Error('async') - setup({instance: new WebAssembly.Instance(new WebAssembly.Module(wasm), imp)}) + if (opts && opts.async) throw new Error('async'); + setup({ instance: new WebAssembly.Instance(new WebAssembly.Module(wasm), imp) }); } catch (err) { - ready = WebAssembly.instantiate(wasm, imp).then(setup) + ready = WebAssembly.instantiate(wasm, imp).then(setup); } - onload(cb) + onload(cb); } - function setup (w) { - mod.exports = w.instance.exports - mod.memory = mod.exports.memory && mod.exports.memory.buffer && new Uint8Array(mod.exports.memory.buffer) + function setup(w) { + mod.exports = w.instance.exports; + mod.memory = mod.exports.memory && mod.exports.memory.buffer && new Uint8Array(mod.exports.memory.buffer); } } -function toUint8Array (s) { - if (typeof atob === 'function') return new Uint8Array(atob(s).split('').map(charCodeAt)) - return (require('buf' + 'fer').Buffer).from(s, 'base64') +function toUint8Array(s) { + if (typeof atob === 'function') return new Uint8Array(atob(s).split('').map(charCodeAt)); + return require('buf' + 'fer').Buffer.from(s, 'base64'); } -function charCodeAt (c) { - return c.charCodeAt(0) +function charCodeAt(c) { + return c.charCodeAt(0); } diff --git a/modules/blake2b-wasm/example.html b/modules/blake2b-wasm/example.html index a87ecc6b84..273c311dec 100644 --- a/modules/blake2b-wasm/example.html +++ b/modules/blake2b-wasm/example.html @@ -1,14 +1,14 @@ - - Blake2b-WASM Demo - - -
    -
  1. Run `npm run demo` if you haven't
  2. -
  3. Reload this page
  4. -
  5. Open the console
  6. -
- - + + Blake2b-WASM Demo + + +
    +
  1. Run `npm run demo` if you haven't
  2. +
  3. Reload this page
  4. +
  5. Open the console
  6. +
+ + diff --git a/modules/blake2b-wasm/example.js b/modules/blake2b-wasm/example.js index 1efed75cc9..5c0cc048c6 100644 --- a/modules/blake2b-wasm/example.js +++ b/modules/blake2b-wasm/example.js @@ -1,13 +1,8 @@ -'use strict' -var blake2b = require('./') +'use strict'; +var blake2b = require('./'); blake2b.ready(function () { - var hash = blake2b() - .update(Buffer.from('hello')) - .update(Buffer.from(' ')) - .update(Buffer.from('world')) - .digest('hex') - - console.log('Blake2b hash of "hello world" is %s', hash) -}) + var hash = blake2b().update(Buffer.from('hello')).update(Buffer.from(' ')).update(Buffer.from('world')).digest('hex'); + console.log('Blake2b hash of "hello world" is %s', hash); +}); diff --git a/modules/blake2b-wasm/generate-rounds.js b/modules/blake2b-wasm/generate-rounds.js index a95d197843..86c961b4e4 100644 --- a/modules/blake2b-wasm/generate-rounds.js +++ b/modules/blake2b-wasm/generate-rounds.js @@ -10,10 +10,10 @@ var sigma = [ [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3] -] + [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], +]; -function G (r, i, a, b, c, d) { +function G(r, i, a, b, c, d) { return ` ;; G(${r}, ${i}) @@ -39,10 +39,10 @@ function G (r, i, a, b, c, d) { (set_local ${c} (i64.add (get_local ${c}) (get_local ${d}))) ;; ${b} = rotr64(${b} ^ ${c}, 63) - (set_local ${b} (i64.rotr (i64.xor (get_local ${b}) (get_local ${c})) (i64.const 63)))` + (set_local ${b} (i64.rotr (i64.xor (get_local ${b}) (get_local ${c})) (i64.const 63)))`; } -function ROUND (r) { +function ROUND(r) { return ` ;; ROUND(${r}) ${G(r, 0, '$v0', '$v4', '$v8', '$v12')} @@ -53,7 +53,7 @@ function ROUND (r) { ${G(r, 5, '$v1', '$v6', '$v11', '$v12')} ${G(r, 6, '$v2', '$v7', '$v8', '$v13')} ${G(r, 7, '$v3', '$v4', '$v9', '$v14')} - ` + `; } console.log( @@ -69,4 +69,4 @@ console.log( ROUND(9), ROUND(10), ROUND(11) -) +); diff --git a/modules/blake2b-wasm/index.js b/modules/blake2b-wasm/index.js index 8409eb5048..3bb19b43c1 100644 --- a/modules/blake2b-wasm/index.js +++ b/modules/blake2b-wasm/index.js @@ -1,137 +1,139 @@ -var assert = require('nanoassert') -var wasm = require('./blake2b')() - -var head = 64 -var freeList = [] - -module.exports = Blake2b -var BYTES_MIN = module.exports.BYTES_MIN = 16 -var BYTES_MAX = module.exports.BYTES_MAX = 64 -var BYTES = module.exports.BYTES = 32 -var KEYBYTES_MIN = module.exports.KEYBYTES_MIN = 16 -var KEYBYTES_MAX = module.exports.KEYBYTES_MAX = 64 -var KEYBYTES = module.exports.KEYBYTES = 32 -var SALTBYTES = module.exports.SALTBYTES = 16 -var PERSONALBYTES = module.exports.PERSONALBYTES = 16 - -function Blake2b (digestLength, key, salt, personal, noAssert) { - if (!(this instanceof Blake2b)) return new Blake2b(digestLength, key, salt, personal, noAssert) - if (!(wasm && wasm.exports)) throw new Error('WASM not loaded. Wait for Blake2b.ready(cb)') - if (!digestLength) digestLength = 32 +var assert = require('nanoassert'); +var wasm = require('./blake2b')(); + +var head = 64; +var freeList = []; + +module.exports = Blake2b; +var BYTES_MIN = (module.exports.BYTES_MIN = 16); +var BYTES_MAX = (module.exports.BYTES_MAX = 64); +var BYTES = (module.exports.BYTES = 32); +var KEYBYTES_MIN = (module.exports.KEYBYTES_MIN = 16); +var KEYBYTES_MAX = (module.exports.KEYBYTES_MAX = 64); +var KEYBYTES = (module.exports.KEYBYTES = 32); +var SALTBYTES = (module.exports.SALTBYTES = 16); +var PERSONALBYTES = (module.exports.PERSONALBYTES = 16); + +function Blake2b(digestLength, key, salt, personal, noAssert) { + if (!(this instanceof Blake2b)) return new Blake2b(digestLength, key, salt, personal, noAssert); + if (!(wasm && wasm.exports)) throw new Error('WASM not loaded. Wait for Blake2b.ready(cb)'); + if (!digestLength) digestLength = 32; if (noAssert !== true) { - assert(digestLength >= BYTES_MIN, 'digestLength must be at least ' + BYTES_MIN + ', was given ' + digestLength) - assert(digestLength <= BYTES_MAX, 'digestLength must be at most ' + BYTES_MAX + ', was given ' + digestLength) + assert(digestLength >= BYTES_MIN, 'digestLength must be at least ' + BYTES_MIN + ', was given ' + digestLength); + assert(digestLength <= BYTES_MAX, 'digestLength must be at most ' + BYTES_MAX + ', was given ' + digestLength); if (key != null) { - assert(key instanceof Uint8Array, 'key must be Uint8Array or Buffer') - assert(key.length >= KEYBYTES_MIN, 'key must be at least ' + KEYBYTES_MIN + ', was given ' + key.length) - assert(key.length <= KEYBYTES_MAX, 'key must be at least ' + KEYBYTES_MAX + ', was given ' + key.length) + assert(key instanceof Uint8Array, 'key must be Uint8Array or Buffer'); + assert(key.length >= KEYBYTES_MIN, 'key must be at least ' + KEYBYTES_MIN + ', was given ' + key.length); + assert(key.length <= KEYBYTES_MAX, 'key must be at least ' + KEYBYTES_MAX + ', was given ' + key.length); } if (salt != null) { - assert(salt instanceof Uint8Array, 'salt must be Uint8Array or Buffer') - assert(salt.length === SALTBYTES, 'salt must be exactly ' + SALTBYTES + ', was given ' + salt.length) + assert(salt instanceof Uint8Array, 'salt must be Uint8Array or Buffer'); + assert(salt.length === SALTBYTES, 'salt must be exactly ' + SALTBYTES + ', was given ' + salt.length); } if (personal != null) { - assert(personal instanceof Uint8Array, 'personal must be Uint8Array or Buffer') - assert(personal.length === PERSONALBYTES, 'personal must be exactly ' + PERSONALBYTES + ', was given ' + personal.length) + assert(personal instanceof Uint8Array, 'personal must be Uint8Array or Buffer'); + assert( + personal.length === PERSONALBYTES, + 'personal must be exactly ' + PERSONALBYTES + ', was given ' + personal.length + ); } } if (!freeList.length) { - freeList.push(head) - head += 216 + freeList.push(head); + head += 216; } - this.digestLength = digestLength - this.finalized = false - this.pointer = freeList.pop() + this.digestLength = digestLength; + this.finalized = false; + this.pointer = freeList.pop(); - wasm.memory.fill(0, 0, 64) - wasm.memory[0] = this.digestLength - wasm.memory[1] = key ? key.length : 0 - wasm.memory[2] = 1 // fanout - wasm.memory[3] = 1 // depth + wasm.memory.fill(0, 0, 64); + wasm.memory[0] = this.digestLength; + wasm.memory[1] = key ? key.length : 0; + wasm.memory[2] = 1; // fanout + wasm.memory[3] = 1; // depth - if (salt) wasm.memory.set(salt, 32) - if (personal) wasm.memory.set(personal, 48) + if (salt) wasm.memory.set(salt, 32); + if (personal) wasm.memory.set(personal, 48); - if (this.pointer + 216 > wasm.memory.length) wasm.realloc(this.pointer + 216) // we need 216 bytes for the state - wasm.exports.blake2b_init(this.pointer, this.digestLength) + if (this.pointer + 216 > wasm.memory.length) wasm.realloc(this.pointer + 216); // we need 216 bytes for the state + wasm.exports.blake2b_init(this.pointer, this.digestLength); if (key) { - this.update(key) - wasm.memory.fill(0, head, head + key.length) // whiteout key - wasm.memory[this.pointer + 200] = 128 + this.update(key); + wasm.memory.fill(0, head, head + key.length); // whiteout key + wasm.memory[this.pointer + 200] = 128; } } - Blake2b.prototype.update = function (input) { - assert(this.finalized === false, 'Hash instance finalized') - assert(input instanceof Uint8Array, 'input must be Uint8Array or Buffer') + assert(this.finalized === false, 'Hash instance finalized'); + assert(input instanceof Uint8Array, 'input must be Uint8Array or Buffer'); - if (head + input.length > wasm.memory.length) wasm.realloc(head + input.length) - wasm.memory.set(input, head) - wasm.exports.blake2b_update(this.pointer, head, head + input.length) - return this -} + if (head + input.length > wasm.memory.length) wasm.realloc(head + input.length); + wasm.memory.set(input, head); + wasm.exports.blake2b_update(this.pointer, head, head + input.length); + return this; +}; Blake2b.prototype.digest = function (enc) { - assert(this.finalized === false, 'Hash instance finalized') - this.finalized = true + assert(this.finalized === false, 'Hash instance finalized'); + this.finalized = true; - freeList.push(this.pointer) - wasm.exports.blake2b_final(this.pointer) + freeList.push(this.pointer); + wasm.exports.blake2b_final(this.pointer); if (!enc || enc === 'binary') { - return wasm.memory.slice(this.pointer + 128, this.pointer + 128 + this.digestLength) + return wasm.memory.slice(this.pointer + 128, this.pointer + 128 + this.digestLength); } if (enc === 'hex') { - return hexSlice(wasm.memory, this.pointer + 128, this.digestLength) + return hexSlice(wasm.memory, this.pointer + 128, this.digestLength); } - assert(enc instanceof Uint8Array && enc.length >= this.digestLength, 'input must be Uint8Array or Buffer') + assert(enc instanceof Uint8Array && enc.length >= this.digestLength, 'input must be Uint8Array or Buffer'); for (var i = 0; i < this.digestLength; i++) { - enc[i] = wasm.memory[this.pointer + 128 + i] + enc[i] = wasm.memory[this.pointer + 128 + i]; } - return enc -} + return enc; +}; // libsodium compat -Blake2b.prototype.final = Blake2b.prototype.digest +Blake2b.prototype.final = Blake2b.prototype.digest; -Blake2b.WASM = wasm && wasm.buffer -Blake2b.SUPPORTED = typeof WebAssembly !== 'undefined' +Blake2b.WASM = wasm && wasm.buffer; +Blake2b.SUPPORTED = typeof WebAssembly !== 'undefined'; Blake2b.ready = function (cb) { - if (!cb) cb = noop - if (!wasm) return cb(new Error('WebAssembly not supported')) + if (!cb) cb = noop; + if (!wasm) return cb(new Error('WebAssembly not supported')); // backwards compat, can be removed in a new major var p = new Promise(function (reject, resolve) { wasm.onload(function (err) { - if (err) resolve() - else reject() - cb(err) - }) - }) + if (err) resolve(); + else reject(); + cb(err); + }); + }); - return p -} + return p; +}; -Blake2b.prototype.ready = Blake2b.ready +Blake2b.prototype.ready = Blake2b.ready; -function noop () {} +function noop() {} -function hexSlice (buf, start, len) { - var str = '' - for (var i = 0; i < len; i++) str += toHex(buf[start + i]) - return str +function hexSlice(buf, start, len) { + var str = ''; + for (var i = 0; i < len; i++) str += toHex(buf[start + i]); + return str; } -function toHex (n) { - if (n < 16) return '0' + n.toString(16) - return n.toString(16) +function toHex(n) { + if (n < 16) return '0' + n.toString(16); + return n.toString(16); } diff --git a/modules/blake2b-wasm/test.js b/modules/blake2b-wasm/test.js index cc90b8f90d..ed404fcc14 100644 --- a/modules/blake2b-wasm/test.js +++ b/modules/blake2b-wasm/test.js @@ -1,85 +1,83 @@ -var tape = require('tape') -var blake2b = require('./') -var vectors = require('blake2b/test-vectors.json') +var tape = require('tape'); +var blake2b = require('./'); +var vectors = require('blake2b/test-vectors.json'); -var readyCalled = false +var readyCalled = false; process.on('exit', function () { - if (!readyCalled) - throw new Error('ready not called') -}) + if (!readyCalled) throw new Error('ready not called'); +}); blake2b.ready(function () { - readyCalled = true + readyCalled = true; tape('hello world', function (t) { var hash = blake2b() .update(Buffer.from('hello')) .update(Buffer.from(' ')) .update(Buffer.from('world')) - .digest('hex') + .digest('hex'); - t.same(hash, '256c83b297114d201b30179f3f0ef0cace9783622da5974326b436178aeef610') - t.end() - }) + t.same(hash, '256c83b297114d201b30179f3f0ef0cace9783622da5974326b436178aeef610'); + t.end(); + }); tape('hello world', function (t) { var hash = blake2b(64) .update(Buffer.from('hello')) .update(Buffer.from(' ')) .update(Buffer.from('world')) - .digest('hex') + .digest('hex'); - t.same(hash, '021ced8799296ceca557832ab941a50b4a11f83478cf141f51f933f653ab9fbcc05a037cddbed06e309bf334942c4e58cdf1a46e237911ccd7fcf9787cbc7fd0') - t.end() - }) + t.same( + hash, + '021ced8799296ceca557832ab941a50b4a11f83478cf141f51f933f653ab9fbcc05a037cddbed06e309bf334942c4e58cdf1a46e237911ccd7fcf9787cbc7fd0' + ); + t.end(); + }); tape('both at the same time', function (t) { - var a = blake2b() - var b = blake2b(64) + var a = blake2b(); + var b = blake2b(64); - var hash = a - .update(Buffer.from('hello')) - .update(Buffer.from(' ')) - .update(Buffer.from('world')) - .digest('hex') + var hash = a.update(Buffer.from('hello')).update(Buffer.from(' ')).update(Buffer.from('world')).digest('hex'); - t.same(hash, '256c83b297114d201b30179f3f0ef0cace9783622da5974326b436178aeef610') + t.same(hash, '256c83b297114d201b30179f3f0ef0cace9783622da5974326b436178aeef610'); - var hash = b - .update(Buffer.from('hello')) - .update(Buffer.from(' ')) - .update(Buffer.from('world')) - .digest('hex') + var hash = b.update(Buffer.from('hello')).update(Buffer.from(' ')).update(Buffer.from('world')).digest('hex'); - t.same(hash, '021ced8799296ceca557832ab941a50b4a11f83478cf141f51f933f653ab9fbcc05a037cddbed06e309bf334942c4e58cdf1a46e237911ccd7fcf9787cbc7fd0') - t.end() - }) + t.same( + hash, + '021ced8799296ceca557832ab941a50b4a11f83478cf141f51f933f653ab9fbcc05a037cddbed06e309bf334942c4e58cdf1a46e237911ccd7fcf9787cbc7fd0' + ); + t.end(); + }); vectors.forEach(function (vector, i) { tape('test-vectors.json #' + i, function (t) { - var key = vector.key && Buffer.from(vector.key, 'hex') - var salt = vector.salt && Buffer.from(vector.salt, 'hex') - var personal = vector.personal && Buffer.from(vector.personal, 'hex') + var key = vector.key && Buffer.from(vector.key, 'hex'); + var salt = vector.salt && Buffer.from(vector.salt, 'hex'); + var personal = vector.personal && Buffer.from(vector.personal, 'hex'); var hash = blake2b(vector.outlen, key, salt, personal, true) .update(Buffer.from(vector.input, 'hex')) - .digest('hex') + .digest('hex'); - t.same(hash, vector.out) - t.end() - }) - }) -}) + t.same(hash, vector.out); + t.end(); + }); + }); +}); tape('.ready()', function (t) { var invokeCount = 0; - blake2b.ready() + blake2b + .ready() .then(function () { - invokeCount++ - throw new Error() + invokeCount++; + throw new Error(); }) .catch(function (err) { - t.same(invokeCount, 1) - t.end() - }) + t.same(invokeCount, 1); + t.end(); + }); }); diff --git a/modules/blake2b/README.md b/modules/blake2b/README.md index 899f3099b5..3673b90fa0 100644 --- a/modules/blake2b/README.md +++ b/modules/blake2b/README.md @@ -7,10 +7,10 @@ This module is based on @dcposch [implementation of BLAKE2b](https://github.com/dcposch/blakejs), with some changes: -* This module requires you to pass in a `out` buffer, saving an allocation -* This module allows you to set the `salt` and `personal` parameters -* This module exports constants for the parameters in libsodium style -* Uses a WASM version (where it is supported) for massive performance boosts +- This module requires you to pass in a `out` buffer, saving an allocation +- This module allows you to set the `salt` and `personal` parameters +- This module exports constants for the parameters in libsodium style +- Uses a WASM version (where it is supported) for massive performance boosts All credit goes to @dcposch for doing the hard work of porting the implementation from C to JavaScript. @@ -18,12 +18,12 @@ implementation from C to JavaScript. ## Usage ```js -var blake2b = require('@bitgo/blake2b') +var blake2b = require('@bitgo/blake2b'); -var output = new Uint8Array(64) -var input = Buffer.from('hello world') +var output = new Uint8Array(64); +var input = Buffer.from('hello world'); -console.log('hash:', blake2b(output.length).update(input).digest('hex')) +console.log('hash:', blake2b(output.length).update(input).digest('hex')); ``` ## API @@ -37,14 +37,14 @@ All parameters must be `Uint8Array`, `Buffer` or another object with a compatibl API. All parameters must also fulfill the following constraints, or an `AssertionError` will be thrown (unless `noAssert = true`): -* `outLength` must within the byte ranges defined by the constants below. -* `key` is optional, but must within the byte ranges defined by the constants - below, if given. This value must be kept secret, and can be used to create - prefix-MACs. -* `salt` is optional, but must be exactly `SALTBYTES`, if given. You can use +- `outLength` must within the byte ranges defined by the constants below. +- `key` is optional, but must within the byte ranges defined by the constants + below, if given. This value must be kept secret, and can be used to create + prefix-MACs. +- `salt` is optional, but must be exactly `SALTBYTES`, if given. You can use this parameter as a kind of per user id, or local versioning scheme. This value is not required to be secret. -* `personal` is optional, but must be exactly `PERSONALBYTES`, if given. You can +- `personal` is optional, but must be exactly `PERSONALBYTES`, if given. You can use this parameter as a kind of app id, or global versioning scheme. This value is not required to be secret. @@ -63,14 +63,14 @@ to have the hash return a new Uint8Array with the hash. ### Constants -* `blake2b.BYTES_MIN` Minimum length of `out` -* `blake2b.BYTES_MAX` Maximum length of `out` -* `blake2b.BYTES` Recommended default length of `out` -* `blake2b.KEYBYTES_MIN` Minimum length of `key` -* `blake2b.KEYBYTES_MAX` Maximum length of `key` -* `blake2b.KEYBYTES` Recommended default length of `key` -* `blake2b.SALTBYTES` Required length of `salt` -* `blake2b.PERSONALBYTES` Required length of `personal` +- `blake2b.BYTES_MIN` Minimum length of `out` +- `blake2b.BYTES_MAX` Maximum length of `out` +- `blake2b.BYTES` Recommended default length of `out` +- `blake2b.KEYBYTES_MIN` Minimum length of `key` +- `blake2b.KEYBYTES_MAX` Maximum length of `key` +- `blake2b.KEYBYTES` Recommended default length of `key` +- `blake2b.SALTBYTES` Required length of `salt` +- `blake2b.PERSONALBYTES` Required length of `personal` ## Install @@ -84,9 +84,9 @@ This repository includes test vectors with `{outlen, out, input, key, salt, personal}` objects for testing conformance against the spec and other implementations: -* Lines [2 - 257](test-vectors.json#L2-L257) are tests for hashing with no key, taken from [BLAKE2 test vectors](https://github.com/BLAKE2/BLAKE2/blob/5cbb39c9ef8007f0b63723e3aea06cd0887e36ad/testvectors/blake2-kat.json) -* Lines [258 - 513](test-vectors.json#L258-L513) are tests for hashing with keys, taken from [BLAKE2 test vectors](https://github.com/BLAKE2/BLAKE2/blob/5cbb39c9ef8007f0b63723e3aea06cd0887e36ad/testvectors/blake2-kat.json) -* Lines [514- 577](test-vectors.json#L514-L577) are tests for hashing with key, salt and personalisation, derived from the [libsodium tests](https://github.com/jedisct1/libsodium/blob/3a9c4c38f7dbe671d91dcfa267c919734b4923df/test/default/generichash3.c) +- Lines [2 - 257](test-vectors.json#L2-L257) are tests for hashing with no key, taken from [BLAKE2 test vectors](https://github.com/BLAKE2/BLAKE2/blob/5cbb39c9ef8007f0b63723e3aea06cd0887e36ad/testvectors/blake2-kat.json) +- Lines [258 - 513](test-vectors.json#L258-L513) are tests for hashing with keys, taken from [BLAKE2 test vectors](https://github.com/BLAKE2/BLAKE2/blob/5cbb39c9ef8007f0b63723e3aea06cd0887e36ad/testvectors/blake2-kat.json) +- Lines [514- 577](test-vectors.json#L514-L577) are tests for hashing with key, salt and personalisation, derived from the [libsodium tests](https://github.com/jedisct1/libsodium/blob/3a9c4c38f7dbe671d91dcfa267c919734b4923df/test/default/generichash3.c) ## License diff --git a/modules/blake2b/example.js b/modules/blake2b/example.js index 1b769ea003..f84dfc9b7d 100644 --- a/modules/blake2b/example.js +++ b/modules/blake2b/example.js @@ -1,11 +1,11 @@ -var blake2b = require('./index.js') +var blake2b = require('./index.js'); -var output = new Uint8Array(32) -var input = Buffer.alloc(2048) +var output = new Uint8Array(32); +var input = Buffer.alloc(2048); -console.log('hash:', blake2b(output.length).update(input).digest('hex')) +console.log('hash:', blake2b(output.length).update(input).digest('hex')); blake2b.ready(function () { - console.log('has wasm?', blake2b.WASM_LOADED) - console.log('hash again:', blake2b(output.length).update(input).digest('hex')) -}) + console.log('has wasm?', blake2b.WASM_LOADED); + console.log('hash again:', blake2b(output.length).update(input).digest('hex')); +}); diff --git a/modules/blake2b/index.js b/modules/blake2b/index.js index b36482a03d..77103a0749 100644 --- a/modules/blake2b/index.js +++ b/modules/blake2b/index.js @@ -1,323 +1,370 @@ -var assert = require('nanoassert') -var b2wasm = require('@bitgo/blake2b-wasm') +var assert = require('nanoassert'); +var b2wasm = require('@bitgo/blake2b-wasm'); // 64-bit unsigned addition // Sets v[a,a+1] += v[b,b+1] // v should be a Uint32Array -function ADD64AA (v, a, b) { - var o0 = v[a] + v[b] - var o1 = v[a + 1] + v[b + 1] +function ADD64AA(v, a, b) { + var o0 = v[a] + v[b]; + var o1 = v[a + 1] + v[b + 1]; if (o0 >= 0x100000000) { - o1++ + o1++; } - v[a] = o0 - v[a + 1] = o1 + v[a] = o0; + v[a + 1] = o1; } // 64-bit unsigned addition // Sets v[a,a+1] += b // b0 is the low 32 bits of b, b1 represents the high 32 bits -function ADD64AC (v, a, b0, b1) { - var o0 = v[a] + b0 +function ADD64AC(v, a, b0, b1) { + var o0 = v[a] + b0; if (b0 < 0) { - o0 += 0x100000000 + o0 += 0x100000000; } - var o1 = v[a + 1] + b1 + var o1 = v[a + 1] + b1; if (o0 >= 0x100000000) { - o1++ + o1++; } - v[a] = o0 - v[a + 1] = o1 + v[a] = o0; + v[a + 1] = o1; } // Little-endian byte access -function B2B_GET32 (arr, i) { - return (arr[i] ^ - (arr[i + 1] << 8) ^ - (arr[i + 2] << 16) ^ - (arr[i + 3] << 24)) +function B2B_GET32(arr, i) { + return arr[i] ^ (arr[i + 1] << 8) ^ (arr[i + 2] << 16) ^ (arr[i + 3] << 24); } // G Mixing function // The ROTRs are inlined for speed -function B2B_G (a, b, c, d, ix, iy) { - var x0 = m[ix] - var x1 = m[ix + 1] - var y0 = m[iy] - var y1 = m[iy + 1] +function B2B_G(a, b, c, d, ix, iy) { + var x0 = m[ix]; + var x1 = m[ix + 1]; + var y0 = m[iy]; + var y1 = m[iy + 1]; - ADD64AA(v, a, b) // v[a,a+1] += v[b,b+1] ... in JS we must store a uint64 as two uint32s - ADD64AC(v, a, x0, x1) // v[a, a+1] += x ... x0 is the low 32 bits of x, x1 is the high 32 bits + ADD64AA(v, a, b); // v[a,a+1] += v[b,b+1] ... in JS we must store a uint64 as two uint32s + ADD64AC(v, a, x0, x1); // v[a, a+1] += x ... x0 is the low 32 bits of x, x1 is the high 32 bits // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated to the right by 32 bits - var xor0 = v[d] ^ v[a] - var xor1 = v[d + 1] ^ v[a + 1] - v[d] = xor1 - v[d + 1] = xor0 + var xor0 = v[d] ^ v[a]; + var xor1 = v[d + 1] ^ v[a + 1]; + v[d] = xor1; + v[d + 1] = xor0; - ADD64AA(v, c, d) + ADD64AA(v, c, d); // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 24 bits - xor0 = v[b] ^ v[c] - xor1 = v[b + 1] ^ v[c + 1] - v[b] = (xor0 >>> 24) ^ (xor1 << 8) - v[b + 1] = (xor1 >>> 24) ^ (xor0 << 8) + xor0 = v[b] ^ v[c]; + xor1 = v[b + 1] ^ v[c + 1]; + v[b] = (xor0 >>> 24) ^ (xor1 << 8); + v[b + 1] = (xor1 >>> 24) ^ (xor0 << 8); - ADD64AA(v, a, b) - ADD64AC(v, a, y0, y1) + ADD64AA(v, a, b); + ADD64AC(v, a, y0, y1); // v[d,d+1] = (v[d,d+1] xor v[a,a+1]) rotated right by 16 bits - xor0 = v[d] ^ v[a] - xor1 = v[d + 1] ^ v[a + 1] - v[d] = (xor0 >>> 16) ^ (xor1 << 16) - v[d + 1] = (xor1 >>> 16) ^ (xor0 << 16) + xor0 = v[d] ^ v[a]; + xor1 = v[d + 1] ^ v[a + 1]; + v[d] = (xor0 >>> 16) ^ (xor1 << 16); + v[d + 1] = (xor1 >>> 16) ^ (xor0 << 16); - ADD64AA(v, c, d) + ADD64AA(v, c, d); // v[b,b+1] = (v[b,b+1] xor v[c,c+1]) rotated right by 63 bits - xor0 = v[b] ^ v[c] - xor1 = v[b + 1] ^ v[c + 1] - v[b] = (xor1 >>> 31) ^ (xor0 << 1) - v[b + 1] = (xor0 >>> 31) ^ (xor1 << 1) + xor0 = v[b] ^ v[c]; + xor1 = v[b + 1] ^ v[c + 1]; + v[b] = (xor1 >>> 31) ^ (xor0 << 1); + v[b + 1] = (xor0 >>> 31) ^ (xor1 << 1); } // Initialization Vector var BLAKE2B_IV32 = new Uint32Array([ - 0xF3BCC908, 0x6A09E667, 0x84CAA73B, 0xBB67AE85, - 0xFE94F82B, 0x3C6EF372, 0x5F1D36F1, 0xA54FF53A, - 0xADE682D1, 0x510E527F, 0x2B3E6C1F, 0x9B05688C, - 0xFB41BD6B, 0x1F83D9AB, 0x137E2179, 0x5BE0CD19 -]) + 0xf3bcc908, 0x6a09e667, 0x84caa73b, 0xbb67ae85, 0xfe94f82b, 0x3c6ef372, 0x5f1d36f1, 0xa54ff53a, 0xade682d1, + 0x510e527f, 0x2b3e6c1f, 0x9b05688c, 0xfb41bd6b, 0x1f83d9ab, 0x137e2179, 0x5be0cd19, +]); var SIGMA8 = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, - 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, - 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, - 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13, - 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, - 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11, - 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, - 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5, - 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 -] + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, 11, 8, 12, + 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4, 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8, 9, 0, 5, 7, 2, 4, 10, + 15, 14, 1, 11, 12, 6, 8, 3, 13, 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9, 12, 5, 1, 15, 14, 13, 4, 10, 0, + 7, 6, 3, 9, 2, 8, 11, 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10, 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, + 1, 4, 10, 5, 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3, +]; // These are offsets into a uint64 buffer. // Multiply them all by 2 to make them offsets into a uint32 buffer, // because this is JavaScript and we don't have uint64s -var SIGMA82 = new Uint8Array(SIGMA8.map(function (x) { return x * 2 })) +var SIGMA82 = new Uint8Array( + SIGMA8.map(function (x) { + return x * 2; + }) +); // Compression function. 'last' flag indicates last block. // Note we're representing 16 uint64s as 32 uint32s -var v = new Uint32Array(32) -var m = new Uint32Array(32) -function blake2bCompress (ctx, last) { - var i = 0 +var v = new Uint32Array(32); +var m = new Uint32Array(32); +function blake2bCompress(ctx, last) { + var i = 0; // init work variables for (i = 0; i < 16; i++) { - v[i] = ctx.h[i] - v[i + 16] = BLAKE2B_IV32[i] + v[i] = ctx.h[i]; + v[i + 16] = BLAKE2B_IV32[i]; } // low 64 bits of offset - v[24] = v[24] ^ ctx.t - v[25] = v[25] ^ (ctx.t / 0x100000000) + v[24] = v[24] ^ ctx.t; + v[25] = v[25] ^ (ctx.t / 0x100000000); // high 64 bits not supported, offset may not be higher than 2**53-1 // last block flag set ? if (last) { - v[28] = ~v[28] - v[29] = ~v[29] + v[28] = ~v[28]; + v[29] = ~v[29]; } // get little-endian words for (i = 0; i < 32; i++) { - m[i] = B2B_GET32(ctx.b, 4 * i) + m[i] = B2B_GET32(ctx.b, 4 * i); } // twelve rounds of mixing for (i = 0; i < 12; i++) { - B2B_G(0, 8, 16, 24, SIGMA82[i * 16 + 0], SIGMA82[i * 16 + 1]) - B2B_G(2, 10, 18, 26, SIGMA82[i * 16 + 2], SIGMA82[i * 16 + 3]) - B2B_G(4, 12, 20, 28, SIGMA82[i * 16 + 4], SIGMA82[i * 16 + 5]) - B2B_G(6, 14, 22, 30, SIGMA82[i * 16 + 6], SIGMA82[i * 16 + 7]) - B2B_G(0, 10, 20, 30, SIGMA82[i * 16 + 8], SIGMA82[i * 16 + 9]) - B2B_G(2, 12, 22, 24, SIGMA82[i * 16 + 10], SIGMA82[i * 16 + 11]) - B2B_G(4, 14, 16, 26, SIGMA82[i * 16 + 12], SIGMA82[i * 16 + 13]) - B2B_G(6, 8, 18, 28, SIGMA82[i * 16 + 14], SIGMA82[i * 16 + 15]) + B2B_G(0, 8, 16, 24, SIGMA82[i * 16 + 0], SIGMA82[i * 16 + 1]); + B2B_G(2, 10, 18, 26, SIGMA82[i * 16 + 2], SIGMA82[i * 16 + 3]); + B2B_G(4, 12, 20, 28, SIGMA82[i * 16 + 4], SIGMA82[i * 16 + 5]); + B2B_G(6, 14, 22, 30, SIGMA82[i * 16 + 6], SIGMA82[i * 16 + 7]); + B2B_G(0, 10, 20, 30, SIGMA82[i * 16 + 8], SIGMA82[i * 16 + 9]); + B2B_G(2, 12, 22, 24, SIGMA82[i * 16 + 10], SIGMA82[i * 16 + 11]); + B2B_G(4, 14, 16, 26, SIGMA82[i * 16 + 12], SIGMA82[i * 16 + 13]); + B2B_G(6, 8, 18, 28, SIGMA82[i * 16 + 14], SIGMA82[i * 16 + 15]); } for (i = 0; i < 16; i++) { - ctx.h[i] = ctx.h[i] ^ v[i] ^ v[i + 16] + ctx.h[i] = ctx.h[i] ^ v[i] ^ v[i + 16]; } } // reusable parameter_block var parameter_block = new Uint8Array([ - 0, 0, 0, 0, // 0: outlen, keylen, fanout, depth - 0, 0, 0, 0, // 4: leaf length, sequential mode - 0, 0, 0, 0, // 8: node offset - 0, 0, 0, 0, // 12: node offset - 0, 0, 0, 0, // 16: node depth, inner length, rfu - 0, 0, 0, 0, // 20: rfu - 0, 0, 0, 0, // 24: rfu - 0, 0, 0, 0, // 28: rfu - 0, 0, 0, 0, // 32: salt - 0, 0, 0, 0, // 36: salt - 0, 0, 0, 0, // 40: salt - 0, 0, 0, 0, // 44: salt - 0, 0, 0, 0, // 48: personal - 0, 0, 0, 0, // 52: personal - 0, 0, 0, 0, // 56: personal - 0, 0, 0, 0 // 60: personal -]) + 0, + 0, + 0, + 0, // 0: outlen, keylen, fanout, depth + 0, + 0, + 0, + 0, // 4: leaf length, sequential mode + 0, + 0, + 0, + 0, // 8: node offset + 0, + 0, + 0, + 0, // 12: node offset + 0, + 0, + 0, + 0, // 16: node depth, inner length, rfu + 0, + 0, + 0, + 0, // 20: rfu + 0, + 0, + 0, + 0, // 24: rfu + 0, + 0, + 0, + 0, // 28: rfu + 0, + 0, + 0, + 0, // 32: salt + 0, + 0, + 0, + 0, // 36: salt + 0, + 0, + 0, + 0, // 40: salt + 0, + 0, + 0, + 0, // 44: salt + 0, + 0, + 0, + 0, // 48: personal + 0, + 0, + 0, + 0, // 52: personal + 0, + 0, + 0, + 0, // 56: personal + 0, + 0, + 0, + 0, // 60: personal +]); // Creates a BLAKE2b hashing context // Requires an output length between 1 and 64 bytes // Takes an optional Uint8Array key -function Blake2b (outlen, key, salt, personal) { +function Blake2b(outlen, key, salt, personal) { // zero out parameter_block before usage - parameter_block.fill(0) + parameter_block.fill(0); // state, 'param block' - this.b = new Uint8Array(128) - this.h = new Uint32Array(16) - this.t = 0 // input count - this.c = 0 // pointer within buffer - this.outlen = outlen // output length in bytes + this.b = new Uint8Array(128); + this.h = new Uint32Array(16); + this.t = 0; // input count + this.c = 0; // pointer within buffer + this.outlen = outlen; // output length in bytes - parameter_block[0] = outlen - if (key) parameter_block[1] = key.length - parameter_block[2] = 1 // fanout - parameter_block[3] = 1 // depth + parameter_block[0] = outlen; + if (key) parameter_block[1] = key.length; + parameter_block[2] = 1; // fanout + parameter_block[3] = 1; // depth - if (salt) parameter_block.set(salt, 32) - if (personal) parameter_block.set(personal, 48) + if (salt) parameter_block.set(salt, 32); + if (personal) parameter_block.set(personal, 48); // initialize hash state for (var i = 0; i < 16; i++) { - this.h[i] = BLAKE2B_IV32[i] ^ B2B_GET32(parameter_block, i * 4) + this.h[i] = BLAKE2B_IV32[i] ^ B2B_GET32(parameter_block, i * 4); } // key the hash, if applicable if (key) { - blake2bUpdate(this, key) + blake2bUpdate(this, key); // at the end - this.c = 128 + this.c = 128; } } Blake2b.prototype.update = function (input) { - assert(input instanceof Uint8Array, 'input must be Uint8Array or Buffer') - blake2bUpdate(this, input) - return this -} + assert(input instanceof Uint8Array, 'input must be Uint8Array or Buffer'); + blake2bUpdate(this, input); + return this; +}; Blake2b.prototype.digest = function (out) { - var buf = (!out || out === 'binary' || out === 'hex') ? new Uint8Array(this.outlen) : out - assert(buf instanceof Uint8Array, 'out must be "binary", "hex", Uint8Array, or Buffer') - assert(buf.length >= this.outlen, 'out must have at least outlen bytes of space') - blake2bFinal(this, buf) - if (out === 'hex') return hexSlice(buf) - return buf -} + var buf = !out || out === 'binary' || out === 'hex' ? new Uint8Array(this.outlen) : out; + assert(buf instanceof Uint8Array, 'out must be "binary", "hex", Uint8Array, or Buffer'); + assert(buf.length >= this.outlen, 'out must have at least outlen bytes of space'); + blake2bFinal(this, buf); + if (out === 'hex') return hexSlice(buf); + return buf; +}; -Blake2b.prototype.final = Blake2b.prototype.digest +Blake2b.prototype.final = Blake2b.prototype.digest; Blake2b.ready = function (cb) { b2wasm.ready(function () { - cb() // ignore the error - }) -} + cb(); // ignore the error + }); +}; // Updates a BLAKE2b streaming hash // Requires hash context and Uint8Array (byte array) -function blake2bUpdate (ctx, input) { +function blake2bUpdate(ctx, input) { for (var i = 0; i < input.length; i++) { - if (ctx.c === 128) { // buffer full ? - ctx.t += ctx.c // add counters - blake2bCompress(ctx, false) // compress (not last) - ctx.c = 0 // counter to zero + if (ctx.c === 128) { + // buffer full ? + ctx.t += ctx.c; // add counters + blake2bCompress(ctx, false); // compress (not last) + ctx.c = 0; // counter to zero } - ctx.b[ctx.c++] = input[i] + ctx.b[ctx.c++] = input[i]; } } // Completes a BLAKE2b streaming hash // Returns a Uint8Array containing the message digest -function blake2bFinal (ctx, out) { - ctx.t += ctx.c // mark last block offset +function blake2bFinal(ctx, out) { + ctx.t += ctx.c; // mark last block offset - while (ctx.c < 128) { // fill up with zeros - ctx.b[ctx.c++] = 0 + while (ctx.c < 128) { + // fill up with zeros + ctx.b[ctx.c++] = 0; } - blake2bCompress(ctx, true) // final block flag = 1 + blake2bCompress(ctx, true); // final block flag = 1 for (var i = 0; i < ctx.outlen; i++) { - out[i] = ctx.h[i >> 2] >> (8 * (i & 3)) + out[i] = ctx.h[i >> 2] >> (8 * (i & 3)); } - return out + return out; } -function hexSlice (buf) { - var str = '' - for (var i = 0; i < buf.length; i++) str += toHex(buf[i]) - return str +function hexSlice(buf) { + var str = ''; + for (var i = 0; i < buf.length; i++) str += toHex(buf[i]); + return str; } -function toHex (n) { - if (n < 16) return '0' + n.toString(16) - return n.toString(16) +function toHex(n) { + if (n < 16) return '0' + n.toString(16); + return n.toString(16); } -var Proto = Blake2b +var Proto = Blake2b; -module.exports = function createHash (outlen, key, salt, personal, noAssert) { +module.exports = function createHash(outlen, key, salt, personal, noAssert) { if (noAssert !== true) { - assert(outlen >= BYTES_MIN, 'outlen must be at least ' + BYTES_MIN + ', was given ' + outlen) - assert(outlen <= BYTES_MAX, 'outlen must be at most ' + BYTES_MAX + ', was given ' + outlen) + assert(outlen >= BYTES_MIN, 'outlen must be at least ' + BYTES_MIN + ', was given ' + outlen); + assert(outlen <= BYTES_MAX, 'outlen must be at most ' + BYTES_MAX + ', was given ' + outlen); if (key != null) { - assert(key instanceof Uint8Array, 'key must be Uint8Array or Buffer') - assert(key.length >= KEYBYTES_MIN, 'key must be at least ' + KEYBYTES_MIN + ', was given ' + key.length) - assert(key.length <= KEYBYTES_MAX, 'key must be at most ' + KEYBYTES_MAX + ', was given ' + key.length) + assert(key instanceof Uint8Array, 'key must be Uint8Array or Buffer'); + assert(key.length >= KEYBYTES_MIN, 'key must be at least ' + KEYBYTES_MIN + ', was given ' + key.length); + assert(key.length <= KEYBYTES_MAX, 'key must be at most ' + KEYBYTES_MAX + ', was given ' + key.length); } if (salt != null) { - assert(salt instanceof Uint8Array, 'salt must be Uint8Array or Buffer') - assert(salt.length === SALTBYTES, 'salt must be exactly ' + SALTBYTES + ', was given ' + salt.length) + assert(salt instanceof Uint8Array, 'salt must be Uint8Array or Buffer'); + assert(salt.length === SALTBYTES, 'salt must be exactly ' + SALTBYTES + ', was given ' + salt.length); } if (personal != null) { - assert(personal instanceof Uint8Array, 'personal must be Uint8Array or Buffer') - assert(personal.length === PERSONALBYTES, 'personal must be exactly ' + PERSONALBYTES + ', was given ' + personal.length) + assert(personal instanceof Uint8Array, 'personal must be Uint8Array or Buffer'); + assert( + personal.length === PERSONALBYTES, + 'personal must be exactly ' + PERSONALBYTES + ', was given ' + personal.length + ); } } - return new Proto(outlen, key, salt, personal) -} + return new Proto(outlen, key, salt, personal); +}; module.exports.ready = function (cb) { - b2wasm.ready(function () { // ignore errors - cb() - }) -} - -module.exports.WASM_SUPPORTED = b2wasm.SUPPORTED -module.exports.WASM_LOADED = false - -var BYTES_MIN = module.exports.BYTES_MIN = 16 -var BYTES_MAX = module.exports.BYTES_MAX = 64 -var BYTES = module.exports.BYTES = 32 -var KEYBYTES_MIN = module.exports.KEYBYTES_MIN = 16 -var KEYBYTES_MAX = module.exports.KEYBYTES_MAX = 64 -var KEYBYTES = module.exports.KEYBYTES = 32 -var SALTBYTES = module.exports.SALTBYTES = 16 -var PERSONALBYTES = module.exports.PERSONALBYTES = 16 + b2wasm.ready(function () { + // ignore errors + cb(); + }); +}; + +module.exports.WASM_SUPPORTED = b2wasm.SUPPORTED; +module.exports.WASM_LOADED = false; + +var BYTES_MIN = (module.exports.BYTES_MIN = 16); +var BYTES_MAX = (module.exports.BYTES_MAX = 64); +var BYTES = (module.exports.BYTES = 32); +var KEYBYTES_MIN = (module.exports.KEYBYTES_MIN = 16); +var KEYBYTES_MAX = (module.exports.KEYBYTES_MAX = 64); +var KEYBYTES = (module.exports.KEYBYTES = 32); +var SALTBYTES = (module.exports.SALTBYTES = 16); +var PERSONALBYTES = (module.exports.PERSONALBYTES = 16); b2wasm.ready(function (err) { if (!err) { - module.exports.WASM_LOADED = true - module.exports = b2wasm + module.exports.WASM_LOADED = true; + module.exports = b2wasm; } -}) +}); diff --git a/modules/blake2b/test.js b/modules/blake2b/test.js index 210f1be34c..900c3e34d8 100644 --- a/modules/blake2b/test.js +++ b/modules/blake2b/test.js @@ -10,7 +10,7 @@ test('wait for ready', function (assert) { }); setup(); -function setup () { +function setup() { test('vectors', function (assert) { for (let i = 0; i < vectors.length; i++) { const v = vectors[i]; @@ -69,7 +69,11 @@ function setup () { const out = Buffer.alloc(blake2b.BYTES); instance.digest(out); - t.same(out.toString('hex'), '405f14acbeeb30396b8030f78e6a84bab0acf08cb1376aa200a500f669f675dc', 'streaming keyed hash'); + t.same( + out.toString('hex'), + '405f14acbeeb30396b8030f78e6a84bab0acf08cb1376aa200a500f669f675dc', + 'streaming keyed hash' + ); t.end(); }); @@ -103,7 +107,7 @@ function setup () { }); } -function hexWrite (buf, string) { +function hexWrite(buf, string) { // must be an even number of digits const strLen = string.length; if (strLen % 2 !== 0) throw new TypeError('Invalid hex string'); diff --git a/modules/blockapis/.mocharc.js b/modules/blockapis/.mocharc.js index e655e52974..8feb26dc6a 100644 --- a/modules/blockapis/.mocharc.js +++ b/modules/blockapis/.mocharc.js @@ -1,4 +1,4 @@ module.exports = { require: 'ts-node/register', - spec: ['test/**/*.ts'] -} + spec: ['test/**/*.ts'], +}; diff --git a/modules/bls-dkg/.mocharc.js b/modules/bls-dkg/.mocharc.js index 6c09cb83e6..b2c45ba9d6 100644 --- a/modules/bls-dkg/.mocharc.js +++ b/modules/bls-dkg/.mocharc.js @@ -3,4 +3,4 @@ module.exports = { timeout: '20000', exit: true, -} +}; diff --git a/modules/bls-dkg/index.js b/modules/bls-dkg/index.js index 6e611c4156..b37eb2cd95 100644 --- a/modules/bls-dkg/index.js +++ b/modules/bls-dkg/index.js @@ -1,49 +1,51 @@ // Implementation of BLS + DKG. -'use strict' -const bls = require('noble-bls12-381') -const math = require('noble-bls12-381/math') +'use strict'; +const bls = require('noble-bls12-381'); +const math = require('noble-bls12-381/math'); const { createHmac } = require('crypto'); const chaincodeBase = 1n << 256n; /** Convert a string to a buffer. */ function stringToBuffer(string) { - const buffer = new Uint8Array(string.length) + const buffer = new Uint8Array(string.length); for (let i = 0; i < string.length; i++) { - buffer[i] = string.charCodeAt(i) + buffer[i] = string.charCodeAt(i); } - return buffer + return buffer; } /** Convert a buffer to a hex string. */ function bufferToHex(buf) { - return Array.from(buf).map(function(val) { - const hex = val.toString(16) - return '0'.slice(0, hex.length % 2) + hex - }).join('') + return Array.from(buf) + .map(function (val) { + const hex = val.toString(16); + return '0'.slice(0, hex.length % 2) + hex; + }) + .join(''); } /** Convert a hex string to a buffer. */ function hexToBuffer(hex) { if (hex.length % 2) { - hex = '0' + hex + hex = '0' + hex; } - const buf = new Uint8Array(hex.length >>> 1) + const buf = new Uint8Array(hex.length >>> 1); for (let i = 0; i < hex.length >>> 1; i++) { - const val = hex.slice(2 * i, 2 * i + 2) - buf[i] = parseInt(val, 16) + const val = hex.slice(2 * i, 2 * i + 2); + buf[i] = parseInt(val, 16); } - return buf + return buf; } /** Convert a buffer to a native BigInt. */ function bufferToBigInt(buf) { - return BigInt('0x' + bufferToHex(buf)) + return BigInt('0x' + bufferToHex(buf)); } /** Convert a native BigInt to a buffer. */ function bigIntToBuffer(bigint) { - return hexToBuffer(bigint.toString(16)) + return hexToBuffer(bigint.toString(16)); } function bigIntToBufferBE(bigint, bytes) { @@ -71,7 +73,8 @@ function i2osp(value, length) { /** Get the indices from a sub key path string */ function getSubKeyPathIndices(path) { - return path.replace(/^m\//, '') + return path + .replace(/^m\//, '') .split('/') .map((index) => parseInt(index, 10)); } @@ -126,65 +129,65 @@ function privateDerive(sk, pk, chaincode, path) { /** Return a random field element as a native BigInt. */ function randomFieldElement() { - const buf = new Uint8Array(32) - if (typeof(crypto) !== 'undefined' && crypto.getRandomValues) { - crypto.getRandomValues(buf) + const buf = new Uint8Array(32); + if (typeof crypto !== 'undefined' && crypto.getRandomValues) { + crypto.getRandomValues(buf); } else { for (let i = 0; i < buf.length; i++) { - buf[i] = Math.floor(Math.random() * 256) + buf[i] = Math.floor(Math.random() * 256); } } - return new math.Fr(bufferToBigInt(buf)).value + return new math.Fr(bufferToBigInt(buf)).value; } /** Generate a polynomial of order m. */ function generatePolynomial(m) { - const poly = Array(m) + const poly = Array(m); for (let i = 0; i < m; i++) { - poly[i] = randomFieldElement() + poly[i] = randomFieldElement(); while (i == m - 1 && poly[i].value === 0n) { - poly[i] = randomFieldElement() + poly[i] = randomFieldElement(); } } - return poly + return poly; } /** Get the value of a point in the polynomial. */ function polynomialValue(poly, point) { - let value = new math.Fr(0n) - let pow = 1n + let value = new math.Fr(0n); + let pow = 1n; for (let i = 0; i < poly.length; i++) { - value = value.add(new math.Fr(poly[i]).multiply(pow)) - pow *= point + value = value.add(new math.Fr(poly[i]).multiply(pow)); + pow *= point; } - return value.value + return value.value; } /** Generate secret shares for n participants. */ function secretShares(poly, n) { - const shares = Array(n) + const shares = Array(n); for (let i = 0n; i < n; i++) { - shares[i] = polynomialValue(poly, i + 1n) + shares[i] = polynomialValue(poly, i + 1n); } - return shares + return shares; } /** Generate a participant's public share. */ function publicShare(poly) { - return bufferToBigInt(bls.PointG1.BASE.multiply(poly[0]).toCompressedHex()) + return bufferToBigInt(bls.PointG1.BASE.multiply(poly[0]).toCompressedHex()); } /** Merge secret shares to produce a signing key. */ function mergeSecretShares(shares) { - return shares.reduce((sum, share) => new math.Fr(sum + share).value, 0n) + return shares.reduce((sum, share) => new math.Fr(sum + share).value, 0n); } /** Merge public shares to produce a common public key. */ function mergePublicShares(shares) { const sum = shares.slice(1).reduce((sum, share) => { - return sum.add(bls.PointG1.fromCompressedHex(bigIntToBuffer(share))) - }, bls.PointG1.fromCompressedHex(bigIntToBuffer(shares[0]))) - return bufferToBigInt(sum.toCompressedHex()) + return sum.add(bls.PointG1.fromCompressedHex(bigIntToBuffer(share))); + }, bls.PointG1.fromCompressedHex(bigIntToBuffer(shares[0]))); + return bufferToBigInt(sum.toCompressedHex()); } function mergeChaincodes(chaincodes) { @@ -193,51 +196,51 @@ function mergeChaincodes(chaincodes) { /** Compute Lagrange coefficients for a point in a polynomial. */ function lagrangeCoefficients(idx) { - const res = Array(idx.length) - const w = idx.reduce((w, id) => w * id, 1n) + const res = Array(idx.length); + const w = idx.reduce((w, id) => w * id, 1n); for (let i = 0; i < idx.length; i++) { - let v = idx[i] + let v = idx[i]; for (let j = 0; j < idx.length; j++) { if (j != i) { - v *= idx[j] - idx[i] + v *= idx[j] - idx[i]; } } - res[i] = new math.Fr(v).invert().multiply(w).value + res[i] = new math.Fr(v).invert().multiply(w).value; } - return res + return res; } /** Compute a shared signature from shares. */ function mergeSignatures(shares) { - const ids = Object.keys(shares) - const coeffs = lagrangeCoefficients(ids.map(id => BigInt(id))) - let sign = bls.PointG2.ZERO + const ids = Object.keys(shares); + const coeffs = lagrangeCoefficients(ids.map((id) => BigInt(id))); + let sign = bls.PointG2.ZERO; for (let i = 0; i < ids.length; i++) { - sign = sign.add(bls.PointG2.fromSignature(bigIntToBuffer(shares[ids[i]])).multiply(coeffs[i])) + sign = sign.add(bls.PointG2.fromSignature(bigIntToBuffer(shares[ids[i]])).multiply(coeffs[i])); } - return bufferToBigInt(sign.toSignature()) + return bufferToBigInt(sign.toSignature()); } /** Generic BLS sign function. Can be used with a secret key or a secret share. */ async function sign(message, key) { if (typeof message === 'string') { - message = stringToBuffer(message) + message = stringToBuffer(message); } - const hashPoint = await bls.PointG2.hashToCurve(message) - return bufferToBigInt(hashPoint.multiply(new math.Fq(key)).toSignature()) + const hashPoint = await bls.PointG2.hashToCurve(message); + return bufferToBigInt(hashPoint.multiply(new math.Fq(key)).toSignature()); } /** Generic BLS verify function. Can be used with a pubilc key or a public share. */ async function verify(sig, message, key) { - sig = bls.PointG2.fromSignature(bigIntToBuffer(sig)) + sig = bls.PointG2.fromSignature(bigIntToBuffer(sig)); if (typeof message === 'string') { - message = stringToBuffer(message) + message = stringToBuffer(message); } - key = bls.PointG1.fromCompressedHex(bigIntToBuffer(key)) - return await bls.verify(sig, message, key) + key = bls.PointG1.fromCompressedHex(bigIntToBuffer(key)); + return await bls.verify(sig, message, key); } -if (typeof(module) !== 'undefined') { +if (typeof module !== 'undefined') { module.exports = { generatePolynomial, secretShares, @@ -250,5 +253,5 @@ if (typeof(module) !== 'undefined') { verify, privateDerive, publicDerive, - } + }; } diff --git a/modules/bls-dkg/test/bls-dkg.js b/modules/bls-dkg/test/bls-dkg.js index 4b1bb8fe6f..cd5131a4d7 100644 --- a/modules/bls-dkg/test/bls-dkg.js +++ b/modules/bls-dkg/test/bls-dkg.js @@ -1,4 +1,4 @@ -'use strict' +'use strict'; const { randomBytes } = require('crypto'); const { generatePolynomial, @@ -14,8 +14,7 @@ const { mergeChaincodes, } = require('..'); -describe('bls-dkg', function() { - +describe('bls-dkg', function () { // Threshold. const m = 2; @@ -30,7 +29,7 @@ describe('bls-dkg', function() { let userPolynomial, userSecretShares, userPublicShare, userSubKey, userChaincode; - before('generates user polynomials and shares', function() { + before('generates user polynomials and shares', function () { userPolynomial = generatePolynomial(m); userChaincode = BigInt('0x' + randomBytes(32).toString('hex')); const userPk = publicShare(userPolynomial); @@ -41,7 +40,7 @@ describe('bls-dkg', function() { let backupPolynomial, backupSecretShares, backupPublicShare, backupChaincode; - before('generates backup polynomial and shares', function() { + before('generates backup polynomial and shares', function () { backupPolynomial = generatePolynomial(m); backupSecretShares = secretShares(backupPolynomial, n); backupPublicShare = publicShare(backupPolynomial); @@ -50,7 +49,7 @@ describe('bls-dkg', function() { let walletPolynomial, walletSecretShares, walletPublicShare, walletChaincode; - before('generates wallet polynomial and shares', function() { + before('generates wallet polynomial and shares', function () { walletPolynomial = generatePolynomial(m); walletSecretShares = secretShares(walletPolynomial, n); walletPublicShare = publicShare(walletPolynomial); @@ -59,83 +58,83 @@ describe('bls-dkg', function() { let commonPub; - before('combines shares into common public key', function() { + before('combines shares into common public key', function () { commonPub = mergePublicShares([userPublicShare, backupPublicShare, walletPublicShare]); }); let commonChaincode; - before('combines chaincodes into common chaincode', function() { + before('combines chaincodes into common chaincode', function () { commonChaincode = mergeChaincodes([userChaincode, backupChaincode, walletChaincode]); }); let userKey; - before('combines shares into user signing key', function() { + before('combines shares into user signing key', function () { userKey = mergeSecretShares([userSecretShares[0], backupSecretShares[0], walletSecretShares[0]]); }); let backupKey; - before('combines shares into backup signing key', function() { + before('combines shares into backup signing key', function () { backupKey = mergeSecretShares([userSecretShares[1], backupSecretShares[1], walletSecretShares[1]]); }); let walletKey; - before('combines shares into wallet signing key', function() { + before('combines shares into wallet signing key', function () { walletKey = mergeSecretShares([userSecretShares[2], backupSecretShares[2], walletSecretShares[2]]); }); let userSig; - before('user signs message', async function() { + before('user signs message', async function () { userSig = await sign(message, userKey); }); let backupSig; - before('backup signs message', async function() { + before('backup signs message', async function () { backupSig = await sign(message, backupKey); }); let walletSig; - before('wallet signs message', async function() { + before('wallet signs message', async function () { walletSig = await sign(message, walletKey); }); - it('verifies user-backup sig', async function() { + it('verifies user-backup sig', async function () { const userBackupSig = mergeSignatures({ 1: userSig, 2: backupSig, }); - if (!await verify(userBackupSig, message, commonPub)) { + if (!(await verify(userBackupSig, message, commonPub))) { throw new Error('Could not verify user + backup signature'); } }); - it('verifies user-wallet sig', async function() { + it('verifies user-wallet sig', async function () { const userWalletSig = mergeSignatures({ 1: userSig, 3: walletSig, }); - if (!await verify(userWalletSig, message, commonPub)) { + if (!(await verify(userWalletSig, message, commonPub))) { throw new Error('Could not verify user + wallet signature'); } }); - it('verifies backup-wallet sig', async function() { + it('verifies backup-wallet sig', async function () { const backupWalletSig = mergeSignatures({ 2: backupSig, 3: walletSig, }); - if (!await verify(backupWalletSig, message, commonPub)) { + if (!(await verify(backupWalletSig, message, commonPub))) { throw new Error('Could not verify backup + wallet signature'); } }); - it('verifies user-backup subkey sig with public derived', async function() { + it('verifies user-backup subkey sig with public derived', async function () { const userPublicShareDKG = publicShare(userPolynomial); const commonPub = mergePublicShares([userPublicShareDKG, backupPublicShare, walletPublicShare]); const derivedUserSk = privateDerive(userPolynomial[0], commonPub, commonChaincode, subKeyPath); @@ -155,7 +154,7 @@ describe('bls-dkg', function() { 2: backupSig, }); - if (!await verify(userBackupSig, message, derivedCommonPub1)) { + if (!(await verify(userBackupSig, message, derivedCommonPub1))) { throw new Error('Could not verify user + backup signature'); } }); diff --git a/modules/express/.mocharc.js b/modules/express/.mocharc.js index e94129b5fb..91bdb6ae9d 100644 --- a/modules/express/.mocharc.js +++ b/modules/express/.mocharc.js @@ -7,4 +7,4 @@ module.exports = { 'reporter-option': ['cdn=true', 'json=false', 'consoleReporter=spec'], exit: true, spec: ['test/unit/**/*.ts'], -} +}; diff --git a/modules/express/EXTERNAL_SIGNER.md b/modules/express/EXTERNAL_SIGNER.md index 9e8ab89421..0cc291ffde 100644 --- a/modules/express/EXTERNAL_SIGNER.md +++ b/modules/express/EXTERNAL_SIGNER.md @@ -1,15 +1,18 @@ # BitGo Express External Signing Mode -BitGo Express can be run in an external signing mode, where the signing of transactions is performed in a separate instance of BitGo Express that has access to the private keys. + +BitGo Express can be run in an external signing mode, where the signing of transactions is performed in a separate instance of BitGo Express that has access to the private keys. This may be preferable for users who would like to apply their signature to their transactions using a more secure environment than BitGo SDK or BitGo Express, such as a signer with restricted access or network connectivity. ![BitGo Express Signer Diagram](express_signer.png) ### External signer mode setup + To set up BitGo Express with an external signer, a url to the external signer instance of BitGo Express must be provided using the `externalSignerUrl` configuration option. The corresponding external signer instance of BitGo Express must have `signerMode` set, and `signerFileSystemPath` set to the path of a json containing the private key. Note that if BitGo Express encounters an `ECONNREFUSED` error when requesting the external signer for a signature, it will retry the request for up to 15 seconds. ### Encrypted private key format + The JSON file containing the unencrypted private key(s) must be in the format `"": ""`. Note that the `encryptedPrivateKey` must contain escape characters for the double quotations(`"`) in order for it to be parsed correctly. Here is an example json file containing two wallet IDs and their corresponding encrypted private keys with escape characters: @@ -20,14 +23,15 @@ Here is an example json file containing two wallet IDs and their corresponding e } ``` -To help with the creation of this JSON file, we have created a file that will fetch the encrypted private keys from BitGo and produce a JSON file with the correct format (including the addition of escape characters). +To help with the creation of this JSON file, we have created a file that will fetch the encrypted private keys from BitGo and produce a JSON file with the correct format (including the addition of escape characters). + +The file is located at `src/fetchEncryptedPrivKeys.ts`. Before using this tool, you will need to either: -The file is located at `src/fetchEncryptedPrivKeys.ts`. Before using this tool, you will need to either: 1. Fill in the `TODOs` by providing a valid `accessToken` as well as the list of `walletIds`, grouped by the cryptocurrency. 2. Using the same information as #1, update the .env file with the `accessToken` and `walletIds` information. | Name | Value | Description | -|------------------------------------|--------|------------------------------------------------| +| ---------------------------------- | ------ | ---------------------------------------------- | | BITGO_EXTERNAL_SIGNER_ENV | string | test | | BITGO_EXTERNAL_SIGNER_ACCESS_TOKEN | string | Access token used for access BitGo Wallets | | BITGO_EXTERNAL_SIGNER_WALLET_IDS | string | JSON formatted string of wallets and their ids | @@ -41,13 +45,14 @@ BITGO_EXTERNAL_SIGNER_WALLET_IDS={"tbtc":[{"walletId":"xxx","walletPassword":"xx Option #2 may make be more convenient for configuration instead of reconfiguring the file every time a new version is released both locally and to Docker. -An example is provided in the file. To run the file, use the command: +An example is provided in the file. To run the file, use the command: ```sh yarn ts-node ``` ### Wallet passphrase environment variable + In order for the external signer instance of BitGo Express to decrypt the private key, the wallet passphrase must be set as an environment variable in the format `WALLET__PASSPHRASE`. Note that the wallet passphrase must be set for each wallet. The environment variable can be set using `export`. For example, the wallet passphrases for the private keys above can be set with the following: @@ -57,14 +62,16 @@ export WALLET_61fb21819c54dd000755f8de3a18e46f_PASSPHRASE=wDX058%c4plL1@pP ``` ### External signer mode configuration values + BitGo Express is able to take configuration options from either command line arguments, or via environment variables. | Flag Short Name | Flag Long Name | Environment Variable | Default Value | Description | -|-----------------|------------------------|----------------------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------| +| --------------- | ---------------------- | -------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------- | | N/A | --externalSignerUrl | `BITGO_EXTERNAL_SIGNER_URL` | N/A | URL specifying the external API to call for remote signing. | | N/A | --signerMode | `BITGO_SIGNER_MODE ` | N/A | If set, run Express as a remote signer. | | N/A | --signerFileSystemPath | `BITGO_SIGNER_FILE_SYSTEM_PATH ` | N/A | Local path specifying where an Express signer machine keeps the encrypted user private keys. Required when signerMode is set. | -#### Example +#### Example + To start up an instance of BitGo Express that will use an external signer, start BitGo Express with `--externalSignerUrl=`. To start up an external signing instance of BitGo Express, which will have access to the encrypted private keys and wallet passphrases, start BitGo Express with `--signerMode --signerFileSystemPath=`. diff --git a/modules/express/README.md b/modules/express/README.md index 670bb0e206..555f62daed 100644 --- a/modules/express/README.md +++ b/modules/express/README.md @@ -18,11 +18,13 @@ For most users, we recommend running BitGo Express as a docker container, since > Deprecation Warning: bitgosdk/express will no longer receive updates. Please use the official bitgo/express images. To try it out, run this command: + ```bash $ docker run -it -p 3080:3080 bitgo/express:latest ``` You should see this output from the container: + ``` BitGo-Express running Environment: test @@ -30,17 +32,20 @@ Base URI: http://0.0.0.0:3080 ``` You can then send a ping request to BitGo Express using curl: + ```bash $ curl localhost:3080/api/v2/ping {"status":"service is ok!","environment":"BitGo Testnet","configEnv":"testnet","configVersion":79} ``` You can also give command line arguments to BitGo Express at the end of the docker run command: + ```bash -$ docker run -it -p 4000:4000 bitgo/express:latest --port 4000 +$ docker run -it -p 4000:4000 bitgo/express:latest --port 4000 ``` BitGo Express will start up on the specified port, 4000: + ``` BitGo-Express running Environment: test @@ -54,22 +59,28 @@ When running BitGo Express in production, we strongly recommended using HTTPS to If you have your own certificate, you can use it. Or, to generate a self-signed certificate, first make a directory and navigate into it: + ```bash $ mkdir certs $ cd certs ``` + Then do the following and fill out the information that it prompts you for: + ```bash $ openssl req -newkey rsa:2048 -nodes -keyout cert.key -x509 -days 3650 -out cert.crt ``` -This will output a key file ```cert.key``` and certificate file ```cert.crt``` -Finally you can run your docker container like this (note, replace ```/path/to``` with the full path to your ```certs``` folder): +This will output a key file `cert.key` and certificate file `cert.crt` + +Finally you can run your docker container like this (note, replace `/path/to` with the full path to your `certs` folder): + ```bash $ docker run -it --volume /path/to/certs:/private -p 4000:4000 bitgo/express:latest -p 4000 -k /private/cert.key -c /private/cert.crt -e prod ``` BitGo Express should start on the specified port, 4000: + ``` BitGo-Express running Environment: prod @@ -79,6 +90,7 @@ Base URI: https://0.0.0.0:4000 ### Building the docker container If you'd like to build the BitGo Express docker container yourself from the source code, first check out the latest **master** branch, then run `docker build` from the project root. Here's the commands: + ```bash $ git clone https://github.com/bitgo/bitgojs $ cd bitgojs @@ -87,6 +99,7 @@ $ docker run -it bitgo-express:latest ``` Another way to build the BitGo Express docker container if you have `yarn` installed: + ```bash $ git clone https://github.com/bitgo/bitgojs $ cd bitgojs @@ -123,6 +136,7 @@ $ yarn run start ``` You should see BitGo Express start up in the default test environment: + ``` BitGo-Express running Environment: test @@ -130,11 +144,13 @@ Base URI: http://localhost:3080 ``` You can also pass startup arguments to BitGo Express: + ``` $ yarn run start --port 4000 ``` BitGo Express will start up on the custom port: + ``` BitGo-Express running Environment: test @@ -145,7 +161,7 @@ Base URI: http://localhost:4000 When running BitGo Express against the BitGo production environment using real funds, you should make sure the `NODE_ENV` environment variable is set to `production`. This will turn off some debugging information which could leak information about the system which is running BitGo Express. If an unsafe configuration is detected, BitGo Express will emit a warning upon startup. In a future version of BitGo Express, this will turn into a hard error and BitGo Express will fail to start up. -Additionally, when running against the production env and listening on external interfaces, BitGo Express must be run with TLS enabled by setting the `keyPath` and `crtPath` configuration options, otherwise BitGo Express will error upon startup with the following message: +Additionally, when running against the production env and listening on external interfaces, BitGo Express must be run with TLS enabled by setting the `keyPath` and `crtPath` configuration options, otherwise BitGo Express will error upon startup with the following message: ``` Fatal error: Must enable TLS when running against prod and listening on external interfaces! @@ -166,14 +182,15 @@ docker run -e BITGO_USE_PROXY="socks://192.0.2.1:12000" -p 3080:3080 bitgo/expre BitGo Express currently supports the following proxy protocols: -* HTTP -* HTTPS -* SOCKSv4 -* SOCKSv5 -* PAC +- HTTP +- HTTPS +- SOCKSv4 +- SOCKSv5 +- PAC ### External Signing Mode -BitGo Express can be run in an external signing mode, where the signing of transactions is performed in a separate instance of BitGo Express that has access to the private keys. + +BitGo Express can be run in an external signing mode, where the signing of transactions is performed in a separate instance of BitGo Express that has access to the private keys. This may be preferable for users who would like to apply their signature to their transactions using a more secure environment than BitGo SDK or BitGo Express, such as a signer with restricted access or network connectivity. For more information please see our [External Signing Mode Documentation](EXTERNAL_SIGNER.md). @@ -182,44 +199,45 @@ For more information please see our [External Signing Mode Documentation](EXTERN BitGo Express is able to take configuration options from either command line arguments, or via environment variables. -| Flag Short Name | Flag Long Name | Environment Variable | Default Value | Description | -| --------------- | ---------------------- | ---------------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------- | -| -p | --port | `BITGO_PORT` | 3080 | Port which bitgo express should listen on. | -| -b | --bind | `BITGO_BIND` | localhost | Interface which bitgo express should listen on. To listen on all interfaces, this should be set to `0.0.0.0`. | -| -e | --env | `BITGO_ENV` | test | BitGo environment to interact with. | -| -t | --timeout | `BITGO_TIMEOUT` | 305000 | Number of milliseconds to wait before requests made by `bitgo-express` time out. -| -d | --debug | N/A, use `BITGO_DEBUG_NAMESPACE` instead | N/A | Enable debug output for bitgo-express. This is equivalent to passing `--debugnamespace bitgo:express`. | +| Flag Short Name | Flag Long Name | Environment Variable | Default Value | Description | +| --------------- | ---------------------- | ---------------------------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| -p | --port | `BITGO_PORT` | 3080 | Port which bitgo express should listen on. | +| -b | --bind | `BITGO_BIND` | localhost | Interface which bitgo express should listen on. To listen on all interfaces, this should be set to `0.0.0.0`. | +| -e | --env | `BITGO_ENV` | test | BitGo environment to interact with. | +| -t | --timeout | `BITGO_TIMEOUT` | 305000 | Number of milliseconds to wait before requests made by `bitgo-express` time out. | +| -d | --debug | N/A, use `BITGO_DEBUG_NAMESPACE` instead | N/A | Enable debug output for bitgo-express. This is equivalent to passing `--debugnamespace bitgo:express`. | | -D | --debugnamespace | `BITGO_DEBUG_NAMESPACE` | N/A | Enable debug output for a particular debug namespace. Multiple debug namespaces can be given as a comma separated list. See the [`bitgo` package README](https://github.com/BitGo/BitGoJS/blob/master/modules/bitgo/README.md#available-debug-namespaces) for a complete list of recognized options, in addition to those listed in the table below. | -| -k | --keypath | `BITGO_KEYPATH` | N/A | Path to SSL .key file (required if running against production environment). | -| -c | --crtpath | `BITGO_CRTPATH` | N/A | Path to SSL .crt file (required if running against production environment). | -| -u | --customrooturi | `BITGO_CUSTOM_ROOT_URI` | N/A | Force a custom BitGo URI. | -| -n | --custombitcoinnetwork | `BITGO_CUSTOM_BITCOIN_NETWORK` | N/A | Force a custom BitGo network | -| -l | --logfile | `BITGO_LOGFILE` | N/A | Filepath to write access logs. | -| N/A | --disablessl | `BITGO_DISABLE_SSL` 0 | N/A | Disable requiring SSL when accessing bitgo production environment. **USE AT YOUR OWN RISK, NOT RECOMMENDED**. | -| N/A | --disableproxy | `BITGO_DISABLE_PROXY` 0 | N/A | Disable proxying of routes not explicitly handled by bitgo-express | -| N/A | --disableenvcheck | `BITGO_DISABLE_ENV_CHECK` 0 | N/A | Disable checking for correct `NODE_ENV` environment variable when running against BitGo production environment. | -| -i | --ipc | `BITGO_IPC` | N/A | If set, bind to the given IPC (unix domain) socket. Binding to an IPC socket can be useful if the caller of bitgo-express resides on the same host as the bitgo-express instance itself, since the socket can be secured using normal file permissions and ownership semantics. Note: This is not supported on Windows platforms. | -| N/A | --authversion | `BITGO_AUTH_VERSION` | 2 | BitGo Authentication scheme version which should be used form making requests to the BitGo server. Please see the [BitGo API documentation](https://app.bitgo.com/docs) for more info on authentication scheme versions. | -| N/A | --externalSignerUrl | `BITGO_EXTERNAL_SIGNER_URL` | N/A | URL specifying the external API to call for remote signing. | -| N/A | --signerMode | `BITGO_SIGNER_MODE ` | N/A | If set, run Express as a remote signer. | -| N/A | --signerFileSystemPath | `BITGO_SIGNER_FILE_SYSTEM_PATH ` | N/A | Local path specifying where an Express signer machine keeps the encrypted user private keys. Required when signerMode is set. | +| -k | --keypath | `BITGO_KEYPATH` | N/A | Path to SSL .key file (required if running against production environment). | +| -c | --crtpath | `BITGO_CRTPATH` | N/A | Path to SSL .crt file (required if running against production environment). | +| -u | --customrooturi | `BITGO_CUSTOM_ROOT_URI` | N/A | Force a custom BitGo URI. | +| -n | --custombitcoinnetwork | `BITGO_CUSTOM_BITCOIN_NETWORK` | N/A | Force a custom BitGo network | +| -l | --logfile | `BITGO_LOGFILE` | N/A | Filepath to write access logs. | +| N/A | --disablessl | `BITGO_DISABLE_SSL` 0 | N/A | Disable requiring SSL when accessing bitgo production environment. **USE AT YOUR OWN RISK, NOT RECOMMENDED**. | +| N/A | --disableproxy | `BITGO_DISABLE_PROXY` 0 | N/A | Disable proxying of routes not explicitly handled by bitgo-express | +| N/A | --disableenvcheck | `BITGO_DISABLE_ENV_CHECK` 0 | N/A | Disable checking for correct `NODE_ENV` environment variable when running against BitGo production environment. | +| -i | --ipc | `BITGO_IPC` | N/A | If set, bind to the given IPC (unix domain) socket. Binding to an IPC socket can be useful if the caller of bitgo-express resides on the same host as the bitgo-express instance itself, since the socket can be secured using normal file permissions and ownership semantics. Note: This is not supported on Windows platforms. | +| N/A | --authversion | `BITGO_AUTH_VERSION` | 2 | BitGo Authentication scheme version which should be used form making requests to the BitGo server. Please see the [BitGo API documentation](https://app.bitgo.com/docs) for more info on authentication scheme versions. | +| N/A | --externalSignerUrl | `BITGO_EXTERNAL_SIGNER_URL` | N/A | URL specifying the external API to call for remote signing. | +| N/A | --signerMode | `BITGO_SIGNER_MODE ` | N/A | If set, run Express as a remote signer. | +| N/A | --signerFileSystemPath | `BITGO_SIGNER_FILE_SYSTEM_PATH ` | N/A | Local path specifying where an Express signer machine keeps the encrypted user private keys. Required when signerMode is set. | \[0]: BitGo will also check the additional environment variables for some options for backwards compatibility, but these environment variables should be considered deprecated: -* Disable SSL - * `DISABLESSL` - * `DISABLE_SSL` - * `BITGO_DISABLESSL` -* Disable Proxy - * `DISABLE_PROXY` -* Disable Environment Check - * `DISABLE_ENV_CHECK` - + +- Disable SSL + - `DISABLESSL` + - `DISABLE_SSL` + - `BITGO_DISABLESSL` +- Disable Proxy + - `DISABLE_PROXY` +- Disable Environment Check + - `DISABLE_ENV_CHECK` + ## Enabling Additional Debug Output In addition to the debug namespaces defined in the [`bitgo` package README](https://github.com/BitGo/BitGoJS/blob/master/modules/bitgo/README.md#available-debug-namespaces) there is a special BitGo Express specific debug namespaces which can be enabled: -| Namespace | Description | -| --- | --- | +| Namespace | Description | +| --------------- | ------------------------------------------------------------------ | | `bitgo:express` | Additional debug information specific to BitGo Express operations. | ### Example diff --git a/modules/express/src/args.ts b/modules/express/src/args.ts index afc3a9edc6..11d92e2d84 100644 --- a/modules/express/src/args.ts +++ b/modules/express/src/args.ts @@ -46,7 +46,7 @@ parser.addArgument(['-c', '--crtpath'], { help: 'Path to the SSL Crt file (required if running production)', }); -parser.addArgument( ['-u', '--customrooturi'], { +parser.addArgument(['-u', '--customrooturi'], { help: 'Force custom root BitGo URI (e.g. https://test.bitgo.com)', }); diff --git a/modules/express/src/config.ts b/modules/express/src/config.ts index 11584e66ec..b198627af7 100644 --- a/modules/express/src/config.ts +++ b/modules/express/src/config.ts @@ -11,7 +11,9 @@ function readEnvVar(name, ...deprecatedAliases): string | undefined { for (const deprecatedAlias of deprecatedAliases) { if (process.env[deprecatedAlias] !== undefined) { - console.warn(`warning: using deprecated environment variable '${deprecatedAlias}'. Please use the '${name}' environment variable instead.`); + console.warn( + `warning: using deprecated environment variable '${deprecatedAlias}'. Please use the '${name}' environment variable instead.` + ); return process.env[deprecatedAlias]; } } @@ -63,18 +65,17 @@ export const EnvConfig = (): Partial => ({ port: Number(readEnvVar('BITGO_PORT')), bind: readEnvVar('BITGO_BIND'), ipc: readEnvVar('BITGO_IPC'), - env: (readEnvVar('BITGO_ENV') as EnvironmentName), + env: readEnvVar('BITGO_ENV') as EnvironmentName, debugNamespace: (readEnvVar('BITGO_DEBUG_NAMESPACE') || '').split(','), keyPath: readEnvVar('BITGO_KEYPATH'), crtPath: readEnvVar('BITGO_CRTPATH'), logFile: readEnvVar('BITGO_LOGFILE'), - disableSSL: readEnvVar('BITGO_DISABLE_SSL', 'BITGO_DISABLESSL', 'DISABLESSL', 'DISABLE_SSL') ? - true : undefined, + disableSSL: readEnvVar('BITGO_DISABLE_SSL', 'BITGO_DISABLESSL', 'DISABLESSL', 'DISABLE_SSL') ? true : undefined, disableProxy: readEnvVar('BITGO_DISABLE_PROXY', 'DISABLE_PROXY') ? true : undefined, disableEnvCheck: readEnvVar('BITGO_DISABLE_ENV_CHECK', 'DISABLE_ENV_CHECK') ? true : undefined, timeout: Number(readEnvVar('BITGO_TIMEOUT')), customRootUri: readEnvVar('BITGO_CUSTOM_ROOT_URI'), - customBitcoinNetwork: (readEnvVar('BITGO_CUSTOM_BITCOIN_NETWORK') as V1Network), + customBitcoinNetwork: readEnvVar('BITGO_CUSTOM_BITCOIN_NETWORK') as V1Network, authVersion: Number(readEnvVar('BITGO_AUTH_VERSION')), externalSignerUrl: readEnvVar('BITGO_EXTERNAL_SIGNER_URL'), signerMode: readEnvVar('BITGO_SIGNER_MODE') ? true : undefined, @@ -123,8 +124,8 @@ function mergeConfigs(...configs: Partial[]): Config { // from each of the config sources in a type safe manner. function get(k: T): Config[T] { return configs.reduce( - (entry: Config[T], config) => !isNilOrNaN(config[k]) ? config[k] as Config[T] : entry, - DefaultConfig[k], + (entry: Config[T], config) => (!isNilOrNaN(config[k]) ? (config[k] as Config[T]) : entry), + DefaultConfig[k] ); } diff --git a/modules/express/src/fetchEncryptedPrivKeys.ts b/modules/express/src/fetchEncryptedPrivKeys.ts index 620cb5d386..2aa51a6223 100644 --- a/modules/express/src/fetchEncryptedPrivKeys.ts +++ b/modules/express/src/fetchEncryptedPrivKeys.ts @@ -12,18 +12,18 @@ import { BitGo, EnvironmentName } from 'bitgo'; import 'dotenv/config'; type Output = { - [key: string]: string -} + [key: string]: string; +}; type Credentials = { - walletId: string, // Id of the BitGo wallet. - walletPassword: string, // Password used for the wallet. - secret: string, // xprv of user key or backup key. -} + walletId: string; // Id of the BitGo wallet. + walletPassword: string; // Password used for the wallet. + secret: string; // xprv of user key or backup key. +}; type WalletIds = { - [key: string]: (string | Credentials)[] -} + [key: string]: (string | Credentials)[]; +}; const esAccessToken = process.env.BITGO_EXTERNAL_SIGNER_ACCESS_TOKEN; const esWalletIDs = process.env.BITGO_EXTERNAL_SIGNER_WALLET_IDS; // example: {"tbtc":[{"walletId":"xxx","walletPassword":"xxx","secret":"xxx"}]} diff --git a/modules/express/test/integration/bitgoExpressV1.ts b/modules/express/test/integration/bitgoExpressV1.ts index 94cff746db..9d6c2ac020 100644 --- a/modules/express/test/integration/bitgoExpressV1.ts +++ b/modules/express/test/integration/bitgoExpressV1.ts @@ -30,9 +30,9 @@ describe('Bitgo Express V1', function () { }); describe('proxied calls', function () { - it('error - not authed', function () { - return agent.get('/api/v1/wallet') + return agent + .get('/api/v1/wallet') .send() .then(function (res) { res.should.have.status(401); @@ -40,17 +40,20 @@ describe('Bitgo Express V1', function () { }); it('error - proxied calls disabled', function () { - const app = expressApp.app(_.extend( - {}, - { - debug: false, - env: 'test', - logfile: '/dev/null', - }, - { disableproxy: true }) + const app = expressApp.app( + _.extend( + {}, + { + debug: false, + env: 'test', + logfile: '/dev/null', + }, + { disableproxy: true } + ) ); const disabledProxyAgent = request.agent(app); - return disabledProxyAgent.get('/') + return disabledProxyAgent + .get('/') .send() .then(function (res) { res.should.have.status(404); @@ -58,7 +61,8 @@ describe('Bitgo Express V1', function () { }); it('market data', function () { - return agent.get('/api/v1/market/latest') + return agent + .get('/api/v1/market/latest') .send() .then(function (res) { res.should.have.status(200); @@ -74,7 +78,8 @@ describe('Bitgo Express V1', function () { }); it('get wallet list (authed)', function () { - return agent.get('/api/v1/wallet') + return agent + .get('/api/v1/wallet') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) .send() .then(function (res) { @@ -86,7 +91,8 @@ describe('Bitgo Express V1', function () { }); it('post unlock (authed)', function () { - return agent.post('/api/v1/user/unlock') + return agent + .post('/api/v1/user/unlock') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) .send({ otp: bitgo.testUserOTP(), duration: 3 }) .then(function (res) { @@ -98,7 +104,8 @@ describe('Bitgo Express V1', function () { it('put label set (authed)', function () { const walletId = '2MvfC3e6njdTXqWDfGvNUqDs5kwimfaTGjK'; - return agent.put('/api/v1/labels/' + walletId + '/msj42CCGruhRsFrGATiUuh25dtxYtnpbTx') + return agent + .put('/api/v1/labels/' + walletId + '/msj42CCGruhRsFrGATiUuh25dtxYtnpbTx') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) .send({ label: 'testLabel_bitgoExpressSDK' }) .then(function (res) { @@ -112,9 +119,9 @@ describe('Bitgo Express V1', function () { }); describe('handled calls', function () { - it('error - not authed', function () { - return agent.post('/api/v1/wallets/simplecreate') + return agent + .post('/api/v1/wallets/simplecreate') .send({ passphrase: 'abc', label: 'helloworld' }) .then(function (res) { res.should.have.status(401); @@ -122,7 +129,8 @@ describe('Bitgo Express V1', function () { }); it('new keychain', function () { - return agent.post('/api/v1/keychain/local') + return agent + .post('/api/v1/keychain/local') .send() .then(function (res) { res.should.have.status(200); @@ -132,7 +140,8 @@ describe('Bitgo Express V1', function () { }); it('derive BIP32 private keychain', function () { - return agent.post('/api/v1/keychain/derive') + return agent + .post('/api/v1/keychain/derive') .send({ path: 'm/1/2/3/4', xprv: 'xprv9s21ZrQH143K3o5A54b28GYVnDAa7gdPSxjWGz9ARzbxqYax8gbds5yGiU4D56GgSRwp7t9T8p54xh6MN19h8n6HJyR5FCkQopoUxC34EV3', @@ -141,14 +150,19 @@ describe('Bitgo Express V1', function () { res.should.have.status(200); res.body.should.have.property('xpub'); res.body.should.have.property('xprv'); - res.body.xprv.should.eql('xprvA1yY6N1A6aT3B9VUb2mhnLpNyPwAguPY3sibAXYXiEUVjT62TZNHTy13LhrdJ4BcGmt2hnRdgGQFLDowBqANkysSRw6KXri2MpGjkPAbGrS'); - res.body.xpub.should.eql('xpub6ExtVsY3vx1LPdZwh4Ji9Um7XRmf6N7PR6eBxux9Ga1UcFRB16gY1mKXBzVPcGZVpnDPYboEPYdPxfsrnq1Yec49RN4usyB5ba8NNtVbHeG'); + res.body.xprv.should.eql( + 'xprvA1yY6N1A6aT3B9VUb2mhnLpNyPwAguPY3sibAXYXiEUVjT62TZNHTy13LhrdJ4BcGmt2hnRdgGQFLDowBqANkysSRw6KXri2MpGjkPAbGrS' + ); + res.body.xpub.should.eql( + 'xpub6ExtVsY3vx1LPdZwh4Ji9Um7XRmf6N7PR6eBxux9Ga1UcFRB16gY1mKXBzVPcGZVpnDPYboEPYdPxfsrnq1Yec49RN4usyB5ba8NNtVbHeG' + ); res.body.path.should.eql('m/1/2/3/4'); }); }); it('derive BIP32 public keychain', function () { - return agent.post('/api/v1/keychain/derive') + return agent + .post('/api/v1/keychain/derive') .send({ path: 'm/3/4/5/6', xpub: 'xpub6ExtVsY3vx1LPdZwh4Ji9Um7XRmf6N7PR6eBxux9Ga1UcFRB16gY1mKXBzVPcGZVpnDPYboEPYdPxfsrnq1Yec49RN4usyB5ba8NNtVbHeG', @@ -157,14 +171,18 @@ describe('Bitgo Express V1', function () { res.should.have.status(200); res.body.should.have.property('xpub'); res.body.should.not.have.property('xprv'); - res.body.xpub.should.eql('xpub6N5Svn29v8op8f6VgHeM9FXvmpoFx7535qW4HKFHeM7HqJDD2dWQq92MKduYZjuWi4FWZQsGDtHwRtLpmCRWMxy3d3r77jcsxDpYNAGpbuY'); + res.body.xpub.should.eql( + 'xpub6N5Svn29v8op8f6VgHeM9FXvmpoFx7535qW4HKFHeM7HqJDD2dWQq92MKduYZjuWi4FWZQsGDtHwRtLpmCRWMxy3d3r77jcsxDpYNAGpbuY' + ); res.body.path.should.eql('m/3/4/5/6'); }); }); it('decrypt', function () { - const encryptedString = '{"iv":"n4zHXVTi/Go/riCP8fNs/A==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"zvLyve+4AJU=","ct":"gNMqheicMoD8ZmNzRwuQfWGAh+HA933l"}'; - return agent.post('/api/v1/decrypt') + const encryptedString = + '{"iv":"n4zHXVTi/Go/riCP8fNs/A==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"zvLyve+4AJU=","ct":"gNMqheicMoD8ZmNzRwuQfWGAh+HA933l"}'; + return agent + .post('/api/v1/decrypt') .send({ input: encryptedString, password: 'password' }) .then(function (res) { res.should.have.status(200); @@ -174,10 +192,13 @@ describe('Bitgo Express V1', function () { }); it('create wallet', function () { - const backupXpub = 'xpub6AHA9hZDN11k2ijHMeS5QqHx2KP9aMBRhTDqANMnwVtdyw2TDYRmF8PjpvwUFcL1Et8Hj59S3gTSMcUQ5gAqTz3Wd8EsMTmF3DChhqPQBnU'; - return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) + const backupXpub = + 'xpub6AHA9hZDN11k2ijHMeS5QqHx2KP9aMBRhTDqANMnwVtdyw2TDYRmF8PjpvwUFcL1Et8Hj59S3gTSMcUQ5gAqTz3Wd8EsMTmF3DChhqPQBnU'; + return testUtil + .unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) .then(function () { - return agent.post('/api/v1/wallets/simplecreate') + return agent + .post('/api/v1/wallets/simplecreate') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) .send({ passphrase: 'chamchatka', label: 'kokoko', backupXpub: backupXpub }); }) @@ -191,20 +212,20 @@ describe('Bitgo Express V1', function () { }); it('create transaction - wallet1 to wallet3', function () { - return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) + return testUtil + .unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) .then(function () { - return agent.post('/api/v1/wallet/' + TestBitGo.TEST_WALLET1_ADDRESS + '/createtransaction') + return agent + .post('/api/v1/wallet/' + TestBitGo.TEST_WALLET1_ADDRESS + '/createtransaction') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) - .send({ recipients: [{ address: TestBitGo.TEST_WALLET3_ADDRESS, amount: 2 * 1e8 }], walletPassphrase: TestBitGo.TEST_WALLET3_PASSCODE }); + .send({ + recipients: [{ address: TestBitGo.TEST_WALLET3_ADDRESS, amount: 2 * 1e8 }], + walletPassphrase: TestBitGo.TEST_WALLET3_PASSCODE, + }); }) .then(function (res) { res.status.should.eql(200); - const { - nP2shInputs = 0, - nP2shP2wshInputs = 0, - nP2pkhInputs, - nOutputs, - } = res.body.txInfo; + const { nP2shInputs = 0, nP2shP2wshInputs = 0, nP2pkhInputs, nOutputs } = res.body.txInfo; (nP2shInputs + nP2shP2wshInputs).should.be.greaterThan(0); nP2pkhInputs.should.eql(0); nOutputs.should.be.greaterThan(2); // change + bitgo fee + destination @@ -212,11 +233,17 @@ describe('Bitgo Express V1', function () { }); it('send coins - wallet1 to wallet3', function () { - return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) + return testUtil + .unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) .then(function () { - return agent.post('/api/v1/wallet/' + TestBitGo.TEST_WALLET1_ADDRESS + '/sendcoins') + return agent + .post('/api/v1/wallet/' + TestBitGo.TEST_WALLET1_ADDRESS + '/sendcoins') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) - .send({ address: TestBitGo.TEST_WALLET3_ADDRESS, amount: 0.002 * 1e8, walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE }); + .send({ + address: TestBitGo.TEST_WALLET3_ADDRESS, + amount: 0.002 * 1e8, + walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE, + }); }) .then(function (res) { res.status.should.equal(200); @@ -228,11 +255,16 @@ describe('Bitgo Express V1', function () { }); it('create transaction - wallet3 to wallet1 with insufficient amount', function () { - return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) + return testUtil + .unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) .then(function () { - return agent.post('/api/v1/wallet/' + TestBitGo.TEST_WALLET3_ADDRESS + '/createtransaction') + return agent + .post('/api/v1/wallet/' + TestBitGo.TEST_WALLET3_ADDRESS + '/createtransaction') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) - .send({ recipients: [{ address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 10000 * 1e8 }], walletPassphrase: TestBitGo.TEST_WALLET3_PASSCODE }); + .send({ + recipients: [{ address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 10000 * 1e8 }], + walletPassphrase: TestBitGo.TEST_WALLET3_PASSCODE, + }); }) .then(function (res) { res.status.should.eql(400); @@ -242,12 +274,7 @@ describe('Bitgo Express V1', function () { res.body.message.should.equal('Insufficient funds'); res.body.fee.should.be.greaterThan(546); res.body.available.should.be.greaterThan(546); - const { - nP2shInputs = 0, - nP2shP2wshInputs = 0, - nP2pkhInputs = 0, - nOutputs, - } = res.body.txInfo; + const { nP2shInputs = 0, nP2shP2wshInputs = 0, nP2pkhInputs = 0, nOutputs } = res.body.txInfo; (nP2shInputs + nP2shP2wshInputs).should.be.greaterThan(0); nP2pkhInputs.should.eql(0); nOutputs.should.be.greaterThan(2); // change + bitgo fee + destination @@ -255,11 +282,18 @@ describe('Bitgo Express V1', function () { }); it('send coins - wallet3 to wallet1 with insufficient amount', function () { - return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) + return testUtil + .unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) .then(function () { - return agent.post('/api/v1/wallet/' + TestBitGo.TEST_WALLET3_ADDRESS + '/sendcoins') + return agent + .post('/api/v1/wallet/' + TestBitGo.TEST_WALLET3_ADDRESS + '/sendcoins') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) - .send({ address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 10000 * 1e8, walletPassphrase: TestBitGo.TEST_WALLET3_PASSCODE, fee: 0.0003 * 1e8 }); + .send({ + address: TestBitGo.TEST_WALLET1_ADDRESS, + amount: 10000 * 1e8, + walletPassphrase: TestBitGo.TEST_WALLET3_PASSCODE, + fee: 0.0003 * 1e8, + }); }) .then(function (res) { res.status.should.equal(400); @@ -268,12 +302,7 @@ describe('Bitgo Express V1', function () { res.body.message.should.equal('Insufficient funds'); res.body.should.have.property('fee'); res.body.fee.should.equal(0.0003 * 1e8); - const { - nP2shInputs = 0, - nP2shP2wshInputs = 0, - nP2pkhInputs = 0, - nOutputs, - } = res.body.txInfo; + const { nP2shInputs = 0, nP2shP2wshInputs = 0, nP2pkhInputs = 0, nOutputs } = res.body.txInfo; (nP2shInputs + nP2shP2wshInputs).should.be.greaterThan(0); nP2pkhInputs.should.eql(0); nOutputs.should.be.greaterThan(2); // change + bitgo fee + destination @@ -281,11 +310,18 @@ describe('Bitgo Express V1', function () { }); it('send coins - wallet3 to wallet1 with fee', function () { - return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) + return testUtil + .unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) .then(function () { - return agent.post('/api/v1/wallet/' + TestBitGo.TEST_WALLET3_ADDRESS + '/sendcoins') + return agent + .post('/api/v1/wallet/' + TestBitGo.TEST_WALLET3_ADDRESS + '/sendcoins') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) - .send({ address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 0.001 * 1e8, walletPassphrase: TestBitGo.TEST_WALLET3_PASSCODE, fee: 0.0003 * 1e8 }); + .send({ + address: TestBitGo.TEST_WALLET1_ADDRESS, + amount: 0.001 * 1e8, + walletPassphrase: TestBitGo.TEST_WALLET3_PASSCODE, + fee: 0.0003 * 1e8, + }); }) .then(function (res) { res.status.should.equal(200); @@ -297,12 +333,14 @@ describe('Bitgo Express V1', function () { }); xit('create and reject a pending approval', function () { - return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) + return testUtil + .unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) .then(function () { return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER, 15); }) .then(function () { - return agent.post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins') + return agent + .post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) .send({ address: TestBitGo.TEST_WALLET1_ADDRESS, @@ -316,7 +354,8 @@ describe('Bitgo Express V1', function () { res.body.should.have.property('pendingApproval'); res.body.status.should.eql('pendingApproval'); const pendingApprovalId = res.body.pendingApproval; - return agent.put('/api/v1/pendingapprovals/' + pendingApprovalId + '/express') + return agent + .put('/api/v1/pendingapprovals/' + pendingApprovalId + '/express') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER) .send({ walletPassphrase: TestBitGo.TEST_PASSWORD, state: 'rejected' }); }) @@ -326,12 +365,14 @@ describe('Bitgo Express V1', function () { }); xit('create a transaction and then reconstruct a tx to approve (with original fee)', function () { - return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER, 15) + return testUtil + .unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER, 15) .then(function () { return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15); }) .then(function () { - return agent.post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins') + return agent + .post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) .send({ address: TestBitGo.TEST_WALLET1_ADDRESS, @@ -345,7 +386,8 @@ describe('Bitgo Express V1', function () { res.body.should.have.property('pendingApproval'); res.body.status.should.eql('pendingApproval'); const pendingApprovalId = res.body.pendingApproval; - return agent.put('/api/v1/pendingapprovals/' + pendingApprovalId + '/constructTx') + return agent + .put('/api/v1/pendingapprovals/' + pendingApprovalId + '/constructTx') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) .send({ walletPassphrase: TestBitGo.TEST_PASSWORD, useOriginalFee: true }); }) @@ -357,7 +399,8 @@ describe('Bitgo Express V1', function () { }); it('calculate tx size from parameters', function () { - return agent.post('/api/v1/calculateminerfeeinfo') + return agent + .post('/api/v1/calculateminerfeeinfo') .send({ feeRate: 20000, nP2shInputs: 2, @@ -373,21 +416,29 @@ describe('Bitgo Express V1', function () { }); xit('create and accept a pending approval', function () { - return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) + return testUtil + .unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) .then(function () { return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER, 15); }) .then(function () { - return agent.post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins') + return agent + .post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) - .send({ address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 0.001 * 1e8, walletPassphrase: TestBitGo.TEST_PASSWORD, otp: bitgo.testUserOTP() }); + .send({ + address: TestBitGo.TEST_WALLET1_ADDRESS, + amount: 0.001 * 1e8, + walletPassphrase: TestBitGo.TEST_PASSWORD, + otp: bitgo.testUserOTP(), + }); }) .then(function (res) { res.should.have.status(202); res.body.should.have.property('pendingApproval'); res.body.status.should.eql('pendingApproval'); const pendingApprovalId = res.body.pendingApproval; - return agent.put('/api/v1/pendingapprovals/' + pendingApprovalId + '/express') + return agent + .put('/api/v1/pendingapprovals/' + pendingApprovalId + '/express') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER) .send({ walletPassphrase: TestBitGo.TEST_PASSWORD, state: 'approved', otp: bitgo.testUserOTP() }); }) @@ -397,23 +448,32 @@ describe('Bitgo Express V1', function () { }); xit('create and accept a pending approval using the xprv', function () { - return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) + return testUtil + .unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) .then(function (res) { return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER, 15); }) .then(function (res) { - return agent.post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins') + return agent + .post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) - .send({ address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 0.001 * 1e8, walletPassphrase: TestBitGo.TEST_PASSWORD, otp: bitgo.testUserOTP() }); + .send({ + address: TestBitGo.TEST_WALLET1_ADDRESS, + amount: 0.001 * 1e8, + walletPassphrase: TestBitGo.TEST_PASSWORD, + otp: bitgo.testUserOTP(), + }); }) .then(function (res) { res.should.have.status(202); res.body.should.have.property('pendingApproval'); res.body.status.should.eql('pendingApproval'); const pendingApprovalId = res.body.pendingApproval; - return agent.put('/api/v1/pendingapprovals/' + pendingApprovalId + '/express') + return agent + .put('/api/v1/pendingapprovals/' + pendingApprovalId + '/express') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER) - .send({ xprv: 'xprv9s21ZrQH143K3GisDvcsLyQZ88CrgtHziPuQ4ZZU6x3v8AZxEYEBZ7ANwfAPVz9mqraSjREVaCdFgv1u7mHvjuDRZ25J4wGJ73yooYhDoJ4', + .send({ + xprv: 'xprv9s21ZrQH143K3GisDvcsLyQZ88CrgtHziPuQ4ZZU6x3v8AZxEYEBZ7ANwfAPVz9mqraSjREVaCdFgv1u7mHvjuDRZ25J4wGJ73yooYhDoJ4', state: 'approved', otp: bitgo.testUserOTP(), }); @@ -425,21 +485,30 @@ describe('Bitgo Express V1', function () { xit('create and accept a pending approval (2 step accept by constructing tx with original user)', function () { let pendingApprovalId; - return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) + return testUtil + .unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15) .then(function (res) { return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER, 15); }) .then(function (res) { - return agent.post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins') + return agent + .post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) - .send({ address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 0.001 * 1e8, walletPassphrase: TestBitGo.TEST_PASSWORD, fee: 12345, otp: bitgo.testUserOTP() }); + .send({ + address: TestBitGo.TEST_WALLET1_ADDRESS, + amount: 0.001 * 1e8, + walletPassphrase: TestBitGo.TEST_PASSWORD, + fee: 12345, + otp: bitgo.testUserOTP(), + }); }) .then(function (res) { res.should.have.status(202); res.body.should.have.property('pendingApproval'); res.body.status.should.eql('pendingApproval'); pendingApprovalId = res.body.pendingApproval; - return agent.put('/api/v1/pendingapprovals/' + pendingApprovalId + '/constructTx') + return agent + .put('/api/v1/pendingapprovals/' + pendingApprovalId + '/constructTx') .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN) .send({ walletPassphrase: TestBitGo.TEST_PASSWORD }); }) @@ -448,7 +517,8 @@ describe('Bitgo Express V1', function () { res.body.tx.should.not.eql(''); res.body.fee.should.not.eql(12345); // fee should be recalculated dynamically const txHex = res.body.tx; - return agent.put('/api/v1/pendingapprovals/' + pendingApprovalId) + return agent + .put('/api/v1/pendingapprovals/' + pendingApprovalId) .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER) .send({ tx: txHex, state: 'approved', otp: bitgo.testUserOTP() }); }) diff --git a/modules/express/test/integration/eth.ts b/modules/express/test/integration/eth.ts index e37565e95c..77f644bedb 100644 --- a/modules/express/test/integration/eth.ts +++ b/modules/express/test/integration/eth.ts @@ -24,155 +24,158 @@ describe('Express ETH', () => { Authorization: 'Bearer ' + TestV2BitGo.TEST_ACCESSTOKEN, }; - before(co(function *() { - const args = { - debug: false, - env: 'test', - logfile: '/dev/null', - }; - const bitgo = new TestV2BitGo(); - bitgo.initializeTestVars(); - const app = expressApp.app(args); - agent = request.agent(app); - yield bitgo.checkFunded(agent); - - // this should exist on the test env hand have some eth funding - testWalletId = TestV2BitGo.V2.TEST_ETH_WALLET_ID; - testWalletPassphrase = TestV2BitGo.V2.TEST_ETH_WALLET_PASSPHRASE; - - // this address belongs to the test wallet - testWalletFirstAddress = TestV2BitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS; - - yield testUtil.unlockToken(agent, TestV2BitGo.TEST_ACCESSTOKEN, 30); - })); - - it('can do sendcoins', co(function *() { - // fetch one new address - let res = yield agent - .get(`/api/v2/teth/wallet/${testWalletId}/addresses`) - .set(authHeader); - res.statusCode.should.equal(200); - const { addresses } = res.body; - const destAddress = addresses[1].address; - - res = yield agent - .post(`/api/v2/teth/wallet/${testWalletId}/sendcoins`) - .set(authHeader) - .send({ + before( + co(function* () { + const args = { + debug: false, + env: 'test', + logfile: '/dev/null', + }; + const bitgo = new TestV2BitGo(); + bitgo.initializeTestVars(); + const app = expressApp.app(args); + agent = request.agent(app); + yield bitgo.checkFunded(agent); + + // this should exist on the test env hand have some eth funding + testWalletId = TestV2BitGo.V2.TEST_ETH_WALLET_ID; + testWalletPassphrase = TestV2BitGo.V2.TEST_ETH_WALLET_PASSPHRASE; + + // this address belongs to the test wallet + testWalletFirstAddress = TestV2BitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS; + + yield testUtil.unlockToken(agent, TestV2BitGo.TEST_ACCESSTOKEN, 30); + }) + ); + + it( + 'can do sendcoins', + co(function* () { + // fetch one new address + let res = yield agent.get(`/api/v2/teth/wallet/${testWalletId}/addresses`).set(authHeader); + res.statusCode.should.equal(200); + const { addresses } = res.body; + const destAddress = addresses[1].address; + + res = yield agent.post(`/api/v2/teth/wallet/${testWalletId}/sendcoins`).set(authHeader).send({ walletPassphrase: testWalletPassphrase, address: destAddress, amount: '10000', }); - res.should.have.status(200); - })); - - - it('can do sendmany', co(function *() { - // fetch two new addresses - let res = yield agent - .get(`/api/v2/teth/wallet/${testWalletId}/addresses`) - .set(authHeader); - res.should.have.status(200); - const { addresses } = res.body; - const destAddress1 = addresses[1].address; - const destAddress2 = addresses[2].address; - - res = yield agent - .post(`/api/v2/teth/wallet/${testWalletId}/sendmany`) - .set(authHeader) - .send({ - walletPassphrase: testWalletPassphrase, - recipients: [ - { address: destAddress1, amount: '10000' }, - { address: destAddress2, amount: '20000' }, - ], - }); - - // Ethereum does not supports sendmany until Batching is enabled - res.should.have.status(400); - - // Sendmany with single recipient is fine - res = yield agent - .post(`/api/v2/teth/wallet/${testWalletId}/sendmany`) - .set(authHeader) - .send({ - walletPassphrase: testWalletPassphrase, - recipients: [ - { address: destAddress1, amount: '10000' }, - ], - }); - res.should.have.status(200); - })); - - it('can create new wallet and delete it', co(function *() { - const label = 'bitgoExpressEth.js temporary test wallet'; - let res = yield agent - .post('/api/v2/teth/wallet/generate') - .set(authHeader) - .send({ passphrase: testWalletPassphrase, label, enterprise: TestV2BitGo.TEST_ENTERPRISE }); - res.statusCode.should.equal(200); - - res = yield agent - .delete(`/api/v2/teth/wallet/${res.body.id}`) - .set(authHeader) - .send({ passphrase: testWalletPassphrase }); - res.statusCode.should.equal(200); - })); - - it('can list wallets', co(function *() { - const res = yield agent - .get('/api/v2/teth/wallet') - .set(authHeader); - res.statusCode.should.equal(200); - res.body.wallets.length.should.not.equal(0); - })); - - it('can fetch testWallet', co(function *() { - const res = yield agent - .get(`/api/v2/teth/wallet/${testWalletId}`) - .set(authHeader); - res.statusCode.should.equal(200); - res.body.id.should.equal(testWalletId); - - res.body.spendableBalanceString.length.should.be.greaterThan(1); - })); - - it('can list deposit addresses', co(function *() { - const res = yield agent - .get(`/api/v2/teth/wallet/${testWalletId}/addresses`) - .set(authHeader); - res.statusCode.should.equal(200); - res.body.addresses - .filter(({ address }) => address === testWalletFirstAddress).length - .should.equal(1); - })); - - it('can start or stop manual deployment and flushing of forwarder', co(function *() { - const deployForwardersManually = true; - // set to 'true' to start manual flushing and 'false' to stop manual flushing - const flushForwardersManually = true; - const payload = { - coinSpecific: { - teth: { - deployForwardersManually, - flushForwardersManually, + res.should.have.status(200); + }) + ); + + it( + 'can do sendmany', + co(function* () { + // fetch two new addresses + let res = yield agent.get(`/api/v2/teth/wallet/${testWalletId}/addresses`).set(authHeader); + res.should.have.status(200); + const { addresses } = res.body; + const destAddress1 = addresses[1].address; + const destAddress2 = addresses[2].address; + + res = yield agent + .post(`/api/v2/teth/wallet/${testWalletId}/sendmany`) + .set(authHeader) + .send({ + walletPassphrase: testWalletPassphrase, + recipients: [ + { address: destAddress1, amount: '10000' }, + { address: destAddress2, amount: '20000' }, + ], + }); + + // Ethereum does not supports sendmany until Batching is enabled + res.should.have.status(400); + + // Sendmany with single recipient is fine + res = yield agent + .post(`/api/v2/teth/wallet/${testWalletId}/sendmany`) + .set(authHeader) + .send({ + walletPassphrase: testWalletPassphrase, + recipients: [{ address: destAddress1, amount: '10000' }], + }); + res.should.have.status(200); + }) + ); + + it( + 'can create new wallet and delete it', + co(function* () { + const label = 'bitgoExpressEth.js temporary test wallet'; + let res = yield agent + .post('/api/v2/teth/wallet/generate') + .set(authHeader) + .send({ passphrase: testWalletPassphrase, label, enterprise: TestV2BitGo.TEST_ENTERPRISE }); + res.statusCode.should.equal(200); + + res = yield agent + .delete(`/api/v2/teth/wallet/${res.body.id}`) + .set(authHeader) + .send({ passphrase: testWalletPassphrase }); + res.statusCode.should.equal(200); + }) + ); + + it( + 'can list wallets', + co(function* () { + const res = yield agent.get('/api/v2/teth/wallet').set(authHeader); + res.statusCode.should.equal(200); + res.body.wallets.length.should.not.equal(0); + }) + ); + + it( + 'can fetch testWallet', + co(function* () { + const res = yield agent.get(`/api/v2/teth/wallet/${testWalletId}`).set(authHeader); + res.statusCode.should.equal(200); + res.body.id.should.equal(testWalletId); + + res.body.spendableBalanceString.length.should.be.greaterThan(1); + }) + ); + + it( + 'can list deposit addresses', + co(function* () { + const res = yield agent.get(`/api/v2/teth/wallet/${testWalletId}/addresses`).set(authHeader); + res.statusCode.should.equal(200); + res.body.addresses.filter(({ address }) => address === testWalletFirstAddress).length.should.equal(1); + }) + ); + + it( + 'can start or stop manual deployment and flushing of forwarder', + co(function* () { + const deployForwardersManually = true; + // set to 'true' to start manual flushing and 'false' to stop manual flushing + const flushForwardersManually = true; + const payload = { + coinSpecific: { + teth: { + deployForwardersManually, + flushForwardersManually, + }, }, - }, - }; - - const res = yield agent - .post(`/api/v2/teth/wallet/${testWalletId}`) - .set(authHeader) - .send(payload); - res.should.have.status(200); - res.body.coinSpecific.deployForwardersManually.should.equal(deployForwardersManually); - res.body.coinSpecific.flushForwardersManually.should.equal(flushForwardersManually); - })); - - it('can create new address', co(function *() { - const res = yield agent - .post(`/api/v2/teth/wallet/${testWalletId}/address`) - .set(authHeader); - res.statusCode.should.equal(200); - })); + }; + + const res = yield agent.post(`/api/v2/teth/wallet/${testWalletId}`).set(authHeader).send(payload); + res.should.have.status(200); + res.body.coinSpecific.deployForwardersManually.should.equal(deployForwardersManually); + res.body.coinSpecific.flushForwardersManually.should.equal(flushForwardersManually); + }) + ); + + it( + 'can create new address', + co(function* () { + const res = yield agent.post(`/api/v2/teth/wallet/${testWalletId}/address`).set(authHeader); + res.statusCode.should.equal(200); + }) + ); }); diff --git a/modules/express/test/lib/asserts.ts b/modules/express/test/lib/asserts.ts index 26dc164615..2d46d380da 100644 --- a/modules/express/test/lib/asserts.ts +++ b/modules/express/test/lib/asserts.ts @@ -13,4 +13,3 @@ Assertion.add('calledOnceWith', function (...args) { // @ts-expect-error - no implicit this this.obj.should.have.been.calledWith(...args); }); - diff --git a/modules/express/test/lib/test_bitgo.ts b/modules/express/test/lib/test_bitgo.ts index 39e0bf9941..21f5238cdb 100644 --- a/modules/express/test/lib/test_bitgo.ts +++ b/modules/express/test/lib/test_bitgo.ts @@ -75,15 +75,16 @@ BitGo.TRAVEL_RULE_TXID = '33447753455651508cfd099c9ebe0db6a2243ccba4766319621fbc BitGo.TEST_WALLET_REGROUP_PASSCODE = 'test security fanout & coalesce'; BitGo.prototype.initializeTestVars = function () { - if (this.getEnv() === 'dev' || this.getEnv() === 'local') { BitGo.TEST_USERID = '54d3e3a4b08fa6dc0a0002c07f8a9f86'; BitGo.TEST_SHARED_KEY_USERID = '54d418de4ea11d050b0006186d08ea5c'; BitGo.TEST_THIRD_USERID = '57056ad593eae8ca0c51e3cee62022cb'; - BitGo.TEST_USER_ECDH_XPUB = 'xpub661MyMwAqRbcF31yYvTH5DbmabEMXVvx1o1p73sZmvEDHM8bhUiZzNQA4gfyDtKarpGz7NPH6Wub8YCqXnUbP8ZMA3Ad8LfwHsBWhWEeJqu'; + BitGo.TEST_USER_ECDH_XPUB = + 'xpub661MyMwAqRbcF31yYvTH5DbmabEMXVvx1o1p73sZmvEDHM8bhUiZzNQA4gfyDtKarpGz7NPH6Wub8YCqXnUbP8ZMA3Ad8LfwHsBWhWEeJqu'; BitGo.TEST_WALLET1_PASSCODE = 'iVWeATjqLS1jJShrPpETti0b'; - BitGo.TEST_WALLET1_XPUB = 'xpub661MyMwAqRbcFgsE3Zg66E8prHy7aohb9wSiZRN9vQA4fp6n1dpXDyRLPT4YnhBTPwkhtDGqR3ynB4tJUenw9WTPhRWwZ3cpqkQrGzXTcFM'; + BitGo.TEST_WALLET1_XPUB = + 'xpub661MyMwAqRbcFgsE3Zg66E8prHy7aohb9wSiZRN9vQA4fp6n1dpXDyRLPT4YnhBTPwkhtDGqR3ynB4tJUenw9WTPhRWwZ3cpqkQrGzXTcFM'; BitGo.TEST_WALLET1_ADDRESS = '2N1vk5Qm6vGPB8SAZUjEQ8Gac6v71EmxgaG'; BitGo.TEST_WALLET1_ADDRESS2 = '2MxCHzAYyK9RgLGUWymw9Jhhtt19VqUtCej'; BitGo.TEST_WALLET2_PASSCODE = 'j0XVTJiTgsMCogKRoHIDzGbz'; @@ -103,18 +104,20 @@ BitGo.prototype.initializeTestVars = function () { BitGo.V2 = {}; BitGo.V2.TEST_USERID = '585caccd5573b0a8416a745ed58d8cb4'; BitGo.V2.TEST_WALLET1_PASSCODE = 'iVWeATjqLS1jJShrPpETti0b'; - BitGo.V2.TEST_WALLET1_XPUB = 'xpub661MyMwAqRbcGicVM5K5UnocWoFt3Yh1RZKzSEHPPARhyMf9w7DVqM3PgBgiVW5NHRp8UteqhMoQb17rCQsLbmGXuPx43MKskyB31R97p3G'; + BitGo.V2.TEST_WALLET1_XPUB = + 'xpub661MyMwAqRbcGicVM5K5UnocWoFt3Yh1RZKzSEHPPARhyMf9w7DVqM3PgBgiVW5NHRp8UteqhMoQb17rCQsLbmGXuPx43MKskyB31R97p3G'; BitGo.V2.TEST_WALLET1_ID = '585cc5335573b0a8416aadb1fce63ce3'; BitGo.V2.OFC_TEST_WALLET_ID = '5cbe3223311315fc7c96ce087f32dbdd'; - } else { BitGo.TEST_USERID = '543c11ed356d00cb7600000b98794503'; BitGo.TEST_SHARED_KEY_USERID = '549d0ee835aec81206004c082757570f'; BitGo.TEST_THIRD_USERID = '57049b9a194a115a06da21fb9731fb71'; - BitGo.TEST_USER_ECDH_XPUB = 'xpub661MyMwAqRbcFkiN8QJXCytQqPyDPW1cfnuG6RGCVFnVyiSQL1b6ZS2iiVJHH7UZYwLbN2ayWsaRVhnBFKYvLz956PTRH2SuuurpEcNGLKv'; + BitGo.TEST_USER_ECDH_XPUB = + 'xpub661MyMwAqRbcFkiN8QJXCytQqPyDPW1cfnuG6RGCVFnVyiSQL1b6ZS2iiVJHH7UZYwLbN2ayWsaRVhnBFKYvLz956PTRH2SuuurpEcNGLKv'; BitGo.TEST_WALLET1_PASSCODE = 'test wallet #1 security'; - BitGo.TEST_WALLET1_XPUB = 'xpub661MyMwAqRbcGU7FnXMKSHMwbWxARxYJUpKD1CoMJP6vonLT9bZZaWYq7A7tKPXmDFFXTKigT7VHMnbtEnjCmxQ1E93ZJe6HDKwxWD28M6f'; + BitGo.TEST_WALLET1_XPUB = + 'xpub661MyMwAqRbcGU7FnXMKSHMwbWxARxYJUpKD1CoMJP6vonLT9bZZaWYq7A7tKPXmDFFXTKigT7VHMnbtEnjCmxQ1E93ZJe6HDKwxWD28M6f'; BitGo.TEST_WALLET1_ADDRESS = '2MtepahRn4qTihhTvUuGTYUyUBkQZzaVBG3'; BitGo.TEST_WALLET1_ADDRESS2 = '2MxKo9RHNZHoPwmvnb5k8ytDJ6Shd1DHnsV'; BitGo.TEST_WALLET2_PASSCODE = 'test wallet #2 security'; @@ -149,25 +152,29 @@ BitGo.prototype.initializeTestVars = function () { BitGo.V2.TEST_USERID = '543c11ed356d00cb7600000b98794503'; BitGo.V2.TEST_WALLET1_PASSCODE = 'iVWeATjqLS1jJShrPpETti0b'; - BitGo.V2.TEST_WALLET1_XPUB = 'xpub661MyMwAqRbcFWFN9gpFpnSVy6bF3kMZAkSXtu3ZYKPgq2KUVo1xEMnMXDcavwDJ4zH57iUHVfEGVK7dEgo7ufKRzTkeWYSBDuye5g7w4pe'; + BitGo.V2.TEST_WALLET1_XPUB = + 'xpub661MyMwAqRbcFWFN9gpFpnSVy6bF3kMZAkSXtu3ZYKPgq2KUVo1xEMnMXDcavwDJ4zH57iUHVfEGVK7dEgo7ufKRzTkeWYSBDuye5g7w4pe'; BitGo.V2.TEST_WALLET1_ID = '593f1ece99d37c23080a557283edcc89'; BitGo.V2.TEST_WALLET1_ADDRESS = '2N3qLG4VMpkoRZN4Ft9PC5sgpGKvm7AV32A'; // this wallet will do consolidate and fannout together, so the number of unspents can be known BitGo.V2.TEST_WALLET2_UNSPENTS_LABEL = 'Test Wallet 2 Unspents'; BitGo.V2.TEST_WALLET2_UNSPENTS_PASSCODE = 'NXh65HxeZpzFqzW2n868'; - BitGo.V2.TEST_WALLET2_UNSPENTS_XPUB = 'xpub661MyMwAqRbcFeeMZtyLiqECMeek7QD6X9NLX2ydBN2DutiBQqLw8nsMnnL9hk3CSWGXZgW1PLV96opu8NzuXwJjK57PuNBqe85jSN6Abm6'; + BitGo.V2.TEST_WALLET2_UNSPENTS_XPUB = + 'xpub661MyMwAqRbcFeeMZtyLiqECMeek7QD6X9NLX2ydBN2DutiBQqLw8nsMnnL9hk3CSWGXZgW1PLV96opu8NzuXwJjK57PuNBqe85jSN6Abm6'; BitGo.V2.TEST_WALLET2_UNSPENTS_ID = '5a1341e7c8421dc90710673b3166bbd5'; BitGo.V2.TEST_SWEEP1_LABEL = 'Sweep 1'; BitGo.V2.TEST_SWEEP1_PASSCODE = 'T8n6S4AzktsDwCqvaE4692895YkjRT'; - BitGo.V2.TEST_SWEEP1_XPUB = 'xpub661MyMwAqRbcFWJ1ZxzvmKm4QCkrgYQLbTGzLgxzKFcGkyQfCjugENuamFmF3WwLHRvP8zWQi16kU8SuTqyMYFhvJcg1U1w8AT1AHKa25sY'; + BitGo.V2.TEST_SWEEP1_XPUB = + 'xpub661MyMwAqRbcFWJ1ZxzvmKm4QCkrgYQLbTGzLgxzKFcGkyQfCjugENuamFmF3WwLHRvP8zWQi16kU8SuTqyMYFhvJcg1U1w8AT1AHKa25sY'; BitGo.V2.TEST_SWEEP1_ID = '5a836a7e7cb43ca807371f123ab3a907'; BitGo.V2.TEST_SWEEP1_ADDRESS = '2N1rGQUpCRV797cSbT3hr34zayyNqS263g9'; BitGo.V2.TEST_SWEEP2_LABEL = 'Sweep 2'; BitGo.V2.TEST_SWEEP2_PASSCODE = 'bMY8jrF06pV2dxzRK42dGZqrmmURS7'; - BitGo.V2.TEST_SWEEP2_XPUB = 'xpub661MyMwAqRbcFhBDq1dbwu51qrNQra923FnujGPxCBaHd2geU6AYZhviMo8jWj3cvwM7Aj2T79CtKqErP37K1vwYSAYgMmFaHiVdJgHJ1nk'; + BitGo.V2.TEST_SWEEP2_XPUB = + 'xpub661MyMwAqRbcFhBDq1dbwu51qrNQra923FnujGPxCBaHd2geU6AYZhviMo8jWj3cvwM7Aj2T79CtKqErP37K1vwYSAYgMmFaHiVdJgHJ1nk'; BitGo.V2.TEST_SWEEP2_ID = '5a836b5e1c0d699a07d42029ccd65836'; BitGo.V2.TEST_SWEEP2_ADDRESS = '2NGV9ChhafuXNK9iFW6L6CKru5bFkMxZjNX'; @@ -192,7 +199,6 @@ BitGo.prototype.initializeTestVars = function () { BitGo.TEST_FEE_SINGLE_KEY_WIF = 'cRVQ6cbUyGHVvByPKF9GnEhaB4HUBFgLQ2jVX1kbQARHaTaD7WJ2'; BitGo.TEST_FEE_SINGLE_KEY_ADDRESS = 'mibJ4uJc9f1fbMeaUXNuWqsB1JgNMcTZK7'; - }; // @@ -208,14 +214,16 @@ BitGo.prototype.testUserOTP = function () { // Authenticate the test user. // BitGo.prototype.authenticateTestUser = function (otp, callback) { - return co(function *() { + return co(function* () { const response = yield this.authenticate({ username: BitGo.TEST_USER, password: BitGo.TEST_PASSWORD, otp: otp }); response.should.have.property('access_token'); response.should.have.property('user'); - }).call(this).asCallback(callback); + }) + .call(this) + .asCallback(callback); }; -BitGo.prototype.checkFunded = co(function *checkFunded() { +BitGo.prototype.checkFunded = co(function* checkFunded() { // We are testing both BTC and ETH funds here, to make sure that // we don't spend for already 'failed' test runs (e.g., spending ETH when we don't have enough BTC) @@ -223,12 +231,7 @@ BitGo.prototype.checkFunded = co(function *checkFunded() { yield this.authenticateTestUser(this.testUserOTP()); const testWalletId = BitGo.V2.TEST_ETH_WALLET_ID; - const { - tethWallet, - tbtcWallet, - unspentWallet, - sweep1Wallet, - } = yield Bluebird.props({ + const { tethWallet, tbtcWallet, unspentWallet, sweep1Wallet } = yield Bluebird.props({ tethWallet: this.coin('teth').wallets().get({ id: testWalletId }), tbtcWallet: this.coin('tbtc').wallets().getWallet({ id: BitGo.V2.TEST_WALLET1_ID }), unspentWallet: this.coin('tbtc').wallets().getWallet({ id: BitGo.V2.TEST_WALLET2_UNSPENTS_ID }), @@ -241,7 +244,9 @@ BitGo.prototype.checkFunded = co(function *checkFunded() { // Check our balance is over 60000 (we spend 50000, add some cushion) if (balance.lt(60000)) { - throw new Error(`The TETH wallet ${testWalletId} does not have enough funds to run the test suite. The current balance is ${balance}. Please fund this wallet!`); + throw new Error( + `The TETH wallet ${testWalletId} does not have enough funds to run the test suite. The current balance is ${balance}. Please fund this wallet!` + ); } // Check we have enough in the wallet to run test suite @@ -251,7 +256,9 @@ BitGo.prototype.checkFunded = co(function *checkFunded() { // Check our balance is over 0.05 tBTC (we spend 0.04, add some cushion) let minimumBalance = 0.05 * 1e8; if (balance.lt(minimumBalance)) { - throw new Error(`The TBTC wallet ${tbtcWallet.id()} does not have enough funds to run the test suite. The current balance is ${balance}. Please fund this wallet!`); + throw new Error( + `The TBTC wallet ${tbtcWallet.id()} does not have enough funds to run the test suite. The current balance is ${balance}. Please fund this wallet!` + ); } // Check we have enough in the wallet to run test suite @@ -261,7 +268,9 @@ BitGo.prototype.checkFunded = co(function *checkFunded() { // Check our balance is over 0.05 tBTC (we spend 0.04, add some cushion) minimumBalance = 0.05 * 1e8; if (balance.lt(minimumBalance)) { - throw new Error(`The TBTC wallet ${unspentWallet.id()} does not have enough funds to run the test suite. The current balance is ${balance}. Please fund this wallet!`); + throw new Error( + `The TBTC wallet ${unspentWallet.id()} does not have enough funds to run the test suite. The current balance is ${balance}. Please fund this wallet!` + ); } // Check we have enough in the wallet to run test suite @@ -272,15 +281,15 @@ BitGo.prototype.checkFunded = co(function *checkFunded() { minimumBalance = 0.05 * 1e8; if (balance.lt(minimumBalance)) { - throw new Error(`The TBTC wallet ${sweep1Wallet.id()} does not have enough funds to run the test suite. The current balance is ${balance}. Please fund this wallet!`); + throw new Error( + `The TBTC wallet ${sweep1Wallet.id()} does not have enough funds to run the test suite. The current balance is ${balance}. Please fund this wallet!` + ); } }); const oldFetchConstants = BitGo.prototype.fetchConstants; BitGo.prototype.fetchConstants = function () { - nock(this._baseUrl) - .get('/api/v1/client/constants') - .reply(200, { ttl: 3600, constants: {} }); + nock(this._baseUrl).get('/api/v1/client/constants').reply(200, { ttl: 3600, constants: {} }); // force client constants reload BitGo.prototype._constants = undefined; diff --git a/modules/express/test/lib/testutil.ts b/modules/express/test/lib/testutil.ts index c03b0514cf..0cacfd32a7 100644 --- a/modules/express/test/lib/testutil.ts +++ b/modules/express/test/lib/testutil.ts @@ -4,7 +4,8 @@ // helper function to unlock a token for a specified time export function unlockToken(agent, accessToken, seconds) { - return agent.post('/api/v1/user/unlock') + return agent + .post('/api/v1/user/unlock') .set('Authorization', 'Bearer ' + accessToken) .send({ otp: '0000000', duration: seconds }) .then(function (res) { diff --git a/modules/express/test/unit/bitgoExpress.ts b/modules/express/test/unit/bitgoExpress.ts index 4b8d8db25b..75ac6cb75f 100644 --- a/modules/express/test/unit/bitgoExpress.ts +++ b/modules/express/test/unit/bitgoExpress.ts @@ -19,17 +19,10 @@ import { TlsConfigurationError, NodeEnvironmentError } from '../../src/errors'; nock.disableNetConnect(); -import { - app as expressApp, - startup, - createServer, - createBaseUri, - prepareIpc, -} from '../../src/expressApp'; +import { app as expressApp, startup, createServer, createBaseUri, prepareIpc } from '../../src/expressApp'; import * as clientRoutes from '../../src/clientRoutes'; describe('Bitgo Express', function () { - describe('server initialization', function () { const validPrvJSON = '{"61f039aad587c2000745c687373e0fa9":"xprv9s21ZrQH143K3EuPWCBuqnWxydaQV6et9htQige4EswvcHKEzNmkVmwTwKoadyHzJYppuADB7Us7AbaNLToNvoFoSxuWqndQRYtnNy5DUY2"}'; @@ -38,16 +31,18 @@ describe('Bitgo Express', function () { const envStub = sinon.stub(process, 'env').value({ NODE_ENV: 'production' }); try { - (() => expressApp({ - env: 'prod', - bind: 'localhost', - } as any)).should.not.throw(); + (() => + expressApp({ + env: 'prod', + bind: 'localhost', + } as any)).should.not.throw(); process.env.NODE_ENV = 'dev'; - (() => expressApp({ - env: 'prod', - bind: 'localhost', - } as any)).should.throw(NodeEnvironmentError); + (() => + expressApp({ + env: 'prod', + bind: 'localhost', + } as any)).should.throw(NodeEnvironmentError); } finally { envStub.restore(); } @@ -57,11 +52,12 @@ describe('Bitgo Express', function () { const envStub = sinon.stub(process, 'env').value({ NODE_ENV: 'dev' }); try { - (() => expressApp({ - env: 'prod', - bind: 'localhost', - disableEnvCheck: true, - } as any)).should.not.throw(); + (() => + expressApp({ + env: 'prod', + bind: 'localhost', + disableEnvCheck: true, + } as any)).should.not.throw(); } finally { envStub.restore(); } @@ -115,41 +111,50 @@ describe('Bitgo Express', function () { (() => expressApp(args)).should.throw(TlsConfigurationError); }); - it('should create an http server when not using TLS', co(function *() { - const createServerStub = sinon.stub(http, 'createServer'); - - const args: any = { - env: 'prod', - bind: 'localhost', - }; + it( + 'should create an http server when not using TLS', + co(function* () { + const createServerStub = sinon.stub(http, 'createServer'); - createServer(args, null as any); - - createServerStub.should.be.calledOnce(); - createServerStub.restore(); - })); - - it('should create an https server when using TLS', co(function *() { - const createServerStub = sinon.stub(https, 'createServer'); - const readFileAsyncStub = sinon.stub(fs.promises, 'readFile' as any) - .onFirstCall().resolves('key') - .onSecondCall().resolves('cert'); - - const args: any = { - env: 'prod', - bind: '1.2.3.4', - crtPath: '/tmp/crt.pem', - keyPath: '/tmp/key.pem', - }; + const args: any = { + env: 'prod', + bind: 'localhost', + }; + + createServer(args, null as any); + + createServerStub.should.be.calledOnce(); + createServerStub.restore(); + }) + ); + + it( + 'should create an https server when using TLS', + co(function* () { + const createServerStub = sinon.stub(https, 'createServer'); + const readFileAsyncStub = sinon + .stub(fs.promises, 'readFile' as any) + .onFirstCall() + .resolves('key') + .onSecondCall() + .resolves('cert'); + + const args: any = { + env: 'prod', + bind: '1.2.3.4', + crtPath: '/tmp/crt.pem', + keyPath: '/tmp/key.pem', + }; - yield createServer(args, null as any); + yield createServer(args, null as any); - https.createServer.should.be.calledOnce(); - https.createServer.should.be.calledWith({ secureOptions: SSL_OP_NO_TLSv1, key: 'key', cert: 'cert' }); + https.createServer.should.be.calledOnce(); + https.createServer.should.be.calledWith({ secureOptions: SSL_OP_NO_TLSv1, key: 'key', cert: 'cert' }); - createServerStub.restore(); - readFileAsyncStub.restore(); - })); + createServerStub.restore(); + readFileAsyncStub.restore(); + }) + ); it('should output basic information upon server startup', () => { const logStub = sinon.stub(console, 'log'); @@ -325,7 +330,7 @@ describe('Bitgo Express', function () { platformStub.restore(); }); - it('should not remove the IPC socket if it doesn\'t exist', async () => { + it("should not remove the IPC socket if it doesn't exist", async () => { const statStub = sinon.stub(fs, 'statSync').throws({ code: 'ENOENT' }); const unlinkStub = sinon.stub(fs, 'unlinkSync'); await prepareIpc('testipc').should.be.resolved(); @@ -335,9 +340,7 @@ describe('Bitgo Express', function () { }); it('should remove the socket before binding if IPC socket exists and is a socket', async () => { - const statStub = sinon.stub(fs, 'statSync').returns( - { isSocket: () => true } as unknown as fs.Stats, - ); + const statStub = sinon.stub(fs, 'statSync').returns({ isSocket: () => true } as unknown as fs.Stats); const unlinkStub = sinon.stub(fs, 'unlinkSync'); await prepareIpc('testipc').should.be.resolved(); unlinkStub.calledWithExactly('testipc').should.be.true(); @@ -347,9 +350,7 @@ describe('Bitgo Express', function () { }); it('should fail if IPC socket is not actually a socket', async () => { - const statStub = sinon.stub(fs, 'statSync').returns( - { isSocket: () => false } as unknown as fs.Stats, - ); + const statStub = sinon.stub(fs, 'statSync').returns({ isSocket: () => false } as unknown as fs.Stats); const unlinkStub = sinon.stub(fs, 'unlinkSync'); await prepareIpc('testipc').should.be.rejectedWith(/IPC socket is not actually a socket/); unlinkStub.notCalled.should.be.true(); diff --git a/modules/express/test/unit/clientRoutes/consolidateAccount.ts b/modules/express/test/unit/clientRoutes/consolidateAccount.ts index fc3c99d23f..7cb7cc6e50 100644 --- a/modules/express/test/unit/clientRoutes/consolidateAccount.ts +++ b/modules/express/test/unit/clientRoutes/consolidateAccount.ts @@ -26,8 +26,9 @@ describe('Consolidate account', () => { }, }; - await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest) - .should.be.rejectedWith('invalid coin selected'); + await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest).should.be.rejectedWith( + 'invalid coin selected' + ); }); it('should pass if coin allows consolidation', async () => { @@ -45,8 +46,9 @@ describe('Consolidate account', () => { }, }; - await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest) - .should.be.resolvedWith(result); + await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest).should.be.resolvedWith( + result + ); consolidationStub.should.be.calledOnceWith(mockRequest.body); }); @@ -64,8 +66,9 @@ describe('Consolidate account', () => { }, }; - await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest) - .should.be.rejectedWith('consolidate address must be an array of addresses'); + await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest).should.be.rejectedWith( + 'consolidate address must be an array of addresses' + ); }); function createConsolidateMocks(res, allowsAccountConsolidations = false, supportsTss = false) { @@ -94,8 +97,10 @@ describe('Consolidate account', () => { body, }; - await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest) - .should.be.rejectedWith({ status: 400, result }); + await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest).should.be.rejectedWith({ + status: 400, + result, + }); consolidationStub.should.be.calledOnceWith(body); }); @@ -111,8 +116,10 @@ describe('Consolidate account', () => { body, }; - await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest) - .should.be.rejectedWith({ status: 202, result }); + await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest).should.be.rejectedWith({ + status: 202, + result, + }); consolidationStub.should.be.calledOnceWith(body); }); @@ -128,8 +135,9 @@ describe('Consolidate account', () => { body, }; - await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest) - .should.be.resolvedWith(result); + await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest).should.be.resolvedWith( + result + ); consolidationStub.should.be.calledOnceWith(body); }); }); diff --git a/modules/express/test/unit/clientRoutes/createAddress.ts b/modules/express/test/unit/clientRoutes/createAddress.ts index 4c05e7d455..a932f69742 100644 --- a/modules/express/test/unit/clientRoutes/createAddress.ts +++ b/modules/express/test/unit/clientRoutes/createAddress.ts @@ -38,8 +38,6 @@ describe('Create Address', () => { }, } as unknown as express.Request; - await handleV2CreateAddress(req) - .should.be.resolvedWith(res); + await handleV2CreateAddress(req).should.be.resolvedWith(res); }); - }); diff --git a/modules/express/test/unit/clientRoutes/enableTokens.ts b/modules/express/test/unit/clientRoutes/enableTokens.ts index f795bf2710..6c3d262322 100644 --- a/modules/express/test/unit/clientRoutes/enableTokens.ts +++ b/modules/express/test/unit/clientRoutes/enableTokens.ts @@ -25,10 +25,7 @@ describe('Enable tokens', () => { id: '23423423423423', }, body: { - enableTokens: [ - { name: 'tsol:usdc' }, - { name: 'tsol:usdt' }, - ], + enableTokens: [{ name: 'tsol:usdc' }, { name: 'tsol:usdt' }], }, } as unknown as express.Request; diff --git a/modules/express/test/unit/clientRoutes/generateWallet.ts b/modules/express/test/unit/clientRoutes/generateWallet.ts index 0e83478018..df6ce6f2eb 100644 --- a/modules/express/test/unit/clientRoutes/generateWallet.ts +++ b/modules/express/test/unit/clientRoutes/generateWallet.ts @@ -14,9 +14,13 @@ import { BaseCoin, Wallets, WalletWithKeychains } from '@bitgo/sdk-core'; describe('Generate Wallet', () => { it('should return the internal wallet object by default', async () => { - const walletStub = sinon.stub<[], Bluebird>().resolves(({ wallet: { toJSON: () => 'walletdata' } }) as any); + const walletStub = sinon + .stub<[], Bluebird>() + .resolves({ wallet: { toJSON: () => 'walletdata' } } as any); const walletsStub = sinon.createStubInstance(Wallets, { generateWallet: walletStub }); - const coinStub = sinon.createStubInstance(BaseCoin, { wallets: sinon.stub<[], Wallets>().returns(walletsStub as any) }); + const coinStub = sinon.createStubInstance(BaseCoin, { + wallets: sinon.stub<[], Wallets>().returns(walletsStub as any), + }); const stubBitgo = sinon.createStubInstance(BitGo, { coin: sinon.stub<[string]>().returns(coinStub) }); const walletGenerateBody = {}; const coin = 'tbtc'; @@ -29,13 +33,16 @@ describe('Generate Wallet', () => { body: walletGenerateBody, } as unknown as express.Request; - await handleV2GenerateWallet(req) - .should.be.resolvedWith('walletdata'); + await handleV2GenerateWallet(req).should.be.resolvedWith('walletdata'); }); it('should return the coin specific result directly if includeKeychains query param is true', async () => { - const walletsStub = sinon.createStubInstance(Wallets, { generateWallet: ({ wallet: { toJSON: () => 'walletdata with keychains' } }) as any }); - const coinStub = sinon.createStubInstance(BaseCoin, { wallets: sinon.stub<[], Wallets>().returns(walletsStub as any) }); + const walletsStub = sinon.createStubInstance(Wallets, { + generateWallet: { wallet: { toJSON: () => 'walletdata with keychains' } } as any, + }); + const coinStub = sinon.createStubInstance(BaseCoin, { + wallets: sinon.stub<[], Wallets>().returns(walletsStub as any), + }); const stubBitgo = sinon.createStubInstance(BitGo, { coin: sinon.stub<[string]>().returns(coinStub) }); const walletGenerateBody = {}; const coin = 'tbtc'; @@ -50,7 +57,6 @@ describe('Generate Wallet', () => { body: walletGenerateBody, } as unknown as express.Request; - await handleV2GenerateWallet(req) - .should.be.resolvedWith({ wallet: 'walletdata with keychains' }); + await handleV2GenerateWallet(req).should.be.resolvedWith({ wallet: 'walletdata with keychains' }); }); }); diff --git a/modules/express/test/unit/clientRoutes/signPayload.ts b/modules/express/test/unit/clientRoutes/signPayload.ts index cf7db274f8..07fa3bb730 100644 --- a/modules/express/test/unit/clientRoutes/signPayload.ts +++ b/modules/express/test/unit/clientRoutes/signPayload.ts @@ -21,33 +21,21 @@ describe('Sign an arbitrary payload with trading account key', function () { const signature = 'signedPayload123'; const walletId = 'myWalletId'; - const walletStub = sinon.createStubInstance( - Wallet as any, - { - id: walletId, - coin: sinon.stub().returns(coin), - toTradingAccount: sinon.stub().returns({ - signPayload: sinon.stub().returns(signature), - }), - }, - ); + const walletStub = sinon.createStubInstance(Wallet as any, { + id: walletId, + coin: sinon.stub().returns(coin), + toTradingAccount: sinon.stub().returns({ + signPayload: sinon.stub().returns(signature), + }), + }); - const walletsStub = sinon.createStubInstance( - Wallets as any, - { - get: sinon.stub().resolves(walletStub), - } - ); + const walletsStub = sinon.createStubInstance(Wallets as any, { + get: sinon.stub().resolves(walletStub), + }); - const coinStub = sinon.createStubInstance( - BaseCoin as any, - ({ wallets: sinon.stub().returns(walletsStub) }) - ); + const coinStub = sinon.createStubInstance(BaseCoin as any, { wallets: sinon.stub().returns(walletsStub) }); - const bitGoStub = sinon.createStubInstance( - BitGo as any, - { coin: sinon.stub().returns(coinStub) } - ); + const bitGoStub = sinon.createStubInstance(BitGo as any, { coin: sinon.stub().returns(coinStub) }); before(() => { process.env['WALLET_myWalletId_PASSPHRASE'] = 'mypass'; @@ -78,7 +66,7 @@ describe('With the handler to sign an arbitrary payload in external signing mode const secret = 'xprv9s21ZrQH143K3EuPWCBuqnWxydaQV6et9htQige4EswvcHKEzNmkVmwTwKoadyHzJYppuADB7Us7AbaNLToNvoFoSxuWqndQRYtnNy5DUY2'; const validPrv = - '{"61f039aad587c2000745c687373e0fa9":"{\\"iv\\":\\"+1u1Y9cvsYuRMeyH2slnXQ==\\",\\"v\\":1,\\"iter\\":10000,\\"ks\\":256,\\"ts\\":64,\\"mode\\":\\"ccm\\",\\"adata\\":\\"\\",\\"cipher\\":\\"aes\\",\\"salt\\":\\"54kOXTqJ9mc=\\",\\"ct\\":\\"JF5wQ82wa1dYyFxFlbHCvK4a+A6MTHdhOqc5uXsz2icWhkY2Lin/3Ab8ZwvwDaR1JYKmC/g1gXIGwVZEOl1M/bRHY420h7sDtmTS6Ebse5NWbF0ItfUJlk6HVATGa+C6mkbaVxJ4kQW/ehnT3riqzU069ATPz8E=\\"}"}'; + '{"61f039aad587c2000745c687373e0fa9":"{\\"iv\\":\\"+1u1Y9cvsYuRMeyH2slnXQ==\\",\\"v\\":1,\\"iter\\":10000,\\"ks\\":256,\\"ts\\":64,\\"mode\\":\\"ccm\\",\\"adata\\":\\"\\",\\"cipher\\":\\"aes\\",\\"salt\\":\\"54kOXTqJ9mc=\\",\\"ct\\":\\"JF5wQ82wa1dYyFxFlbHCvK4a+A6MTHdhOqc5uXsz2icWhkY2Lin/3Ab8ZwvwDaR1JYKmC/g1gXIGwVZEOl1M/bRHY420h7sDtmTS6Ebse5NWbF0ItfUJlk6HVATGa+C6mkbaVxJ4kQW/ehnT3riqzU069ATPz8E=\\"}"}'; const payload = { this: { @@ -95,12 +83,11 @@ describe('With the handler to sign an arbitrary payload in external signing mode it('should return a payload signed with trading account key read from the local file system', async () => { const stubbedSignature = Buffer.from('mysign'); const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(validPrv); - const envStub = sinon.stub(process, 'env') + const envStub = sinon + .stub(process, 'env') .value({ WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE: walletPassword }); - - const signMessageStub = sinon - .stub(Coin.Ofc.prototype, 'signMessage') - .resolves(stubbedSignature); + + const signMessageStub = sinon.stub(Coin.Ofc.prototype, 'signMessage').resolves(stubbedSignature); const stubbedSigHex = stubbedSignature.toString('hex'); @@ -133,7 +120,7 @@ describe('With the handler to sign an arbitrary payload in external signing mode describe('With invalid setup', () => { const invalidPrv = '{"61f039aad587c2000745c687373e0fa9":"invalid"}'; - + it('should throw an error with missing wallet passphrase in env', async () => { const req = { bitgo, @@ -143,11 +130,14 @@ describe('With the handler to sign an arbitrary payload in external signing mode }, } as unknown as Request; - await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith('Could not find wallet passphrase WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE in environment'); + await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith( + 'Could not find wallet passphrase WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE in environment' + ); }); it('should throw an error with undefined signerFileSystemPath in env', async () => { - const envStub = sinon.stub(process, 'env') + const envStub = sinon + .stub(process, 'env') .value({ WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE: walletPassword }); const req = { @@ -161,13 +151,16 @@ describe('With the handler to sign an arbitrary payload in external signing mode }, } as unknown as Request; - await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith('Missing required configuration: signerFileSystemPath'); + await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith( + 'Missing required configuration: signerFileSystemPath' + ); envStub.restore(); }); it('should throw error when trying to decrypt with invalid private key', async () => { const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(invalidPrv); - const envStub = sinon.stub(process, 'env') + const envStub = sinon + .stub(process, 'env') .value({ WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE: walletPassword }); const req = { @@ -180,8 +173,10 @@ describe('With the handler to sign an arbitrary payload in external signing mode signerFileSystemPath: 'signerFileSystemPath', }, } as unknown as Request; - - await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith('Error when trying to decrypt private key: INVALID: json decode: this isn\'t json!'); + + await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith( + "Error when trying to decrypt private key: INVALID: json decode: this isn't json!" + ); readFileStub.restore(); envStub.restore(); @@ -189,7 +184,8 @@ describe('With the handler to sign an arbitrary payload in external signing mode it('should throw error when trying to decrypt with invalid wallet passphrase key', async () => { const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(validPrv); - const envStub = sinon.stub(process, 'env') + const envStub = sinon + .stub(process, 'env') .value({ WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE: 'invalidPassphrase' }); const req = { @@ -203,8 +199,10 @@ describe('With the handler to sign an arbitrary payload in external signing mode }, } as unknown as Request; - await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith('Error when trying to decrypt private key: CORRUPT: password error - ccm: tag doesn\'t match'); - + await handleV2OFCSignPayloadInExtSigningMode(req).should.be.rejectedWith( + "Error when trying to decrypt private key: CORRUPT: password error - ccm: tag doesn't match" + ); + readFileStub.restore(); envStub.restore(); }); diff --git a/modules/express/test/unit/config.ts b/modules/express/test/unit/config.ts index ea13644c0c..39b253282a 100644 --- a/modules/express/test/unit/config.ts +++ b/modules/express/test/unit/config.ts @@ -39,7 +39,9 @@ describe('Config:', () => { it('should transform urls to secure urls when disableSSL is undefined', () => { const argStub = sinon.stub(args, 'args').returns({ disableSSL: undefined, customrooturi: 'test.com' }); - const envStub = sinon.stub(process, 'env').value({ BITGO_DISABLE_SSL: undefined, BITGO_CUSTOM_ROOT_URI: 'test.com' }); + const envStub = sinon + .stub(process, 'env') + .value({ BITGO_DISABLE_SSL: undefined, BITGO_CUSTOM_ROOT_URI: 'test.com' }); config().disableSSL.should.equal(false); config().should.have.property('customRootUri', 'https://test.com'); argStub.restore(); diff --git a/modules/key-card/src/drawKeycard.ts b/modules/key-card/src/drawKeycard.ts index 2b6ced28ec..6479bec0bb 100644 --- a/modules/key-card/src/drawKeycard.ts +++ b/modules/key-card/src/drawKeycard.ts @@ -33,7 +33,13 @@ function moveDown(y: number, ydelta: number): number { return y + ydelta; } -function drawOnePageOfQrCodes(qrImages: HTMLCanvasElement[], doc: jsPDF, y: number, qrSize: number, startIndex): number { +function drawOnePageOfQrCodes( + qrImages: HTMLCanvasElement[], + doc: jsPDF, + y: number, + qrSize: number, + startIndex +): number { doc.setFont('helvetica'); let qrIndex: number = startIndex; for (; qrIndex < qrImages.length; qrIndex++) { @@ -57,7 +63,13 @@ function drawOnePageOfQrCodes(qrImages: HTMLCanvasElement[], doc: jsPDF, y: numb return qrIndex + 1; } -export async function drawKeycard({ activationCode, questions, keyCardImage, qrData, walletLabel }: { +export async function drawKeycard({ + activationCode, + questions, + keyCardImage, + qrData, + walletLabel, +}: { activationCode?: string; keyCardImage?: HTMLImageElement; qrData: QrData; @@ -118,7 +130,7 @@ export async function drawKeycard({ activationCode, questions, keyCardImage, qrD y = moveDown(y, 35); const qrSize = 130; - const qrKeys = ['user', 'passcode', 'backup', 'bitgo'].filter(key => !!qrData[key]); + const qrKeys = ['user', 'passcode', 'backup', 'bitgo'].filter((key) => !!qrData[key]); for (let index = 0; index < qrKeys.length; index++) { const name = qrKeys[index]; if (index === 2) { diff --git a/modules/key-card/src/faq.ts b/modules/key-card/src/faq.ts index 5acb7af62d..433bf3b569 100644 --- a/modules/key-card/src/faq.ts +++ b/modules/key-card/src/faq.ts @@ -5,14 +5,10 @@ export interface FAQ { } export function generateFaq(coinName: string): FAQ[] { - const sectionACoinSpecific = - `The KeyCard contains important information which can be used to recover the ${coinName} `; - const sectionBCoinSpecific = - `If you have lost or damaged all copies of your KeyCard, your ${coinName} is still safe, but this `; - const sectionCCoinSpecific = - `source tools at https://github.com/bitgo to recover your ${coinName}. Note: You should never enter `; - const sectionDCoinSpecific = - `your KeyCard will be able to steal your ${coinName}. We recommend keeping your wallet password `; + const sectionACoinSpecific = `The KeyCard contains important information which can be used to recover the ${coinName} `; + const sectionBCoinSpecific = `If you have lost or damaged all copies of your KeyCard, your ${coinName} is still safe, but this `; + const sectionCCoinSpecific = `source tools at https://github.com/bitgo to recover your ${coinName}. Note: You should never enter `; + const sectionDCoinSpecific = `your KeyCard will be able to steal your ${coinName}. We recommend keeping your wallet password `; return [ { diff --git a/modules/key-card/src/generateQrData.ts b/modules/key-card/src/generateQrData.ts index 111fbd6236..dea32f0d1f 100644 --- a/modules/key-card/src/generateQrData.ts +++ b/modules/key-card/src/generateQrData.ts @@ -5,13 +5,13 @@ import * as assert from 'assert'; export interface GenerateQrDataParams { // The backup keychain as it is returned from the BitGo API upon creation - backupKeychain: Keychain, + backupKeychain: Keychain; // The name of the 3rd party provider of the backup key if neither the user nor BitGo stores it backupKeyProvider?: string; // The key id of the backup key, only used for cold keys backupMasterKey?: string; // The BitGo keychain as it is returned from the BitGo API upon creation - bitgoKeychain: Keychain, + bitgoKeychain: Keychain; // The coin of the wallet that was/ is about to be created coin: Readonly; // A code that can be used to encrypt the wallet password to. @@ -73,13 +73,17 @@ function generateUserQrData(userKeychain: Keychain, userMasterKey?: string): QrD }; } -function generateBackupQrData(coin: Readonly, backupKeychain: Keychain, { - backupKeyProvider, - backupMasterKey, -}: { - backupKeyProvider?: string; - backupMasterKey?: string; -} = {}): QrDataEntry { +function generateBackupQrData( + coin: Readonly, + backupKeychain: Keychain, + { + backupKeyProvider, + backupMasterKey, + }: { + backupKeyProvider?: string; + backupMasterKey?: string; + } = {} +): QrDataEntry { const title = 'B: Backup Key'; if (backupKeychain.encryptedPrv) { return { @@ -94,7 +98,8 @@ function generateBackupQrData(coin: Readonly, backupKeychain: Keychain assert(keyShares?.length === 2); return { title: 'B: Backup Key Shares', - description: `These are the key shares for ${backupKeyProvider}. If BitGo Inc. goes out of business,\r\n` + + description: + `These are the key shares for ${backupKeyProvider}. If BitGo Inc. goes out of business,\r\n` + `contact ${backupKeyProvider} and they will help you recover your funds.`, data: JSON.stringify(keyShares), }; @@ -106,7 +111,8 @@ function generateBackupQrData(coin: Readonly, backupKeychain: Keychain if (backupKeyProvider) { return { title: 'B: Backup Key', - description: `This is the public key held at ${backupKeyProvider}, an ${coin.name} recovery service. ` + + description: + `This is the public key held at ${backupKeyProvider}, an ${coin.name} recovery service. ` + `If you lose\r\nyour key, ${backupKeyProvider} will be able to sign transactions to recover funds.`, data: pub, }; @@ -127,8 +133,7 @@ function generateBitGoQrData(bitgoKeychain: Keychain): QrDataEntry { return { title: 'C: BitGo Public Key', description: - 'This is the public part of the key that BitGo will use to ' + - 'co-sign transactions\r\nwith you on your wallet.', + 'This is the public part of the key that BitGo will use to ' + 'co-sign transactions\r\nwith you on your wallet.', data: bitgoData, }; } diff --git a/modules/key-card/test/unit/generateQrData.ts b/modules/key-card/test/unit/generateQrData.ts index 5cca75ca9d..fc0df866d1 100644 --- a/modules/key-card/test/unit/generateQrData.ts +++ b/modules/key-card/test/unit/generateQrData.ts @@ -67,13 +67,16 @@ describe('generateQrData', function () { assert(qrData.bitgo); qrData.bitgo.title.should.equal('C: BitGo Public Key'); - qrData.bitgo.description.should.equal('This is the public part of the key that BitGo will use to ' + - 'co-sign transactions\r\nwith you on your wallet.'); + qrData.bitgo.description.should.equal( + 'This is the public part of the key that BitGo will use to ' + 'co-sign transactions\r\nwith you on your wallet.' + ); qrData.bitgo.data.should.equal(bitgoPub); assert(qrData.passcode); qrData.passcode.title.should.equal('D: Encrypted wallet Password'); - qrData.passcode.description.should.equal('This is the wallet password, encrypted client-side with a key held by BitGo.'); + qrData.passcode.description.should.equal( + 'This is the wallet password, encrypted client-side with a key held by BitGo.' + ); const decryptedData = decrypt(passcodeEncryptionCode, qrData.passcode.data); decryptedData.should.equal(passphrase); }); @@ -159,13 +162,15 @@ describe('generateQrData', function () { assert(qrData.backup); qrData.backup.title.should.equal('B: Backup Key'); - qrData.backup.description.should.equal('This is the public key held at ' + - provider + - ', an ' + - coin.name + - ' recovery service. If you lose\r\nyour key, ' + - provider + - ' will be able to sign transactions to recover funds.'); + qrData.backup.description.should.equal( + 'This is the public key held at ' + + provider + + ', an ' + + coin.name + + ' recovery service. If you lose\r\nyour key, ' + + provider + + ' will be able to sign transactions to recover funds.' + ); qrData.backup.data.should.equal(backupPub); assert(qrData.bitgo); @@ -177,8 +182,18 @@ describe('generateQrData', function () { const userEncryptedPrv = 'prv123encrypted'; const provider = 'BitGoTrustAsKRS'; const backupKeyProvider = 'BitGo Trust'; - const userToBackupKeyShare: ApiKeyShare = { from: 'user', to: 'backup', publicShare: 'userToBackupPublic', privateShare: 'userToBackupPrivate' }; - const bitgoToBackupKeyShare: ApiKeyShare = { from: 'bitgo', to: 'backup', publicShare: 'bitgoToBackupPublic', privateShare: 'bitgoToBackupPrivate' }; + const userToBackupKeyShare: ApiKeyShare = { + from: 'user', + to: 'backup', + publicShare: 'userToBackupPublic', + privateShare: 'userToBackupPrivate', + }; + const bitgoToBackupKeyShare: ApiKeyShare = { + from: 'bitgo', + to: 'backup', + publicShare: 'bitgoToBackupPublic', + privateShare: 'bitgoToBackupPrivate', + }; const bitgoCommonKeychain = 'commonCommonBitGo'; const qrData = generateQrData({ backupKeychain: createKeychain({ @@ -202,12 +217,16 @@ describe('generateQrData', function () { assert(qrData.backup); qrData.backup.title.should.equal('B: Backup Key Shares'); - qrData.backup.description.should.equal(`These are the key shares for ${backupKeyProvider}. If BitGo Inc. goes out of business,\r\ncontact ${backupKeyProvider} and they will help you recover your funds.`); + qrData.backup.description.should.equal( + `These are the key shares for ${backupKeyProvider}. If BitGo Inc. goes out of business,\r\ncontact ${backupKeyProvider} and they will help you recover your funds.` + ); qrData.backup.data.should.equal(JSON.stringify([userToBackupKeyShare, bitgoToBackupKeyShare])); assert(qrData.bitgo); qrData.bitgo.title.should.equal('C: BitGo Public Key'); - qrData.bitgo.description.should.equal('This is the public part of the key that BitGo will use to co-sign transactions\r\nwith you on your wallet.'); + qrData.bitgo.description.should.equal( + 'This is the public part of the key that BitGo will use to co-sign transactions\r\nwith you on your wallet.' + ); qrData.bitgo.data.should.equal(bitgoCommonKeychain); }); }); diff --git a/modules/utxo-bin/README.md b/modules/utxo-bin/README.md index 1b9db3fd72..1444be44d1 100644 --- a/modules/utxo-bin/README.md +++ b/modules/utxo-bin/README.md @@ -28,6 +28,7 @@ utxo-bin -n bitcoin parseTx --clipboard ``` #### From txid + ```bash utxo-bin -n bitcoin parseTx --txid b0b7e5c2fbbbeb42478f91e1c14b300624a9419631e70dd1564084fb28a55155 ``` @@ -40,7 +41,6 @@ utxo-bin -n bitcoin parseTx \ --fetchInputs ``` - ## parseAddress ``` diff --git a/modules/utxo-lib/EXAMPLES.md b/modules/utxo-lib/EXAMPLES.md index 6212c9a045..44d92c8fe2 100644 --- a/modules/utxo-lib/EXAMPLES.md +++ b/modules/utxo-lib/EXAMPLES.md @@ -4,8 +4,8 @@ Many examples for Bitcoin, Bitcoin Cash, Bitcoin Gold, Bitcoin SV, and Litecoin ## Bitcoin | Bitcoin Cash | Bitcoin SV | Litecoin -* [Create Address](./examples/utxo/create-address.ts) +- [Create Address](./examples/utxo/create-address.ts) ## Bitcoin Gold -* [Create Address](./examples/utxo/create-address-btg.ts) +- [Create Address](./examples/utxo/create-address-btg.ts) diff --git a/modules/utxo-lib/README.md b/modules/utxo-lib/README.md index 666990c9a5..a13b7c0db4 100644 --- a/modules/utxo-lib/README.md +++ b/modules/utxo-lib/README.md @@ -3,12 +3,13 @@ This library is a wrapper around [bitcoinjs-lib](https://github.com/bitcoinjs/bitcoinjs-lib) adding altcoin support. ## Features + - Multicoin support: Configurable behaviour based on [network](https://github.com/BitGo/bitgo-utxo-lib/blob/master/src/networks.js) objects. - Backed by [BitGo](https://www.bitgo.com/info/) ## Installation -``` bash +```bash # using npm npm install @bitgo/utxo-lib @@ -19,20 +20,22 @@ yarn add @bitgo/utxo-lib ## Setup JavaScript (ESM) -``` javascript -import * as utxolib from '@bitgo/utxo-lib' + +```javascript +import * as utxolib from '@bitgo/utxo-lib'; ``` NodeJS (CJS) -``` javascript -const utxolib = require('@bitgo/utxo-lib') + +```javascript +const utxolib = require('@bitgo/utxo-lib'); ``` ## Usage Support for parsing and building altcoin transactions is provided by the following methods -``` typescript +```typescript utxolib.bitgo.createTransactionFromBuffer(buffer, network): UtxoTransaction // (similarly `createTransactionFromHex(string, network)`) @@ -45,15 +48,15 @@ The `UtxoTransaction(Builder)` classes have the same interface as the `Transacti ## Supported coins -|Network|Mainnet|Testnet| -|---|---|---| -|Bitcoin|`utxolib.networks.bitcoin`|`utxolib.networks.testnet`| -|Bitcoin Cash|`utxolib.networks.bitcoincash`|`utxolib.networks.bitcoincashTestnet`| -|Bitcoin Gold|`utxolib.networks.bitcoingold`|`utxolib.networks.bitcoingoldTestnet`| -|Bitcoin SV (Satoshi Vision)|`utxolib.networks.bitcoinsv`|`utxolib.networks.bitcoinsvTestnet`| -|Dash|`utxolib.networks.dash`|`utxolib.networks.dash`| -|eCash|`utxolib.networks.ecash`|`utxolib.networks.ecashTestnet`| -|Litecoin|`utxolib.networks.litecoin`|`utxolib.networks.litecoinTest`| -|Zcash|`utxolib.networks.zcash`|`utxolib.networks.zcashTest`| +| Network | Mainnet | Testnet | +| --------------------------- | ------------------------------ | ------------------------------------- | +| Bitcoin | `utxolib.networks.bitcoin` | `utxolib.networks.testnet` | +| Bitcoin Cash | `utxolib.networks.bitcoincash` | `utxolib.networks.bitcoincashTestnet` | +| Bitcoin Gold | `utxolib.networks.bitcoingold` | `utxolib.networks.bitcoingoldTestnet` | +| Bitcoin SV (Satoshi Vision) | `utxolib.networks.bitcoinsv` | `utxolib.networks.bitcoinsvTestnet` | +| Dash | `utxolib.networks.dash` | `utxolib.networks.dash` | +| eCash | `utxolib.networks.ecash` | `utxolib.networks.ecashTestnet` | +| Litecoin | `utxolib.networks.litecoin` | `utxolib.networks.litecoinTest` | +| Zcash | `utxolib.networks.zcash` | `utxolib.networks.zcashTest` | > [Bitcoin SV](https://blog.bitgo.com/bsv-deprecation-6b3fff4df34c) no longer supports sending funds to BitGo wallets. Existing customers with Bitcoin SV in BitGo wallets will still be able to access and sweep funds to an external Bitcoin SV wallet. diff --git a/scripts/check-package-dependencies.ts b/scripts/check-package-dependencies.ts index baf7d5a09e..0e949f60f6 100644 --- a/scripts/check-package-dependencies.ts +++ b/scripts/check-package-dependencies.ts @@ -2,16 +2,14 @@ const fs = require('fs'); const path = require('path'); const depcheck = require('depcheck'); -const { promises: { readdir } } = fs; +const { + promises: { readdir }, +} = fs; const options = { ignoreBinPackage: false, skipMissing: false, - ignorePatterns: [ - 'dist', - 'example', - 'examples', - ], + ignorePatterns: ['dist', 'example', 'examples'], ignoreMatches: [ '@components/**', '@types/**', @@ -62,8 +60,8 @@ const options = { async function getPackages(source) { return (await readdir(source, { withFileTypes: true })) - .filter(dirent => dirent.isDirectory()) - .map(dirent => dirent.name); + .filter((dirent) => dirent.isDirectory()) + .map((dirent) => dirent.name); } async function main() { @@ -89,8 +87,8 @@ async function main() { let showDepWarnings = false; const depWarningModules: string[] = []; if (pkg.data.dependencies.length) { - pkg.data.dependencies.forEach(module => { - const index = rootDependencies.findIndex(x => x === module); + pkg.data.dependencies.forEach((module) => { + const index = rootDependencies.findIndex((x) => x === module); if (index === -1) { showDepWarnings = true; depWarningModules.push(`\x1b[34m - ${module} \x1b[0m`); @@ -101,15 +99,14 @@ async function main() { if (showDepWarnings && depWarningModules.length) { exitCode = 1; console.warn(`\x1b[31m Warning: dependencies declared but not detected in code - ${pkg.name} \x1b[0m`); - depWarningModules.forEach(x => console.log(x)); + depWarningModules.forEach((x) => console.log(x)); } - let showDevDepWarnings = false; const devDepWarningModules: string[] = []; if (pkg.data.devDependencies.length) { - pkg.data.devDependencies.forEach(module => { - const index = rootDevDependencies.findIndex(x => x === module); + pkg.data.devDependencies.forEach((module) => { + const index = rootDevDependencies.findIndex((x) => x === module); if (index === -1) { showDevDepWarnings = true; devDepWarningModules.push(`\x1b[34m - ${module} \x1b[0m`); @@ -120,16 +117,16 @@ async function main() { if (showDevDepWarnings && devDepWarningModules.length) { exitCode = 1; console.warn(`\x1b[31m Warning: devDependencies declared but not detected in code - ${pkg.name} \x1b[0m`); - devDepWarningModules.forEach(x => console.log(x)); + devDepWarningModules.forEach((x) => console.log(x)); } const pkgWarningModules: string[] = []; const missing = Object.keys(pkg.data.missing); if (missing.length) { - missing.forEach(module => { - const indexDep = rootDependencies.findIndex(x => x === module); - const indexDevDep = rootDevDependencies.findIndex(x => x === module); + missing.forEach((module) => { + const indexDep = rootDependencies.findIndex((x) => x === module); + const indexDevDep = rootDevDependencies.findIndex((x) => x === module); if (indexDep === -1 && indexDevDep === -1) { exitCode = 1; pkgWarningModules.push(`\x1b[34m - ${module} \x1b[0m`); @@ -139,15 +136,16 @@ async function main() { if (exitCode && pkgWarningModules.length) { console.error(`\x1b[31m Error: packages used but missing in package.json of ${pkg.name} \x1b[0m:`); - pkgWarningModules.forEach(x => console.log(x)); + pkgWarningModules.forEach((x) => console.log(x)); } - }); return exitCode; } -main().then(process.exit).catch((e) => { - console.error(e); - process.exit(1); -}); +main() + .then(process.exit) + .catch((e) => { + console.error(e); + process.exit(1); + }); diff --git a/scripts/prepare-release.ts b/scripts/prepare-release.ts index 9de2d26848..8bced833f6 100644 --- a/scripts/prepare-release.ts +++ b/scripts/prepare-release.ts @@ -16,11 +16,7 @@ let filesChanged = 0; */ function getLernaRunner(lernaPath: string) { return async (command: string, args: string[] = [], options = {}) => { - const { stdout } = await execa( - lernaPath, - [command, ...args], - options, - ); + const { stdout } = await execa(lernaPath, [command, ...args], options); return stdout; }; } @@ -29,7 +25,9 @@ const getLernaModules = async (): Promise => { const { stdout: lernaBinary } = await execa('yarn', ['bin', 'lerna'], { cwd: process.cwd() }); const lerna = getLernaRunner(lernaBinary); - const modules: Array<{ name: string, location: string }> = JSON.parse(await lerna('list', ['--loglevel', 'silent', '--json', '--all'])); + const modules: Array<{ name: string; location: string }> = JSON.parse( + await lerna('list', ['--loglevel', 'silent', '--json', '--all']) + ); lernaModules = modules.map(({ name }) => name); lernaModuleLocations = modules.map(({ location }) => location); }; @@ -43,10 +41,7 @@ const walk = (dir: string): string[] => { const stat = statSync(file); if (stat && stat.isDirectory()) { if (!ignoredFolders.some((folder) => folder.test(file))) { - results = [ - ...results, - ...walk(file), - ]; + results = [...results, ...walk(file)]; } } else if (['.ts', '.tsx', '.js', '.json'].includes(path.extname(file))) { // Is a file @@ -70,16 +65,13 @@ const changeScopeInFile = (filePath: string): void => { }; const replacePackageScopes = () => { - // replace all @bitgo packages & source code with alternate SCOPE - const filePaths = [ - ...walk(path.join(__dirname, '../', 'modules')), - ...walk(path.join(__dirname, '../', 'webpack')), - ]; + // replace all @bitgo packages & source code with alternate SCOPE + const filePaths = [...walk(path.join(__dirname, '../', 'modules')), ...walk(path.join(__dirname, '../', 'webpack'))]; filePaths.forEach((file) => changeScopeInFile(file)); }; /** - * Makes an HTTP request to fetch all the dist tags for a given package. + * Makes an HTTP request to fetch all the dist tags for a given package. */ const getDistTags = async (packageName: string): Promise> => { return new Promise((resolve) => { @@ -102,24 +94,27 @@ const replaceBitGoPackageScope = () => { const cwd = path.join(__dirname, '../', 'modules', 'bitgo'); const json = JSON.parse(readFileSync(path.join(cwd, 'package.json'), { encoding: 'utf-8' })); json.name = `${TARGET_SCOPE}/bitgo`; - writeFileSync( - path.join(cwd, 'package.json'), - JSON.stringify(json, null, 2) + '\n' - ); + writeFileSync(path.join(cwd, 'package.json'), JSON.stringify(json, null, 2) + '\n'); }; /** Small version checkers in place of an npm dependency installation */ function compareversion(version1, version2) { - let result = false; - if (typeof version1 !== 'object') { version1 = version1.toString().split('.'); } - if (typeof version2 !== 'object') { version2 = version2.toString().split('.'); } - - for (let i = 0;i < (Math.max(version1.length, version2.length));i++) { + if (typeof version1 !== 'object') { + version1 = version1.toString().split('.'); + } + if (typeof version2 !== 'object') { + version2 = version2.toString().split('.'); + } - if (version1[i] === undefined) { version1[i] = 0; } - if (version2[i] === undefined) { version2[i] = 0; } + for (let i = 0; i < Math.max(version1.length, version2.length); i++) { + if (version1[i] === undefined) { + version1[i] = 0; + } + if (version2[i] === undefined) { + version2[i] = 0; + } if (Number(version1[i]) < Number(version2[i])) { result = true; @@ -129,12 +124,12 @@ function compareversion(version1, version2) { break; } } - return (result); + return result; } /** * increment the version based on the preid. default to `beta` - * + * * @param {String | undefined} preid */ const incrementVersions = async (preid = 'beta') => { @@ -160,10 +155,7 @@ const incrementVersions = async (preid = 'beta') => { const next = inc(prevTag, 'prerelease', undefined, preid); console.log(`Setting next version for ${json.name} to ${next}`); json.version = next; - writeFileSync( - path.join(modulePath, 'package.json'), - JSON.stringify(json, null, 2) + '\n' - ); + writeFileSync(path.join(modulePath, 'package.json'), JSON.stringify(json, null, 2) + '\n'); // since we're manually setting new versions, we must also reconcile all other lerna packages to now use the 'next' version for this module lernaModuleLocations.forEach((otherModulePath) => { // skip it for the current version @@ -179,10 +171,7 @@ const incrementVersions = async (preid = 'beta') => { if (otherJson.devDependencies && otherJson.devDependencies[json.name]) { otherJson.devDependencies[json.name] = next; } - writeFileSync( - path.join(otherModulePath, 'package.json'), - JSON.stringify(otherJson, null, 2) + '\n' - ); + writeFileSync(path.join(otherModulePath, 'package.json'), JSON.stringify(otherJson, null, 2) + '\n'); } }); } diff --git a/scripts/sdk-coin-generator/index.js b/scripts/sdk-coin-generator/index.js index d456275047..3e118c927c 100644 --- a/scripts/sdk-coin-generator/index.js +++ b/scripts/sdk-coin-generator/index.js @@ -1,24 +1,11 @@ const Generator = require('yeoman-generator'); const fs = require('fs'); -const UTXO_DEPENDENCIES = [ - 'abstract-utxo', - 'sdk-core', - 'utxo-lib', -]; -const ACCOUNT_DEPENDENCIES = [ - 'abstract-eth', - 'sdk-core', - 'statics', -]; -const SIMPLE_DEPENDENCIES = [ - 'sdk-core', -]; - -const DEV_DEPENDENCIES = [ - 'sdk-api', - 'sdk-test', -]; +const UTXO_DEPENDENCIES = ['abstract-utxo', 'sdk-core', 'utxo-lib']; +const ACCOUNT_DEPENDENCIES = ['abstract-eth', 'sdk-core', 'statics']; +const SIMPLE_DEPENDENCIES = ['sdk-core']; + +const DEV_DEPENDENCIES = ['sdk-api', 'sdk-test']; require('yeoman-generator/lib/actions/install'); @@ -34,7 +21,7 @@ module.exports = class extends Generator { type: 'input', name: 'coin', message: 'What is the name of your coin? (e.g. Bitcoin) - Sentence Case', - validate: function(input) { + validate: function (input) { const done = this.async(); if (!input) { done('Please provide the name of the coin.'); @@ -46,7 +33,7 @@ module.exports = class extends Generator { type: 'input', name: 'symbol', message: 'What is the symbol of your coin? (e.g. btc) - Lowercase', - validate: function(input) { + validate: function (input) { const done = this.async(); if (!input) { done('Please provide a symbol.'); @@ -63,14 +50,14 @@ module.exports = class extends Generator { type: 'input', name: 'testnetSymbol', message: 'What is the testnet symbol of your coin? (e.g. tbtc) - Lowercase', - validate: function(input) { + validate: function (input) { const done = this.async(); if (!input) { done('Please provide a testnet symbol.'); } done(null, true); }, - when: function(answers) { + when: function (answers) { if (answers.testnetConfirm) { return true; } @@ -80,7 +67,7 @@ module.exports = class extends Generator { type: 'input', name: 'baseFactor', message: 'What is the base factor? (e.g. 1e6)', - validate: function(input) { + validate: function (input) { const done = this.async(); if (!input) { done('Please provide a base factor.'); @@ -116,7 +103,7 @@ module.exports = class extends Generator { } this.answers = { ...answers }; } - + paths() { const destinationPath = `${this.contextRoot}/modules/sdk-coin-${this.answers.symbol}`; const templatePath = `${this.contextRoot}/scripts/sdk-coin-generator/template`; @@ -124,37 +111,15 @@ module.exports = class extends Generator { this.destinationRoot(destinationPath); this.sourceRoot(templatePath); } - + async writing() { - this.fs.copyTpl( - this.templatePath('./base'), - this.destinationPath(), - { ...this.answers } - ); - this.fs.copyTpl( - this.templatePath('./base/.eslintignore'), - this.destinationPath('.eslintignore') - ); - this.fs.copyTpl( - this.templatePath('./base/.gitignore'), - this.destinationPath('.gitignore') - ); - this.fs.copyTpl( - this.templatePath('./base/.mocharc.yml'), - this.destinationPath('.mocharc.yml') - ); - this.fs.copyTpl( - this.templatePath('./base/.npmignore'), - this.destinationPath('.npmignore') - ); - this.fs.copyTpl( - this.templatePath('./base/.prettierignore'), - this.destinationPath('.prettierignore') - ); - this.fs.copyTpl( - this.templatePath('./base/.prettierrc.yml'), - this.destinationPath('.prettierrc.yml') - ); + this.fs.copyTpl(this.templatePath('./base'), this.destinationPath(), { ...this.answers }); + this.fs.copyTpl(this.templatePath('./base/.eslintignore'), this.destinationPath('.eslintignore')); + this.fs.copyTpl(this.templatePath('./base/.gitignore'), this.destinationPath('.gitignore')); + this.fs.copyTpl(this.templatePath('./base/.mocharc.yml'), this.destinationPath('.mocharc.yml')); + this.fs.copyTpl(this.templatePath('./base/.npmignore'), this.destinationPath('.npmignore')); + this.fs.copyTpl(this.templatePath('./base/.prettierignore'), this.destinationPath('.prettierignore')); + this.fs.copyTpl(this.templatePath('./base/.prettierrc.yml'), this.destinationPath('.prettierrc.yml')); let templatePath = './boilerplates/simple'; @@ -170,23 +135,17 @@ module.exports = class extends Generator { break; } - this.fs.copyTpl( - this.templatePath(templatePath), - this.destinationPath('./src'), - { ...this.answers } - ); + this.fs.copyTpl(this.templatePath(templatePath), this.destinationPath('./src'), { ...this.answers }); this.fs.copyTpl( this.templatePath(`${templatePath}/.mainnet.ts`), this.destinationPath(`./src/${this.answers.symbol}.ts`), { ...this.answers } ); - - this.fs.copyTpl( - this.templatePath(`${templatePath}/.tsconfig.json`), - this.destinationPath(`./tsconfig.json`), - { ...this.answers } - ); + + this.fs.copyTpl(this.templatePath(`${templatePath}/.tsconfig.json`), this.destinationPath(`./tsconfig.json`), { + ...this.answers, + }); if (this.answers.testnetSymbol) { this.fs.copyTpl( @@ -225,7 +184,7 @@ module.exports = class extends Generator { function getDependencies(contextRoot, depArr) { const dependencies = {}; - depArr.forEach(dependency => { + depArr.forEach((dependency) => { const file = `${contextRoot}/modules/${dependency}/package.json`; const rawData = fs.readFileSync(file); const data = JSON.parse(rawData); @@ -239,11 +198,12 @@ function addNewCoinToTsConfig(contextRoot, answers) { const rawData = fs.readFileSync(file); const data = JSON.parse(rawData); - + data.references.push({ path: `./modules/sdk-coin-${answers.symbol}` }); - data.references = data.references.filter((value, index, self) => - index === self.findIndex((t) => (t.path === value.path))); - data.references.sort((a, b) => a.path > b.path ? 1 : -1); + data.references = data.references.filter( + (value, index, self) => index === self.findIndex((t) => t.path === value.path) + ); + data.references.sort((a, b) => (a.path > b.path ? 1 : -1)); fs.writeFileSync(file, JSON.stringify(data, null, 2).concat('\n')); } @@ -256,7 +216,7 @@ function addNewCoinToBitgo(contextRoot, answers) { data.dependencies[`@bitgo/sdk-coin-${answers.symbol}`] = '^1.0.0'; - const depArr = Object.entries(data.dependencies).sort((a, b) => a[0] > b[0] ? 1 : -1); + const depArr = Object.entries(data.dependencies).sort((a, b) => (a[0] > b[0] ? 1 : -1)); data.dependencies = depArr.reduce((acc, cur) => { acc[cur[0]] = cur[1]; return acc; @@ -272,14 +232,17 @@ function addNewCoinToBitgoTsConfig(contextRoot, answers) { const data = JSON.parse(rawData); data.references.push({ path: `../sdk-coin-${answers.symbol}` }); - data.references = data.references.filter((value, index, self) => - index === self.findIndex((t) => (t.path === value.path))); - data.references.sort((a, b) => a.path > b.path ? 1 : -1); + data.references = data.references.filter( + (value, index, self) => index === self.findIndex((t) => t.path === value.path) + ); + data.references.sort((a, b) => (a.path > b.path ? 1 : -1)); fs.writeFileSync(file, JSON.stringify(data, null, 2).concat('\n')); } function toSentenceCase(theString) { - const newString = theString.toLowerCase().replace(/(^\s*\w|[\.\!\?]\s*\w)/g, function(c) {return c.toUpperCase();}); + const newString = theString.toLowerCase().replace(/(^\s*\w|[\.\!\?]\s*\w)/g, function (c) { + return c.toUpperCase(); + }); return newString; } diff --git a/scripts/update-dockerfile.ts b/scripts/update-dockerfile.ts index b905cf1b8e..815d4988f0 100644 --- a/scripts/update-dockerfile.ts +++ b/scripts/update-dockerfile.ts @@ -15,17 +15,20 @@ type ManagedModule = { */ function getLernaRunner(lernaPath: string) { return async (command: string, args: string[] = [], options = {}) => { - const { stdout } = await execa( - lernaPath, - [command, ...args], - options, - ); + const { stdout } = await execa(lernaPath, [command, ...args], options); return stdout; }; } -const walkDependencies = (packageName: string, setDeps: Set, graph: Record, managedModules: ManagedModule[]) => { - const managedDeps = graph[packageName].filter((dep) => graph[dep]).map((name) => managedModules.find((mod) => mod.name === name)); +const walkDependencies = ( + packageName: string, + setDeps: Set, + graph: Record, + managedModules: ManagedModule[] +) => { + const managedDeps = graph[packageName] + .filter((dep) => graph[dep]) + .map((name) => managedModules.find((mod) => mod.name === name)); managedDeps.forEach((module) => { if (module && !module.private && !setDeps.has(module)) { setDeps.add(module); @@ -40,10 +43,11 @@ const walkDependencies = (packageName: string, setDeps: Set, grap * @returns {Promise<{path: *, name: *, deps: *, version: *}[]>} */ async function updateDockerFile(lerna) { - const depGraph: Record = JSON.parse(await lerna('list', ['--loglevel', 'silent', '--graph', '--all'])); + const depGraph: Record = JSON.parse( + await lerna('list', ['--loglevel', 'silent', '--graph', '--all']) + ); const managedModules: ManagedModule[] = JSON.parse(await lerna('list', ['--loglevel', 'silent', '--json', '--all'])); - const setDeps = new Set(); walkDependencies('@bitgo/express', setDeps, depGraph, managedModules); let dockerContents = fs.readFileSync('Dockerfile', { encoding: 'utf-8' }); @@ -53,8 +57,10 @@ async function updateDockerFile(lerna) { copyContent += `COPY --from=builder /tmp/bitgo${modPath} /var${modPath}/\n`; copyContent += `RUN cd /var${modPath} && yarn link\n`; }); - - const linkers = Array.from(setDeps).map((dep) => ` yarn link ${dep.name}`).join(' && \\\n'); + + const linkers = Array.from(setDeps) + .map((dep) => ` yarn link ${dep.name}`) + .join(' && \\\n'); const linkContent = `RUN cd /var/bitgo-express && \\\n${linkers}\n`; // add metadata about the build to docker labels diff --git a/scripts/verify-release.ts b/scripts/verify-release.ts index 0a52efeaa2..0999570317 100644 --- a/scripts/verify-release.ts +++ b/scripts/verify-release.ts @@ -12,11 +12,7 @@ let lernaModuleLocations: string[] = []; */ function getLernaRunner(lernaPath: string) { return async (command: string, args: string[] = [], options = {}) => { - const { stdout } = await execa( - lernaPath, - [command, ...args], - options, - ); + const { stdout } = await execa(lernaPath, [command, ...args], options); return stdout; }; } @@ -25,13 +21,15 @@ const getLernaModules = async (): Promise => { const { stdout: lernaBinary } = await execa('yarn', ['bin', 'lerna'], { cwd: process.cwd() }); const lerna = getLernaRunner(lernaBinary); - const modules: Array<{name: string, location: string}> = JSON.parse(await lerna('list', ['--loglevel', 'silent', '--json', '--all', '--toposort'])); - - lernaModuleLocations = modules.map(({ location }) => location ); + const modules: Array<{ name: string; location: string }> = JSON.parse( + await lerna('list', ['--loglevel', 'silent', '--json', '--all', '--toposort']) + ); + + lernaModuleLocations = modules.map(({ location }) => location); }; /** - * Makes an HTTP request to fetch all the dist tags for a given package. + * Makes an HTTP request to fetch all the dist tags for a given package. */ const getDistTags = async (packageName: string): Promise> => { return new Promise((resolve) => { @@ -48,7 +46,6 @@ const getDistTags = async (packageName: string): Promise> }); }; - const verifyPackage = async (dir: string, preid: string = 'beta'): Promise => { const cwd = dir; const json = JSON.parse(readFileSync(path.join(cwd, 'package.json'), { encoding: 'utf-8' })); @@ -71,7 +68,7 @@ const verify = async (preid?: string) => { await getLernaModules(); for (let i = 0; i < lernaModuleLocations.length; i++) { const dir = lernaModuleLocations[i]; - if (!await verifyPackage(dir, preid)) { + if (!(await verifyPackage(dir, preid))) { console.error('Failed to verify outstanding packages.'); return; } diff --git a/types/bignumber.js/index.d.ts b/types/bignumber.js/index.d.ts index 2e25549f89..b3c3e74d2b 100644 --- a/types/bignumber.js/index.d.ts +++ b/types/bignumber.js/index.d.ts @@ -5,6 +5,10 @@ import { BigNumber } from 'bignumber.js'; declare module 'bignumber.js' { export declare class BigNumber implements BigNumber.Instance { - toFormat(decimalPlaces: number | null, roundingMode: BigNumber.RoundingMode | null, format?: BigNumber.Format): string; + toFormat( + decimalPlaces: number | null, + roundingMode: BigNumber.RoundingMode | null, + format?: BigNumber.Format + ): string; } } diff --git a/types/should-sinon/index.d.ts b/types/should-sinon/index.d.ts index 7c7cc3edf9..a5ac2749c0 100644 --- a/types/should-sinon/index.d.ts +++ b/types/should-sinon/index.d.ts @@ -13,4 +13,3 @@ declare module 'should' { static add: (name: string, handler: (args: any[]) => void) => void; } } - diff --git a/webpack/bitgojs.config.js b/webpack/bitgojs.config.js index 6800dd7d31..149194780d 100644 --- a/webpack/bitgojs.config.js +++ b/webpack/bitgojs.config.js @@ -11,9 +11,7 @@ module.exports = { resolve: { alias: { // this is only required if using bitgo instead of just the sdk-api - '@hashgraph/sdk': path.resolve( - '../../node_modules/@hashgraph/sdk/src/browser.js', - ), + '@hashgraph/sdk': path.resolve('../../node_modules/@hashgraph/sdk/src/browser.js'), 'superagent-proxy': false, // use the default version here since we're webpacking ourselves '@bitgo/sdk-api': path.resolve('../sdk-api/dist/src/index.js'), @@ -45,7 +43,10 @@ module.exports = { process: 'process/browser', }), - new webpack.NormalModuleReplacementPlugin(/\@emurgo\/cardano-serialization-lib-nodejs/, '@emurgo/cardano-serialization-lib-browser'), + new webpack.NormalModuleReplacementPlugin( + /\@emurgo\/cardano-serialization-lib-nodejs/, + '@emurgo/cardano-serialization-lib-browser' + ), new webpack.ContextReplacementPlugin(/cardano-serialization-lib-browser/), ], diff --git a/webpack/mergeCustomizer.js b/webpack/mergeCustomizer.js index d3f11f45ce..fccc7e0ffb 100644 --- a/webpack/mergeCustomizer.js +++ b/webpack/mergeCustomizer.js @@ -1,8 +1,7 @@ module.exports = { - mergeCustomizer: function(objValue, srcValue) { + mergeCustomizer: function (objValue, srcValue) { if (Array.isArray(objValue)) { return objValue.concat(srcValue); } }, }; -