diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index bfa1c067..cbb45007 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -5,7 +5,7 @@ name: Node.js CI on: push: - branches: [ main, 1.x ] + branches: [main, 1.x] pull_request: workflow_dispatch: @@ -57,7 +57,7 @@ jobs: strategy: matrix: - node-version: [12.x, 14.x, 16.x] + node-version: [12.x, 14.x, 16.x, 18.x] steps: - uses: actions/checkout@v3 @@ -98,15 +98,14 @@ jobs: strategy: matrix: - node-version: [12.x, 14.x, 16.x] + node-version: [12.x, 14.x, 16.x, 18.x] services: rippled: image: natenichols/rippled-standalone:latest ports: - - 6006:6006 - options: - --health-cmd="wget localhost:6006 || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s + - 6006:6006 + options: --health-cmd="wget localhost:6006 || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s steps: - uses: actions/checkout@v3 @@ -156,9 +155,8 @@ jobs: rippled: image: natenichols/rippled-standalone:latest ports: - - 6006:6006 - options: - --health-cmd="wget localhost:6006 || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s + - 6006:6006 + options: --health-cmd="wget localhost:6006 || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s steps: - uses: actions/checkout@v3 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0bd6b4c1..c7e3f2f8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,13 @@ # Contributing +### High Level Process to Contribute Code + +- You should open a PR against `main` and ensure that all CI passes. +- Your changes should have [unit](#unit-tests) and/or [integration tests](#integration-tests). +- Your changes should [pass the linter](#run-the-linter). +- You should get a full code review from two of the maintainers. +- Then you can merge your changes. (Which will then be included in the next release) + ## Set up your dev environment ### Requirements @@ -38,6 +46,7 @@ npm run lint ``` ## Running Tests + For integration and browser tests, we use a `rippled` node in standalone mode to test xrpl.js code against. To set this up, you can either run `rippled` locally, or set up the Docker container `natenichols/rippled-standalone:latest` for this purpose. The latter will require you to [install Docker](https://docs.docker.com/get-docker/). ### Unit Tests @@ -73,6 +82,50 @@ docker run -p 6006:6006 -it natenichols/rippled-standalone:latest npm run test:browser ``` +## High Level Architecture + +This is a monorepo, which means that there are multiple packages in a single GitHub repository using [Lerna](https://lerna.js.org/). + +The 4 packages currently here are: + +1. xrpl.js - The client library for interacting with the ledger. +2. ripple-binary-codec - A library for serializing and deserializing transactions for the ledger. +3. ripple-keypairs - A library for generating and using cryptographic keypairs. +4. ripple-address-codec - A library for encoding and decoding XRP Ledger addresses and seeds. + +Each package has it's own README which dives deeper into what it's main purpose is, and the core functionality it offers. +They also run tests independently as they were originally in separate repositories. + +These are managed in a monorepo because often a change in a lower-level library will also require a change in xrpl.js, and so it makes sense to be able to allow for modifications of all packages at once without coordinating versions across multiple repositories. + +Let's dive a bit into how xrpl.js is structured! + +### The File Structure + +Within the xrpl package, each folder has a specific purpose: + +**Client** - This contains logic for handling the websocket connection to rippled servers. +**Models** - These types model LedgerObjects, Requests/Methods, and Transactions in order to give type hints and nice errors for users. +**Sugar** - This is where handy helper functions end up, like `submit`, `autofill`, and `getXRPBalance` amongst others. +**Utils** - These are shared functions which are useful for conversions, or internal implementation details within the library. +**Wallet** - This logic handles managing keys, addresses, and signing within xrpl.js + +### Writing Tests for xrpl.js + +For every file in `src`, we try to have a corresponding file in `test` with unit tests. + +The goal is to maintain above 80% code coverage, and generally any new feature or bug fix should be accompanied by unit tests, and integration tests if applicable. + +For an example of a unit test, check out the [autofill tests here](./packages/xrpl/test/client/autofill.ts). + +If your code connects to the ledger (ex. Adding a new transaction type) it's handy to write integration tests to ensure that you can successfully interact with the ledger. Integration tests are generally run against a docker instance of rippled which contains the latest updates. Since standalone mode allows us to manually close ledgers, this allows us to run integration tests at a much faster rate than if we had to wait 4-5 seconds per transaction for the ledger to validate the transaction. [See above](#running-tests) for how to start up the docker container to run integration tests. + +All integration tests should be written in the `test/integration` folder, with new `Requests` and `Transactions` tests being in their respective folders. + +One last note for integration tests is that all imports from `xrpl.js` should be from `xrpl-local` instead of `../../src`. This is required for the integraiton tests to run in the browser. + +For an example of how to write an integration test for `xrpl.js`, you can look at the [Payment integration test](./packages/xrpl/test/integration/transactions/payment.ts). + ## Generate reference docs You can see the complete reference documentation at [`xrpl.js` docs](https://js.xrpl.org). You can also generate them locally using `typedoc`: @@ -84,6 +137,7 @@ npm run docgen This updates `docs/` at the top level, where GitHub Pages looks for the docs. ## Update `definitions.json` + Use [this repo](https://github.com/RichardAH/xrpl-codec-gen) to generate a new `definitions.json` file from the rippled source code. Instructions are available in that README. ## Adding and removing packages @@ -119,21 +173,12 @@ npm uninstall abbrev -w xrpl ## Release process -### Editing the Code - -* Your changes should have unit and/or integration tests. -* Your changes should pass the linter. -* Your code should pass all the tests on Github (which check the linter, unit and integration tests on Node 12/14/16, and browser tests). -* Open a PR against `main` and ensure that all CI passes. -* Get a full code review from one of the maintainers. -* Merge your changes. - ### Release 1. Ensure that all tests passed on the last CI that ran on `main`. -___ + NOW WE ARE READY TO PUBLISH! No new code changes happen manually now. -___ + 2. Checkout `main` and `git pull`. 3. Create a new branch to capture updates that take place during this process. `git checkout -b ` 4. Update `HISTORY.md` to reflect release changes. @@ -149,9 +194,8 @@ ___ 14. Create a new branch to capture the updated packages from the release (`git checkout -b `) 15. Make a PR to merge those changes into `main` -___ NOW YOU HAVE PUBLISHED! But you're not done; we have to notify people! -___ + 16. Pull the most recent changes to main locally. 17. Run `git tag -m `, where `` is the new package and version (e.g. `xrpl@2.1.1`), for each version released. 18. Run `git push --follow-tags`, to push the tags to Github. @@ -163,6 +207,7 @@ ___ 24. Send an email to [xrpl-announce](https://groups.google.com/g/xrpl-announce). ## Mailing Lists + We have a low-traffic mailing list for announcements of new `xrpl.js` releases. (About 1 email every couple of weeks) + [Subscribe to xrpl-announce](https://groups.google.com/g/xrpl-announce) diff --git a/README.md b/README.md index 5e49434e..09e537b0 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,16 @@ main() For more examples, see the [documentation](#documentation). +## Try it out now! + +If you just want to try xrpl.js, you can fork this Code Sandbox template: +https://codesandbox.io/s/xrpl-intro-pxgdjr?file=/src/App.js + +It goes through: +1. Creating a new test account +2. Sending a payment transaction +3. And sending requests to see your account balance + ### Using xrpl.js with `create-react-app` To use `xrpl.js` with React, you need to install shims for core NodeJS modules. Starting with version 5, Webpack stopped including shims by default, so you must modify your Webpack configuration to add the shims you need. Either you can eject your config and modify it, or you can use a library such as `react-app-rewired`. The example below uses `react-app-rewired`. @@ -129,6 +139,9 @@ To use `xrpl.js` with React, you need to install shims for core NodeJS modules. "test": "react-app-rewired test", ``` +This online template uses these steps to run xrpl.js with React in the browser: +https://codesandbox.io/s/xrpl-intro-pxgdjr?file=/src/App.js + ### Using xrpl.js with React Native If you want to use `xrpl.js` with React Native you will need to install shims for core NodeJS modules. To help with this you can use a module like [rn-nodeify](https://github.com/tradle/rn-nodeify). diff --git a/docs/classes/Wallet.html b/docs/classes/Wallet.html index 550cfd97..ed7b845c 100644 --- a/docs/classes/Wallet.html +++ b/docs/classes/Wallet.html @@ -18,7 +18,7 @@ A wallet can be derived from either a seed, mnemonic, or entropy (array of random numbers). It provides functionality to sign/verify transactions offline.

-

Example

// Derive a wallet from a bip39 Mnemonic
const wallet = Wallet.fromMnemonic(
'jewel insect retreat jump claim horse second chef west gossip bone frown exotic embark laundry'
)
console.log(wallet)
// Wallet {
// publicKey: '02348F89E9A6A3615BA317F8474A3F51D66221562D3CA32BFA8D21348FF67012B2',
// privateKey: '00A8F2E77FC0E05890C1B5088AFE0ECF9D96466A4419B897B1AB383E336E1735A2',
// classicAddress: 'rwZiksrExmVkR64pf87Jor4cYbmff47SUm',
// seed: undefined
// }.

// Derive a wallet from a base58 encoded seed.
const seedWallet = Wallet.fromSeed('ssZkdwURFMBXenJPbrpE14b6noJSu')
console.log(seedWallet)
// Wallet {
// publicKey: '02FE9932A9C4AA2AC9F0ED0F2B89302DE7C2C95F91D782DA3CF06E64E1C1216449',
// privateKey: '00445D0A16DD05EFAF6D5AF45E6B8A6DE4170D93C0627021A0B8E705786CBCCFF7',
// classicAddress: 'rG88FVLjvYiQaGftSa1cKuE2qNx7aK5ivo',
// seed: 'ssZkdwURFMBXenJPbrpE14b6noJSu'
// }.

// Sign a JSON Transaction
const signed = seedWallet.signTransaction({
TransactionType: 'Payment',
Account: 'rG88FVLjvYiQaGftSa1cKuE2qNx7aK5ivo'
...........
}).

console.log(signed)
// '1200007321......B01BE1DFF3'.
console.log(decode(signed))
// {
// TransactionType: 'Payment',
// SigningPubKey: '02FE9932A9C4AA2AC9F0ED0F2B89302DE7C2C95F91D782DA3CF06E64E1C1216449',
// TxnSignature: '3045022100AAD......5B631ABD21171B61B07D304',
// Account: 'rG88FVLjvYiQaGftSa1cKuE2qNx7aK5ivo'
// ...........
// } +

Example


// Derive a wallet from a base58 encoded seed.
const seedWallet = Wallet.fromSeed('ssZkdwURFMBXenJPbrpE14b6noJSu')
console.log(seedWallet)
// Wallet {
// publicKey: '02FE9932A9C4AA2AC9F0ED0F2B89302DE7C2C95F91D782DA3CF06E64E1C1216449',
// privateKey: '00445D0A16DD05EFAF6D5AF45E6B8A6DE4170D93C0627021A0B8E705786CBCCFF7',
// classicAddress: 'rG88FVLjvYiQaGftSa1cKuE2qNx7aK5ivo',
// seed: 'ssZkdwURFMBXenJPbrpE14b6noJSu'
// }.

// Sign a JSON Transaction
const signed = seedWallet.signTransaction({
TransactionType: 'Payment',
Account: 'rG88FVLjvYiQaGftSa1cKuE2qNx7aK5ivo'
...........
}).

console.log(signed)
// '1200007321......B01BE1DFF3'.
console.log(decode(signed))
// {
// TransactionType: 'Payment',
// SigningPubKey: '02FE9932A9C4AA2AC9F0ED0F2B89302DE7C2C95F91D782DA3CF06E64E1C1216449',
// TxnSignature: '3045022100AAD......5B631ABD21171B61B07D304',
// Account: 'rG88FVLjvYiQaGftSa1cKuE2qNx7aK5ivo'
// ...........
// }
@@ -26,7 +26,7 @@ It provides functionality to sign/verify transactions offline.

  • Wallet
+
  • Defined in packages/xrpl/src/Wallet/index.ts:83
  • @@ -96,29 +96,29 @@ It provides functionality to sign/verify transactions offline.

    Returns Wallet

    +
  • Defined in packages/xrpl/src/Wallet/index.ts:107
  • Properties

    classicAddress: string
    +
  • Defined in packages/xrpl/src/Wallet/index.ts:86
  • privateKey: string
    +
  • Defined in packages/xrpl/src/Wallet/index.ts:85
  • publicKey: string
    +
  • Defined in packages/xrpl/src/Wallet/index.ts:84
  • seed?: string
    +
  • Defined in packages/xrpl/src/Wallet/index.ts:87
  • fromSecret: ((seed: string, opts?: { algorithm?: ECDSA; masterAddress?: string }) => Wallet) = Wallet.fromSeed
    @@ -155,7 +155,7 @@ It provides functionality to sign/verify transactions offline.

    Returns Wallet

    +
  • Defined in packages/xrpl/src/Wallet/index.ts:163
  • Accessors

    @@ -169,7 +169,7 @@ It provides functionality to sign/verify transactions offline.

    Returns string

    +
  • Defined in packages/xrpl/src/Wallet/index.ts:94
  • Methods

    @@ -199,7 +199,7 @@ the serialized Transaction desn't match the original transaction.

    Returns void

    +
  • Defined in packages/xrpl/src/Wallet/index.ts:405
    • @@ -222,7 +222,7 @@ the serialized Transaction desn't match the original transaction.

    Returns string

    +
  • Defined in packages/xrpl/src/Wallet/index.ts:389
    • @@ -258,7 +258,7 @@ the serialized Transaction desn't match the original transaction.

    • tx_blob: string
    +
  • Defined in packages/xrpl/src/Wallet/index.ts:311
    • @@ -277,7 +277,7 @@ the serialized Transaction desn't match the original transaction.

    Returns boolean

    +
  • Defined in packages/xrpl/src/Wallet/index.ts:372
    • @@ -309,7 +309,7 @@ the serialized Transaction desn't match the original transaction.

    Returns Wallet

    +
  • Defined in packages/xrpl/src/Wallet/index.ts:287
    • @@ -341,7 +341,7 @@ the serialized Transaction desn't match the original transaction.

    Returns Wallet

    +
  • Defined in packages/xrpl/src/Wallet/index.ts:174
    • @@ -349,6 +349,11 @@ the serialized Transaction desn't match the original transaction.

    • Derives a wallet from a bip39 or RFC1751 mnemonic (Defaults to bip39).

      +

      Deprecated

      since version 2.6.1. +Will be deleted in version 3.0.0. +This representation is currently deprecated in rippled. +You should use another method to represent your keys such as a seed or public/private keypair.

      +

      Returns

      A Wallet derived from a mnemonic.

      Throws

      ValidationError if unable to derive private key from mnemonic input.

      @@ -386,7 +391,7 @@ the serialized Transaction desn't match the original transaction.

    Returns Wallet

    +
  • Defined in packages/xrpl/src/Wallet/index.ts:210
    • @@ -418,7 +423,7 @@ the serialized Transaction desn't match the original transaction.

    Returns Wallet

    +
  • Defined in packages/xrpl/src/Wallet/index.ts:259
    • @@ -450,7 +455,7 @@ the serialized Transaction desn't match the original transaction.

    Returns Wallet

    +
  • Defined in packages/xrpl/src/Wallet/index.ts:143
    • @@ -469,7 +474,7 @@ the serialized Transaction desn't match the original transaction.

    Returns Wallet

    +
  • Defined in packages/xrpl/src/Wallet/index.ts:129