diff --git a/modules/bitgo/README.md b/modules/bitgo/README.md index f3089e3132..70b6cb2ab1 100644 --- a/modules/bitgo/README.md +++ b/modules/bitgo/README.md @@ -9,6 +9,7 @@ Please email us at support@bitgo.com if you have questions or comments about thi [![Known Vulnerabilities](https://snyk.io/test/github/BitGo/BitGoJS/badge.svg)](https://snyk.io/test/github/BitGo/BitGoJS) [![BitGo SDK](https://github.com/BitGo/BitGoJS/actions/workflows/ci.yml/badge.svg)](https://github.com/BitGo/BitGoJS/actions/workflows/ci.yml) + # Installation Please make sure you are running at least Node version 8 (the latest LTS release is recommended) and NPM version 6. @@ -29,7 +30,9 @@ You can find the complete release notes (since version 4.44.0) [here](https://gi # Example Usage ## Initialize SDK + Create an access token by logging into your bitgo account, going to the API access tab [in the settings area](https://www.bitgo.com/settings) and making a developer token. + ```js const BitGo = require('bitgo'); const bitgo = new BitGo.BitGo({ accessToken: ACCESS_TOKEN }); // defaults to testnet. add env: 'prod' if you want to go against mainnet @@ -38,37 +41,42 @@ console.dir(result); ``` ## Create Wallet + ```js const params = { - "passphrase": "replaceme", - "label": "firstwallet" + passphrase: 'replaceme', + label: 'firstwallet', }; const { wallet } = await bitgo.coin('tbtc').wallets().generateWallet(params); console.dir(wallet); ``` ## Create new address + ```js const address = await wallet.createAddress(); console.dir(address); ``` ## View wallet transfers + ```js const transfers = await wallet.transfers(); ``` ## Send coins + ```js const result = await wallet.sendCoins({ - address: "2NEe9QhKPB2gnQLB3hffMuDcoFKZFjHYJYx", + address: '2NEe9QhKPB2gnQLB3hffMuDcoFKZFjHYJYx', amount: 0.01 * 1e8, - walletPassphrase: "replaceme" + walletPassphrase: 'replaceme', }); console.dir(result); ``` ## More examples + Further demos and examples in both JavaScript and TypeScript can be found in the [example](example) directory. # Enabling additional debugging output @@ -78,21 +86,23 @@ Further demos and examples in both JavaScript and TypeScript can be found in the When using the `bitgo` npm package, the easiest way to enable debug output is by setting the `DEBUG` environment variable to one or more of the debug namespaces in the table below. Multiple debug namespaces can be enabled by giving a comma-separated list or by using `*` as a wildcard. See the [debug package documentation](https://github.com/visionmedia/debug#readme) for more details. ## Available Debug Namespaces -| Namespace | Description | -| --- | --- | -| `bitgo:index` | Core BitGo object. Currently only constant fetch failures and HMAC response failures will emit debug information for this namespace. | -| `bitgo:v1:txb` | Version 1 (legacy) transaction builder | -| `bitgo:v2:pendingapprovals` | Pending approval operations. Currently only wallet fetch errors will emit debug information for this namespace. | -| `bitgo:v2:wallet` | Wallet operations including transaction prebuild, sendMany calls and consolidation transactions | -| `bitgo:v2:utxo` | Low level operations for UTXO coins, including transaction parsing, verification, signing and explanations | -| `bitgo:v2:eth` | Ethereum specific output. Currently only failures to require the optional Ethereum libraries are reported | -| `bitgo:v2:util` | SDK utilities specific output. Currently only failures to require the optional Ethereum libraries are reported | + +| Namespace | Description | +| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| `bitgo:index` | Core BitGo object. Currently only constant fetch failures and HMAC response failures will emit debug information for this namespace. | +| `bitgo:v1:txb` | Version 1 (legacy) transaction builder | +| `bitgo:v2:pendingapprovals` | Pending approval operations. Currently only wallet fetch errors will emit debug information for this namespace. | +| `bitgo:v2:wallet` | Wallet operations including transaction prebuild, sendMany calls and consolidation transactions | +| `bitgo:v2:utxo` | Low level operations for UTXO coins, including transaction parsing, verification, signing and explanations | +| `bitgo:v2:eth` | Ethereum specific output. Currently only failures to require the optional Ethereum libraries are reported | +| `bitgo:v2:util` | SDK utilities specific output. Currently only failures to require the optional Ethereum libraries are reported | Another debug namespace which is not provided by BitGoJS but is helpful nonetheless is the `superagent` namespace, which will output all HTTP requests and responses (only the URL, not bodies). ## Example To run an SDK script with debug output enabled, export the DEBUG environment variable before running. + ```shell script export DEBUG='bitgo:*' # enable all bitgo debug namespaces node myScript.js diff --git a/modules/bitgo/karma.conf.js b/modules/bitgo/karma.conf.js index 5df5c347c5..83e207d427 100644 --- a/modules/bitgo/karma.conf.js +++ b/modules/bitgo/karma.conf.js @@ -6,16 +6,13 @@ if (!process.env.CHROME_BIN) { module.exports = function (config) { config.set({ - // base path that will be used to resolve all patterns (eg. files, exclude) basePath: '', - // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter frameworks: ['jasmine', 'karma-typescript'], - // list of files / patterns to load in the browser files: [ 'dist/browser/BitGoJS.min.js', @@ -24,16 +21,9 @@ module.exports = function (config) { { pattern: 'dist/browser/*.wasm', included: false, served: true, watched: false, nocache: true }, ], - plugins: [ - require('karma-jasmine'), - require('karma-typescript'), - require('karma-chrome-launcher'), - ], + plugins: [require('karma-jasmine'), require('karma-typescript'), require('karma-chrome-launcher')], // list of files / patterns to exclude - exclude: [ - 'node_modules', - ], - + exclude: ['node_modules'], // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor @@ -47,13 +37,7 @@ module.exports = function (config) { compilerOptions: { sourceMap: true, target: 'es6', - lib: [ - 'dom', - 'es6', - 'es5', - 'es2017', - 'es2018', - ], + lib: ['dom', 'es6', 'es5', 'es2017', 'es2018'], types: ['jasmine'], }, include: ['test/browser/**/*.ts'], @@ -64,24 +48,19 @@ module.exports = function (config) { // available reporters: https://npmjs.org/browse/keyword/karma-reporter reporters: ['progress'], - // web server port port: 9876, - // enable / disable colors in the output (reporters and logs) colors: true, - // level of logging // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG logLevel: config.LOG_INFO, - // enable / disable watching file and executing tests whenever any file changes autoWatch: true, - // start these browsers browsers: ['HeadlessChromeNoSandbox'], customLaunchers: { diff --git a/modules/bitgo/scripts/upload-docs.js b/modules/bitgo/scripts/upload-docs.js index 1709d195c1..1395c3370a 100755 --- a/modules/bitgo/scripts/upload-docs.js +++ b/modules/bitgo/scripts/upload-docs.js @@ -4,10 +4,7 @@ const S3 = require('aws-sdk/clients/s3'); const { version } = require('../package.json'); const { promisify } = require('util'); -const { - reports_s3_akid, - reports_s3_sak, -} = process.env; +const { reports_s3_akid, reports_s3_sak } = process.env; const s3 = new S3({ accessKeyId: reports_s3_akid, @@ -92,6 +89,5 @@ async function uploadDocs(root, key) { if (!fs.existsSync(DOCS_ROOT) || !fs.statSync(DOCS_ROOT).isDirectory()) { console.warn(`Docs directory '${DOCS_ROOT}' not found. Skipping docs upload...`); } else { - uploadDocs(DOCS_ROOT, OBJECT_ROOT) - .catch((e) => console.error('fatal', e, e.stack)); + uploadDocs(DOCS_ROOT, OBJECT_ROOT).catch((e) => console.error('fatal', e, e.stack)); } diff --git a/modules/bitgo/scripts/upload-tools/README.md b/modules/bitgo/scripts/upload-tools/README.md index 0999afc03c..b3a6643b03 100644 --- a/modules/bitgo/scripts/upload-tools/README.md +++ b/modules/bitgo/scripts/upload-tools/README.md @@ -3,8 +3,10 @@ `bitgo/upload-tools` is a `node:10`-derived docker image which has a few npm packages pre-installed to reduce install times during builds. Currently, the following binaries are installed via `yarn global add`: -* `codecov` -* `typedoc` + +- `codecov` +- `typedoc` The following libraries are installed via `yarn add`: -* `aws-sdk` + +- `aws-sdk` diff --git a/modules/bitgo/src/bitgo.ts b/modules/bitgo/src/bitgo.ts index fcfa160eb1..1f51a6758a 100644 --- a/modules/bitgo/src/bitgo.ts +++ b/modules/bitgo/src/bitgo.ts @@ -8,10 +8,7 @@ import * as _ from 'lodash'; import GlobalCoinFactory from './v2/coinFactory'; import { BaseCoin, common } from '@bitgo/sdk-core'; -import { - BitGoAPI, - BitGoAPIOptions, -} from '@bitgo/sdk-api'; +import { BitGoAPI, BitGoAPIOptions } from '@bitgo/sdk-api'; export type BitGoOptions = BitGoAPIOptions; @@ -21,12 +18,28 @@ export class BitGo extends BitGoAPI { */ constructor(params: BitGoAPIOptions = {}) { super(params); - if (!common.validateParams(params, [], ['clientId', 'clientSecret', 'refreshToken', 'accessToken', 'userAgent', 'customRootURI', 'customBitcoinNetwork', 'serverXpub', 'stellarFederationServerUrl']) || - (params.useProduction && !_.isBoolean(params.useProduction))) { + if ( + !common.validateParams( + params, + [], + [ + 'clientId', + 'clientSecret', + 'refreshToken', + 'accessToken', + 'userAgent', + 'customRootURI', + 'customBitcoinNetwork', + 'serverXpub', + 'stellarFederationServerUrl', + ] + ) || + (params.useProduction && !_.isBoolean(params.useProduction)) + ) { throw new Error('invalid argument'); } - if ((!params.clientId) !== (!params.clientSecret)) { + if (!params.clientId !== !params.clientSecret) { throw new Error('invalid argument - must provide both client id and secret'); } diff --git a/modules/bitgo/src/config.ts b/modules/bitgo/src/config.ts index bcbf5b43ce..a31b514392 100644 --- a/modules/bitgo/src/config.ts +++ b/modules/bitgo/src/config.ts @@ -1,4 +1,3 @@ import { ethGasConfigs, mainnetTokens, testnetTokens, Tokens, tokens } from '@bitgo/statics'; import { Config, defaults, defaultConstants } from '@bitgo/sdk-core'; export { Config, defaultConstants, defaults, ethGasConfigs, mainnetTokens, testnetTokens, tokens, Tokens }; - diff --git a/modules/bitgo/src/v2/coins/index.ts b/modules/bitgo/src/v2/coins/index.ts index f659374810..042c5f3c06 100644 --- a/modules/bitgo/src/v2/coins/index.ts +++ b/modules/bitgo/src/v2/coins/index.ts @@ -82,4 +82,3 @@ export { Tzec, Zec }; import { coins } from '@bitgo/sdk-core'; const { Ofc, OfcToken, Susd, FiatUsd, FiatEur, FiatGBP, Tsusd, TfiatUsd, TfiatEur, TfiatGBP } = coins; export { FiatEur, FiatGBP, FiatUsd, Ofc, OfcToken, Susd, TfiatEur, TfiatGBP, TfiatUsd, Tsusd }; - diff --git a/modules/bitgo/src/v2/internal/seedValidator.ts b/modules/bitgo/src/v2/internal/seedValidator.ts index b06de035ef..bf02ae4b79 100644 --- a/modules/bitgo/src/v2/internal/seedValidator.ts +++ b/modules/bitgo/src/v2/internal/seedValidator.ts @@ -7,7 +7,6 @@ import { Hbar, Algo } from '@bitgo/account-lib'; * This classes intention is to guess/verify what seeds come from where. */ export class SeedValidator { - /** * Try to guess what kind of seed this could be * @param seed @@ -66,5 +65,4 @@ export class SeedValidator { } return true; } - } diff --git a/modules/bitgo/test/browser/browser.spec.ts b/modules/bitgo/test/browser/browser.spec.ts index dea645efc6..27cb43b92e 100644 --- a/modules/bitgo/test/browser/browser.spec.ts +++ b/modules/bitgo/test/browser/browser.spec.ts @@ -1,49 +1,51 @@ describe('BitGoJS in the browser', () => { - it('Should work', () => { - const BitGoJS = window['BitGoJS']; - expect(BitGoJS).toBeTruthy(); - }); + it('Should work', () => { + const BitGoJS = window['BitGoJS']; + expect(BitGoJS).toBeTruthy(); + }); }); describe('Coins', () => { - it('Should work for all coins', () => { - const BitGoJS = window['BitGoJS']; - const bitgo = new BitGoJS.BitGo({ env: 'test' }); - // these objects are defined in BitGoJS.Coin, but are not coins in the traditional sense - const excludedKeys = { - 'AbstractUtxoCoin': 1, - 'Erc20Token': 1, - 'OfcToken': 1, - 'StellarToken': 1, - 'CeloToken': 1, - 'EosToken': 1, - 'AlgoToken': 1, - 'AvaxCToken': 1, - 'PolygonToken': 1, - 'BscToken': 1, - }; - Object.keys(BitGoJS.Coin) - .filter((coinName) => !excludedKeys[coinName]) - .forEach((coinName) => { - const coinIdentifier = coinName.toLowerCase(); - const coin = bitgo.coin(coinIdentifier); - expect(coin).toBeTruthy(); - expect(coin.type).toEqual(coinIdentifier); - }) - }) + it('Should work for all coins', () => { + const BitGoJS = window['BitGoJS']; + const bitgo = new BitGoJS.BitGo({ env: 'test' }); + // these objects are defined in BitGoJS.Coin, but are not coins in the traditional sense + const excludedKeys = { + AbstractUtxoCoin: 1, + Erc20Token: 1, + OfcToken: 1, + StellarToken: 1, + CeloToken: 1, + EosToken: 1, + AlgoToken: 1, + AvaxCToken: 1, + PolygonToken: 1, + BscToken: 1, + }; + Object.keys(BitGoJS.Coin) + .filter((coinName) => !excludedKeys[coinName]) + .forEach((coinName) => { + const coinIdentifier = coinName.toLowerCase(); + const coin = bitgo.coin(coinIdentifier); + expect(coin).toBeTruthy(); + expect(coin.type).toEqual(coinIdentifier); + }); + }); - it('UTXO bufferutils should work', () => { - const BitGoJS = window['BitGoJS']; - const bitgo = new BitGoJS.BitGo({ env: 'test' }); + it('UTXO bufferutils should work', () => { + const BitGoJS = window['BitGoJS']; + const bitgo = new BitGoJS.BitGo({ env: 'test' }); - const txHex = '0100000002008287fa5a4e9d393134b525ae038cbcb4c757eadaa378c33caeed294c63137f000000006b48304502204dc8131adb9420729ff1580bbbcf01f5ef879defee5225a8261b5681075b8a120221009dc3386f5301ab4a88dfd89d8927a7807242a30ee252fa864d61d0b079aaa2c20121038c4b3c81572d84ce32a2a41c5bb54d4c408b5ce3df9be451f4f57ba8bd8ebf59ffffffff17ed0cc32384bf9c410d023d4ab25f4499992824308e89c448fd570e1060fc0e000000006b48304502202c0ff069c0783c11259936307ef906b211542a01ca33cf6993ddb7b8d55b42ac02210095c4bceb1886f5bcc6ca2dbb909259c0509e768693a93fe2d01d511a57356f25012102e99ed9483d91f1fa67abd838f21afd80bf6a3732128ab5aad0ee5b975679c13dffffffff02bca2b100000000001976a914cc3aa0deca267914cbcf96f79ccd1b679d85e20188ac08c2eb0b000000001976a914380c5a7247e945a5aa242056f9b046a9366fe21788ac00000000'; - const btc = bitgo.coin('btc'); - const tx = btc.createTransactionFromHex(txHex); - expect(tx.getId()).toEqual('4f666850ac8a54c834a90e62fc9dc50b3c99275dd1f91960e1ea89813970e444'); + const txHex = + '0100000002008287fa5a4e9d393134b525ae038cbcb4c757eadaa378c33caeed294c63137f000000006b48304502204dc8131adb9420729ff1580bbbcf01f5ef879defee5225a8261b5681075b8a120221009dc3386f5301ab4a88dfd89d8927a7807242a30ee252fa864d61d0b079aaa2c20121038c4b3c81572d84ce32a2a41c5bb54d4c408b5ce3df9be451f4f57ba8bd8ebf59ffffffff17ed0cc32384bf9c410d023d4ab25f4499992824308e89c448fd570e1060fc0e000000006b48304502202c0ff069c0783c11259936307ef906b211542a01ca33cf6993ddb7b8d55b42ac02210095c4bceb1886f5bcc6ca2dbb909259c0509e768693a93fe2d01d511a57356f25012102e99ed9483d91f1fa67abd838f21afd80bf6a3732128ab5aad0ee5b975679c13dffffffff02bca2b100000000001976a914cc3aa0deca267914cbcf96f79ccd1b679d85e20188ac08c2eb0b000000001976a914380c5a7247e945a5aa242056f9b046a9366fe21788ac00000000'; + const btc = bitgo.coin('btc'); + const tx = btc.createTransactionFromHex(txHex); + expect(tx.getId()).toEqual('4f666850ac8a54c834a90e62fc9dc50b3c99275dd1f91960e1ea89813970e444'); - const txHexBig = '0100000002008287fa5a4e9d393134b525ae038cbcb4c757eadaa378c33caeed294c63137f000000006b48304502204dc8131adb9420729ff1580bbbcf01f5ef879defee5225a8261b5681075b8a120221009dc3386f5301ab4a88dfd89d8927a7807242a30ee252fa864d61d0b079aaa2c20121038c4b3c81572d84ce32a2a41c5bb54d4c408b5ce3df9be451f4f57ba8bd8ebf59ffffffff17ed0cc32384bf9c410d023d4ab25f4499992824308e89c448fd570e1060fc0e000000006b48304502202c0ff069c0783c11259936307ef906b211542a01ca33cf6993ddb7b8d55b42ac02210095c4bceb1886f5bcc6ca2dbb909259c0509e768693a93fe2d01d511a57356f25012102e99ed9483d91f1fa67abd838f21afd80bf6a3732128ab5aad0ee5b975679c13dffffffff02f8ffc42ebca2b1001976a914cc3aa0deca267914cbcf96f79ccd1b679d85e20188ac08c2eb0b000000001976a914380c5a7247e945a5aa242056f9b046a9366fe21788ac00000000'; - const doge = bitgo.coin('doge'); - const txBig = doge.createTransactionFromHex(txHexBig); - expect(txBig.outs[0].value.toString()).toEqual('49999999999999992'); - }) + const txHexBig = + '0100000002008287fa5a4e9d393134b525ae038cbcb4c757eadaa378c33caeed294c63137f000000006b48304502204dc8131adb9420729ff1580bbbcf01f5ef879defee5225a8261b5681075b8a120221009dc3386f5301ab4a88dfd89d8927a7807242a30ee252fa864d61d0b079aaa2c20121038c4b3c81572d84ce32a2a41c5bb54d4c408b5ce3df9be451f4f57ba8bd8ebf59ffffffff17ed0cc32384bf9c410d023d4ab25f4499992824308e89c448fd570e1060fc0e000000006b48304502202c0ff069c0783c11259936307ef906b211542a01ca33cf6993ddb7b8d55b42ac02210095c4bceb1886f5bcc6ca2dbb909259c0509e768693a93fe2d01d511a57356f25012102e99ed9483d91f1fa67abd838f21afd80bf6a3732128ab5aad0ee5b975679c13dffffffff02f8ffc42ebca2b1001976a914cc3aa0deca267914cbcf96f79ccd1b679d85e20188ac08c2eb0b000000001976a914380c5a7247e945a5aa242056f9b046a9366fe21788ac00000000'; + const doge = bitgo.coin('doge'); + const txBig = doge.createTransactionFromHex(txHexBig); + expect(txBig.outs[0].value.toString()).toEqual('49999999999999992'); + }); }); diff --git a/modules/bitgo/test/browser/karmaHelper.js b/modules/bitgo/test/browser/karmaHelper.js index 395eef3ad8..c5fc234046 100644 --- a/modules/bitgo/test/browser/karmaHelper.js +++ b/modules/bitgo/test/browser/karmaHelper.js @@ -1,11 +1,11 @@ // intercept & mock all the redudant calls to fetch constants by the browser -(function(global) { - const constants = {}; - BitGoJS.BitGo.prototype.getConstants = (params) => constants; - BitGoJS.BitGo.prototype.fetchConstants = (params, callback) => +(function (global) { + const constants = {}; + BitGoJS.BitGo.prototype.getConstants = (params) => constants; + BitGoJS.BitGo.prototype.fetchConstants = (params, callback) => new Promise((resolve) => { resolve({ ...constants, }); }); -})(window) \ No newline at end of file +})(window); diff --git a/modules/bitgo/test/integration/accesstoken.ts b/modules/bitgo/test/integration/accesstoken.ts index 83f03ee304..bd27a0a7dc 100644 --- a/modules/bitgo/test/integration/accesstoken.ts +++ b/modules/bitgo/test/integration/accesstoken.ts @@ -22,11 +22,14 @@ describe('Access Token', function () { before(function () { bitgo = new TestBitGo(); bitgo.initializeTestVars(); - return bitgo.authenticateTestUser(bitgo.testUserOTP()) + return bitgo + .authenticateTestUser(bitgo.testUserOTP()) .then(function () { loginAccessTokenHex = bitgo._token; - const filterFunc = function (tok) { return tok.label; }; + const filterFunc = function (tok) { + return tok.label; + }; return TestUtil.deleteTestTokens(bitgo, filterFunc); }) .then(function () { @@ -40,7 +43,8 @@ describe('Access Token', function () { describe('authentication with access token', function () { let addedTokenHex; it('should authenticate with added access token', function () { - return bitgo.addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', scope: someScopes }) + return bitgo + .addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', scope: someScopes }) .then(function (res) { addedTokenHex = res.token; return bitgo.authenticateWithAccessToken({ accessToken: addedTokenHex }); @@ -62,40 +66,56 @@ describe('Access Token', function () { describe('Add', function () { describe('bad args', function () { it('arguments', function () { - assert.throws(function () { bitgo.addAccessToken({}, 'invalid'); }); - assert.throws(function () { bitgo.addAccessToken({}, function () {}); }); + assert.throws(function () { + bitgo.addAccessToken({}, 'invalid'); + }); + assert.throws(function () { + bitgo.addAccessToken({}, function () {}); + }); assert.throws(function () { - bitgo.addAccessToken({ - otp: bitgo.testUserOTP(), - scope: ['wallet_view_all', 'openid', 'profile'], - }, 'invalid'); + bitgo.addAccessToken( + { + otp: bitgo.testUserOTP(), + scope: ['wallet_view_all', 'openid', 'profile'], + }, + 'invalid' + ); }); }); it('fails to add without scope', function () { assert.throws(function () { - bitgo.addAccessToken({ - otp: bitgo.testUserOTP(), - }, function () {}); + bitgo.addAccessToken( + { + otp: bitgo.testUserOTP(), + }, + function () {} + ); }); }); it('fails to add with empty scope', function () { assert.throws(function () { - bitgo.addAccessToken({ - otp: bitgo.testUserOTP(), - scope: [], - }, function () {}); + bitgo.addAccessToken( + { + otp: bitgo.testUserOTP(), + scope: [], + }, + function () {} + ); }); }); it('fails to add with incorrect type of scope', function () { assert.throws(function () { - bitgo.addAccessToken({ - otp: bitgo.testUserOTP(), - scope: 'notAnArray', - }, function () {}); + bitgo.addAccessToken( + { + otp: bitgo.testUserOTP(), + scope: 'notAnArray', + }, + function () {} + ); }); }); @@ -111,13 +131,13 @@ describe('Access Token', function () { }); describe('success', function () { - afterEach(function () { return bitgo.removeAccessToken({ label: 'test token' }); }); it('simple add', function () { - return bitgo.addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', scope: someScopes }) + return bitgo + .addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', scope: someScopes }) .then(function (res) { res.should.have.property('user'); res.should.have.property('scope'); @@ -144,13 +164,14 @@ describe('Access Token', function () { it('duration', function () { const DURATION = 3600 * 10; // ten days - return bitgo.addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', duration: DURATION, scope: someScopes }) + return bitgo + .addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', duration: DURATION, scope: someScopes }) .then(function (res) { res.label.should.equal('test token'); const created = res.created; const expires = res.expires; - const createdPlusDuration = new Date(new Date(created).getTime() + (DURATION * 1000)).getTime(); + const createdPlusDuration = new Date(new Date(created).getTime() + DURATION * 1000).getTime(); const expiresTime = new Date(expires).getTime(); const leeway = 10; // because of the miniscule time it takes to execute a function, we give a 10 ms leeway in the time differences createdPlusDuration.should.be.greaterThan(expiresTime - leeway); @@ -160,7 +181,8 @@ describe('Access Token', function () { it('ipRestrict', function () { const IPRESTRICT = ['0.0.0.0', '8.8.8.8']; - return bitgo.addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', ipRestrict: IPRESTRICT, scope: someScopes }) + return bitgo + .addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', ipRestrict: IPRESTRICT, scope: someScopes }) .then(function (token) { token.should.have.property('token'); }); @@ -168,7 +190,13 @@ describe('Access Token', function () { it('txValueLimit', function () { const TXVALUELIMIT = 1e8; // 1 BTC - return bitgo.addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', txValueLimit: TXVALUELIMIT, scope: someScopes }) + return bitgo + .addAccessToken({ + otp: bitgo.testUserOTP(), + label: 'test token', + txValueLimit: TXVALUELIMIT, + scope: someScopes, + }) .then(function (res) { res.unlock.txValueLimit.should.equal(1e8); }); @@ -176,7 +204,8 @@ describe('Access Token', function () { // see some examples of Scope Values under https://www.bitgo.com/api/#partner-oauth it('scopes', function () { - return bitgo.addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', scope: someScopes }) + return bitgo + .addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', scope: someScopes }) .then(function (res) { res.scope.should.have.length(4); }); @@ -186,14 +215,14 @@ describe('Access Token', function () { describe('List', function () { it('should list no new access token', function () { - return bitgo.listAccessTokens() - .then(function (tokens) { - tokens.length.should.equal(INITIAL_TOKEN_COUNT); - }); + return bitgo.listAccessTokens().then(function (tokens) { + tokens.length.should.equal(INITIAL_TOKEN_COUNT); + }); }); it('should add and list single access token', function () { - return bitgo.addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', scope: someScopes }) + return bitgo + .addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', scope: someScopes }) .then(function (res) { res.label.should.equal('test token'); @@ -211,7 +240,8 @@ describe('Access Token', function () { it('should add another and list multiple access tokens', function () { let token1; let token2; - return bitgo.addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token 2', scope: someScopes }) + return bitgo + .addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token 2', scope: someScopes }) .then(function (res) { res.label.should.equal('test token 2'); @@ -251,15 +281,24 @@ describe('Access Token', function () { }); it('arguments', function () { - assert.throws(function () { bitgo.removeAccessToken({}, 'invalid'); }); - assert.throws(function () { bitgo.removeAccessToken({}, function () {}); }); - assert.throws(function () { bitgo.removeAccessToken({ id: 'non-existent id' }, 'invalid'); }); - assert.throws(function () { bitgo.removeAccessToken({ label: 'non-existent label' }, 'invalid'); }); + assert.throws(function () { + bitgo.removeAccessToken({}, 'invalid'); + }); + assert.throws(function () { + bitgo.removeAccessToken({}, function () {}); + }); + assert.throws(function () { + bitgo.removeAccessToken({ id: 'non-existent id' }, 'invalid'); + }); + assert.throws(function () { + bitgo.removeAccessToken({ label: 'non-existent label' }, 'invalid'); + }); }); it('should fail with ambigous remove', function () { // begin by adding second token - return bitgo.addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', scope: someScopes }) + return bitgo + .addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', scope: someScopes }) .then(function (token) { ambiguousTokenId = token.id; const promise = bitgo.removeAccessToken({ label: 'test token' }); @@ -268,7 +307,8 @@ describe('Access Token', function () { }); it('should remove by label', function () { - return bitgo.listAccessTokens() + return bitgo + .listAccessTokens() .then(function (tokens) { tokens.length.should.equal(INITIAL_TOKEN_COUNT + 2); @@ -292,7 +332,8 @@ describe('Access Token', function () { }); it('should remove access token by id', function () { - return bitgo.addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', scope: someScopes }) + return bitgo + .addAccessToken({ otp: bitgo.testUserOTP(), label: 'test token', scope: someScopes }) .then(function (tok) { return bitgo.removeAccessToken({ id: tok.id }); }) diff --git a/modules/bitgo/test/integration/blockchain.ts b/modules/bitgo/test/integration/blockchain.ts index a91639d8d1..4b7cab083a 100644 --- a/modules/bitgo/test/integration/blockchain.ts +++ b/modules/bitgo/test/integration/blockchain.ts @@ -34,8 +34,12 @@ describe('Address', function () { describe('Get Address', function () { it('arguments', function (done) { - assert.throws(function () { blockchain.getAddress('invalid', function () {}); }); - assert.throws(function () { blockchain.getAddress({}); }); + assert.throws(function () { + blockchain.getAddress('invalid', function () {}); + }); + assert.throws(function () { + blockchain.getAddress({}); + }); done(); }); @@ -53,8 +57,12 @@ describe('Address', function () { describe('Get Address Transactions', function () { it('arguments', function (done) { - assert.throws(function () { blockchain.getAddressTransactions('invalid', function () {}); }); - assert.throws(function () { blockchain.getAddressTransactions({}); }); + assert.throws(function () { + blockchain.getAddressTransactions('invalid', function () {}); + }); + assert.throws(function () { + blockchain.getAddressTransactions({}); + }); done(); }); @@ -88,9 +96,15 @@ describe('Address', function () { describe('Get Address Unspents', function () { it('arguments', function (done) { - assert.throws(function () { blockchain.getAddressUnspents('invalid', function () {}); }); - assert.throws(function () { blockchain.getAddressUnspents({ limit: 'a string!' }, function () {}); }); - assert.throws(function () { blockchain.getAddressUnspents({}); }); + assert.throws(function () { + blockchain.getAddressUnspents('invalid', function () {}); + }); + assert.throws(function () { + blockchain.getAddressUnspents({ limit: 'a string!' }, function () {}); + }); + assert.throws(function () { + blockchain.getAddressUnspents({}); + }); done(); }); @@ -106,9 +120,15 @@ describe('Address', function () { describe('Get Transaction', function () { it('arguments', function (done) { - assert.throws(function () { blockchain.getTransaction('invalid', function () {}); }); - assert.throws(function () { blockchain.getTransaction({}); }); - assert.throws(function () { blockchain.getTransaction({}, function () {}); }); + assert.throws(function () { + blockchain.getTransaction('invalid', function () {}); + }); + assert.throws(function () { + blockchain.getTransaction({}); + }); + assert.throws(function () { + blockchain.getTransaction({}, function () {}); + }); done(); }); @@ -131,12 +151,30 @@ describe('Address', function () { describe('Get Transaction By Input', function () { it('arguments', function (done) { - assert.throws(function () { blockchain.getTransactionByInput('invalid', function () {}); }); - assert.throws(function () { blockchain.getTransactionByInput({ txid: '90411397fd43aa1e285a0c2b3ac8cb341f26805e14e69264dacf91801d9fd6e2' }, function () {}); }); - assert.throws(function () { blockchain.getTransactionByInput({ vout: 999 }, function () {}); }); - assert.throws(function () { blockchain.getTransactionByInput({ txid: '90411397fd43aa1e285a0c2b3ac8cb341f26805e14e69264dacf91801d9fd6e2', vout: 'asdf' }, function () {}); }); - assert.throws(function () { blockchain.getTransactionByInput({}); }); - assert.throws(function () { blockchain.getTransactionByInput({}, function () {}); }); + assert.throws(function () { + blockchain.getTransactionByInput('invalid', function () {}); + }); + assert.throws(function () { + blockchain.getTransactionByInput( + { txid: '90411397fd43aa1e285a0c2b3ac8cb341f26805e14e69264dacf91801d9fd6e2' }, + function () {} + ); + }); + assert.throws(function () { + blockchain.getTransactionByInput({ vout: 999 }, function () {}); + }); + assert.throws(function () { + blockchain.getTransactionByInput( + { txid: '90411397fd43aa1e285a0c2b3ac8cb341f26805e14e69264dacf91801d9fd6e2', vout: 'asdf' }, + function () {} + ); + }); + assert.throws(function () { + blockchain.getTransactionByInput({}); + }); + assert.throws(function () { + blockchain.getTransactionByInput({}, function () {}); + }); done(); }); @@ -162,9 +200,15 @@ describe('Address', function () { describe('Get Block', function () { it('arguments', function (done) { - assert.throws(function () { blockchain.getBlock('invalid', function () {}); }); - assert.throws(function () { blockchain.getBlock({}); }); - assert.throws(function () { blockchain.getBlock({}, function () {}); }); + assert.throws(function () { + blockchain.getBlock('invalid', function () {}); + }); + assert.throws(function () { + blockchain.getBlock({}); + }); + assert.throws(function () { + blockchain.getBlock({}, function () {}); + }); done(); }); diff --git a/modules/bitgo/test/integration/enterprise.ts b/modules/bitgo/test/integration/enterprise.ts index f1463db854..8d68f61333 100644 --- a/modules/bitgo/test/integration/enterprise.ts +++ b/modules/bitgo/test/integration/enterprise.ts @@ -13,97 +13,108 @@ const BigNumber = require('bignumber.js'); const TestBitGo = require('../lib/test_bitgo'); describe('Enterprise', function () { - let bitgo; - before(co(function *() { - bitgo = new TestBitGo({ env: 'test' }); - bitgo.initializeTestVars(); - yield bitgo.authenticateEnterpriseCreatorTestUser(bitgo.testUserOTP()); - - })); + before( + co(function* () { + bitgo = new TestBitGo({ env: 'test' }); + bitgo.initializeTestVars(); + yield bitgo.authenticateEnterpriseCreatorTestUser(bitgo.testUserOTP()); + }) + ); describe('Fetch Enterprise', function () { - - it('should fetch an enterprise', co(function *() { - const enterprises = bitgo.coin('tltc').enterprises(); - const entList = yield enterprises.list(); - entList.length.should.be.greaterThan(6); - const enterprise1 = entList[0]; - enterprise1.id.should.equal('5a84db9be4b3cab007c08ab59fb93ec3'); - enterprise1.name.should.equal('Test Enterprise'); - })); - - it('should fetch the users of an enterprise', co(function *() { - const enterprises = bitgo.coin('tltc').enterprises(); - const enterprise = (yield enterprises.list())[0]; - const users = yield enterprise.users(); - users.should.have.property('adminUsers'); - users.should.have.property('walletUsers'); - const { adminUsers, walletUsers } = users; - adminUsers.length.should.equal(2); - walletUsers.length.should.equal(1); - const walletUser = walletUsers[0]; - walletUser.should.have.property('id'); - walletUser.should.have.property('username'); - walletUser.id.should.equal('5a84db312cd303af07897eebb5a0fba2'); - walletUser.username.should.equal('enterprisecreator@bitgo.com'); - const adminUser = adminUsers[0]; - adminUser.should.have.property('id'); - adminUser.should.have.property('username'); - adminUser.should.have.property('verified'); - adminUser.id.should.equal('5a849b8cb6f7cb5007b77741e632675a'); - adminUser.username.should.equal('enterprisetester@bitgo.com'); - adminUser.verified.should.equal(true); - })); - - it('should fetch an enterprise eth fee balance', co(function *() { - const enterprises = bitgo.coin('teth').enterprises(); - const enterprise = (yield enterprises.list())[0]; - const feeBalance = yield enterprise.getFeeAddressBalance(); - feeBalance.should.have.property('balance'); - const balance = new BigNumber(feeBalance.balance); - balance.greaterThan(1000).should.equal(true); - })); + it( + 'should fetch an enterprise', + co(function* () { + const enterprises = bitgo.coin('tltc').enterprises(); + const entList = yield enterprises.list(); + entList.length.should.be.greaterThan(6); + const enterprise1 = entList[0]; + enterprise1.id.should.equal('5a84db9be4b3cab007c08ab59fb93ec3'); + enterprise1.name.should.equal('Test Enterprise'); + }) + ); + + it( + 'should fetch the users of an enterprise', + co(function* () { + const enterprises = bitgo.coin('tltc').enterprises(); + const enterprise = (yield enterprises.list())[0]; + const users = yield enterprise.users(); + users.should.have.property('adminUsers'); + users.should.have.property('walletUsers'); + const { adminUsers, walletUsers } = users; + adminUsers.length.should.equal(2); + walletUsers.length.should.equal(1); + const walletUser = walletUsers[0]; + walletUser.should.have.property('id'); + walletUser.should.have.property('username'); + walletUser.id.should.equal('5a84db312cd303af07897eebb5a0fba2'); + walletUser.username.should.equal('enterprisecreator@bitgo.com'); + const adminUser = adminUsers[0]; + adminUser.should.have.property('id'); + adminUser.should.have.property('username'); + adminUser.should.have.property('verified'); + adminUser.id.should.equal('5a849b8cb6f7cb5007b77741e632675a'); + adminUser.username.should.equal('enterprisetester@bitgo.com'); + adminUser.verified.should.equal(true); + }) + ); + + it( + 'should fetch an enterprise eth fee balance', + co(function* () { + const enterprises = bitgo.coin('teth').enterprises(); + const enterprise = (yield enterprises.list())[0]; + const feeBalance = yield enterprise.getFeeAddressBalance(); + feeBalance.should.have.property('balance'); + const balance = new BigNumber(feeBalance.balance); + balance.greaterThan(1000).should.equal(true); + }) + ); }); // TODO: remove enterprises after creating them once the functionality is available describe('Modify Enterprise', function () { - // TODO: figure out how to approve the removal request from another user - it('should add and remove user from enterprise', co(function *() { - const enterprise = yield bitgo.coin('tltc').enterprises().create({ name: 'Test Enterprise' }); - const refetchedEnterprise = yield bitgo.coin('tltc').enterprises().get({ id: enterprise.id }); - const users0 = yield refetchedEnterprise.users(); - yield enterprise.addUser({ username: 'enterprisetester@bitgo.com' }); - const users1 = yield refetchedEnterprise.users(); - const removalPendingApproval = yield enterprise.removeUser({ username: 'enterprisetester@bitgo.com' }); - enterprise.id.should.equal(refetchedEnterprise.id); - refetchedEnterprise.name.should.equal('Test Enterprise'); - users0.adminUsers.length.should.equal(1); - users1.adminUsers.length.should.equal(2); - users0.walletUsers.length.should.equal(0); - users1.walletUsers.length.should.equal(0); - removalPendingApproval.state.should.equal('pending'); - })); - - it('should add wallets and then list them on an enterprise', co(function *coEnterpriseWalletAdditionTest() { - const enterprise = yield bitgo.coin('tltc').enterprises().create({ name: 'Test Enterprise' }); - const wallet = yield bitgo.coin('tltc').wallets().generateWallet({ - label: 'Enterprise Test Wallet', - enterprise: enterprise.id, - passphrase: TestBitGo.TEST_WALLET1_PASSCODE, - }); - const enterpriseWallets = yield enterprise.coinWallets(); - enterpriseWallets.should.have.property('wallets'); - enterpriseWallets.wallets.length.should.equal(1); - enterpriseWallets.wallets[0].id().should.equal(wallet.wallet.id()); - yield wallet.wallet.remove(); - const updatedEnterpriseWallets = yield enterprise.coinWallets(); - updatedEnterpriseWallets.should.have.property('wallets'); - updatedEnterpriseWallets.wallets.length.should.equal(0); - })); - + it( + 'should add and remove user from enterprise', + co(function* () { + const enterprise = yield bitgo.coin('tltc').enterprises().create({ name: 'Test Enterprise' }); + const refetchedEnterprise = yield bitgo.coin('tltc').enterprises().get({ id: enterprise.id }); + const users0 = yield refetchedEnterprise.users(); + yield enterprise.addUser({ username: 'enterprisetester@bitgo.com' }); + const users1 = yield refetchedEnterprise.users(); + const removalPendingApproval = yield enterprise.removeUser({ username: 'enterprisetester@bitgo.com' }); + enterprise.id.should.equal(refetchedEnterprise.id); + refetchedEnterprise.name.should.equal('Test Enterprise'); + users0.adminUsers.length.should.equal(1); + users1.adminUsers.length.should.equal(2); + users0.walletUsers.length.should.equal(0); + users1.walletUsers.length.should.equal(0); + removalPendingApproval.state.should.equal('pending'); + }) + ); + + it( + 'should add wallets and then list them on an enterprise', + co(function* coEnterpriseWalletAdditionTest() { + const enterprise = yield bitgo.coin('tltc').enterprises().create({ name: 'Test Enterprise' }); + const wallet = yield bitgo.coin('tltc').wallets().generateWallet({ + label: 'Enterprise Test Wallet', + enterprise: enterprise.id, + passphrase: TestBitGo.TEST_WALLET1_PASSCODE, + }); + const enterpriseWallets = yield enterprise.coinWallets(); + enterpriseWallets.should.have.property('wallets'); + enterpriseWallets.wallets.length.should.equal(1); + enterpriseWallets.wallets[0].id().should.equal(wallet.wallet.id()); + yield wallet.wallet.remove(); + const updatedEnterpriseWallets = yield enterprise.coinWallets(); + updatedEnterpriseWallets.should.have.property('wallets'); + updatedEnterpriseWallets.wallets.length.should.equal(0); + }) + ); }); - }); diff --git a/modules/bitgo/test/integration/index.html b/modules/bitgo/test/integration/index.html index 465a209373..32c4c42e4e 100644 --- a/modules/bitgo/test/integration/index.html +++ b/modules/bitgo/test/integration/index.html @@ -2,14 +2,16 @@