- yarn version 1 (classic)
- node version >=14.18.0 and <17
In the BitGoJS/ directory:
$ yarn install
API and SDK documentation can be found at: https://app.bitgo.com/docs/.
Pull requests from third parties are more than welcome! When creating a pull request, a BitGo engineer will be automatically added as a reviewer.
If you notice that the integration test job never runs, don't worry - that's expected. The integration tests use a secret testing password, and so we can't run these tests on untrusted code (PRs from third parties) without reviewing first. Once your code is passing unit tests and has an initial review, a BitGo engineer will re-create your PR and sign your commits, and link back to the original PR.
You should not be using the tsc
command in terminal. Doing so WITHOUT a tsconfig file (which informs tsc where to install files) would lead to translation files (ending with d.ts
and d.ts.map
) installed in an incorrect location.
If this happens, navigate to the BitGoJs directory and run git clean -f -d
to remove any errant files. Avoid using npm commands and stick with yarn.
Instead, you should just run:
yarn dev
from the root of the repo while developing. This will compile all of the linked TypeScript packages & begin watching for changes. If you want to just do a one time build, then simply running:
yarn
From the root of the repo is what you'll want to do.
BitGoJS checks all commits against the Conventional Commit Standard, and this is checked by CI when creating new pull requests using commitlint.
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:
$ yarn run unit-test --scope bitgo
You can also run unit tests for all modules in parallel:
$ yarn run unit-test
Or just the modules which have changed since master:
$ yarn run unit-test-changed
Or the file that contains a specific string
- if you are a specific module:
$ yarn run unit-test --grep"keyword"
- if you are in the BitGoJs/ top-level directory
$ 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.
The link to this report is output in the "upload reports" stage of each build pipeline.
Here is an example of this output:
@bitgo/express: === TEST REPORT UPLOADED SUCCESSFULLY ===
@bitgo/express: https://bitgo-sdk-test-reports.s3.amazonaws.com/1036/express/unit tests (node:6).html
This is a question you should ask before making large changes to the SDK. The original goal of modularizing the SDK was to allow users to only include support for the features they actually want to use, instead of bringing in hundreds of megabytes of dependencies which they won't use.
Therefore, if your feature meets the following criteria, then it is a good candidate for being its own module. Otherwise, perhaps not.
- Will this feature require additional dependencies to be added? How heavy are those dependencies?
- Is this feature something which would only be used by a small fraction of SDK users?
- Is this feature extending existing bitgo functionality, or is it providing entirely new functionality? For example, adding a new coin would be extending existing bitgo functionality.
These recommendations are just that, recommendations. Please use your best judgement when it comes to how your change is architected.
If you are implementing a new coin, skip to Coin Implementation
Each module should have the following basic file structure:
- modules/
- mymodule/
- src/
- index.ts
- test/
- unit/
- test-feature.ts
- integration/
- test-feature.ts
- package.json
- README.md
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
.
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 |
clean |
Clean up generated build files | No |
audit |
Run a vulnerability against the module dependencies | Yes |
gen-coverage |
Generate a code coverage report | No |
upload-coverage |
Upload a code coverage report | No |
upload-artifacts |
Upload any artifacts produced by the build and test process | No |
Additional scripts which are too large for the package.json file should be placed in scripts/
and should be plain javascript or bash.
This shall always be set for all modules to:
{
"repository": {
"type": "git",
"url": "https://github.com/BitGo/BitGoJS.git"
}
}
License shall be Apache-2.0
.
Engines should be set to the following:
{
"engines": {
"node": ">=14.18.0 <17",
"npm": ">=3.10.10"
}
}
There are a few things each module's tsconfig.json
must do:
- Extend the root tsconfig.json
- Set the
outDir
androotDir
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.
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "."
},
"include": [
"src/**/*",
"package.json"
],
"references": [
{
"path": "../sdk-core"
},
{
"path": "../statics"
}
]
}
Each package should also be listed in the root level tsconfig.packages.json
as well.
As a result of BitGoJS running a monolithic code base with multiple packages supported by Lerna, we take advantage of Lerna's hoisting features. This allows us to maintain consistent version support between various packages and keep development bundle sizing down. There are a few simple rules for package installation.
- If your module consumes a library not specific to any given coin and is shared among multiple modules as a
devDependency
, it is recommended to be installed at the root of BitGoJS. - If your module
devDependency
is specific to your module and/or moduledependencies
within the module, it may be appropriate to leave it in the module (pending a pull request review).
- Most dependencies found in the
dependencies
object are required in order for a package to run and/or compile. You should not run into issues where a dependency needs to be hoisted to the root levelpackage.json
file. - Please move dependencies that are not needed for build/run-time to the
devDependencies
object. From there further evaluate if they belong in a given module or at the root level.
- Testing libraries should be unified, installed, and ran from the root level of BitGoJS. Since development, ci/cd, publishing, etc... on BitGoJS requires installing from the root, all testing libraries should be in the root
devDependencies
object. They will then be consumed in respective module testing suites.
- 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 rootpackage.json
ornode_modules
.
Examples of exceptions include:
express
web-demo
SDK coins provide a modular approach to a monolithic architecture. This and all BitGoJS SDK coins allow developers to use only the coins needed for a given project.
To implement a new coin for BitGoJS, from the root BitGoJS/ run:
npm install -g yo
You can now run the coin generation script:
yarn sdk-coin:new
This will prompt you for both the coin's name (mainnet and testnet), symbol, and base factor. A new coin folder will be autogenerated in the /modules
folder. This new coin folder will follow all the above conventions and set you up with the base implementation to implement coin specific packages with BitGo required classes.
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 |
---|---|
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 |
Upon creating coins, you are given different options to choose from to create your boilerplate. This skeleton gives you the base needs for implementing a coin to interact with BitGo services. You will need to install coin specific packages into your newly created and registered bitgo package. You will then need to hook up coin package methods into the boilerplate provided.
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. |