Skip to content

Latest commit

 

History

History
281 lines (195 loc) · 11.8 KB

DEVELOPERS.md

File metadata and controls

281 lines (195 loc) · 11.8 KB

Requirements

  • yarn version 1 (classic)
  • node version >=14.18.0 and <17

Installing

In the BitGoJS/ directory:

$ yarn install

Documentation

API and SDK documentation can be found at: https://app.bitgo.com/docs/.

Pull Requests

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.

Things to Avoid

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.

Commit Messages

BitGoJS checks all commits against the Conventional Commit Standard, and this is checked by CI when creating new pull requests using commitlint.

Running tests

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

Working with modules

Should I make a new module for my contribution?

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.

  1. Will this feature require additional dependencies to be added? How heavy are those dependencies?
  2. Is this feature something which would only be used by a small fraction of SDK users?
  3. 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.

Module Configuration

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

package.json

  • 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

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.

  • repository

This shall always be set for all modules to:

{
  "repository": {
    "type": "git",
    "url": "https://github.com/BitGo/BitGoJS.git"
  }
}
  • license

License shall be Apache-2.0.

  • engines

Engines should be set to the following:

{
  "engines": {
    "node": ">=14.18.0 <17",
    "npm": ">=3.10.10"
  }
}

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

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"
    }
  ]
}

tsconfig.packages.json

Each package should also be listed in the root level tsconfig.packages.json as well.

Package Installation

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.

Dev Dependencies

  • 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 module dependencies within the module, it may be appropriate to leave it in the module (pending a pull request review).

Dependencies

  • 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 level package.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.

Tests

  • 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.

Exceptions

  • 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

New Coin Implementation

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

Coin Creation Options

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.