From 8b95ee5fab242d14986675a46500b185d13daf2c Mon Sep 17 00:00:00 2001 From: Nathan Nichols Date: Thu, 26 Aug 2021 21:22:40 -0500 Subject: [PATCH] build: Initial linting setup (#1560) * sets up linting config and runs `yarn lint --fix` once, so that all changes will show up correctly in future PRs. * Note that there are still a lot of linter errors. --- .eslintignore | 2 + .eslintrc.js | 99 + .eslintrc.json | 29 - .github/workflows/nodejs.yml | 29 +- .prettierrc | 10 - .vscode/extenstions.json | 6 + .vscode/settings.json | 35 + package.json | 39 +- snippets/src/decoder.ts | 14 +- snippets/src/getTransaction.ts | 35 +- snippets/src/parseAccountFlags.ts | 33 +- snippets/src/paths.ts | 88 +- snippets/src/reliableTransactionSubmission.ts | 394 +-- snippets/tsconfig.json | 6 +- src/Wallet.ts | 120 +- src/client/backoff.ts | 40 +- src/client/broadcastClient.ts | 66 +- src/client/connection.ts | 503 ++-- src/client/index.ts | 520 ++-- src/client/rangeSet.ts | 51 +- src/client/wsWrapper.ts | 56 +- src/common/constants.ts | 52 +- src/common/ecdsa.ts | 6 +- src/common/errors.ts | 50 +- src/common/fee.ts | 33 +- src/common/index.ts | 27 +- src/common/schema-validator.ts | 298 +- src/common/txflags.ts | 24 +- src/common/types/commands/account_info.ts | 28 +- src/common/types/commands/account_lines.ts | 26 +- src/common/types/commands/account_objects.ts | 56 +- src/common/types/commands/account_offers.ts | 36 +- src/common/types/commands/book_offers.ts | 38 +- src/common/types/commands/gateway_balances.ts | 26 +- src/common/types/commands/index.ts | 20 +- src/common/types/commands/ledger.ts | 28 +- src/common/types/commands/ledger_data.ts | 16 +- src/common/types/commands/ledger_entry.ts | 42 +- src/common/types/commands/server_info.ts | 80 +- src/common/types/objects/adjustments.ts | 26 +- src/common/types/objects/amounts.ts | 14 +- src/common/types/objects/index.ts | 24 +- src/common/types/objects/ledger.ts | 52 +- src/common/types/objects/ledger_data.ts | 10 +- src/common/types/objects/ledger_entries.ts | 261 +- src/common/types/objects/memos.ts | 8 +- src/common/types/objects/orders.ts | 24 +- src/common/types/objects/queue_data.ts | 22 +- src/common/types/objects/settings.ts | 54 +- src/common/types/objects/signers.ts | 6 +- src/common/types/objects/transactions.ts | 42 +- src/common/types/objects/trustlines.ts | 66 +- src/common/validate.ts | 140 +- src/index.ts | 14 +- src/ledger/balances.ts | 81 +- src/ledger/orderbook.ts | 97 +- src/ledger/parse/account-delete.ts | 27 +- src/ledger/parse/account-order.ts | 58 +- src/ledger/parse/account-trustline.ts | 25 +- src/ledger/parse/amendment.ts | 6 +- src/ledger/parse/amount.ts | 18 +- src/ledger/parse/cancellation.ts | 13 +- src/ledger/parse/check-cancel.ts | 20 +- src/ledger/parse/check-cash.ts | 28 +- src/ledger/parse/check-create.ts | 33 +- src/ledger/parse/deposit-preauth.ts | 22 +- src/ledger/parse/escrow-cancellation.ts | 16 +- src/ledger/parse/escrow-creation.ts | 18 +- src/ledger/parse/escrow-execution.ts | 16 +- src/ledger/parse/fee-update.ts | 16 +- src/ledger/parse/fields.ts | 42 +- src/ledger/parse/flags.ts | 10 +- src/ledger/parse/ledger.ts | 121 +- src/ledger/parse/order.ts | 43 +- src/ledger/parse/orderbook-order.ts | 84 +- src/ledger/parse/pathfind.ts | 52 +- src/ledger/parse/payment-channel-claim.ts | 23 +- src/ledger/parse/payment-channel-create.ts | 18 +- src/ledger/parse/payment-channel-fund.ts | 18 +- src/ledger/parse/payment-channel.ts | 41 +- src/ledger/parse/payment.ts | 43 +- src/ledger/parse/settings.ts | 72 +- src/ledger/parse/ticket-create.ts | 16 +- src/ledger/parse/transaction.ts | 115 +- src/ledger/parse/trustline.ts | 27 +- src/ledger/parse/utils.ts | 143 +- src/ledger/pathfind-types.ts | 86 +- src/ledger/pathfind.ts | 192 +- src/ledger/trustlines.ts | 50 +- src/ledger/utils.ts | 137 +- src/models/common/index.ts | 42 +- src/models/common/metadata.ts | 50 +- src/models/common/transaction.ts | 50 +- src/models/ledger/accountRoot.ts | 36 +- src/models/ledger/amendments.ts | 16 +- src/models/ledger/baseLedgerEntry.ts | 4 +- src/models/ledger/check.ts | 31 +- src/models/ledger/depositPreauth.ts | 16 +- src/models/ledger/directoryNode.ts | 24 +- src/models/ledger/escrow.ts | 30 +- src/models/ledger/feeSettings.ts | 14 +- src/models/ledger/index.ts | 61 +- src/models/ledger/ledger.ts | 33 +- src/models/ledger/ledgerHashes.ts | 10 +- src/models/ledger/negativeUNL.ts | 14 +- src/models/ledger/offer.ts | 27 +- src/models/ledger/payChannel.ts | 34 +- src/models/ledger/rippleState.ts | 31 +- src/models/ledger/signerList.ts | 24 +- src/models/ledger/ticket.ts | 16 +- src/models/methods/accountChannels.ts | 63 +- src/models/methods/accountCurrencies.ts | 33 +- src/models/methods/accountInfo.ts | 61 +- src/models/methods/accountLines.ts | 59 +- src/models/methods/accountObjects.ts | 64 +- src/models/methods/accountOffers.ts | 41 +- src/models/methods/accountTx.ts | 47 +- src/models/methods/baseMethod.ts | 36 +- src/models/methods/bookOffers.ts | 43 +- src/models/methods/channelVerify.ts | 16 +- src/models/methods/depositAuthorized.ts | 31 +- src/models/methods/fee.ts | 42 +- src/models/methods/gatewayBalances.ts | 37 +- src/models/methods/index.ts | 382 +-- src/models/methods/ledger.ts | 68 +- src/models/methods/ledgerClosed.ts | 12 +- src/models/methods/ledgerCurrent.ts | 10 +- src/models/methods/ledgerData.ts | 35 +- src/models/methods/ledgerEntry.ts | 107 +- src/models/methods/manifest.ts | 26 +- src/models/methods/norippleCheck.ts | 25 +- src/models/methods/pathFind.ts | 52 +- src/models/methods/ping.ts | 4 +- src/models/methods/random.ts | 6 +- src/models/methods/ripplePathFind.ts | 39 +- src/models/methods/serverInfo.ts | 131 +- src/models/methods/serverState.ts | 102 +- src/models/methods/submit.ts | 36 +- src/models/methods/submitMultisigned.ts | 18 +- src/models/methods/subscribe.ts | 165 +- src/models/methods/transactionEntry.ts | 19 +- src/models/methods/tx.ts | 23 +- src/models/methods/unsubscribe.ts | 23 +- src/models/transactions/accountDelete.ts | 41 +- src/models/transactions/accountSet.ts | 117 +- src/models/transactions/checkCancel.ts | 24 +- src/models/transactions/checkCash.ts | 62 +- src/models/transactions/checkCreate.ts | 79 +- src/models/transactions/common.ts | 226 +- src/models/transactions/depositPreauth.ts | 71 +- src/models/transactions/escrowCancel.ts | 45 +- src/models/transactions/escrowCreate.ts | 90 +- src/models/transactions/escrowFinish.ts | 59 +- src/models/transactions/index.ts | 40 +- src/models/transactions/offerCancel.ts | 33 +- src/models/transactions/offerCreate.ts | 72 +- .../transactions/paymentChannelClaim.ts | 67 +- .../transactions/paymentChannelCreate.ts | 98 +- src/models/transactions/paymentChannelFund.ts | 50 +- src/models/transactions/paymentTransaction.ts | 188 +- src/models/transactions/setRegularKey.ts | 24 +- src/models/transactions/signerListSet.ts | 63 +- src/models/transactions/ticketCreate.ts | 41 +- src/models/transactions/transaction.ts | 69 +- src/models/transactions/trustSet.ts | 76 +- src/models/utils/index.ts | 24 +- src/transaction/check-cancel.ts | 31 +- src/transaction/check-cash.ts | 49 +- src/transaction/check-create.ts | 49 +- src/transaction/combine.ts | 87 +- src/transaction/escrow-cancellation.ts | 40 +- src/transaction/escrow-creation.ts | 68 +- src/transaction/escrow-execution.ts | 54 +- src/transaction/order.ts | 65 +- src/transaction/ordercancellation.ts | 32 +- src/transaction/payment-channel-claim.ts | 79 +- src/transaction/payment-channel-create.ts | 53 +- src/transaction/payment-channel-fund.ts | 41 +- src/transaction/payment.ts | 178 +- src/transaction/settings.ts | 136 +- src/transaction/sign.ts | 210 +- src/transaction/ticket.ts | 45 +- src/transaction/trustline.ts | 55 +- src/transaction/types.ts | 227 +- src/transaction/utils.ts | 372 +-- src/tsconfig.json | 11 - src/utils/derive.ts | 16 +- src/utils/generateAddress.ts | 65 +- src/utils/hashes/hashPrefix.ts | 4 +- src/utils/hashes/index.ts | 213 +- src/utils/hashes/ledgerSpaces.ts | 38 +- src/utils/hashes/sha512Half.ts | 14 +- src/utils/hashes/shamap.ts | 152 +- src/utils/index.ts | 239 +- src/utils/ledgerHash.ts | 94 +- src/utils/signPaymentChannelClaim.ts | 22 +- src/utils/verifyPaymentChannelClaim.ts | 22 +- src/wallet/wallet-generation.ts | 181 +- test/backoff.ts | 65 +- test/broadcastClient.ts | 77 +- test/browser/browserIntegration.ts | 55 +- test/client/combine.ts | 40 +- test/client/constructor.ts | 34 +- test/client/deriveXAddress.ts | 29 +- test/client/errors.ts | 21 +- test/client/formatBidsAndAsks.ts | 22 +- test/client/getBalances.ts | 114 +- test/client/getFee.ts | 101 +- test/client/getOrderbook.ts | 139 +- test/client/getPaths.ts | 63 +- test/client/getTrustlines.ts | 78 +- test/client/hasNextPage.ts | 56 +- test/client/isConnected.ts | 17 +- test/client/isValidAddress.ts | 27 +- test/client/isValidSecret.ts | 17 +- test/client/prepareCheckCancel.ts | 67 +- test/client/prepareCheckCash.ts | 90 +- test/client/prepareCheckCreate.ts | 94 +- test/client/prepareEscrowCancellation.ts | 100 +- test/client/prepareEscrowCreation.ts | 131 +- test/client/prepareEscrowExecution.ts | 146 +- test/client/prepareOrder.ts | 152 +- test/client/prepareOrderCancellation.ts | 159 +- test/client/preparePayment.ts | 818 +++--- test/client/preparePaymentChannelClaim.ts | 196 +- test/client/preparePaymentChannelCreate.ts | 108 +- test/client/preparePaymentChannelFund.ts | 100 +- test/client/prepareSettings.ts | 564 ++-- test/client/prepareTicket.ts | 74 +- test/client/prepareTransaction.ts | 2450 ++++++++++------- test/client/prepareTrustline.ts | 165 +- test/client/request.ts | 50 +- test/client/requestNextPage.ts | 64 +- test/client/sign.ts | 574 ++-- test/connection.ts | 771 +++--- test/integration/integration.ts | 682 ++--- test/mockRippled.ts | 141 +- test/mockedServer.ts | 18 +- test/models/accountDelete.ts | 133 +- test/models/accountSet.ts | 177 +- test/models/baseTransaction.ts | 403 +-- test/models/checkCancel.ts | 58 +- test/models/checkCash.ts | 149 +- test/models/checkCreate.ts | 220 +- test/models/depositPreauth.ts | 142 +- test/models/escrowCancel.ts | 105 +- test/models/escrowCreate.ts | 231 +- test/models/escrowFinish.ts | 121 +- test/models/offerCancel.ts | 94 +- test/models/offerCreate.ts | 332 +-- test/models/paymentChannelClaim.ts | 172 +- test/models/paymentChannelCreate.ts | 241 +- test/models/paymentChannelFund.ts | 136 +- test/models/paymentTransaction.ts | 236 +- test/models/setRegularKey.ts | 67 +- test/models/signerListSet.ts | 133 +- test/models/ticketCreate.ts | 118 +- test/models/trustSet.ts | 114 +- test/models/utils.ts | 45 +- test/rangeset.ts | 131 +- test/rippleClient.ts | 57 +- test/rippleClientPrivate.ts | 242 +- test/setupClient.ts | 59 +- test/setupClientWeb.ts | 53 +- test/shamap.ts | 92 +- test/testUtils.ts | 128 +- test/tsconfig.json | 3 - test/utils/computeLedgerHash.ts | 184 +- test/utils/dropsToXrp.ts | 167 +- test/utils/generateAddress.ts | 260 +- test/utils/hashes.ts | 210 +- test/utils/signPaymentChannelClaim.ts | 35 +- test/utils/verifyPaymentChannelClaim.ts | 32 +- test/utils/xrpToDrops.ts | 163 +- test/wallet/fromEntropy.ts | 57 +- test/wallet/fromMnemonic.ts | 33 +- test/wallet/fromSeed.ts | 45 +- test/wallet/signTransaction.ts | 37 +- test/wallet/verifyTransaction.ts | 48 +- test/walletGeneration.ts | 51 +- tsconfig-base.json | 23 - tsconfig.build.json | 4 + tsconfig.eslint.json | 11 + tsconfig.json | 30 +- webpack.config.js | 184 +- yarn.lock | 1093 +++++--- 286 files changed, 15508 insertions(+), 12691 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.js delete mode 100644 .eslintrc.json delete mode 100644 .prettierrc create mode 100644 .vscode/extenstions.json create mode 100644 .vscode/settings.json delete mode 100644 src/tsconfig.json delete mode 100644 test/tsconfig.json delete mode 100644 tsconfig-base.json create mode 100644 tsconfig.build.json create mode 100644 tsconfig.eslint.json diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..de4d1f00 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +dist +node_modules diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..f7f6f6a1 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,99 @@ +module.exports = { + root: true, + + // Make ESLint compatible with TypeScript + parser: '@typescript-eslint/parser', + parserOptions: { + // Enable linting rules with type information from our tsconfig + tsconfigRootDir: __dirname, + project: ['./tsconfig.eslint.json'], + + // Allow the use of imports / ES modules + sourceType: 'module', + + ecmaFeatures: { + // Enable global strict mode + impliedStrict: true + } + }, + + // Specify global variables that are predefined + env: { + node: true, // Enable node global variables & Node.js scoping + es2020: true // Add all ECMAScript 2020 globals and automatically set the ecmaVersion parser option to ES2020 + }, + + plugins: [], + extends: ['@xrplf/eslint-config/base', 'plugin:mocha/recommended'], + rules: { + // Certain rippled APIs require snake_case naming + '@typescript-eslint/naming-convention': [ + 'error', + { + selector: 'interface', + format: ['PascalCase'] + }, + { + selector: 'interface', + format: ['snake_case'] + } + ], + + // Ignore type imports when counting dependencies. + 'import/max-dependencies': [ + 'error', + { + max: 5, + ignoreTypeImports: true + } + ], + // Removes comments and blank lines from the max-line rules + 'max-lines-per-function': [ + 'warn', + { + max: 50, + skipBlankLines: true, + skipComments: true + } + ], + 'max-lines': [ + 'warn', + { + max: 250, + skipBlankLines: true, + skipComments: true + } + ] + }, + overrides: [ + { + files: ['test/**/*.ts'], + rules: { + // Removed the max for test files and test helper files, since tests usually need to import more things + 'import/max-dependencies': 'off', + + // describe blocks count as a function in Mocha tests, and can be insanely long + 'max-lines-per-function': 'off', + + // Tests can be very long turns off max-line count + 'max-lines': 'off', + + // We have lots of statements in tests + 'max-statements': 'off', + + // We have lots of magic numbers in tests + 'no-magic-number': 'off' + } + }, + { + files: ['.eslintrc.js', 'jest.config.js'], + rules: { + // Removed no-commonjs requirement as eslint must be in common js format + 'import/no-commonjs': 'off', + + // Removed this as eslint prevents us from doing this differently + 'import/unambiguous': 'off' + } + } + ] +} diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index e34889a2..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "env": { - "browser": true, - "es6": true, - "node": true, - "mocha": true - }, - "extends": [ - "eslint:recommended" - ], - "globals": { - "NodeJS": true - }, - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 2018, - "sourceType": "module" - }, - "plugins": [ - "@typescript-eslint" - ], - "rules": { - "no-useless-constructor": 0, - "no-unused-vars": 0, - "no-prototype-builtins": 0, - "require-atomic-updates": 0, - "no-dupe-class-members": 0 - } -} \ No newline at end of file diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 51785f6c..e2c77c15 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -10,10 +10,27 @@ on: workflow_dispatch: jobs: - unit: + # build-and-lint: + # runs-on: ubuntu-latest + # strategy: + # matrix: + # node-version: [14.x] + + # steps: + # - uses: actions/checkout@v2 + # - name: Use Node.js ${{ matrix.node-version }} + # uses: actions/setup-node@v1 + # with: + # node-version: ${{ matrix.node-version }} + # - run: yarn install + # - run: yarn lint + # - run: yarn build + + unit: runs-on: ubuntu-latest + strategy: matrix: node-version: [12.x, 14.x, 16.x] @@ -24,10 +41,8 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - - run: yarn install + - run: yarn install --ignore-engines - run: yarn test - - run: yarn lint - - run: yarn build integration: runs-on: ubuntu-latest @@ -42,7 +57,7 @@ jobs: ports: - 6006:6006 options: - --health-cmd="wget localhost:6006 || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s + --health-cmd="wget localhost:6006 || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s steps: - uses: actions/checkout@v2 @@ -50,7 +65,7 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - - run: yarn install + - run: yarn install --ignore-engines - run: yarn test:integration env: HOST: localhost @@ -69,7 +84,7 @@ jobs: ports: - 6006:6006 options: - --health-cmd="wget localhost:6006 || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s + --health-cmd="wget localhost:6006 || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s steps: - uses: actions/checkout@v2 diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 7f0aa514..00000000 --- a/.prettierrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "parser": "typescript", - "printWidth": 80, - "tabWidth": 2, - "semi": false, - "singleQuote": true, - "trailingComma": "none", - "quoteProps": "consistent", - "bracketSpacing": false -} diff --git a/.vscode/extenstions.json b/.vscode/extenstions.json new file mode 100644 index 00000000..33bf1cb0 --- /dev/null +++ b/.vscode/extenstions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode" + ] + } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..55c00dc4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,35 @@ +{ + "editor.tabSize": 2, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, + "[javascriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, + "[typescriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true + }, + "eslint.alwaysShowStatus": true, + "eslint.lintTask.enable": true, + "eslint.codeAction.showDocumentation": { + "enable": true + }, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + "files.insertFinalNewline": true, + "files.trimFinalNewlines": true, + "files.trimTrailingWhitespace": true, + "files.watcherExclude": { + "**/.git/objects/**": true, + "**/.git/subtree-cache/**": true, + "**/.hg/store/**": true + }, +} diff --git a/package.json b/package.json index 76e1da41..234c96ec 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,6 @@ "unpkg": "build/ripple-latest-min.js", "jsdelivr": "build/ripple-latest-min.js", "types": "dist/npm/index.d.ts", - "browser": { - "ws": "./dist/npm/client/wsWrapper.js", - "https-proxy-agent": false - }, "directories": { "test": "test" }, @@ -41,8 +37,10 @@ "@types/chai": "^4.2.21", "@types/mocha": "^9.0.0", "@types/node": "^16.4.3", - "@typescript-eslint/eslint-plugin": "^2.3.3", - "@typescript-eslint/parser": "^2.27.0", + "@types/puppeteer": "5.4.4", + "@typescript-eslint/eslint-plugin": "^3.7.0", + "@typescript-eslint/parser": "^3.7.0", + "@xrplf/eslint-config": "^1.1.0", "assert": "^2.0.0", "assert-diff": "^3.0.0", "buffer": "^6.0.2", @@ -50,21 +48,29 @@ "crypto-browserify": "^3.12.0", "doctoc": "^2.0.0", "ejs": "^3.0.1", - "eslint": "^6.5.1", + "eslint": "^7.5.0", + "eslint-plugin-array-func": "^3.1.7", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-import": "^2.24.1", + "eslint-plugin-jsdoc": "^29.0.0", + "eslint-plugin-mocha": "^9.0.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^3.4.0", + "eslint-plugin-tsdoc": "^0.2.14", "eventemitter2": "^6.0.0", "https-browserify": "^1.0.0", "json-schema-to-markdown-table": "^0.4.0", "mocha": "^9", "nyc": "^15", "path-browserify": "1.0.1", - "prettier": "^2.0.5", + "prettier": "^2.3.2", "process": "^0.11.10", "puppeteer": "10.2.0", "stream-browserify": "^3.0.0", "stream-http": "3.2.0", "ts-loader": "^9.2.5", "ts-node": "^10.1.0", - "typescript": "^3.9.9", + "typescript": "^3.9.10", "url": "^0.11.0", "webpack": "^5.6.0", "webpack-bundle-analyzer": "^4.1.0", @@ -72,21 +78,22 @@ }, "scripts": { "build:schemas": "mkdir -p dist/npm/common && cp -r src/common/schemas dist/npm/common/", - "build:lib": "tsc --build", + "build:snippets": "tsc --build ./snippets/tsconfig.json", + "build:lib": "tsc --build tsconfig.build.json", "build:web": "webpack", - "build": "yarn build:schemas && yarn build:lib && yarn build:web", + "build": "yarn build:schemas && yarn build:lib && yarn build:snippets && yarn build:web", "analyze": "yarn build:web --analyze", "watch": "yarn build:lib --watch", - "clean": "rm -rf dist/npm", + "clean": "rm -rf dist", "doctoc": "doctoc docs/index.md --title '# RippleAPI Reference' --github --maxlevel 2", "docgen": "node --harmony scripts/build_docs.js", "prepublish": "yarn clean && yarn build", - "test": "TS_NODE_PROJECT=src/tsconfig.json nyc mocha --config=test/.mocharc.json --exit", - "test:integration": "TS_NODE_PROJECT=src/tsconfig.json nyc mocha ./test/integration/*.ts", - "test:browser": "TS_NODE_PROJECT=src/tsconfig.json nyc mocha ./test/browser/*.ts", + "test": "nyc mocha --config=test/.mocharc.json --exit", + "test:integration": "TS_NODE_PROJECT=tsconfig.build.json nyc mocha ./test/integration/*.ts", + "test:browser": "TS_NODE_PROJECT=tsconfig.build.json nyc mocha ./test/browser/*.ts", "test:watch": "TS_NODE_PROJECT=src/tsconfig.json mocha --config=test/.mocharc.json --watch --reporter dot", "format": "prettier --write '{src,test}/**/*.ts'", - "lint": "eslint 'src/**/*.ts' 'test/*.{ts,js}'", + "lint": "eslint . --ext .ts --max-warnings 0", "perf": "./scripts/perf_test.sh", "compile:snippets": "tsc -p snippets/tsconfig.json", "start:snippet": "npm run compile:snippets && node ./snippets/dist/start.js", diff --git a/snippets/src/decoder.ts b/snippets/src/decoder.ts index c62c73df..57b06b0a 100644 --- a/snippets/src/decoder.ts +++ b/snippets/src/decoder.ts @@ -1,9 +1,13 @@ -import * as codec from 'ripple-binary-codec' +// import * as codec from 'ripple-binary-codec' -const original = codec.decode('12000022800200002400000001201B00EF81E661EC6386F26FC0FFFF0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461968400000000000000C6940000000000000646AD3504529A0465E2E0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D1664619732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D87446304402200A693FB5CA6B21250EBDFD8CFF526EE0DF7C9E4E31EB0660692E75E6A93BF5F802203CC39463DDA21386898CA31E18AD1A6828647D65741DD637BAD71BC83E29DB9481145E7B112523F68D2F5E879DB4EAC51C6698A693048314CA6EDC7A28252DAEA6F2045B24F4D7C333E146170112300000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461900') +// const original = codec.decode( +// '12000022800200002400000001201B00EF81E661EC6386F26FC0FFFF0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461968400000000000000C6940000000000000646AD3504529A0465E2E0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D1664619732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D87446304402200A693FB5CA6B21250EBDFD8CFF526EE0DF7C9E4E31EB0660692E75E6A93BF5F802203CC39463DDA21386898CA31E18AD1A6828647D65741DD637BAD71BC83E29DB9481145E7B112523F68D2F5E879DB4EAC51C6698A693048314CA6EDC7A28252DAEA6F2045B24F4D7C333E146170112300000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461900' +// ) -const test = codec.decode('12000022800200002400000017201B008694F261EC6386F26FC0FFFF0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461968400000000000000C6940000000000000646AD3504529A0465E2E0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D1664619732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D874473045022100D8B57E8E06EAE27B1343AF8CAD3F501E18260CCF8BCED08066074106F0F191A3022058FEA6CE9E7FA69D1244C3A70F18983CC2DAF0B10CBB86A6677CF2A5D2B8A68081145E7B112523F68D2F5E879DB4EAC51C6698A693048314CA6EDC7A28252DAEA6F2045B24F4D7C333E146170112300000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461900') +// const test = codec.decode( +// '12000022800200002400000017201B008694F261EC6386F26FC0FFFF0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461968400000000000000C6940000000000000646AD3504529A0465E2E0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D1664619732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D874473045022100D8B57E8E06EAE27B1343AF8CAD3F501E18260CCF8BCED08066074106F0F191A3022058FEA6CE9E7FA69D1244C3A70F18983CC2DAF0B10CBB86A6677CF2A5D2B8A68081145E7B112523F68D2F5E879DB4EAC51C6698A693048314CA6EDC7A28252DAEA6F2045B24F4D7C333E146170112300000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461900' +// ) -console.log('original:', JSON.stringify(original)) +// console.log('original:', JSON.stringify(original)) -console.log('test:', JSON.stringify(test)) +// console.log('test:', JSON.stringify(test)) diff --git a/snippets/src/getTransaction.ts b/snippets/src/getTransaction.ts index fc0a89ab..2d0a5ddc 100644 --- a/snippets/src/getTransaction.ts +++ b/snippets/src/getTransaction.ts @@ -1,19 +1,22 @@ -import {Client} from '../../dist/npm' -import { TransactionMetadata } from '../../src/models/common/transaction' +// import {Client} from '../../dist/npm' +// import {TransactionMetadata} from '../../src/models/common/transaction' -const client = new Client('wss://s.altnet.rippletest.net:51233') +// const client = new Client('wss://s.altnet.rippletest.net:51233') -getTransaction() +// getTransaction() -async function getTransaction() { - await client.connect() - const ledger = await client.request({command: 'ledger', transactions: true}) - console.log(ledger) - const tx = await client.request({ - command: 'tx', - transaction: ledger.result.ledger.transactions[0] as string - }) - console.log(tx) - console.log('deliveredAmount:', (tx.result.meta as TransactionMetadata).DeliveredAmount) - process.exit(0) -} +// async function getTransaction() { +// await client.connect() +// const ledger = await client.request({command: 'ledger', transactions: true}) +// console.log(ledger) +// const tx = await client.request({ +// command: 'tx', +// transaction: ledger.result.ledger.transactions[0] as string +// }) +// console.log(tx) +// console.log( +// 'deliveredAmount:', +// (tx.result.meta as TransactionMetadata).DeliveredAmount +// ) +// process.exit(0) +// } diff --git a/snippets/src/parseAccountFlags.ts b/snippets/src/parseAccountFlags.ts index d9facf20..9d62d679 100644 --- a/snippets/src/parseAccountFlags.ts +++ b/snippets/src/parseAccountFlags.ts @@ -1,18 +1,21 @@ -import {Client} from '../../dist/npm' -import { AccountFlags } from '../../dist/npm/common/constants' +// import {Client} from '../../dist/npm' +// import {AccountFlags} from '../../dist/npm/common/constants' -const client = new Client('wss://s.altnet.rippletest.net:51233') +// const client = new Client('wss://s.altnet.rippletest.net:51233') -parseAccountFlags() +// parseAccountFlags() -async function parseAccountFlags() { - await client.connect() - const account_info = await client.request({command: 'account_info', account: 'rKsdkGhyZH6b2Zzd5hNnEqSv2wpznn4n6N'}) - const flags = account_info.result.account_data.Flags - for (const flagName in AccountFlags) { - if (flags & AccountFlags[flagName]) { - console.log(`${flagName} enabled`) - } - } - process.exit(0) -} +// async function parseAccountFlags() { +// await client.connect() +// const account_info = await client.request({ +// command: 'account_info', +// account: 'rKsdkGhyZH6b2Zzd5hNnEqSv2wpznn4n6N' +// }) +// const flags = account_info.result.account_data.Flags +// for (const flagName in AccountFlags) { +// if (flags & AccountFlags[flagName]) { +// console.log(`${flagName} enabled`) +// } +// } +// process.exit(0) +// } diff --git a/snippets/src/paths.ts b/snippets/src/paths.ts index 4ad4acff..f049e665 100644 --- a/snippets/src/paths.ts +++ b/snippets/src/paths.ts @@ -1,47 +1,53 @@ -import {Client} from '../../dist/npm' +// import {Client} from '../../dist/npm' -const client = new Client( - // 'wss://s.altnet.rippletest.net:51233' - // 'ws://35.158.96.209:51233' - 'ws://34.210.87.206:51233' -) +// const client = new Client( +// // 'wss://s.altnet.rippletest.net:51233' +// // 'ws://35.158.96.209:51233' +// 'ws://34.210.87.206:51233' +// ) -sign() +// sign() -async function sign() { - await client.connect() - const pathfind: any = { - source: { - address: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', - amount: { - currency: 'drops', - value: '100' - } - }, - destination: { - address: 'rKT4JX4cCof6LcDYRz8o3rGRu7qxzZ2Zwj', - amount: { - currency: 'USD', - counterparty: 'rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc' - } - } - } +// async function sign() { +// await client.connect() +// const pathfind: any = { +// source: { +// address: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', +// amount: { +// currency: 'drops', +// value: '100' +// } +// }, +// destination: { +// address: 'rKT4JX4cCof6LcDYRz8o3rGRu7qxzZ2Zwj', +// amount: { +// currency: 'USD', +// counterparty: 'rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc' +// } +// } +// } - await client.getPaths(pathfind).then(async (data) => { - console.log('paths:', JSON.stringify(data)) - const fakeSecret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' +// await client +// .getPaths(pathfind) +// .then(async (data) => { +// console.log('paths:', JSON.stringify(data)) +// const fakeSecret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' - pathfind.paths = data[0].paths - pathfind.destination = data[0].destination - await client.preparePayment('r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', pathfind).then(ret => { - const signed = client.sign(ret.txJSON, fakeSecret) - console.log('signed:', signed) - }).catch(err => { - console.log('ERR 1:', JSON.stringify(err)) - }) - }).catch(err => { - console.log('ERR 2:', err) - }) +// pathfind.paths = data[0].paths +// pathfind.destination = data[0].destination +// await client +// .preparePayment('r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', pathfind) +// .then((ret) => { +// const signed = client.sign(ret.txJSON, fakeSecret) +// console.log('signed:', signed) +// }) +// .catch((err) => { +// console.log('ERR 1:', JSON.stringify(err)) +// }) +// }) +// .catch((err) => { +// console.log('ERR 2:', err) +// }) - client.disconnect() -} +// client.disconnect() +// } diff --git a/snippets/src/reliableTransactionSubmission.ts b/snippets/src/reliableTransactionSubmission.ts index e782fefb..2f6bfe91 100644 --- a/snippets/src/reliableTransactionSubmission.ts +++ b/snippets/src/reliableTransactionSubmission.ts @@ -1,201 +1,215 @@ -import { - Client, - AccountInfoResponse, - LedgerClosedEvent -} from '../../dist/npm' -import https = require('https') +// import https = require('https') -/** - * When implementing Reliable Transaction Submission, there are many potential solutions, each with different trade-offs. The main decision points are: - * 1) Transaction preparation: - * - How do we decide which account sequence and LastLedgerSequence numbers to use? - * (To prevent unintentional duplicate transactions, an {account, account_sequence} pair can be used as a transaction's idempotency key) - * - How do we decide how much to pay for the transaction fee? (If our transactions have been failing due to low fee, we should consider increasing this value) - * 2) Transaction status retrieval. Options include: - * - Poll for transaction status: - * - On a regular interval (e.g. every 3-5 seconds), or - * - When a new validated ledger is detected - * + (To accommodate an edge case in transaction retrieval, check the sending account's Sequence number to confirm that it has the expected value; - * alternatively, wait until a few additional ledgers have been validated before deciding that a transaction has definitively not been included in a validated ledger) - * - Listen for transaction status: scan all validated transactions to see if our transactions are among them - * 3) What do we do when a transaction fails? It is possible to implement retry logic, but caution is advised. Note that there are a few ways for a transaction to fail: - * A) `tec`: The transaction was included in a ledger but only claimed the transaction fee - * B) `tesSUCCESS` but unexpected result: The transaction was successful but did not have the expected result. This generally does not occur for XRP-to-XRP payments - * C) The transaction was not, and never will be, included in a validated ledger [3C] - * - * References: - * - https://xrpl.org/reliable-transaction-submission.html - * - https://xrpl.org/send-xrp.html - * - https://xrpl.org/look-up-transaction-results.html - * - https://xrpl.org/get-started-with-rippleapi-for-javascript.html - * - https://xrpl.org/monitor-incoming-payments-with-websocket.html - * - * For the implementation in this example, we have made the following decisions: - * 1) The script will choose the account sequence and LastLedgerSequence numbers automatically. We allow ripple-lib to choose the fee. - * Payments are defined upfront, and idempotency is not needed. If the script is run a second time, duplicate payments will result. - * 2) We will listen for notification that a new validated ledger has been found, and poll for transaction status at that time. - * Futhermore, as a precaution, we will wait until the server is 3 ledgers past the transaction's LastLedgerSequence - * (with the transaction nowhere to be seen) before deciding that it has definitively failed per [3C] - * 3) Transactions will not be automatically retried. Transactions are limited to XRP-to-XRP payments and cannot "succeed" in an unexpected way. - */ -reliableTransactionSubmissionExample() +// import {Client, AccountInfoResponse, LedgerClosedEvent} from '../../dist/npm' -async function reliableTransactionSubmissionExample() { - /** - * Array of payments to execute. - * - * For brevity, these are XRP-to-XRP payments, taking a source, destination, and an amount in drops. - * - * The script will attempt to make all of these payments as quickly as possible, and report the final status of each. Transactions that fail are NOT retried. - */ - const payments = [] +// /** +// * When implementing Reliable Transaction Submission, there are many potential solutions, each with different trade-offs. The main decision points are: +// * 1) Transaction preparation: +// * - How do we decide which account sequence and LastLedgerSequence numbers to use? +// * (To prevent unintentional duplicate transactions, an {account, account_sequence} pair can be used as a transaction's idempotency key) +// * - How do we decide how much to pay for the transaction fee? (If our transactions have been failing due to low fee, we should consider increasing this value) +// * 2) Transaction status retrieval. Options include: +// * - Poll for transaction status: +// * - On a regular interval (e.g. Every 3-5 seconds), or +// * - When a new validated ledger is detected +// * + (To accommodate an edge case in transaction retrieval, check the sending account's Sequence number to confirm that it has the expected value; +// * alternatively, wait until a few additional ledgers have been validated before deciding that a transaction has definitively not been included in a validated ledger) +// * - Listen for transaction status: scan all validated transactions to see if our transactions are among them +// * 3) What do we do when a transaction fails? It is possible to implement retry logic, but caution is advised. Note that there are a few ways for a transaction to fail: +// * A) `tec`: The transaction was included in a ledger but only claimed the transaction fee +// * B) `tesSUCCESS` but unexpected result: The transaction was successful but did not have the expected result. This generally does not occur for XRP-to-XRP payments +// * C) The transaction was not, and never will be, included in a validated ledger [3C]. +// * +// * References: +// * - https://xrpl.org/reliable-transaction-submission.html +// * - https://xrpl.org/send-xrp.html +// * - https://xrpl.org/look-up-transaction-results.html +// * - https://xrpl.org/get-started-with-rippleapi-for-javascript.html +// * - https://xrpl.org/monitor-incoming-payments-with-websocket.html. +// * +// * For the implementation in this example, we have made the following decisions: +// * 1) The script will choose the account sequence and LastLedgerSequence numbers automatically. We allow ripple-lib to choose the fee. +// * Payments are defined upfront, and idempotency is not needed. If the script is run a second time, duplicate payments will result. +// * 2) We will listen for notification that a new validated ledger has been found, and poll for transaction status at that time. +// * Futhermore, as a precaution, we will wait until the server is 3 ledgers past the transaction's LastLedgerSequence +// * (with the transaction nowhere to be seen) before deciding that it has definitively failed per [3C] +// * 3) Transactions will not be automatically retried. Transactions are limited to XRP-to-XRP payments and cannot "succeed" in an unexpected way. +// */ +// reliableTransactionSubmissionExample() - const sourceAccount = (await generateTestnetAccount()).account - console.log(`Generated new Testnet account: ${sourceAccount.classicAddress}/${sourceAccount.secret}`) - // Send amounts from 1 drop to 10 drops - for (let i = 1; i <= 10; i++) { - payments.push({ - source: sourceAccount, - destination: 'rhsoCozhUxwcyQgzFi1FVRoMVQgk7cZd4L', // Random Testnet destination - amount_drops: i.toString(), - }) - } - const results = await performPayments(payments) - console.log(JSON.stringify(results, null, 2)) - process.exit(0) -} +// async function reliableTransactionSubmissionExample() { +// /** +// * Array of payments to execute. +// * +// * For brevity, these are XRP-to-XRP payments, taking a source, destination, and an amount in drops. +// * +// * The script will attempt to make all of these payments as quickly as possible, and report the final status of each. Transactions that fail are NOT retried. +// */ +// const payments = [] -async function performPayments(payments) { - const finalResults = [] - const txFinalizedPromises = [] - const client = new Client('wss://s.altnet.rippletest.net:51233') - await client.connect() +// const sourceAccount = (await generateTestnetAccount()).account +// console.log( +// `Generated new Testnet account: ${sourceAccount.classicAddress}/${sourceAccount.secret}` +// ) +// // Send amounts from 1 drop to 10 drops +// for (let i = 1; i <= 10; i++) { +// payments.push({ +// source: sourceAccount, +// destination: 'rhsoCozhUxwcyQgzFi1FVRoMVQgk7cZd4L', // Random Testnet destination +// amount_drops: i.toString() +// }) +// } +// const results = await performPayments(payments) +// console.log(JSON.stringify(results, null, 2)) +// process.exit(0) +// } - for (let i = 0; i < payments.length; i++) { - const payment = payments[i] - const account_info: AccountInfoResponse = await client.request({ - command: 'account_info', - account: payment.source.classicAddress, - ledger_index: 'current'}) - const sequence = account_info.result.account_data.Sequence - const preparedPayment = await client.preparePayment(payment.source.classicAddress, { - source: { - address: payment.source.classicAddress, - amount: { - value: payment.amount_drops, - currency: 'drops' - } - }, - destination: { - address: payment.destination, - minAmount: { - value: payment.amount_drops, - currency: 'drops' - } - } - }, { - sequence - }) - const signed = client.sign(preparedPayment.txJSON, payment.source.secret) - finalResults.push({ - id: signed.id - }) - const response = await client.request({command: 'submit', tx_blob: signed.signedTransaction}) +// async function performPayments(payments) { +// const finalResults = [] +// const txFinalizedPromises = [] +// const client = new Client('wss://s.altnet.rippletest.net:51233') +// await client.connect() - // Most of the time we'll get 'tesSUCCESS' or (after many submissions) 'terQUEUED' - console.log(`tx ${i} - tentative: ${response.result.engine_result}`) +// for (let i = 0; i < payments.length; i++) { +// const payment = payments[i] +// const account_info: AccountInfoResponse = await client.request({ +// command: 'account_info', +// account: payment.source.classicAddress, +// ledger_index: 'current' +// }) +// const sequence = account_info.result.account_data.Sequence +// const preparedPayment = await client.preparePayment( +// payment.source.classicAddress, +// { +// source: { +// address: payment.source.classicAddress, +// amount: { +// value: payment.amount_drops, +// currency: 'drops' +// } +// }, +// destination: { +// address: payment.destination, +// minAmount: { +// value: payment.amount_drops, +// currency: 'drops' +// } +// } +// }, +// { +// sequence +// } +// ) +// const signed = client.sign(preparedPayment.txJSON, payment.source.secret) +// finalResults.push({ +// id: signed.id +// }) +// const response = await client.request({ +// command: 'submit', +// tx_blob: signed.signedTransaction +// }) - const txFinalizedPromise = new Promise((resolve) => { - const ledgerClosedCallback = async (event: LedgerClosedEvent) => { - let status - try { - status = await client.request({command: 'tx', transaction: signed.id}) - } catch (e) { - // Typical error when the tx hasn't been validated yet: - if (e.name !== 'MissingLedgerHistoryError') { - console.log(e) - } +// // Most of the time we'll get 'tesSUCCESS' or (after many submissions) 'terQUEUED' +// console.log(`tx ${i} - tentative: ${response.result.engine_result}`) - if (event.ledger_index > preparedPayment.instructions.maxLedgerVersion + 3) { - // Assumptions: - // - We are still connected to the same rippled server - // - No ledger gaps occurred - // - All ledgers between the time we submitted the tx and now have been checked for the tx - status = { - finalResult: 'Transaction was not, and never will be, included in a validated ledger' - } - } else { - // Check again later: - client.connection.once('ledgerClosed', ledgerClosedCallback) - return - } - } +// const txFinalizedPromise = new Promise((resolve) => { +// const ledgerClosedCallback = async (event: LedgerClosedEvent) => { +// let status +// try { +// status = await client.request({command: 'tx', transaction: signed.id}) +// } catch (e) { +// // Typical error when the tx hasn't been validated yet: +// if (e.name !== 'MissingLedgerHistoryError') { +// console.log(e) +// } - for (let j = 0; j < finalResults.length; j++) { - if (finalResults[j].id === signed.id) { - finalResults[j].result = status.address ? { - source: status.address, - destination: status.specification.destination.address, - deliveredAmount: status.outcome.deliveredAmount, - result: status.outcome.result, - timestamp: status.outcome.timestamp, - ledgerVersion: status.outcome.ledgerVersion - } : status - process.stdout.write('.') - return resolve() - } - } - } - client.connection.once('ledgerClosed', ledgerClosedCallback) - }) - txFinalizedPromises.push(txFinalizedPromise) - } - await Promise.all(txFinalizedPromises) - return finalResults -} +// if ( +// event.ledger_index > +// preparedPayment.instructions.maxLedgerVersion + 3 +// ) { +// // Assumptions: +// // - We are still connected to the same rippled server +// // - No ledger gaps occurred +// // - All ledgers between the time we submitted the tx and now have been checked for the tx +// status = { +// finalResult: +// 'Transaction was not, and never will be, included in a validated ledger' +// } +// } else { +// // Check again later: +// client.connection.once('ledgerClosed', ledgerClosedCallback) +// return +// } +// } -/** - * Generate a new Testnet account by requesting one from the faucet - */ -async function generateTestnetAccount(): Promise<{ - account: { - xAddress: string, - classicAddress, string, - secret: string - }, - balance: number - }> { - const options = { - hostname: 'faucet.altnet.rippletest.net', - port: 443, - path: '/accounts', - method: 'POST' - } - return new Promise((resolve, reject) => { - const request = https.request(options, response => { - const chunks = [] - response.on('data', d => { - chunks.push(d) - }) - response.on('end', () => { - const body = Buffer.concat(chunks).toString() +// for (let j = 0; j < finalResults.length; j++) { +// if (finalResults[j].id === signed.id) { +// finalResults[j].result = status.address +// ? { +// source: status.address, +// destination: status.specification.destination.address, +// deliveredAmount: status.outcome.deliveredAmount, +// result: status.outcome.result, +// timestamp: status.outcome.timestamp, +// ledgerVersion: status.outcome.ledgerVersion +// } +// : status +// process.stdout.write('.') +// return resolve() +// } +// } +// } +// client.connection.once('ledgerClosed', ledgerClosedCallback) +// }) +// txFinalizedPromises.push(txFinalizedPromise) +// } +// await Promise.all(txFinalizedPromises) +// return finalResults +// } - // "application/json; charset=utf-8" - if (response.headers['content-type'].startsWith('application/json')) { - resolve(JSON.parse(body)) - } else { - reject({ - statusCode: response.statusCode, - contentType: response.headers['content-type'], - body - }) - } - }) - }) - request.on('error', error => { - console.error(error) - reject(error) - }) - request.end() - }) -} +// /** +// * Generate a new Testnet account by requesting one from the faucet. +// */ +// async function generateTestnetAccount(): Promise<{ +// account: { +// xAddress: string +// classicAddress +// string +// secret: string +// } +// balance: number +// }> { +// const options = { +// hostname: 'faucet.altnet.rippletest.net', +// port: 443, +// path: '/accounts', +// method: 'POST' +// } +// return new Promise((resolve, reject) => { +// const request = https.request(options, (response) => { +// const chunks = [] +// response.on('data', (d) => { +// chunks.push(d) +// }) +// response.on('end', () => { +// const body = Buffer.concat(chunks).toString() + +// // "application/json; charset=utf-8" +// if (response.headers['content-type'].startsWith('application/json')) { +// resolve(JSON.parse(body)) +// } else { +// reject({ +// statusCode: response.statusCode, +// contentType: response.headers['content-type'], +// body +// }) +// } +// }) +// }) +// request.on('error', (error) => { +// console.error(error) +// reject(error) +// }) +// request.end() +// }) +// } diff --git a/snippets/tsconfig.json b/snippets/tsconfig.json index 15c9a629..1d440aca 100644 --- a/snippets/tsconfig.json +++ b/snippets/tsconfig.json @@ -1,12 +1,8 @@ { - "extends": "../tsconfig-base", + "extends": "../tsconfig.build.json", "compilerOptions": { "outDir": "./dist", - "rootDir": "./src" }, - "references": [ - { "path": "../src" } - ], "include": [ "./src/**/*.ts" ] diff --git a/src/Wallet.ts b/src/Wallet.ts index 09982b42..9a6cd58c 100644 --- a/src/Wallet.ts +++ b/src/Wallet.ts @@ -1,12 +1,13 @@ -import {fromSeed} from 'bip32' -import {mnemonicToSeedSync} from 'bip39' -import {decode, encodeForSigning} from 'ripple-binary-codec' -import {deriveKeypair, generateSeed, verify} from 'ripple-keypairs' -import ECDSA from './common/ecdsa' -import {SignedTransaction} from './common/types/objects' -import {signOffline} from './transaction/sign' -import {SignOptions} from './transaction/types' -import {ValidationError} from './common/errors' +import { fromSeed } from "bip32"; +import { mnemonicToSeedSync } from "bip39"; +import { decode, encodeForSigning } from "ripple-binary-codec"; +import { deriveKeypair, generateSeed, verify } from "ripple-keypairs"; + +import ECDSA from "./common/ecdsa"; +import { ValidationError } from "./common/errors"; +import { SignedTransaction } from "./common/types/objects"; +import { signOffline } from "./transaction/sign"; +import { SignOptions } from "./transaction/types"; /** * A utility for deriving a wallet composed of a keypair (publicKey/privateKey). @@ -14,53 +15,61 @@ import {ValidationError} from './common/errors' * It provides functionality to sign/verify transactions offline. */ class Wallet { - readonly publicKey: string - readonly privateKey: string - private static readonly defaultAlgorithm: ECDSA = ECDSA.ed25519 - private static readonly defaultDerivationPath: string = "m/44'/144'/0'/0/0" + readonly publicKey: string; + readonly privateKey: string; + private static readonly defaultAlgorithm: ECDSA = ECDSA.ed25519; + private static readonly defaultDerivationPath: string = "m/44'/144'/0'/0/0"; constructor(publicKey: string, privateKey: string) { - this.publicKey = publicKey - this.privateKey = privateKey + this.publicKey = publicKey; + this.privateKey = privateKey; } /** * Derives a wallet from a seed. - * @param {string} seed A string used to generate a keypair (publicKey/privateKey) to derive a wallet. - * @param {ECDSA} algorithm The digital signature algorithm to generate an address for. - * @returns {Wallet} A Wallet derived from a seed. + * + * @param seed - A string used to generate a keypair (publicKey/privateKey) to derive a wallet. + * @param algorithm - The digital signature algorithm to generate an address for. + * @returns A Wallet derived from a seed. */ - static fromSeed(seed: string, algorithm: ECDSA = Wallet.defaultAlgorithm): Wallet { - return Wallet.deriveWallet(seed, algorithm) + static fromSeed( + seed: string, + algorithm: ECDSA = Wallet.defaultAlgorithm + ): Wallet { + return Wallet.deriveWallet(seed, algorithm); } /** * Derives a wallet from a mnemonic. - * @param {string} mnemonic A string consisting of words (whitespace delimited) used to derive a wallet. - * @param {string} derivationPath The path to derive a keypair (publicKey/privateKey) from a seed (that was converted from a mnemonic). - * @returns {Wallet} A Wallet derived from a mnemonic. + * + * @param mnemonic - A string consisting of words (whitespace delimited) used to derive a wallet. + * @param derivationPath - The path to derive a keypair (publicKey/privateKey) from a seed (that was converted from a mnemonic). + * @returns A Wallet derived from a mnemonic. */ static fromMnemonic( mnemonic: string, derivationPath: string = Wallet.defaultDerivationPath ): Wallet { - const seed = mnemonicToSeedSync(mnemonic) - const masterNode = fromSeed(seed) - const node = masterNode.derivePath(derivationPath) + const seed = mnemonicToSeedSync(mnemonic); + const masterNode = fromSeed(seed); + const node = masterNode.derivePath(derivationPath); if (node.privateKey === undefined) { - throw new ValidationError('Unable to derive privateKey from mnemonic input') + throw new ValidationError( + "Unable to derive privateKey from mnemonic input" + ); } - const publicKey = Wallet.hexFromBuffer(node.publicKey) - const privateKey = Wallet.hexFromBuffer(node.privateKey) - return new Wallet(publicKey, `00${privateKey}`) + const publicKey = Wallet.hexFromBuffer(node.publicKey); + const privateKey = Wallet.hexFromBuffer(node.privateKey); + return new Wallet(publicKey, `00${privateKey}`); } /** * Derives a wallet from an entropy (array of random numbers). - * @param {Uint8Array | number[]} entropy An array of random numbers to generate a seed used to derive a wallet. - * @param {ECDSA} algorithm The digital signature algorithm to generate an address for. - * @returns {Wallet} A Wallet derived from an entropy. + * + * @param entropy - An array of random numbers to generate a seed used to derive a wallet. + * @param algorithm - The digital signature algorithm to generate an address for. + * @returns A Wallet derived from an entropy. */ static fromEntropy( entropy: Uint8Array | number[], @@ -68,45 +77,50 @@ class Wallet { ): Wallet { const options = { entropy: Uint8Array.from(entropy), - algorithm - } - const seed = generateSeed(options) - return Wallet.deriveWallet(seed, algorithm) + algorithm, + }; + const seed = generateSeed(options); + return Wallet.deriveWallet(seed, algorithm); } private static hexFromBuffer(buffer: Buffer): string { - return buffer.toString('hex').toUpperCase() + return buffer.toString("hex").toUpperCase(); } - private static deriveWallet(seed: string, algorithm: ECDSA = Wallet.defaultAlgorithm): Wallet { - const {publicKey, privateKey} = deriveKeypair(seed, {algorithm}) - return new Wallet(publicKey, privateKey) + private static deriveWallet( + seed: string, + algorithm: ECDSA = Wallet.defaultAlgorithm + ): Wallet { + const { publicKey, privateKey } = deriveKeypair(seed, { algorithm }); + return new Wallet(publicKey, privateKey); } /** * Signs a transaction offline. - * @param {object} transaction A transaction to be signed offline. - * @param {SignOptions} options Options to include for signing. - * @returns {SignedTransaction} A signed transaction. + * + * @param transaction - A transaction to be signed offline. + * @param options - Options to include for signing. + * @returns A signed transaction. */ signTransaction( transaction: any, // TODO: transaction should be typed with Transaction type. - options: SignOptions = {signAs: ''} + options: SignOptions = { signAs: "" } ): SignedTransaction { - return signOffline(this, JSON.stringify(transaction), options) + return signOffline(this, JSON.stringify(transaction), options); } /** * Verifies a signed transaction offline. - * @param {string} signedTransaction A signed transaction (hex string of signTransaction result) to be verified offline. - * @returns {boolean} Returns true if a signedTransaction is valid. + * + * @param signedTransaction - A signed transaction (hex string of signTransaction result) to be verified offline. + * @returns Returns true if a signedTransaction is valid. */ verifyTransaction(signedTransaction: string): boolean { - const tx = decode(signedTransaction) - const messageHex: string = encodeForSigning(tx) - const signature = tx.TxnSignature - return verify(messageHex, signature, this.publicKey) + const tx = decode(signedTransaction); + const messageHex: string = encodeForSigning(tx); + const signature = tx.TxnSignature; + return verify(messageHex, signature, this.publicKey); } } -export default Wallet +export default Wallet; diff --git a/src/client/backoff.ts b/src/client/backoff.ts index 29b227b7..22ef47de 100644 --- a/src/client/backoff.ts +++ b/src/client/backoff.ts @@ -1,44 +1,42 @@ -/* - * Original code based on "backo" - https://github.com/segmentio/backo - * MIT License - Copyright 2014 Segment.io - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ +// Original code based on "backo" - https://github.com/segmentio/backo +// MIT License - Copyright 2014 Segment.io +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /** * A Back off strategy that increases exponentially. Useful with repeated * setTimeout calls over a network (where the destination may be down). */ export class ExponentialBackoff { - private readonly ms: number - private readonly max: number - private readonly factor: number = 2 - private readonly jitter: number = 0 - attempts: number = 0 + private readonly ms: number; + private readonly max: number; + private readonly factor: number = 2; + private readonly jitter: number = 0; + attempts = 0; - constructor(opts: {min?: number; max?: number} = {}) { - this.ms = opts.min || 100 - this.max = opts.max || 10000 + constructor(opts: { min?: number; max?: number } = {}) { + this.ms = opts.min || 100; + this.max = opts.max || 10000; } /** * Return the backoff duration. */ duration() { - var ms = this.ms * Math.pow(this.factor, this.attempts++) + let ms = this.ms * this.factor ** this.attempts++; if (this.jitter) { - var rand = Math.random() - var deviation = Math.floor(rand * this.jitter * ms) - ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation + const rand = Math.random(); + const deviation = Math.floor(rand * this.jitter * ms); + ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation; } - return Math.min(ms, this.max) | 0 + return Math.min(ms, this.max) | 0; } /** * Reset the number of attempts. */ reset() { - this.attempts = 0 + this.attempts = 0; } } diff --git a/src/client/broadcastClient.ts b/src/client/broadcastClient.ts index 9a63adef..d4353248 100644 --- a/src/client/broadcastClient.ts +++ b/src/client/broadcastClient.ts @@ -1,62 +1,66 @@ -import {Client, ClientOptions} from './' +import { Client, ClientOptions } from "."; class BroadcastClient extends Client { - ledgerVersion: number | undefined = undefined - private _clients: Client[] + ledgerVersion: number | undefined = undefined; + private readonly _clients: Client[]; constructor(servers, options: ClientOptions = {}) { - super(servers[0], options) + super(servers[0], options); const clients: Client[] = servers.map( (server) => new Client(server, options) - ) + ); // exposed for testing - this._clients = clients + this._clients = clients; this.getMethodNames().forEach((name) => { this[name] = function () { // eslint-disable-line no-loop-func - return Promise.race(clients.map((client) => client[name](...arguments))) - } - }) + return Promise.race( + clients.map((client) => client[name](...arguments)) + ); + }; + }); // connection methods must be overridden to apply to all client instances this.connect = async function () { - await Promise.all(clients.map((client) => client.connect())) - } + await Promise.all(clients.map((client) => client.connect())); + }; this.disconnect = async function () { - await Promise.all(clients.map((client) => client.disconnect())) - } + await Promise.all(clients.map((client) => client.disconnect())); + }; this.isConnected = function () { - return clients.map((client) => client.isConnected()).every(Boolean) - } + return clients.map((client) => client.isConnected()).every(Boolean); + }; // synchronous methods are all passed directly to the first client instance - const defaultClient = clients[0] - const syncMethods = ['sign'] + const defaultClient = clients[0]; + const syncMethods = ["sign"]; syncMethods.forEach((name) => { - this[name] = defaultClient[name].bind(defaultClient) - }) + this[name] = defaultClient[name].bind(defaultClient); + }); clients.forEach((client) => { - client.on('error', (errorCode, errorMessage, data) => - this.emit('error', errorCode, errorMessage, data) - ) - }) + client.on("error", (errorCode, errorMessage, data) => + this.emit("error", errorCode, errorMessage, data) + ); + }); } getMethodNames() { - const methodNames: string[] = [] - const firstClient = this._clients[0] - const methods = Object.getOwnPropertyNames(firstClient) - methods.push(...Object.getOwnPropertyNames(Object.getPrototypeOf(firstClient))) + const methodNames: string[] = []; + const firstClient = this._clients[0]; + const methods = Object.getOwnPropertyNames(firstClient); + methods.push( + ...Object.getOwnPropertyNames(Object.getPrototypeOf(firstClient)) + ); for (const name of methods) { - if (typeof firstClient[name] === 'function' && name !== 'constructor') { - methodNames.push(name) + if (typeof firstClient[name] === "function" && name !== "constructor") { + methodNames.push(name); } } - return methodNames + return methodNames; } } -export {BroadcastClient} +export { BroadcastClient }; diff --git a/src/client/connection.ts b/src/client/connection.ts index 0d7a4b13..fd67af1b 100644 --- a/src/client/connection.ts +++ b/src/client/connection.ts @@ -1,7 +1,9 @@ -import _ from 'lodash' -import {EventEmitter} from 'events' -import {parse as parseURL} from 'url' -import WebSocket from 'ws' +import { EventEmitter } from "events"; +import { parse as parseURL } from "url"; + +import _ from "lodash"; +import WebSocket from "ws"; + import { RippledError, DisconnectedError, @@ -9,25 +11,26 @@ import { TimeoutError, ResponseFormatError, ConnectionError, - RippleError -} from '../common/errors' -import {ExponentialBackoff} from './backoff' -import { Response } from '../models/methods' + RippleError, +} from "../common/errors"; +import { Response } from "../models/methods"; + +import { ExponentialBackoff } from "./backoff"; /** * ConnectionOptions is the configuration for the Connection class. */ export interface ConnectionOptions { - trace?: boolean | ((id: string, message: string) => void) - proxy?: string - proxyAuthorization?: string - authorization?: string - trustedCertificates?: string[] - key?: string - passphrase?: string - certificate?: string - timeout: number // request timeout - connectionTimeout: number + trace?: boolean | ((id: string, message: string) => void); + proxy?: string; + proxyAuthorization?: string; + authorization?: string; + trustedCertificates?: string[]; + key?: string; + passphrase?: string; + certificate?: string; + timeout: number; // request timeout + connectionTimeout: number; } /** @@ -35,82 +38,88 @@ export interface ConnectionOptions { * is optional, so any ConnectionOptions configuration that has a default value is * still optional at the point that the user provides it. */ -export type ConnectionUserOptions = Partial +export type ConnectionUserOptions = Partial; -/** - * Represents an intentionally triggered web-socket disconnect code. - * WebSocket spec allows 4xxx codes for app/library specific codes. - * See: https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent - **/ -const INTENTIONAL_DISCONNECT_CODE = 4000 +// +// Represents an intentionally triggered web-socket disconnect code. +// WebSocket spec allows 4xxx codes for app/library specific codes. +// See: https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent +// +const INTENTIONAL_DISCONNECT_CODE = 4000; /** * Create a new websocket given your URL and optional proxy/certificate * configuration. + * + * @param url + * @param config */ function createWebSocket(url: string, config: ConnectionOptions): WebSocket { - const options: WebSocket.ClientOptions = {} + const options: WebSocket.ClientOptions = {}; if (config.proxy != null) { // TODO: replace deprecated method - const parsedURL = parseURL(url) - const parsedProxyURL = parseURL(config.proxy) + const parsedURL = parseURL(url); + const parsedProxyURL = parseURL(config.proxy); const proxyOverrides = _.omitBy( { - secureEndpoint: parsedURL.protocol === 'wss:', - secureProxy: parsedProxyURL.protocol === 'https:', + secureEndpoint: parsedURL.protocol === "wss:", + secureProxy: parsedProxyURL.protocol === "https:", auth: config.proxyAuthorization, ca: config.trustedCertificates, key: config.key, passphrase: config.passphrase, - cert: config.certificate + cert: config.certificate, }, (value) => value == null - ) - const proxyOptions = {...parsedProxyURL, ...proxyOverrides} - let HttpsProxyAgent + ); + const proxyOptions = { ...parsedProxyURL, ...proxyOverrides }; + let HttpsProxyAgent; try { - HttpsProxyAgent = require('https-proxy-agent') + HttpsProxyAgent = require("https-proxy-agent"); } catch (error) { - throw new Error('"proxy" option is not supported in the browser') + throw new Error('"proxy" option is not supported in the browser'); } - options.agent = new HttpsProxyAgent(proxyOptions) + options.agent = new HttpsProxyAgent(proxyOptions); } if (config.authorization != null) { - const base64 = Buffer.from(config.authorization).toString('base64') - options.headers = {Authorization: `Basic ${base64}`} + const base64 = Buffer.from(config.authorization).toString("base64"); + options.headers = { Authorization: `Basic ${base64}` }; } const optionsOverrides = _.omitBy( { ca: config.trustedCertificates, key: config.key, passphrase: config.passphrase, - cert: config.certificate + cert: config.certificate, }, (value) => value == null - ) - const websocketOptions = {...options, ...optionsOverrides} - const websocket = new WebSocket(url, null, websocketOptions) + ); + const websocketOptions = { ...options, ...optionsOverrides }; + const websocket = new WebSocket(url, websocketOptions); // we will have a listener for each outstanding request, // so we have to raise the limit (the default is 10) - if (typeof websocket.setMaxListeners === 'function') { - websocket.setMaxListeners(Infinity) + if (typeof websocket.setMaxListeners === "function") { + websocket.setMaxListeners(Infinity); } - return websocket + return websocket; } /** - * ws.send(), but promisified. + * Ws.send(), but promisified. + * + * @param ws + * @param message */ function websocketSendAsync(ws: WebSocket, message: string) { return new Promise((resolve, reject) => { - ws.send(message, undefined, (error) => { + ws.send(message, (error) => { if (error) { - reject(new DisconnectedError(error.message, error)) + reject(new DisconnectedError(error.message, error)); } else { - resolve() + resolve(); } - }) - }) + }); + }); } /** @@ -119,25 +128,25 @@ function websocketSendAsync(ws: WebSocket, message: string) { * after-the-fact. */ class ConnectionManager { - private promisesAwaitingConnection: { - resolve: Function - reject: Function - }[] = [] + private promisesAwaitingConnection: Array<{ + resolve: Function; + reject: Function; + }> = []; resolveAllAwaiting() { - this.promisesAwaitingConnection.map(({resolve}) => resolve()) - this.promisesAwaitingConnection = [] + this.promisesAwaitingConnection.map(({ resolve }) => resolve()); + this.promisesAwaitingConnection = []; } rejectAllAwaiting(error: Error) { - this.promisesAwaitingConnection.map(({reject}) => reject(error)) - this.promisesAwaitingConnection = [] + this.promisesAwaitingConnection.map(({ reject }) => reject(error)); + this.promisesAwaitingConnection = []; } awaitConnection(): Promise { return new Promise((resolve, reject) => { - this.promisesAwaitingConnection.push({resolve, reject}) - }) + this.promisesAwaitingConnection.push({ resolve, reject }); + }); } } @@ -148,231 +157,247 @@ class ConnectionManager { * original request. */ class RequestManager { - private nextId = 0 - private promisesAwaitingResponse: { - resolve: Function - reject: Function - timer: NodeJS.Timeout - }[] = [] + private nextId = 0; + private promisesAwaitingResponse: Array<{ + resolve: Function; + reject: Function; + timer: NodeJS.Timeout; + }> = []; cancel(id: number) { - const {timer} = this.promisesAwaitingResponse[id] - clearTimeout(timer) - delete this.promisesAwaitingResponse[id] + const { timer } = this.promisesAwaitingResponse[id]; + clearTimeout(timer); + delete this.promisesAwaitingResponse[id]; } resolve(id: string | number, data: Response) { - const {timer, resolve} = this.promisesAwaitingResponse[id] - clearTimeout(timer) - resolve(data) - delete this.promisesAwaitingResponse[id] + const { timer, resolve } = this.promisesAwaitingResponse[id]; + clearTimeout(timer); + resolve(data); + delete this.promisesAwaitingResponse[id]; } reject(id: string | number, error: Error) { - const {timer, reject} = this.promisesAwaitingResponse[id] - clearTimeout(timer) - reject(error) - delete this.promisesAwaitingResponse[id] + const { timer, reject } = this.promisesAwaitingResponse[id]; + clearTimeout(timer); + reject(error); + delete this.promisesAwaitingResponse[id]; } rejectAll(error: Error) { this.promisesAwaitingResponse.forEach((_, id) => { - this.reject(id, error) - }) + this.reject(id, error); + }); } /** * Creates a new WebSocket request. This sets up a timeout timer to catch * hung responses, and a promise that will resolve with the response once * the response is seen & handled. + * + * @param data + * @param timeout */ - createRequest(data: any, timeout: number): [string | number, string, Promise] { - const newId = data.id ? data.id : this.nextId++ - const newData = JSON.stringify({...data, id: newId}) + createRequest( + data: any, + timeout: number + ): [string | number, string, Promise] { + const newId = data.id ? data.id : this.nextId++; + const newData = JSON.stringify({ ...data, id: newId }); const timer = setTimeout( () => this.reject(newId, new TimeoutError()), timeout - ) + ); // Node.js won't exit if a timer is still running, so we tell Node to ignore. // (Node will still wait for the request to complete). if (timer.unref) { - timer.unref() + timer.unref(); } - const newPromise = new Promise((resolve: (data: Response) => void, reject) => { - this.promisesAwaitingResponse[newId] = {resolve, reject, timer} - }) - return [newId, newData, newPromise] + const newPromise = new Promise( + (resolve: (data: Response) => void, reject) => { + this.promisesAwaitingResponse[newId] = { resolve, reject, timer }; + } + ); + return [newId, newData, newPromise]; } /** - * Handle a "response". Responses match to the earlier request handlers, + * Handle a "response". Responses match to the earlier request handlers, * and resolve/reject based on the data received. + * + * @param data */ handleResponse(data: Response) { if (!Number.isInteger(data.id) || data.id < 0) { - throw new ResponseFormatError('valid id not found in response', data) + throw new ResponseFormatError("valid id not found in response", data); } if (!this.promisesAwaitingResponse[data.id]) { - return + return; } - if (data.status === 'error') { - const error = new RippledError(data.error_message || data.error, data) - this.reject(data.id, error) - return + if (data.status === "error") { + const error = new RippledError(data.error_message || data.error, data); + this.reject(data.id, error); + return; } - if (data.status !== 'success') { + if (data.status !== "success") { const error = new ResponseFormatError( `unrecognized status: ${data.status}`, data - ) - this.reject(data.id, error) - return + ); + this.reject(data.id, error); + return; } - this.resolve(data.id, data) + this.resolve(data.id, data); } } /** * The main Connection class. Responsible for connecting to & managing * an active WebSocket connection to a XRPL node. + * + * @param errorOrCode */ export class Connection extends EventEmitter { - private _url: string - private _ws: null | WebSocket = null - private _reconnectTimeoutID: null | NodeJS.Timeout = null - private _heartbeatIntervalID: null | NodeJS.Timeout = null - private _retryConnectionBackoff = new ExponentialBackoff({ + private readonly _url: string | undefined; + private _ws: null | WebSocket = null; + private _reconnectTimeoutID: null | NodeJS.Timeout = null; + private _heartbeatIntervalID: null | NodeJS.Timeout = null; + private readonly _retryConnectionBackoff = new ExponentialBackoff({ min: 100, - max: 60 * 1000 - }) + max: 60 * 1000, + }); - private _trace: (id: string, message: string) => void = () => {} - private _config: ConnectionOptions - private _requestManager = new RequestManager() - private _connectionManager = new ConnectionManager() + private readonly _trace: (id: string, message: string) => void = () => {}; + private readonly _config: ConnectionOptions; + private readonly _requestManager = new RequestManager(); + private readonly _connectionManager = new ConnectionManager(); constructor(url?: string, options: ConnectionUserOptions = {}) { - super() - this.setMaxListeners(Infinity) - this._url = url + super(); + this.setMaxListeners(Infinity); + this._url = url; this._config = { timeout: 20 * 1000, connectionTimeout: 5 * 1000, - ...options - } - if (typeof options.trace === 'function') { - this._trace = options.trace - } else if (options.trace === true) { - this._trace = console.log + ...options, + }; + if (typeof options.trace === "function") { + this._trace = options.trace; + } else if (options.trace) { + this._trace = console.log; } } private _onMessage(message) { - this._trace('receive', message) - let data: any + this._trace("receive", message); + let data: any; try { - data = JSON.parse(message) + data = JSON.parse(message); } catch (error) { - this.emit('error', 'badMessage', error.message, message) - return + this.emit("error", "badMessage", error.message, message); + return; } if (data.type == null && data.error) { - this.emit('error', data.error, data.error_message, data) // e.g. slowDown - return + this.emit("error", data.error, data.error_message, data); // e.g. slowDown + return; } if (data.type) { - this.emit(data.type, data) + this.emit(data.type, data); } - if (data.type === 'response') { + if (data.type === "response") { try { - this._requestManager.handleResponse(data) + this._requestManager.handleResponse(data); } catch (error) { - this.emit('error', 'badMessage', error.message, message) + this.emit("error", "badMessage", error.message, message); } } } private get _state() { - return this._ws ? this._ws.readyState : WebSocket.CLOSED + return this._ws ? this._ws.readyState : WebSocket.CLOSED; } private get _shouldBeConnected() { - return this._ws !== null + return this._ws !== null; } - private _clearHeartbeatInterval = () => { - clearInterval(this._heartbeatIntervalID) - } + private readonly _clearHeartbeatInterval = () => { + if (this._heartbeatIntervalID) { + clearInterval(this._heartbeatIntervalID); + } + }; - private _startHeartbeatInterval = () => { - this._clearHeartbeatInterval() + private readonly _startHeartbeatInterval = () => { + this._clearHeartbeatInterval(); this._heartbeatIntervalID = setInterval( () => this._heartbeat(), this._config.timeout - ) - } + ); + }; /** * A heartbeat is just a "ping" command, sent on an interval. * If this succeeds, we're good. If it fails, disconnect so that the consumer can reconnect, if desired. */ - private _heartbeat = () => { - return this.request({command: 'ping'}).catch(() => { + private readonly _heartbeat = () => { + return this.request({ command: "ping" }).catch(() => { return this.reconnect().catch((error) => { - this.emit('error', 'reconnect', error.message, error) - }) - }) - } + this.emit("error", "reconnect", error.message, error); + }); + }); + }; - private _onConnectionFailed = (errorOrCode: Error | number | null) => { + private readonly _onConnectionFailed = ( + errorOrCode: Error | number | null + ) => { if (this._ws) { - this._ws.removeAllListeners() - this._ws.on('error', () => { + this._ws.removeAllListeners(); + this._ws.on("error", () => { // Correctly listen for -- but ignore -- any future errors: If you // don't have a listener on "error" node would log a warning on error. - }) - this._ws.close() - this._ws = null + }); + this._ws.close(); + this._ws = null; } - if (typeof errorOrCode === 'number') { + if (typeof errorOrCode === "number") { this._connectionManager.rejectAllAwaiting( new NotConnectedError(`Connection failed with code ${errorOrCode}.`, { - code: errorOrCode + code: errorOrCode, }) - ) + ); } else if (errorOrCode && errorOrCode.message) { this._connectionManager.rejectAllAwaiting( new NotConnectedError(errorOrCode.message, errorOrCode) - ) + ); } else { this._connectionManager.rejectAllAwaiting( - new NotConnectedError('Connection failed.') - ) + new NotConnectedError("Connection failed.") + ); } - } + }; isConnected() { - return this._state === WebSocket.OPEN + return this._state === WebSocket.OPEN; } connect(): Promise { if (this.isConnected()) { - return Promise.resolve() + return Promise.resolve(); } if (this._state === WebSocket.CONNECTING) { - return this._connectionManager.awaitConnection() + return this._connectionManager.awaitConnection(); } if (!this._url) { return Promise.reject( - new ConnectionError('Cannot connect because no server was specified') - ) + new ConnectionError("Cannot connect because no server was specified") + ); } if (this._ws) { return Promise.reject( - new RippleError('Websocket connection never cleaned up.', { - state: this._state + new RippleError("Websocket connection never cleaned up.", { + state: this._state, }) - ) + ); } // Create the connection timeout, in case the connection hangs longer than expected. @@ -383,58 +408,71 @@ export class Connection extends EventEmitter { `If your internet connection is working, the rippled server may be blocked or inaccessible. ` + `You can also try setting the 'connectionTimeout' option in the Client constructor.` ) - ) - }, this._config.connectionTimeout) + ); + }, this._config.connectionTimeout); // Connection listeners: these stay attached only until a connection is done/open. - this._ws = createWebSocket(this._url, this._config) - this._ws.on('error', this._onConnectionFailed) - this._ws.on('error', () => clearTimeout(connectionTimeoutID)) - this._ws.on('close', this._onConnectionFailed) - this._ws.on('close', () => clearTimeout(connectionTimeoutID)) - this._ws.once('open', async () => { + this._ws = createWebSocket(this._url, this._config); + + if (this._ws == null) { + throw new Error("Connect: created null websocket"); + } + + this._ws.on("error", this._onConnectionFailed); + this._ws.on("error", () => clearTimeout(connectionTimeoutID)); + this._ws.on("close", this._onConnectionFailed); + this._ws.on("close", () => clearTimeout(connectionTimeoutID)); + this._ws.once("open", async () => { + if (this._ws == null) { + throw new Error("onceOpen: ws is null"); + } + // Once the connection completes successfully, remove all old listeners - this._ws.removeAllListeners() - clearTimeout(connectionTimeoutID) + this._ws.removeAllListeners(); + clearTimeout(connectionTimeoutID); // Add new, long-term connected listeners for messages and errors - this._ws.on('message', (message: string) => this._onMessage(message)) - this._ws.on('error', (error) => - this.emit('error', 'websocket', error.message, error) - ) + this._ws.on("message", (message: string) => this._onMessage(message)); + this._ws.on("error", (error) => + this.emit("error", "websocket", error.message, error) + ); // Handle a closed connection: reconnect if it was unexpected - this._ws.once('close', (code, reason) => { - this._clearHeartbeatInterval() + this._ws.once("close", (code, reason) => { + if (this._ws == null) { + throw new Error("onceClose: ws is null"); + } + + this._clearHeartbeatInterval(); this._requestManager.rejectAll( new DisconnectedError(`websocket was closed, ${reason}`) - ) - this._ws.removeAllListeners() - this._ws = null - this.emit('disconnected', code) + ); + this._ws.removeAllListeners(); + this._ws = null; + this.emit("disconnected", code); // If this wasn't a manual disconnect, then lets reconnect ASAP. if (code !== INTENTIONAL_DISCONNECT_CODE) { - const retryTimeout = this._retryConnectionBackoff.duration() - this._trace('reconnect', `Retrying connection in ${retryTimeout}ms.`) - this.emit('reconnecting', this._retryConnectionBackoff.attempts) + const retryTimeout = this._retryConnectionBackoff.duration(); + this._trace("reconnect", `Retrying connection in ${retryTimeout}ms.`); + this.emit("reconnecting", this._retryConnectionBackoff.attempts); // Start the reconnect timeout, but set it to `this._reconnectTimeoutID` // so that we can cancel one in-progress on disconnect. this._reconnectTimeoutID = setTimeout(() => { this.reconnect().catch((error) => { - this.emit('error', 'reconnect', error.message, error) - }) - }, retryTimeout) + this.emit("error", "reconnect", error.message, error); + }); + }, retryTimeout); } - }) + }); // Finalize the connection and resolve all awaiting connect() requests try { - this._retryConnectionBackoff.reset() - this._startHeartbeatInterval() - this._connectionManager.resolveAllAwaiting() - this.emit('connected') + this._retryConnectionBackoff.reset(); + this._startHeartbeatInterval(); + this._connectionManager.resolveAllAwaiting(); + this.emit("connected"); } catch (error) { - this._connectionManager.rejectAllAwaiting(error) - await this.disconnect().catch(() => {}) // Ignore this error, propagate the root cause. + this._connectionManager.rejectAllAwaiting(error); + await this.disconnect().catch(() => {}); // Ignore this error, propagate the root cause. } - }) - return this._connectionManager.awaitConnection() + }); + return this._connectionManager.awaitConnection(); } /** @@ -445,20 +483,30 @@ export class Connection extends EventEmitter { * If no open websocket connection exists, resolve with no code (`undefined`). */ disconnect(): Promise { - clearTimeout(this._reconnectTimeoutID) - this._reconnectTimeoutID = null - if (this._state === WebSocket.CLOSED || !this._ws) { - return Promise.resolve(undefined) + if (this._reconnectTimeoutID !== null) { + clearTimeout(this._reconnectTimeoutID); + this._reconnectTimeoutID = null; } + if (this._state === WebSocket.CLOSED) { + return Promise.resolve(undefined); + } + if (this._ws === null) { + return Promise.resolve(undefined); + } + return new Promise((resolve) => { - this._ws.once('close', (code) => resolve(code)) + if (this._ws === null) { + return Promise.resolve(undefined); + } + + this._ws.once("close", (code) => resolve(code)); // Connection already has a disconnect handler for the disconnect logic. // Just close the websocket manually (with our "intentional" code) to // trigger that. - if (this._state !== WebSocket.CLOSING) { - this._ws.close(INTENTIONAL_DISCONNECT_CODE) + if (this._ws != null && this._state !== WebSocket.CLOSING) { + this._ws.close(INTENTIONAL_DISCONNECT_CODE); } - }) + }); } /** @@ -468,33 +516,36 @@ export class Connection extends EventEmitter { // NOTE: We currently have a "reconnecting" event, but that only triggers // through an unexpected connection retry logic. // See: https://github.com/ripple/ripple-lib/pull/1101#issuecomment-565360423 - this.emit('reconnect') - await this.disconnect() - await this.connect() + this.emit("reconnect"); + await this.disconnect(); + await this.connect(); } - async request(request: T, timeout?: number): Promise { - if (!this._shouldBeConnected) { - throw new NotConnectedError() + async request( + request: T, + timeout?: number + ): Promise { + if (!this._shouldBeConnected || this._ws == null) { + throw new NotConnectedError(); } const [id, message, responsePromise] = this._requestManager.createRequest( request, timeout || this._config.timeout - ) - this._trace('send', message) + ); + this._trace("send", message); websocketSendAsync(this._ws, message).catch((error) => { - this._requestManager.reject(id, error) - }) + this._requestManager.reject(id, error); + }); - return responsePromise + return responsePromise; } /** - * Get the Websocket connection URL + * Get the Websocket connection URL. * - * @returns The Websocket connection URL + * @returns The Websocket connection URL. */ getUrl(): string { - return this._url + return this._url ?? ""; } } diff --git a/src/client/index.ts b/src/client/index.ts index ffdcc0e6..940f3cb0 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -1,32 +1,31 @@ -import {EventEmitter} from 'events' +import { EventEmitter } from "events"; + import { - constants, - errors, - txFlags, -} from '../common' -import { Connection, ConnectionUserOptions } from './connection' -import getTrustlines from '../ledger/trustlines' -import getBalances from '../ledger/balances' -import getPaths from '../ledger/pathfind' -import {getOrderbook, formatBidsAndAsks} from '../ledger/orderbook' -import preparePayment from '../transaction/payment' -import prepareTrustline from '../transaction/trustline' -import prepareOrder from '../transaction/order' -import prepareOrderCancellation from '../transaction/ordercancellation' -import prepareEscrowCreation from '../transaction/escrow-creation' -import prepareEscrowExecution from '../transaction/escrow-execution' -import prepareEscrowCancellation from '../transaction/escrow-cancellation' -import preparePaymentChannelCreate from '../transaction/payment-channel-create' -import preparePaymentChannelFund from '../transaction/payment-channel-fund' -import preparePaymentChannelClaim from '../transaction/payment-channel-claim' -import prepareCheckCreate from '../transaction/check-create' -import prepareCheckCancel from '../transaction/check-cancel' -import prepareCheckCash from '../transaction/check-cash' -import prepareSettings from '../transaction/settings' -import prepareTicketCreate from '../transaction/ticket' -import {sign} from '../transaction/sign' -import combine from '../transaction/combine' -import {deriveAddress, deriveXAddress} from '../utils/derive' + classicAddressToXAddress, + xAddressToClassicAddress, + isValidXAddress, + isValidClassicAddress, + encodeSeed, + decodeSeed, + encodeAccountID, + decodeAccountID, + encodeNodePublic, + decodeNodePublic, + encodeAccountPublic, + decodeAccountPublic, + encodeXAddress, + decodeXAddress, +} from "ripple-address-codec"; + +import { constants, errors, txFlags, ensureClassicAddress } from "../common"; +import { ValidationError } from "../common/errors"; +import { getFee } from "../common/fee"; +import * as schemaValidator from "../common/schema-validator"; +import getBalances from "../ledger/balances"; +import { getOrderbook, formatBidsAndAsks } from "../ledger/orderbook"; +import getPaths from "../ledger/pathfind"; +import getTrustlines from "../ledger/trustlines"; +import { clamp } from "../ledger/utils"; import { Request, Response, @@ -94,162 +93,172 @@ import { PingRequest, PingResponse, RandomRequest, - RandomResponse -} from '../models/methods' + RandomResponse, +} from "../models/methods"; +import prepareCheckCancel from "../transaction/check-cancel"; +import prepareCheckCash from "../transaction/check-cash"; +import prepareCheckCreate from "../transaction/check-create"; +import combine from "../transaction/combine"; +import prepareEscrowCancellation from "../transaction/escrow-cancellation"; +import prepareEscrowCreation from "../transaction/escrow-creation"; +import prepareEscrowExecution from "../transaction/escrow-execution"; +import prepareOrder from "../transaction/order"; +import prepareOrderCancellation from "../transaction/ordercancellation"; +import preparePayment from "../transaction/payment"; +import preparePaymentChannelClaim from "../transaction/payment-channel-claim"; +import preparePaymentChannelCreate from "../transaction/payment-channel-create"; +import preparePaymentChannelFund from "../transaction/payment-channel-fund"; +import prepareSettings from "../transaction/settings"; +import { sign } from "../transaction/sign"; +import prepareTicketCreate from "../transaction/ticket"; +import prepareTrustline from "../transaction/trustline"; +import { TransactionJSON, Instructions, Prepare } from "../transaction/types"; +import * as transactionUtils from "../transaction/utils"; +import { deriveAddress, deriveXAddress } from "../utils/derive"; +import generateFaucetWallet from "../wallet/wallet-generation"; -import * as transactionUtils from '../transaction/utils' -import * as schemaValidator from '../common/schema-validator' -import {getFee} from '../common/fee' -import {ensureClassicAddress} from '../common' -import {clamp} from '../ledger/utils' -import {TransactionJSON, Instructions, Prepare} from '../transaction/types' -import { - classicAddressToXAddress, - xAddressToClassicAddress, - isValidXAddress, - isValidClassicAddress, - encodeSeed, - decodeSeed, - encodeAccountID, - decodeAccountID, - encodeNodePublic, - decodeNodePublic, - encodeAccountPublic, - decodeAccountPublic, - encodeXAddress, - decodeXAddress -} from 'ripple-address-codec' -import generateFaucetWallet from '../wallet/wallet-generation' -import { ValidationError } from '../common/errors' +import { Connection, ConnectionUserOptions } from "./connection"; export interface ClientOptions extends ConnectionUserOptions { - feeCushion?: number - maxFeeXRP?: string - proxy?: string - timeout?: number + feeCushion?: number; + maxFeeXRP?: string; + proxy?: string; + timeout?: number; } /** * Get the response key / property name that contains the listed data for a * command. This varies from command to command, but we need to know it to * properly count across many requests. + * + * @param command */ function getCollectKeyFromCommand(command: string): string | null { switch (command) { - case 'account_channels': - return 'channels' - case 'account_lines': - return 'lines' - case 'account_objects': - return 'account_objects' - case 'account_tx': - return 'transactions' - case 'account_offers': - case 'book_offers': - return 'offers' - case 'ledger_data': - return 'state' + case "account_channels": + return "channels"; + case "account_lines": + return "lines"; + case "account_objects": + return "account_objects"; + case "account_tx": + return "transactions"; + case "account_offers": + case "book_offers": + return "offers"; + case "ledger_data": + return "state"; default: - return null + return null; } } -type MarkerRequest = AccountChannelsRequest - | AccountLinesRequest - | AccountObjectsRequest - | AccountOffersRequest - | AccountTxRequest - | LedgerDataRequest +type MarkerRequest = + | AccountChannelsRequest + | AccountLinesRequest + | AccountObjectsRequest + | AccountOffersRequest + | AccountTxRequest + | LedgerDataRequest; -type MarkerResponse = AccountChannelsResponse - | AccountLinesResponse - | AccountObjectsResponse - | AccountOffersResponse - | AccountTxResponse - | LedgerDataResponse +type MarkerResponse = + | AccountChannelsResponse + | AccountLinesResponse + | AccountObjectsResponse + | AccountOffersResponse + | AccountTxResponse + | LedgerDataResponse; class Client extends EventEmitter { // Factor to multiply estimated fee by to provide a cushion in case the // required fee rises during submission of a transaction. Defaults to 1.2. - _feeCushion: number + _feeCushion: number; // Maximum fee to use with transactions, in XRP. Must be a string-encoded // number. Defaults to '2'. - _maxFeeXRP: string + _maxFeeXRP: string; // New in > 0.21.0 // non-validated ledger versions are allowed, and passed to rippled as-is. - connection: Connection + connection: Connection; constructor(server: string, options: ClientOptions = {}) { - super() - if (typeof server !== 'string' || !server.match("^(wss?|wss?\\+unix)://")) { - throw new ValidationError("server URI must start with `wss://`, `ws://`, `wss+unix://`, or `ws+unix://`.") + super(); + if (typeof server !== "string" || !server.match("^(wss?|wss?\\+unix)://")) { + throw new ValidationError( + "server URI must start with `wss://`, `ws://`, `wss+unix://`, or `ws+unix://`." + ); } - this._feeCushion = options.feeCushion || 1.2 - this._maxFeeXRP = options.maxFeeXRP || '2' + this._feeCushion = options.feeCushion || 1.2; + this._maxFeeXRP = options.maxFeeXRP || "2"; - this.connection = new Connection(server, options) + this.connection = new Connection(server, options); - this.connection.on('error', (errorCode, errorMessage, data) => { - this.emit('error', errorCode, errorMessage, data) - }) + this.connection.on("error", (errorCode, errorMessage, data) => { + this.emit("error", errorCode, errorMessage, data); + }); - this.connection.on('connected', () => { - this.emit('connected') - }) - - this.connection.on('disconnected', (code) => { - let finalCode = code + this.connection.on("connected", () => { + this.emit("connected"); + }); + + this.connection.on("disconnected", (code) => { + let finalCode = code; // 4000: Connection uses a 4000 code internally to indicate a manual disconnect/close // Since 4000 is a normal disconnect reason, we convert this to the standard exit code 1000 if (finalCode === 4000) { - finalCode = 1000 + finalCode = 1000; } - this.emit('disconnected', finalCode) - }) + this.emit("disconnected", finalCode); + }); } /** * Makes a request to the client with the given command and * additional request body parameters. */ - public request(r: AccountChannelsRequest): Promise - public request(r: AccountCurrenciesRequest): Promise - public request(r: AccountInfoRequest): Promise - public request(r: AccountLinesRequest): Promise - public request(r: AccountObjectsRequest): Promise - public request(r: AccountOffersRequest): Promise - public request(r: AccountTxRequest): Promise - public request(r: BookOffersRequest): Promise - public request(r: ChannelVerifyRequest): Promise - public request(r: DepositAuthorizedRequest): Promise - public request(r: FeeRequest): Promise - public request(r: GatewayBalancesRequest): Promise - public request(r: LedgerRequest): Promise - public request(r: LedgerClosedRequest): Promise - public request(r: LedgerCurrentRequest): Promise - public request(r: LedgerDataRequest): Promise - public request(r: LedgerEntryRequest): Promise - public request(r: ManifestRequest): Promise - public request(r: NoRippleCheckRequest): Promise - public request(r: PathFindRequest): Promise - public request(r: PingRequest): Promise - public request(r: RandomRequest): Promise - public request(r: RipplePathFindRequest): Promise - public request(r: ServerInfoRequest): Promise - public request(r: ServerStateRequest): Promise - public request(r: SubmitRequest): Promise - public request(r: SubmitMultisignedRequest): Promise - public request(r: TransactionEntryRequest): Promise - public request(r: TxRequest): Promise + public request(r: AccountChannelsRequest): Promise; + public request( + r: AccountCurrenciesRequest + ): Promise; + public request(r: AccountInfoRequest): Promise; + public request(r: AccountLinesRequest): Promise; + public request(r: AccountObjectsRequest): Promise; + public request(r: AccountOffersRequest): Promise; + public request(r: AccountTxRequest): Promise; + public request(r: BookOffersRequest): Promise; + public request(r: ChannelVerifyRequest): Promise; + public request( + r: DepositAuthorizedRequest + ): Promise; + public request(r: FeeRequest): Promise; + public request(r: GatewayBalancesRequest): Promise; + public request(r: LedgerRequest): Promise; + public request(r: LedgerClosedRequest): Promise; + public request(r: LedgerCurrentRequest): Promise; + public request(r: LedgerDataRequest): Promise; + public request(r: LedgerEntryRequest): Promise; + public request(r: ManifestRequest): Promise; + public request(r: NoRippleCheckRequest): Promise; + public request(r: PathFindRequest): Promise; + public request(r: PingRequest): Promise; + public request(r: RandomRequest): Promise; + public request(r: RipplePathFindRequest): Promise; + public request(r: ServerInfoRequest): Promise; + public request(r: ServerStateRequest): Promise; + public request(r: SubmitRequest): Promise; + public request( + r: SubmitMultisignedRequest + ): Promise; + public request(r: TransactionEntryRequest): Promise; + public request(r: TxRequest): Promise; public request(r: R): Promise { // TODO: should this be typed with `extends BaseRequest/BaseResponse`? return this.connection.request({ ...r, - // @ts-ignore + // @ts-expect-error account: r.account ? ensureClassicAddress(r.account) : undefined, - }) + }); } /** @@ -258,38 +267,64 @@ class Client extends EventEmitter { * When there are more results than contained in the response, the response * includes a `marker` field. * - * See https://ripple.com/build/rippled-apis/#markers-and-pagination + * See https://ripple.com/build/rippled-apis/#markers-and-pagination. + * + * @param response */ hasNextPage(response: MarkerResponse): boolean { - return !!response.result.marker + return Boolean(response.result.marker); } - async requestNextPage(req: AccountChannelsRequest, resp: AccountChannelsResponse): Promise - async requestNextPage(req: AccountLinesRequest, resp: AccountLinesResponse): Promise - async requestNextPage(req: AccountObjectsRequest, resp: AccountObjectsResponse): Promise - async requestNextPage(req: AccountOffersRequest, resp: AccountOffersResponse): Promise - async requestNextPage(req: AccountTxRequest, resp: AccountTxResponse): Promise - async requestNextPage(req: LedgerDataRequest, resp: LedgerDataResponse): Promise - async requestNextPage(req: T, resp: U): Promise { + async requestNextPage( + req: AccountChannelsRequest, + resp: AccountChannelsResponse + ): Promise; + async requestNextPage( + req: AccountLinesRequest, + resp: AccountLinesResponse + ): Promise; + async requestNextPage( + req: AccountObjectsRequest, + resp: AccountObjectsResponse + ): Promise; + async requestNextPage( + req: AccountOffersRequest, + resp: AccountOffersResponse + ): Promise; + async requestNextPage( + req: AccountTxRequest, + resp: AccountTxResponse + ): Promise; + async requestNextPage( + req: LedgerDataRequest, + resp: LedgerDataResponse + ): Promise; + async requestNextPage( + req: T, + resp: U + ): Promise { if (!resp.result.marker) { return Promise.reject( - new errors.NotFoundError('response does not have a next page') - ) + new errors.NotFoundError("response does not have a next page") + ); } - const nextPageRequest = {...req, marker: resp.result.marker} - return this.connection.request(nextPageRequest) + const nextPageRequest = { ...req, marker: resp.result.marker }; + return this.connection.request(nextPageRequest); } /** * Prepare a transaction. * * You can later submit the transaction with a `submit` request. + * + * @param txJSON + * @param instructions */ async prepareTransaction( txJSON: TransactionJSON, instructions: Instructions = {} ): Promise { - return transactionUtils.prepareTransaction(txJSON, this, instructions) + return transactionUtils.prepareTransaction(txJSON, this, instructions); } /** @@ -297,15 +332,15 @@ class Client extends EventEmitter { * * This can be used to generate `MemoData`, `MemoType`, and `MemoFormat`. * - * @param string string to convert to hex + * @param string - String to convert to hex. */ convertStringToHex(string: string): string { - return transactionUtils.convertStringToHex(string) + return transactionUtils.convertStringToHex(string); } /** * Makes multiple paged requests to the client to return a given number of - * resources. requestAll() will make multiple requests until the `limit` + * resources. Multiple paged requests will be made until the `limit` * number of resources is reached (if no `limit` is provided, a single request * will be made). * @@ -316,129 +351,136 @@ class Client extends EventEmitter { * general use. Instead, use rippled's built-in pagination and make multiple * requests as needed. */ - async requestAll(req: AccountChannelsRequest): Promise - async requestAll(req: AccountLinesRequest): Promise - async requestAll(req: AccountObjectsRequest): Promise - async requestAll(req: AccountOffersRequest): Promise - async requestAll(req: AccountTxRequest): Promise - async requestAll(req: BookOffersRequest): Promise - async requestAll(req: LedgerDataRequest): Promise - async requestAll(request: T, options: {collect?: string} = {}): Promise { + async requestAll( + req: AccountChannelsRequest + ): Promise; + async requestAll(req: AccountLinesRequest): Promise; + async requestAll( + req: AccountObjectsRequest + ): Promise; + async requestAll(req: AccountOffersRequest): Promise; + async requestAll(req: AccountTxRequest): Promise; + async requestAll(req: BookOffersRequest): Promise; + async requestAll(req: LedgerDataRequest): Promise; + async requestAll( + request: T, + options: { collect?: string } = {} + ): Promise { // The data under collection is keyed based on the command. Fail if command // not recognized and collection key not provided. - const collectKey = options.collect || getCollectKeyFromCommand(request.command) + const collectKey = + options.collect || getCollectKeyFromCommand(request.command); if (!collectKey) { - throw new errors.ValidationError(`no collect key for command ${request.command}`) + throw new errors.ValidationError( + `no collect key for command ${request.command}` + ); } // If limit is not provided, fetches all data over multiple requests. // NOTE: This may return much more than needed. Set limit when possible. - const countTo: number = request.limit != null ? request.limit : Infinity - let count: number = 0 - let marker: string = request.marker - let lastBatchLength: number - const results = [] + const countTo: number = request.limit != null ? request.limit : Infinity; + let count = 0; + let marker: string = request.marker; + let lastBatchLength: number; + const results: any[] = []; do { - const countRemaining = clamp(countTo - count, 10, 400) + const countRemaining = clamp(countTo - count, 10, 400); const repeatProps = { ...request, limit: countRemaining, - marker - } - const singleResponse = await this.connection.request(repeatProps) - const singleResult = singleResponse.result - const collectedData = singleResult[collectKey] - marker = singleResult['marker'] - results.push(singleResponse) + marker, + }; + const singleResponse = await this.connection.request(repeatProps); + const singleResult = singleResponse.result; + const collectedData = singleResult[collectKey]; + marker = singleResult.marker; + results.push(singleResponse); // Make sure we handle when no data (not even an empty array) is returned. - const isExpectedFormat = Array.isArray(collectedData) + const isExpectedFormat = Array.isArray(collectedData); if (isExpectedFormat) { - count += collectedData.length - lastBatchLength = collectedData.length + count += collectedData.length; + lastBatchLength = collectedData.length; } else { - lastBatchLength = 0 + lastBatchLength = 0; } - } while (!!marker && count < countTo && lastBatchLength !== 0) - return results + } while (Boolean(marker) && count < countTo && lastBatchLength !== 0); + return results; } isConnected(): boolean { - return this.connection.isConnected() + return this.connection.isConnected(); } - + async connect(): Promise { - return this.connection.connect() + return this.connection.connect(); } - + async disconnect(): Promise { // backwards compatibility: connection.disconnect() can return a number, but // this method returns nothing. SO we await but don't return any result. - await this.connection.disconnect() + await this.connection.disconnect(); } - getFee = getFee + getFee = getFee; - getTrustlines = getTrustlines - getBalances = getBalances - getPaths = getPaths - getOrderbook = getOrderbook + getTrustlines = getTrustlines; + getBalances = getBalances; + getPaths = getPaths; + getOrderbook = getOrderbook; - preparePayment = preparePayment - prepareTrustline = prepareTrustline - prepareOrder = prepareOrder - prepareOrderCancellation = prepareOrderCancellation - prepareEscrowCreation = prepareEscrowCreation - prepareEscrowExecution = prepareEscrowExecution - prepareEscrowCancellation = prepareEscrowCancellation - preparePaymentChannelCreate = preparePaymentChannelCreate - preparePaymentChannelFund = preparePaymentChannelFund - preparePaymentChannelClaim = preparePaymentChannelClaim - prepareCheckCreate = prepareCheckCreate - prepareCheckCash = prepareCheckCash - prepareCheckCancel = prepareCheckCancel - prepareTicketCreate = prepareTicketCreate - prepareSettings = prepareSettings - sign = sign - combine = combine + preparePayment = preparePayment; + prepareTrustline = prepareTrustline; + prepareOrder = prepareOrder; + prepareOrderCancellation = prepareOrderCancellation; + prepareEscrowCreation = prepareEscrowCreation; + prepareEscrowExecution = prepareEscrowExecution; + prepareEscrowCancellation = prepareEscrowCancellation; + preparePaymentChannelCreate = preparePaymentChannelCreate; + preparePaymentChannelFund = preparePaymentChannelFund; + preparePaymentChannelClaim = preparePaymentChannelClaim; + prepareCheckCreate = prepareCheckCreate; + prepareCheckCash = prepareCheckCash; + prepareCheckCancel = prepareCheckCancel; + prepareTicketCreate = prepareTicketCreate; + prepareSettings = prepareSettings; + sign = sign; + combine = combine; - generateFaucetWallet = generateFaucetWallet + generateFaucetWallet = generateFaucetWallet; - errors = errors + errors = errors; - static deriveXAddress = deriveXAddress + static deriveXAddress = deriveXAddress; // Client.deriveClassicAddress (static) is a new name for client.deriveAddress - static deriveClassicAddress = deriveAddress + static deriveClassicAddress = deriveAddress; - static formatBidsAndAsks = formatBidsAndAsks + static formatBidsAndAsks = formatBidsAndAsks; /** - * Static methods to expose ripple-address-codec methods + * Static methods to expose ripple-address-codec methods. */ - static classicAddressToXAddress = classicAddressToXAddress - static xAddressToClassicAddress = xAddressToClassicAddress - static isValidXAddress = isValidXAddress - static isValidClassicAddress = isValidClassicAddress - static encodeSeed = encodeSeed - static decodeSeed = decodeSeed - static encodeAccountID = encodeAccountID - static decodeAccountID = decodeAccountID - static encodeNodePublic = encodeNodePublic - static decodeNodePublic = decodeNodePublic - static encodeAccountPublic = encodeAccountPublic - static decodeAccountPublic = decodeAccountPublic - static encodeXAddress = encodeXAddress - static decodeXAddress = decodeXAddress + static classicAddressToXAddress = classicAddressToXAddress; + static xAddressToClassicAddress = xAddressToClassicAddress; + static isValidXAddress = isValidXAddress; + static isValidClassicAddress = isValidClassicAddress; + static encodeSeed = encodeSeed; + static decodeSeed = decodeSeed; + static encodeAccountID = encodeAccountID; + static decodeAccountID = decodeAccountID; + static encodeNodePublic = encodeNodePublic; + static decodeNodePublic = decodeNodePublic; + static encodeAccountPublic = encodeAccountPublic; + static decodeAccountPublic = decodeAccountPublic; + static encodeXAddress = encodeXAddress; + static decodeXAddress = decodeXAddress; - txFlags = txFlags - static txFlags = txFlags - accountSetFlags = constants.AccountSetFlags - static accountSetFlags = constants.AccountSetFlags + txFlags = txFlags; + static txFlags = txFlags; + accountSetFlags = constants.AccountSetFlags; + static accountSetFlags = constants.AccountSetFlags; - isValidAddress = schemaValidator.isValidAddress - isValidSecret = schemaValidator.isValidSecret + isValidAddress = schemaValidator.isValidAddress; + isValidSecret = schemaValidator.isValidSecret; } -export { - Client, - Connection -} +export { Client, Connection }; diff --git a/src/client/rangeSet.ts b/src/client/rangeSet.ts index 4a45c466..16b55426 100644 --- a/src/client/rangeSet.ts +++ b/src/client/rangeSet.ts @@ -1,63 +1,64 @@ -import * as _ from 'lodash' -import * as assert from 'assert' +import * as assert from "assert"; -type Interval = [number, number] +import * as _ from "lodash"; + +type Interval = [number, number]; function mergeIntervals(intervals: Interval[]): Interval[] { - const stack: Interval[] = [[-Infinity, -Infinity]] + const stack: Interval[] = [[-Infinity, -Infinity]]; _.sortBy(intervals, (x) => x[0]).forEach((interval) => { - const lastInterval: Interval = stack.pop()! + const lastInterval: Interval = stack.pop()!; if (interval[0] <= lastInterval[1] + 1) { - stack.push([lastInterval[0], Math.max(interval[1], lastInterval[1])]) + stack.push([lastInterval[0], Math.max(interval[1], lastInterval[1])]); } else { - stack.push(lastInterval) - stack.push(interval) + stack.push(lastInterval); + stack.push(interval); } - }) - return stack.slice(1) + }); + return stack.slice(1); } class RangeSet { - ranges: Array<[number, number]> + ranges: Array<[number, number]> = []; constructor() { - this.reset() + this.reset(); } reset() { - this.ranges = [] + this.ranges = []; } serialize() { return this.ranges - .map((range) => range[0].toString() + '-' + range[1].toString()) - .join(',') + .map((range) => `${range[0].toString()}-${range[1].toString()}`) + .join(","); } addRange(start: number, end: number) { - assert.ok(start <= end, `invalid range ${start} <= ${end}`) - this.ranges = mergeIntervals(this.ranges.concat([[start, end]])) + assert.ok(start <= end, `invalid range ${start} <= ${end}`); + this.ranges = mergeIntervals(this.ranges.concat([[start, end]])); } addValue(value: number) { - this.addRange(value, value) + this.addRange(value, value); } parseAndAddRanges(rangesString: string) { - const rangeStrings = rangesString.split(',') + const rangeStrings = rangesString.split(","); rangeStrings.forEach((rangeString) => { - const range = rangeString.split('-').map(Number) - this.addRange(range[0], range.length === 1 ? range[0] : range[1]) - }) + const range = rangeString.split("-").map(Number); + this.addRange(range[0], range.length === 1 ? range[0] : range[1]); + }); } containsRange(start: number, end: number) { - return this.ranges.some((range) => range[0] <= start && range[1] >= end) + return this.ranges.some((range) => range[0] <= start && range[1] >= end); } containsValue(value: number) { - return this.containsRange(value, value) + return this.containsRange(value, value); } } -export default RangeSet +export default RangeSet; diff --git a/src/client/wsWrapper.ts b/src/client/wsWrapper.ts index 86a20b9d..684ae151 100644 --- a/src/client/wsWrapper.ts +++ b/src/client/wsWrapper.ts @@ -1,15 +1,15 @@ -import {EventEmitter} from 'events' +import { EventEmitter } from "events"; // Define the global WebSocket class found on the native browser declare class WebSocket { - onclose?: Function - onopen?: Function - onerror?: Function - onmessage?: Function - readyState: number - constructor(url: string) - close() - send(message: string) + onclose?: Function; + onopen?: Function; + onerror?: Function; + onmessage?: Function; + readyState: number; + constructor(url: string); + close(); + send(message: string); } /** @@ -17,46 +17,46 @@ declare class WebSocket { * same, as `ws` package provides. */ export default class WSWrapper extends EventEmitter { - private _ws: WebSocket - static CONNECTING = 0 - static OPEN = 1 - static CLOSING = 2 - static CLOSED = 3 + private readonly _ws: WebSocket; + static CONNECTING = 0; + static OPEN = 1; + static CLOSING = 2; + static CLOSED = 3; constructor(url, _protocols: any, _websocketOptions: any) { - super() - this.setMaxListeners(Infinity) + super(); + this.setMaxListeners(Infinity); - this._ws = new WebSocket(url) + this._ws = new WebSocket(url); this._ws.onclose = () => { - this.emit('close') - } + this.emit("close"); + }; this._ws.onopen = () => { - this.emit('open') - } + this.emit("open"); + }; this._ws.onerror = (error) => { - this.emit('error', error) - } + this.emit("error", error); + }; this._ws.onmessage = (message) => { - this.emit('message', message.data) - } + this.emit("message", message.data); + }; } close() { if (this.readyState === 1) { - this._ws.close() + this._ws.close(); } } send(message) { - this._ws.send(message) + this._ws.send(message); } get readyState() { - return this._ws.readyState + return this._ws.readyState; } } diff --git a/src/common/constants.ts b/src/common/constants.ts index 555fb8f1..0b04b0b0 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -1,4 +1,4 @@ -import {txFlagIndices} from './txflags' +import { txFlagIndices } from "./txflags"; // Ordering from https://developers.ripple.com/accountroot.html const accountRootFlags = { @@ -43,8 +43,8 @@ const accountRootFlags = { // lsfRequireDestTag: // Require a DestinationTag for incoming payments. - RequireDestTag: 0x00020000 -} + RequireDestTag: 0x00020000, +}; const AccountFlags = { passwordSpent: accountRootFlags.PasswordSpent, @@ -55,19 +55,19 @@ const AccountFlags = { disableMasterKey: accountRootFlags.DisableMaster, noFreeze: accountRootFlags.NoFreeze, globalFreeze: accountRootFlags.GlobalFreeze, - defaultRipple: accountRootFlags.DefaultRipple -} + defaultRipple: accountRootFlags.DefaultRipple, +}; export interface Settings { - passwordSpent?: boolean - requireDestinationTag?: boolean - requireAuthorization?: boolean - depositAuth?: boolean - disallowIncomingXRP?: boolean - disableMasterKey?: boolean - noFreeze?: boolean - globalFreeze?: boolean - defaultRipple?: boolean + passwordSpent?: boolean; + requireDestinationTag?: boolean; + requireAuthorization?: boolean; + depositAuth?: boolean; + disallowIncomingXRP?: boolean; + disableMasterKey?: boolean; + noFreeze?: boolean; + globalFreeze?: boolean; + defaultRipple?: boolean; } const AccountSetFlags = { @@ -79,21 +79,21 @@ const AccountSetFlags = { enableTransactionIDTracking: txFlagIndices.AccountSet.asfAccountTxnID, noFreeze: txFlagIndices.AccountSet.asfNoFreeze, globalFreeze: txFlagIndices.AccountSet.asfGlobalFreeze, - defaultRipple: txFlagIndices.AccountSet.asfDefaultRipple -} + defaultRipple: txFlagIndices.AccountSet.asfDefaultRipple, +}; const AccountFields = { EmailHash: { - name: 'emailHash', - encoding: 'hex', + name: "emailHash", + encoding: "hex", length: 32, - defaults: '00000000000000000000000000000000' + defaults: "00000000000000000000000000000000", }, - WalletLocator: {name: 'walletLocator'}, - MessageKey: {name: 'messageKey'}, - Domain: {name: 'domain', encoding: 'hex'}, - TransferRate: {name: 'transferRate', defaults: 0, shift: 9}, - TickSize: {name: 'tickSize', defaults: 0} -} + WalletLocator: { name: "walletLocator" }, + MessageKey: { name: "messageKey" }, + Domain: { name: "domain", encoding: "hex" }, + TransferRate: { name: "transferRate", defaults: 0, shift: 9 }, + TickSize: { name: "tickSize", defaults: 0 }, +}; -export {AccountFields, AccountSetFlags, AccountFlags} +export { AccountFields, AccountSetFlags, AccountFlags }; diff --git a/src/common/ecdsa.ts b/src/common/ecdsa.ts index affb7587..426a70a8 100644 --- a/src/common/ecdsa.ts +++ b/src/common/ecdsa.ts @@ -1,6 +1,6 @@ enum ECDSA { - ed25519 = 'ed25519', - secp256k1 = 'ecdsa-secp256k1', + ed25519 = "ed25519", + secp256k1 = "ecdsa-secp256k1", } -export default ECDSA +export default ECDSA; diff --git a/src/common/errors.ts b/src/common/errors.ts index 6633bd75..f8695abb 100644 --- a/src/common/errors.ts +++ b/src/common/errors.ts @@ -1,35 +1,35 @@ -import {inspect} from 'util' +import { inspect } from "util"; class RippleError extends Error { - name: string - message: string - data?: any + name: string; + message: string; + data?: any; - constructor(message = '', data?: any) { - super(message) + constructor(message = "", data?: any) { + super(message); - this.name = this.constructor.name - this.message = message - this.data = data + this.name = this.constructor.name; + this.message = message; + this.data = data; if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor) + Error.captureStackTrace(this, this.constructor); } } toString() { - let result = '[' + this.name + '(' + this.message + let result = `[${this.name}(${this.message}`; if (this.data) { - result += ', ' + inspect(this.data) + result += `, ${inspect(this.data)}`; } - result += ')]' - return result + result += ")]"; + return result; } - /* console.log in node uses util.inspect on object, and util.inspect allows - us to customize its output: - https://nodejs.org/api/util.html#util_custom_inspect_function_on_objects */ + // console.log in node uses util.inspect on object, and util.inspect allows + // us to customize its output: + // https://nodejs.org/api/util.html#util_custom_inspect_function_on_objects inspect() { - return this.toString() + return this.toString(); } } @@ -56,14 +56,14 @@ class ValidationError extends RippleError {} class XRPLFaucetError extends RippleError {} class NotFoundError extends RippleError { - constructor(message = 'Not found') { - super(message) + constructor(message = "Not found") { + super(message); } } class MissingLedgerHistoryError extends RippleError { constructor(message?: string) { - super(message || 'Server is missing ledger history in the specified range') + super(message || "Server is missing ledger history in the specified range"); } } @@ -72,8 +72,8 @@ class PendingLedgerVersionError extends RippleError { super( message || "maxLedgerVersion is greater than server's most recent" + - ' validated ledger' - ) + " validated ledger" + ); } } @@ -92,5 +92,5 @@ export { PendingLedgerVersionError, MissingLedgerHistoryError, LedgerVersionError, - XRPLFaucetError -} + XRPLFaucetError, +}; diff --git a/src/common/fee.ts b/src/common/fee.ts index bc11c2a9..847e8fe7 100644 --- a/src/common/fee.ts +++ b/src/common/fee.ts @@ -1,29 +1,38 @@ -import _ from 'lodash' -import BigNumber from 'bignumber.js' -import {Client} from '..' +import BigNumber from "bignumber.js"; +import _ from "lodash"; + +import { Client } from ".."; // This is a public API that can be called directly. // This is not used by the `prepare*` methods. See `src/transaction/utils.ts` async function getFee(this: Client, cushion?: number): Promise { if (cushion == null) { - cushion = this._feeCushion + cushion = this._feeCushion; } if (cushion == null) { - cushion = 1.2 + cushion = 1.2; } - const serverInfo = (await this.request({command: "server_info"})).result.info - const baseFeeXrp = new BigNumber(serverInfo.validated_ledger.base_fee_xrp) + const serverInfo = (await this.request({ command: "server_info" })).result + .info; + + const baseFee = serverInfo.validated_ledger?.base_fee_xrp; + + if (baseFee == null) { + throw new Error("getFee: Could not get base_fee_xrp from server_info"); + } + + const baseFeeXrp = new BigNumber(baseFee); if (serverInfo.load_factor == null) { // https://github.com/ripple/rippled/issues/3812#issuecomment-816871100 - serverInfo.load_factor = 1 + serverInfo.load_factor = 1; } - let fee = baseFeeXrp.times(serverInfo.load_factor).times(cushion) + let fee = baseFeeXrp.times(serverInfo.load_factor).times(cushion); // Cap fee to `this._maxFeeXRP` - fee = BigNumber.min(fee, this._maxFeeXRP) + fee = BigNumber.min(fee, this._maxFeeXRP); // Round fee to 6 decimal places - return new BigNumber(fee.toFixed(6)).toString(10) + return new BigNumber(fee.toFixed(6)).toString(10); } -export {getFee} +export { getFee }; diff --git a/src/common/index.ts b/src/common/index.ts index 439b585a..fac617e2 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -1,27 +1,30 @@ -import * as constants from './constants' -import * as errors from './errors' -import * as validate from './validate' -import {xAddressToClassicAddress, isValidXAddress} from 'ripple-address-codec' +import { + xAddressToClassicAddress, + isValidXAddress, +} from "ripple-address-codec"; + +import * as constants from "./constants"; +import * as errors from "./errors"; +import * as validate from "./validate"; export function ensureClassicAddress(account: string): string { if (isValidXAddress(account)) { - const {classicAddress, tag} = xAddressToClassicAddress(account) + const { classicAddress, tag } = xAddressToClassicAddress(account); // Except for special cases, X-addresses used for requests // must not have an embedded tag. In other words, // `tag` should be `false`. if (tag !== false) { throw new Error( - 'This command does not support the use of a tag. Use an address without a tag.' - ) + "This command does not support the use of a tag. Use an address without a tag." + ); } // For rippled requests that use an account, always use a classic address. - return classicAddress - } else { - return account + return classicAddress; } + return account; } -export {constants, errors, validate} -export {txFlags} from './txflags' +export { constants, errors, validate }; +export { txFlags } from "./txflags"; diff --git a/src/common/schema-validator.ts b/src/common/schema-validator.ts index 23ab4f84..6609e7da 100644 --- a/src/common/schema-validator.ts +++ b/src/common/schema-validator.ts @@ -1,134 +1,140 @@ -import _ from 'lodash' -import * as assert from 'assert' -const {Validator} = require('jsonschema') -import {ValidationError} from './errors' -import {isValidClassicAddress, isValidXAddress} from 'ripple-address-codec' -import {isValidSecret} from '../utils' +import * as assert from "assert"; + +import _ from "lodash"; +import { isValidClassicAddress, isValidXAddress } from "ripple-address-codec"; + +import { isValidSecret } from "../utils"; + +import { ValidationError } from "./errors"; + +const { Validator } = require("jsonschema"); function loadSchemas() { // listed explicitly for webpack (instead of scanning schemas directory) const schemas = [ - require('./schemas/objects/tx-json.json'), - require('./schemas/objects/transaction-type.json'), - require('./schemas/objects/hash128.json'), - require('./schemas/objects/hash256.json'), - require('./schemas/objects/sequence.json'), - require('./schemas/objects/ticket-sequence.json'), - require('./schemas/objects/signature.json'), - require('./schemas/objects/issue.json'), - require('./schemas/objects/ledger-version.json'), - require('./schemas/objects/max-adjustment.json'), - require('./schemas/objects/memo.json'), - require('./schemas/objects/memos.json'), - require('./schemas/objects/public-key.json'), - require('./schemas/objects/private-key.json'), - require('./schemas/objects/uint32.json'), - require('./schemas/objects/value.json'), - require('./schemas/objects/source-adjustment.json'), - require('./schemas/objects/destination-adjustment.json'), - require('./schemas/objects/tag.json'), - require('./schemas/objects/lax-amount.json'), - require('./schemas/objects/lax-lax-amount.json'), - require('./schemas/objects/min-adjustment.json'), - require('./schemas/objects/source-exact-adjustment.json'), - require('./schemas/objects/destination-exact-adjustment.json'), - require('./schemas/objects/destination-address-tag.json'), - require('./schemas/objects/transaction-hash.json'), - require('./schemas/objects/address.json'), - require('./schemas/objects/x-address.json'), - require('./schemas/objects/classic-address.json'), - require('./schemas/objects/adjustment.json'), - require('./schemas/objects/quality.json'), - require('./schemas/objects/amount.json'), - require('./schemas/objects/amountbase.json'), - require('./schemas/objects/balance.json'), - require('./schemas/objects/blob.json'), - require('./schemas/objects/currency.json'), - require('./schemas/objects/signed-value.json'), - require('./schemas/objects/orderbook.json'), - require('./schemas/objects/instructions.json'), - require('./schemas/objects/settings-plus-memos.json'), - require('./schemas/specifications/settings.json'), - require('./schemas/specifications/payment.json'), - require('./schemas/specifications/get-payment.json'), - require('./schemas/specifications/escrow-cancellation.json'), - require('./schemas/specifications/order-cancellation.json'), - require('./schemas/specifications/order.json'), - require('./schemas/specifications/escrow-execution.json'), - require('./schemas/specifications/escrow-creation.json'), - require('./schemas/specifications/payment-channel-create.json'), - require('./schemas/specifications/payment-channel-fund.json'), - require('./schemas/specifications/payment-channel-claim.json'), - require('./schemas/specifications/check-create.json'), - require('./schemas/specifications/check-cash.json'), - require('./schemas/specifications/check-cancel.json'), - require('./schemas/specifications/trustline.json'), - require('./schemas/specifications/deposit-preauth.json'), - require('./schemas/specifications/account-delete.json'), - require('./schemas/output/sign.json'), - require('./schemas/output/submit.json'), - require('./schemas/output/get-account-info.json'), - require('./schemas/output/get-account-objects.json'), - require('./schemas/output/get-balances.json'), - require('./schemas/output/get-balance-sheet.json'), - require('./schemas/output/get-ledger.json'), - require('./schemas/output/get-orderbook.json'), - require('./schemas/output/get-orders.json'), - require('./schemas/output/order-change.json'), - require('./schemas/output/get-payment-channel.json'), - require('./schemas/output/prepare.json'), - require('./schemas/output/ledger-event.json'), - require('./schemas/output/get-paths.json'), - require('./schemas/output/get-server-info.json'), - require('./schemas/output/get-settings.json'), - require('./schemas/output/orderbook-orders.json'), - require('./schemas/output/outcome.json'), - require('./schemas/output/get-transaction.json'), - require('./schemas/output/get-transactions.json'), - require('./schemas/output/get-trustlines.json'), - require('./schemas/output/sign-payment-channel-claim.json'), - require('./schemas/output/verify-payment-channel-claim.json'), - require('./schemas/input/get-balances.json'), - require('./schemas/input/get-balance-sheet.json'), - require('./schemas/input/get-ledger.json'), - require('./schemas/input/get-orders.json'), - require('./schemas/input/get-orderbook.json'), - require('./schemas/input/get-paths.json'), - require('./schemas/input/get-payment-channel.json'), - require('./schemas/input/api-options.json'), - require('./schemas/input/get-settings.json'), - require('./schemas/input/get-account-info.json'), - require('./schemas/input/get-account-objects.json'), - require('./schemas/input/get-transaction.json'), - require('./schemas/input/get-transactions.json'), - require('./schemas/input/get-trustlines.json'), - require('./schemas/input/prepare-payment.json'), - require('./schemas/input/prepare-order.json'), - require('./schemas/input/prepare-trustline.json'), - require('./schemas/input/prepare-order-cancellation.json'), - require('./schemas/input/prepare-settings.json'), - require('./schemas/input/prepare-escrow-creation.json'), - require('./schemas/input/prepare-escrow-cancellation.json'), - require('./schemas/input/prepare-escrow-execution.json'), - require('./schemas/input/prepare-payment-channel-create.json'), - require('./schemas/input/prepare-payment-channel-fund.json'), - require('./schemas/input/prepare-payment-channel-claim.json'), - require('./schemas/input/prepare-check-create.json'), - require('./schemas/input/prepare-check-cash.json'), - require('./schemas/input/prepare-check-cancel.json'), - require('./schemas/input/prepare-ticket-create.json'), - require('./schemas/input/compute-ledger-hash.json'), - require('./schemas/input/sign.json'), - require('./schemas/input/submit.json'), - require('./schemas/input/generate-address.json'), - require('./schemas/input/sign-payment-channel-claim.json'), - require('./schemas/input/verify-payment-channel-claim.json'), - require('./schemas/input/combine.json') - ] - const titles = schemas.map((schema) => schema.title) - const duplicates = Object.keys(_.pickBy(_.countBy(titles), (count) => count > 1)) - assert.ok(duplicates.length === 0, 'Duplicate schemas for: ' + duplicates) - const validator = new Validator() + require("./schemas/objects/tx-json.json"), + require("./schemas/objects/transaction-type.json"), + require("./schemas/objects/hash128.json"), + require("./schemas/objects/hash256.json"), + require("./schemas/objects/sequence.json"), + require("./schemas/objects/ticket-sequence.json"), + require("./schemas/objects/signature.json"), + require("./schemas/objects/issue.json"), + require("./schemas/objects/ledger-version.json"), + require("./schemas/objects/max-adjustment.json"), + require("./schemas/objects/memo.json"), + require("./schemas/objects/memos.json"), + require("./schemas/objects/public-key.json"), + require("./schemas/objects/private-key.json"), + require("./schemas/objects/uint32.json"), + require("./schemas/objects/value.json"), + require("./schemas/objects/source-adjustment.json"), + require("./schemas/objects/destination-adjustment.json"), + require("./schemas/objects/tag.json"), + require("./schemas/objects/lax-amount.json"), + require("./schemas/objects/lax-lax-amount.json"), + require("./schemas/objects/min-adjustment.json"), + require("./schemas/objects/source-exact-adjustment.json"), + require("./schemas/objects/destination-exact-adjustment.json"), + require("./schemas/objects/destination-address-tag.json"), + require("./schemas/objects/transaction-hash.json"), + require("./schemas/objects/address.json"), + require("./schemas/objects/x-address.json"), + require("./schemas/objects/classic-address.json"), + require("./schemas/objects/adjustment.json"), + require("./schemas/objects/quality.json"), + require("./schemas/objects/amount.json"), + require("./schemas/objects/amountbase.json"), + require("./schemas/objects/balance.json"), + require("./schemas/objects/blob.json"), + require("./schemas/objects/currency.json"), + require("./schemas/objects/signed-value.json"), + require("./schemas/objects/orderbook.json"), + require("./schemas/objects/instructions.json"), + require("./schemas/objects/settings-plus-memos.json"), + require("./schemas/specifications/settings.json"), + require("./schemas/specifications/payment.json"), + require("./schemas/specifications/get-payment.json"), + require("./schemas/specifications/escrow-cancellation.json"), + require("./schemas/specifications/order-cancellation.json"), + require("./schemas/specifications/order.json"), + require("./schemas/specifications/escrow-execution.json"), + require("./schemas/specifications/escrow-creation.json"), + require("./schemas/specifications/payment-channel-create.json"), + require("./schemas/specifications/payment-channel-fund.json"), + require("./schemas/specifications/payment-channel-claim.json"), + require("./schemas/specifications/check-create.json"), + require("./schemas/specifications/check-cash.json"), + require("./schemas/specifications/check-cancel.json"), + require("./schemas/specifications/trustline.json"), + require("./schemas/specifications/deposit-preauth.json"), + require("./schemas/specifications/account-delete.json"), + require("./schemas/output/sign.json"), + require("./schemas/output/submit.json"), + require("./schemas/output/get-account-info.json"), + require("./schemas/output/get-account-objects.json"), + require("./schemas/output/get-balances.json"), + require("./schemas/output/get-balance-sheet.json"), + require("./schemas/output/get-ledger.json"), + require("./schemas/output/get-orderbook.json"), + require("./schemas/output/get-orders.json"), + require("./schemas/output/order-change.json"), + require("./schemas/output/get-payment-channel.json"), + require("./schemas/output/prepare.json"), + require("./schemas/output/ledger-event.json"), + require("./schemas/output/get-paths.json"), + require("./schemas/output/get-server-info.json"), + require("./schemas/output/get-settings.json"), + require("./schemas/output/orderbook-orders.json"), + require("./schemas/output/outcome.json"), + require("./schemas/output/get-transaction.json"), + require("./schemas/output/get-transactions.json"), + require("./schemas/output/get-trustlines.json"), + require("./schemas/output/sign-payment-channel-claim.json"), + require("./schemas/output/verify-payment-channel-claim.json"), + require("./schemas/input/get-balances.json"), + require("./schemas/input/get-balance-sheet.json"), + require("./schemas/input/get-ledger.json"), + require("./schemas/input/get-orders.json"), + require("./schemas/input/get-orderbook.json"), + require("./schemas/input/get-paths.json"), + require("./schemas/input/get-payment-channel.json"), + require("./schemas/input/api-options.json"), + require("./schemas/input/get-settings.json"), + require("./schemas/input/get-account-info.json"), + require("./schemas/input/get-account-objects.json"), + require("./schemas/input/get-transaction.json"), + require("./schemas/input/get-transactions.json"), + require("./schemas/input/get-trustlines.json"), + require("./schemas/input/prepare-payment.json"), + require("./schemas/input/prepare-order.json"), + require("./schemas/input/prepare-trustline.json"), + require("./schemas/input/prepare-order-cancellation.json"), + require("./schemas/input/prepare-settings.json"), + require("./schemas/input/prepare-escrow-creation.json"), + require("./schemas/input/prepare-escrow-cancellation.json"), + require("./schemas/input/prepare-escrow-execution.json"), + require("./schemas/input/prepare-payment-channel-create.json"), + require("./schemas/input/prepare-payment-channel-fund.json"), + require("./schemas/input/prepare-payment-channel-claim.json"), + require("./schemas/input/prepare-check-create.json"), + require("./schemas/input/prepare-check-cash.json"), + require("./schemas/input/prepare-check-cancel.json"), + require("./schemas/input/prepare-ticket-create.json"), + require("./schemas/input/compute-ledger-hash.json"), + require("./schemas/input/sign.json"), + require("./schemas/input/submit.json"), + require("./schemas/input/generate-address.json"), + require("./schemas/input/sign-payment-channel-claim.json"), + require("./schemas/input/verify-payment-channel-claim.json"), + require("./schemas/input/combine.json"), + ]; + const titles = schemas.map((schema) => schema.title); + const duplicates = Object.keys( + _.pickBy(_.countBy(titles), (count) => count > 1) + ); + assert.ok(duplicates.length === 0, `Duplicate schemas for: ${duplicates}`); + const validator = new Validator(); // Register custom format validators that ignore undefined instances // since jsonschema will still call the format validator on a missing // (optional) property @@ -136,49 +142,47 @@ function loadSchemas() { // This relies on "format": "xAddress" in `x-address.json`! validator.customFormats.xAddress = function (instance) { if (instance == null) { - return true + return true; } - return isValidXAddress(instance) - } + return isValidXAddress(instance); + }; // This relies on "format": "classicAddress" in `classic-address.json`! validator.customFormats.classicAddress = function (instance) { if (instance == null) { - return true + return true; } - return isValidAddress(instance) - } + return isValidAddress(instance); + }; validator.customFormats.secret = function (instance) { if (instance == null) { - return true + return true; } - return isValidSecret(instance) - } + return isValidSecret(instance); + }; // Register under the root URI '/' - schemas.forEach((schema) => - validator.addSchema(schema, '/' + schema.title) - ) - return validator + schemas.forEach((schema) => validator.addSchema(schema, `/${schema.title}`)); + return validator; } -const schemaValidator = loadSchemas() +const schemaValidator = loadSchemas(); function schemaValidate(schemaName: string, object: any): void { // Lookup under the root URI '/' - const schema = schemaValidator.getSchema('/' + schemaName) + const schema = schemaValidator.getSchema(`/${schemaName}`); if (schema == null) { - throw new ValidationError('no schema for ' + schemaName) + throw new ValidationError(`no schema for ${schemaName}`); } - const result = schemaValidator.validate(object, schema) + const result = schemaValidator.validate(object, schema); if (!result.valid) { - throw new ValidationError(result.errors.join()) + throw new ValidationError(result.errors.join()); } } function isValidAddress(address: string): boolean { - return isValidXAddress(address) || isValidClassicAddress(address) + return isValidXAddress(address) || isValidClassicAddress(address); } -export {schemaValidate, isValidSecret, isValidAddress} +export { schemaValidate, isValidSecret, isValidAddress }; diff --git a/src/common/txflags.ts b/src/common/txflags.ts index 9991153d..1bb410cd 100644 --- a/src/common/txflags.ts +++ b/src/common/txflags.ts @@ -1,7 +1,7 @@ const txFlags = { // Universal flags can apply to any transaction type Universal: { - FullyCanonicalSig: 0x80000000 + FullyCanonicalSig: 0x80000000, }, AccountSet: { @@ -10,7 +10,7 @@ const txFlags = { RequireAuth: 0x00040000, OptionalAuth: 0x00080000, DisallowXRP: 0x00100000, - AllowXRP: 0x00200000 + AllowXRP: 0x00200000, }, TrustSet: { @@ -19,27 +19,27 @@ const txFlags = { SetNoRipple: 0x00020000, ClearNoRipple: 0x00040000, SetFreeze: 0x00100000, - ClearFreeze: 0x00200000 + ClearFreeze: 0x00200000, }, OfferCreate: { Passive: 0x00010000, ImmediateOrCancel: 0x00020000, FillOrKill: 0x00040000, - Sell: 0x00080000 + Sell: 0x00080000, }, Payment: { NoRippleDirect: 0x00010000, PartialPayment: 0x00020000, - LimitQuality: 0x00040000 + LimitQuality: 0x00040000, }, PaymentChannelClaim: { Renew: 0x00010000, - Close: 0x00020000 - } -} + Close: 0x00020000, + }, +}; // The following are integer (as opposed to bit) flags // that can be set for particular transactions in the @@ -54,8 +54,8 @@ const txFlagIndices = { asfNoFreeze: 6, asfGlobalFreeze: 7, asfDefaultRipple: 8, - asfDepositAuth: 9 - } -} + asfDepositAuth: 9, + }, +}; -export {txFlags, txFlagIndices} +export { txFlags, txFlagIndices }; diff --git a/src/common/types/commands/account_info.ts b/src/common/types/commands/account_info.ts index 13b74037..d91b5ded 100644 --- a/src/common/types/commands/account_info.ts +++ b/src/common/types/commands/account_info.ts @@ -1,23 +1,23 @@ import { AccountRootLedgerEntry, SignerListLedgerEntry, - QueueData -} from '../objects' + QueueData, +} from "../objects"; export interface AccountInfoRequest { - account: string - strict?: boolean - queue?: boolean - ledger_hash?: string - ledger_index?: number | ('validated' | 'closed' | 'current') - signer_lists?: boolean + account: string; + strict?: boolean; + queue?: boolean; + ledger_hash?: string; + ledger_index?: number | ("validated" | "closed" | "current"); + signer_lists?: boolean; } export interface AccountInfoResponse { - account_data: AccountRootLedgerEntry - signer_lists?: SignerListLedgerEntry[] - ledger_current_index?: number - ledger_index?: number - queue_data?: QueueData - validated?: boolean + account_data: AccountRootLedgerEntry; + signer_lists?: SignerListLedgerEntry[]; + ledger_current_index?: number; + ledger_index?: number; + queue_data?: QueueData; + validated?: boolean; } diff --git a/src/common/types/commands/account_lines.ts b/src/common/types/commands/account_lines.ts index 352597ef..d93c0972 100644 --- a/src/common/types/commands/account_lines.ts +++ b/src/common/types/commands/account_lines.ts @@ -1,19 +1,19 @@ -import {Trustline} from '../objects' +import { Trustline } from "../objects"; export interface AccountLinesRequest { - account: string - ledger_hash?: string - ledger_index?: number | ('validated' | 'closed' | 'current') - peer?: string - limit?: number - marker?: any + account: string; + ledger_hash?: string; + ledger_index?: number | ("validated" | "closed" | "current"); + peer?: string; + limit?: number; + marker?: any; } export interface AccountLinesResponse { - account: string - lines: Trustline[] - ledger_current_index?: number - ledger_index?: number - ledger_hash?: string - marker?: any + account: string; + lines: Trustline[]; + ledger_current_index?: number; + ledger_index?: number; + ledger_hash?: string; + marker?: any; } diff --git a/src/common/types/commands/account_objects.ts b/src/common/types/commands/account_objects.ts index 57d76a3a..bedb7fb1 100644 --- a/src/common/types/commands/account_objects.ts +++ b/src/common/types/commands/account_objects.ts @@ -1,4 +1,4 @@ -import { AccountObjectType } from '../../../models/common'; +import { AccountObjectType } from "../../../models/common"; import { CheckLedgerEntry, RippleStateLedgerEntry, @@ -6,46 +6,46 @@ import { SignerListLedgerEntry, EscrowLedgerEntry, PayChannelLedgerEntry, - DepositPreauthLedgerEntry -} from '../objects' + DepositPreauthLedgerEntry, +} from "../objects"; export interface GetAccountObjectsOptions { - type?: AccountObjectType - ledgerHash?: string - ledgerIndex?: number | ('validated' | 'closed' | 'current') - limit?: number - marker?: string + type?: AccountObjectType; + ledgerHash?: string; + ledgerIndex?: number | ("validated" | "closed" | "current"); + limit?: number; + marker?: string; } export interface AccountObjectsRequest { - account: string + account: string; // (Optional) Filter results to include only this type of ledger object. type?: | string | ( - | 'check' - | 'escrow' - | 'offer' - | 'payment_channel' - | 'signer_list' - | 'state' - ) + | "check" + | "escrow" + | "offer" + | "payment_channel" + | "signer_list" + | "state" + ); // (Optional) A 20-byte hex string for the ledger version to use. - ledger_hash?: string + ledger_hash?: string; // (Optional) The sequence number of the ledger to use, // or a shortcut string to choose a ledger automatically. - ledger_index?: number | ('validated' | 'closed' | 'current') + ledger_index?: number | ("validated" | "closed" | "current"); - limit?: number + limit?: number; - marker?: string + marker?: string; } export interface AccountObjectsResponse { - account: string + account: string; // Array of objects owned by this account. // from the getAccountObjects section of the dev center @@ -57,29 +57,29 @@ export interface AccountObjectsResponse { | EscrowLedgerEntry | PayChannelLedgerEntry | DepositPreauthLedgerEntry - > + >; // (May be omitted) The identifying hash of the ledger // that was used to generate this response. - ledger_hash?: string + ledger_hash?: string; // (May be omitted) The sequence number of the ledger version // that was used to generate this response. - ledger_index?: number + ledger_index?: number; // (May be omitted) The sequence number of the current in-progress ledger // version that was used to generate this response. - ledger_current_index?: number + ledger_current_index?: number; // The limit that was used in this request, if any. - limit?: number + limit?: number; // Server-defined value indicating the response is paginated. Pass this // to the next call to resume where this call left off. Omitted when there // are no additional pages after this one. - marker?: string + marker?: string; // If true, this information comes from a ledger version // that has been validated by consensus. - validated?: boolean + validated?: boolean; } diff --git a/src/common/types/commands/account_offers.ts b/src/common/types/commands/account_offers.ts index db148a9d..50eee18a 100644 --- a/src/common/types/commands/account_offers.ts +++ b/src/common/types/commands/account_offers.ts @@ -1,27 +1,27 @@ -import {RippledAmount} from '../objects' +import { RippledAmount } from "../objects"; export interface AccountOffersRequest { - account: string - ledger_hash?: string - ledger_index?: number | ('validated' | 'closed' | 'current') - limit?: number - marker?: any + account: string; + ledger_hash?: string; + ledger_index?: number | ("validated" | "closed" | "current"); + limit?: number; + marker?: any; } export interface AccountOffersResponse { - account: string - ledger_hash?: string - ledger_current_index?: number - ledger_index?: number - marker?: any - offers?: AccountOffer[] + account: string; + ledger_hash?: string; + ledger_current_index?: number; + ledger_index?: number; + marker?: any; + offers?: AccountOffer[]; } export interface AccountOffer { - seq: number - flags: number - taker_gets: RippledAmount - taker_pays: RippledAmount - quality: string - expiration?: number + seq: number; + flags: number; + taker_gets: RippledAmount; + taker_pays: RippledAmount; + quality: string; + expiration?: number; } diff --git a/src/common/types/commands/book_offers.ts b/src/common/types/commands/book_offers.ts index 7e34fae7..a5017bc8 100644 --- a/src/common/types/commands/book_offers.ts +++ b/src/common/types/commands/book_offers.ts @@ -1,26 +1,30 @@ -import {TakerRequestAmount, RippledAmount, OfferLedgerEntry} from '../objects' +import { + TakerRequestAmount, + RippledAmount, + OfferLedgerEntry, +} from "../objects"; export interface BookOffersRequest { - taker?: string - taker_gets: TakerRequestAmount - taker_pays: TakerRequestAmount - ledger_hash?: string - ledger_index?: number | ('validated' | 'closed' | 'current') - limit?: number - marker?: any + taker?: string; + taker_gets: TakerRequestAmount; + taker_pays: TakerRequestAmount; + ledger_hash?: string; + ledger_index?: number | ("validated" | "closed" | "current"); + limit?: number; + marker?: any; } export interface BookOffersResponse { - offers: BookOffer[] - ledger_hash?: string - ledger_current_index?: number - ledger_index?: number - marker?: any + offers: BookOffer[]; + ledger_hash?: string; + ledger_current_index?: number; + ledger_index?: number; + marker?: any; } export interface BookOffer extends OfferLedgerEntry { - quality?: string - owner_funds?: string - taker_gets_funded?: RippledAmount - taker_pays_funded?: RippledAmount + quality?: string; + owner_funds?: string; + taker_gets_funded?: RippledAmount; + taker_pays_funded?: RippledAmount; } diff --git a/src/common/types/commands/gateway_balances.ts b/src/common/types/commands/gateway_balances.ts index b200b2fb..4698f3ec 100644 --- a/src/common/types/commands/gateway_balances.ts +++ b/src/common/types/commands/gateway_balances.ts @@ -1,19 +1,19 @@ -import {Amount} from '../objects' +import { Amount } from "../objects"; export interface GatewayBalancesRequest { - account: string - strict?: boolean - hotwallet: string | Array - ledger_hash?: string - ledger_index?: number | ('validated' | 'closed' | 'current') + account: string; + strict?: boolean; + hotwallet: string | string[]; + ledger_hash?: string; + ledger_index?: number | ("validated" | "closed" | "current"); } export interface GatewayBalancesResponse { - account: string - obligations?: {[currency: string]: string} - balances?: {[address: string]: Amount[]} - assets?: {[address: string]: Amount[]} - ledger_hash?: string - ledger_current_index?: number - ledger_index?: number + account: string; + obligations?: { [currency: string]: string }; + balances?: { [address: string]: Amount[] }; + assets?: { [address: string]: Amount[] }; + ledger_hash?: string; + ledger_current_index?: number; + ledger_index?: number; } diff --git a/src/common/types/commands/index.ts b/src/common/types/commands/index.ts index 43ac8ffc..33645cdd 100644 --- a/src/common/types/commands/index.ts +++ b/src/common/types/commands/index.ts @@ -1,10 +1,10 @@ -export * from './account_info' -export * from './account_lines' -export * from './account_objects' -export * from './account_offers' -export * from './book_offers' -export * from './gateway_balances' -export * from './ledger' -export * from './ledger_data' -export * from './ledger_entry' -export * from './server_info' +export * from "./account_info"; +export * from "./account_lines"; +export * from "./account_objects"; +export * from "./account_offers"; +export * from "./book_offers"; +export * from "./gateway_balances"; +export * from "./ledger"; +export * from "./ledger_data"; +export * from "./ledger_entry"; +export * from "./server_info"; diff --git a/src/common/types/commands/ledger.ts b/src/common/types/commands/ledger.ts index 05599113..4edb00a1 100644 --- a/src/common/types/commands/ledger.ts +++ b/src/common/types/commands/ledger.ts @@ -1,20 +1,20 @@ -import {Ledger, QueueData} from '../objects' +import { Ledger, QueueData } from "../objects"; export interface LedgerRequest { - ledger_hash?: string - ledger_index?: number | ('validated' | 'closed' | 'current') - full?: boolean - accounts?: boolean - transactions?: boolean - expand?: boolean - owner_funds?: boolean - binary?: boolean - queue?: boolean + ledger_hash?: string; + ledger_index?: number | ("validated" | "closed" | "current"); + full?: boolean; + accounts?: boolean; + transactions?: boolean; + expand?: boolean; + owner_funds?: boolean; + binary?: boolean; + queue?: boolean; } export interface LedgerResponse { - ledger_index: number - ledger_hash: string - ledger: Ledger - queue_data?: QueueData + ledger_index: number; + ledger_hash: string; + ledger: Ledger; + queue_data?: QueueData; } diff --git a/src/common/types/commands/ledger_data.ts b/src/common/types/commands/ledger_data.ts index cca3f782..8c5b8a8e 100644 --- a/src/common/types/commands/ledger_data.ts +++ b/src/common/types/commands/ledger_data.ts @@ -1,12 +1,12 @@ -import {LedgerData} from '../objects' +import { LedgerData } from "../objects"; export interface LedgerDataRequest { - id?: any - ledger_hash?: string - ledger_index?: string - binary?: boolean - limit?: number - marker?: string + id?: any; + ledger_hash?: string; + ledger_index?: string; + binary?: boolean; + limit?: number; + marker?: string; } -export type LedgerDataResponse = LedgerData +export type LedgerDataResponse = LedgerData; diff --git a/src/common/types/commands/ledger_entry.ts b/src/common/types/commands/ledger_entry.ts index a3f55339..94030c54 100644 --- a/src/common/types/commands/ledger_entry.ts +++ b/src/common/types/commands/ledger_entry.ts @@ -1,36 +1,36 @@ -import {LedgerEntry} from '../objects' +import { LedgerEntry } from "../objects"; export interface LedgerEntryRequest { - ledger_hash?: string - ledger_index?: number | ('validated' | 'closed' | 'current') - index?: string - account_root?: string + ledger_hash?: string; + ledger_index?: number | ("validated" | "closed" | "current"); + index?: string; + account_root?: string; directory?: | string | { - sub_index?: number - dir_root: string + sub_index?: number; + dir_root: string; } | { - sub_index?: number - owner: string - } + sub_index?: number; + owner: string; + }; offer?: | string | { - account: string - seq: number - } + account: string; + seq: number; + }; ripple_state?: { - accounts: [string, string] - currency: string - } - binary?: boolean + accounts: [string, string]; + currency: string; + }; + binary?: boolean; } export interface LedgerEntryResponse { - index: string - ledger_index: number - node_binary?: string - node?: LedgerEntry + index: string; + ledger_index: number; + node_binary?: string; + node?: LedgerEntry; } diff --git a/src/common/types/commands/server_info.ts b/src/common/types/commands/server_info.ts index ebf01e4f..4223c0cc 100644 --- a/src/common/types/commands/server_info.ts +++ b/src/common/types/commands/server_info.ts @@ -1,51 +1,51 @@ export interface ServerInfoRequest { - id?: number + id?: number; } export interface ServerInfoResponse { info: { - amendment_blocked?: boolean - build_version: string - closed_ledger?: LedgerInfo - complete_ledgers: string - hostid: string - io_latency_ms: number + amendment_blocked?: boolean; + build_version: string; + closed_ledger?: LedgerInfo; + complete_ledgers: string; + hostid: string; + io_latency_ms: number; last_close: { - converge_time_s: number - proposers: number - } + converge_time_s: number; + proposers: number; + }; load?: { - job_types: { - job_type: string - per_second: number - in_progress: number - }[] - threads: number - } - load_factor: number - load_factor_local?: number - load_factor_net?: number - load_factor_cluster?: number - load_factor_fee_escalation?: number - load_factor_fee_queue?: number - load_factor_server?: number - peers: number - pubkey_node: string - pubkey_validator: string - server_state: string - state_accounting: any - uptime: number - validated_ledger?: LedgerInfo - validation_quorum: number - validator_list_expires: string - } + job_types: Array<{ + job_type: string; + per_second: number; + in_progress: number; + }>; + threads: number; + }; + load_factor: number; + load_factor_local?: number; + load_factor_net?: number; + load_factor_cluster?: number; + load_factor_fee_escalation?: number; + load_factor_fee_queue?: number; + load_factor_server?: number; + peers: number; + pubkey_node: string; + pubkey_validator: string; + server_state: string; + state_accounting: any; + uptime: number; + validated_ledger?: LedgerInfo; + validation_quorum: number; + validator_list_expires: string; + }; } export interface LedgerInfo { - age: number - base_fee_xrp: number - hash: string - reserve_base_xrp: number - reserve_inc_xrp: number - seq: number + age: number; + base_fee_xrp: number; + hash: string; + reserve_base_xrp: number; + reserve_inc_xrp: number; + seq: number; } diff --git a/src/common/types/objects/adjustments.ts b/src/common/types/objects/adjustments.ts index ea9e2fb2..fd7a115e 100644 --- a/src/common/types/objects/adjustments.ts +++ b/src/common/types/objects/adjustments.ts @@ -1,19 +1,19 @@ -import {Amount} from './amounts' +import { Amount } from "./amounts"; -export type Adjustment = { - address: string - amount: Amount - tag?: number +export interface Adjustment { + address: string; + amount: Amount; + tag?: number; } -export type MaxAdjustment = { - address: string - maxAmount: Amount - tag?: number +export interface MaxAdjustment { + address: string; + maxAmount: Amount; + tag?: number; } -export type MinAdjustment = { - address: string - minAmount: Amount - tag?: number +export interface MinAdjustment { + address: string; + minAmount: Amount; + tag?: number; } diff --git a/src/common/types/objects/amounts.ts b/src/common/types/objects/amounts.ts index c7c45481..5cc48355 100644 --- a/src/common/types/objects/amounts.ts +++ b/src/common/types/objects/amounts.ts @@ -1,8 +1,8 @@ export interface Amount extends Issue { - value: string + value: string; } -export type RippledAmount = string | Amount +export type RippledAmount = string | Amount; /** * Specification of which currency the account taking the offer would pay/ @@ -10,15 +10,15 @@ export type RippledAmount = string | Amount * Similar to currency amounts. */ export interface TakerRequestAmount { - currency: string - issuer?: string + currency: string; + issuer?: string; } /** * A currency-counterparty pair, or just currency if it's XRP. */ export interface Issue { - currency: string - issuer?: string - counterparty?: string + currency: string; + issuer?: string; + counterparty?: string; } diff --git a/src/common/types/objects/index.ts b/src/common/types/objects/index.ts index 26658a51..6ac25d41 100644 --- a/src/common/types/objects/index.ts +++ b/src/common/types/objects/index.ts @@ -1,12 +1,12 @@ -export * from './adjustments' -export * from './amounts' -export * from './ledger' -export * from './ledger_data' -export * from './ledger_entries' -export * from './memos' -export * from './orders' -export * from './queue_data' -export * from './settings' -export * from './signers' -export * from './transactions' -export * from './trustlines' +export * from "./adjustments"; +export * from "./amounts"; +export * from "./ledger"; +export * from "./ledger_data"; +export * from "./ledger_entries"; +export * from "./memos"; +export * from "./orders"; +export * from "./queue_data"; +export * from "./settings"; +export * from "./signers"; +export * from "./transactions"; +export * from "./trustlines"; diff --git a/src/common/types/objects/ledger.ts b/src/common/types/objects/ledger.ts index dcc8c701..68ac06db 100644 --- a/src/common/types/objects/ledger.ts +++ b/src/common/types/objects/ledger.ts @@ -1,31 +1,31 @@ export interface Ledger { - account_hash: string - close_time: number - close_time_human: string - close_time_resolution: number - closed: boolean - ledger_hash: string - ledger_index: string - parent_hash: string - total_coins: string - transaction_hash: string - transactions: string[] | object[] - close_flags?: number - parent_close_time?: number - accountState?: any[] - validated?: boolean + account_hash: string; + close_time: number; + close_time_human: string; + close_time_resolution: number; + closed: boolean; + ledger_hash: string; + ledger_index: string; + parent_hash: string; + total_coins: string; + transaction_hash: string; + transactions: string[] | object[]; + close_flags?: number; + parent_close_time?: number; + accountState?: any[]; + validated?: boolean; } // https://xrpl.org/subscribe.html#ledger-stream -export type LedgerClosedEvent = { - type: 'ledgerClosed' - fee_base: number - fee_ref: number - ledger_hash: string - ledger_index: number - ledger_time: number - reserve_base: number - reserve_inc: number - txn_count: number - validated_ledgers: string +export interface LedgerClosedEvent { + type: "ledgerClosed"; + fee_base: number; + fee_ref: number; + ledger_hash: string; + ledger_index: number; + ledger_time: number; + reserve_base: number; + reserve_inc: number; + txn_count: number; + validated_ledgers: string; } diff --git a/src/common/types/objects/ledger_data.ts b/src/common/types/objects/ledger_data.ts index 7ad27e72..e123ac0b 100644 --- a/src/common/types/objects/ledger_data.ts +++ b/src/common/types/objects/ledger_data.ts @@ -1,6 +1,8 @@ export interface LedgerData { - ledger_index: string - ledger_hash: string - marker: string - state: ({data?: string; LedgerEntryType?: string; index: string} & any)[] + ledger_index: string; + ledger_hash: string; + marker: string; + state: Array< + { data?: string; LedgerEntryType?: string; index: string } & any + >; } diff --git a/src/common/types/objects/ledger_entries.ts b/src/common/types/objects/ledger_entries.ts index beefd558..e2661b6a 100644 --- a/src/common/types/objects/ledger_entries.ts +++ b/src/common/types/objects/ledger_entries.ts @@ -1,175 +1,176 @@ -import {SignerEntry} from './index' -import {Amount, RippledAmount} from './amounts' +import { Amount, RippledAmount } from "./amounts"; + +import { SignerEntry } from "./index"; export interface AccountRootLedgerEntry { - LedgerEntryType: 'AccountRoot' - Account: string - Balance: string - Flags: number - OwnerCount: number - PreviousTxnID: string - PreviousTxnLgrSeq: number - Sequence: number - AccountTxnID?: string - Domain?: string - EmailHash?: string - MessageKey?: string - RegularKey?: string - TickSize?: number - TransferRate?: number - WalletLocator?: string - WalletSize?: number // DEPRECATED + LedgerEntryType: "AccountRoot"; + Account: string; + Balance: string; + Flags: number; + OwnerCount: number; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; + Sequence: number; + AccountTxnID?: string; + Domain?: string; + EmailHash?: string; + MessageKey?: string; + RegularKey?: string; + TickSize?: number; + TransferRate?: number; + WalletLocator?: string; + WalletSize?: number; // DEPRECATED } export interface AmendmentsLedgerEntry { - LedgerEntryType: 'Amendments' - Amendments?: string[] - Majorities?: any[] - Flags: 0 + LedgerEntryType: "Amendments"; + Amendments?: string[]; + Majorities?: any[]; + Flags: 0; } export interface CheckLedgerEntry { - LedgerEntryType: 'Check' - Account: string - Destination - string - Flags: 0 - OwnerNode: string - PreviousTxnID: string - PreviousTxnLgrSeq: number - SendMax: string | object - Sequence: number - DestinationNode: string - DestinationTag: number - Expiration: number - InvoiceID: string - SourceTag: number + LedgerEntryType: "Check"; + Account: string; + Destination; + string; + Flags: 0; + OwnerNode: string; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; + SendMax: string | object; + Sequence: number; + DestinationNode: string; + DestinationTag: number; + Expiration: number; + InvoiceID: string; + SourceTag: number; } export interface DepositPreauthLedgerEntry { - LedgerEntryType: 'DepositPreauth' - Account: string - Authorize: string - OwnerNode: string - PreviousTxnID: string - PreviousTxnLgrSeq: number + LedgerEntryType: "DepositPreauth"; + Account: string; + Authorize: string; + OwnerNode: string; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; } export interface DirectoryNodeLedgerEntry { - LedgerEntryType: 'DirectoryNode' - Flags: number - RootIndex: string - Indexes: string[] - IndexNext?: number - IndexPrevious?: number + LedgerEntryType: "DirectoryNode"; + Flags: number; + RootIndex: string; + Indexes: string[]; + IndexNext?: number; + IndexPrevious?: number; } export interface OfferDirectoryNodeLedgerEntry extends DirectoryNodeLedgerEntry { - TakerPaysCurrency: string - TakerPaysIssuer: string - TakerGetsCurrency: string - TakerGetsIssuer: string - ExchangeRate?: number // DEPRECATED + TakerPaysCurrency: string; + TakerPaysIssuer: string; + TakerGetsCurrency: string; + TakerGetsIssuer: string; + ExchangeRate?: number; // DEPRECATED } export interface OwnerDirectoryNodeLedgerEntry extends DirectoryNodeLedgerEntry { - Owner: string + Owner: string; } export interface EscrowLedgerEntry { - LedgerEntryType: 'Escrow' - Account: string - Destination: string - Amount: string - Condition?: string - CancelAfter?: number - FinishAfter?: number - Flags: number - SourceTag?: number - DestinationTag?: number - OwnerNode: string - DestinationNode?: string - PreviousTxnID: string - PreviousTxnLgrSeq: number + LedgerEntryType: "Escrow"; + Account: string; + Destination: string; + Amount: string; + Condition?: string; + CancelAfter?: number; + FinishAfter?: number; + Flags: number; + SourceTag?: number; + DestinationTag?: number; + OwnerNode: string; + DestinationNode?: string; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; } export interface FeeSettingsLedgerEntry { - LedgerEntryType: 'FeeSettings' - BaseFee: string - ReferenceFeeUnits: number - ReserveBase: number - ReserveIncrement: number - Flags: number + LedgerEntryType: "FeeSettings"; + BaseFee: string; + ReferenceFeeUnits: number; + ReserveBase: number; + ReserveIncrement: number; + Flags: number; } export interface LedgerHashesLedgerEntry { - LedgerEntryType: 'LedgerHashes' - Hashes: string[] - Flags: number - FirstLedgerSequence?: number // DEPRECATED - LastLedgerSequence?: number + LedgerEntryType: "LedgerHashes"; + Hashes: string[]; + Flags: number; + FirstLedgerSequence?: number; // DEPRECATED + LastLedgerSequence?: number; } export interface OfferLedgerEntry { - LedgerEntryType: 'Offer' - Flags: number - Account: string - Sequence: number - TakerPays: RippledAmount - TakerGets: RippledAmount - BookDirectory: string - BookNode: string - OwnerNode: string - PreviousTxnID: string - PreviousTxnLgrSeq: number - Expiration?: number + LedgerEntryType: "Offer"; + Flags: number; + Account: string; + Sequence: number; + TakerPays: RippledAmount; + TakerGets: RippledAmount; + BookDirectory: string; + BookNode: string; + OwnerNode: string; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; + Expiration?: number; } export interface PayChannelLedgerEntry { - LedgerEntryType: 'PayChannel' - Sequence: number - Account: string - Amount: string - Balance: string - PublicKey: string - Destination: string - SettleDelay: number - Expiration?: number - CancelAfter?: number - SourceTag?: number - DestinationTag?: number - OwnerNode: string - PreviousTxnID: string - PreviousTxnLgrSeq: number - index: string + LedgerEntryType: "PayChannel"; + Sequence: number; + Account: string; + Amount: string; + Balance: string; + PublicKey: string; + Destination: string; + SettleDelay: number; + Expiration?: number; + CancelAfter?: number; + SourceTag?: number; + DestinationTag?: number; + OwnerNode: string; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; + index: string; } export interface RippleStateLedgerEntry { - LedgerEntryType: 'RippleState' - Flags: number - Balance: Amount - LowLimit: Amount - HighLimit: Amount - PreviousTxnID: string - PreviousTxnLgrSeq: number - LowNode?: string - HighNode?: string - LowQualityIn?: number - LowQualityOut?: number - HighQualityIn?: number - HighQualityOut?: number + LedgerEntryType: "RippleState"; + Flags: number; + Balance: Amount; + LowLimit: Amount; + HighLimit: Amount; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; + LowNode?: string; + HighNode?: string; + LowQualityIn?: number; + LowQualityOut?: number; + HighQualityIn?: number; + HighQualityOut?: number; } export interface SignerListLedgerEntry { - LedgerEntryType: 'SignerList' - OwnerNode: string - SignerQuorum: number - SignerEntries: SignerEntry[] - SignerListID: number - PreviousTxnID: string - PreviousTxnLgrSeq: number + LedgerEntryType: "SignerList"; + OwnerNode: string; + SignerQuorum: number; + SignerEntries: SignerEntry[]; + SignerListID: number; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; } // see https://ripple.com/build/ledger-format/#ledger-object-types @@ -187,4 +188,4 @@ export type LedgerEntry = | OfferLedgerEntry | PayChannelLedgerEntry | RippleStateLedgerEntry - | SignerListLedgerEntry + | SignerListLedgerEntry; diff --git a/src/common/types/objects/memos.ts b/src/common/types/objects/memos.ts index e5692e9b..bc181a01 100644 --- a/src/common/types/objects/memos.ts +++ b/src/common/types/objects/memos.ts @@ -1,5 +1,5 @@ -export type Memo = { - type?: string - format?: string - data?: string +export interface Memo { + type?: string; + format?: string; + data?: string; } diff --git a/src/common/types/objects/orders.ts b/src/common/types/objects/orders.ts index 05552293..c8a1bde6 100644 --- a/src/common/types/objects/orders.ts +++ b/src/common/types/objects/orders.ts @@ -1,17 +1,17 @@ -import {Amount} from './amounts' -import {Memo} from './memos' +import { Amount } from "./amounts"; +import { Memo } from "./memos"; -export type FormattedOrderSpecification = { - direction: string - quantity: Amount - totalPrice: Amount - immediateOrCancel?: boolean - fillOrKill?: boolean - expirationTime?: string - orderToReplace?: number - memos?: Memo[] +export interface FormattedOrderSpecification { + direction: string; + quantity: Amount; + totalPrice: Amount; + immediateOrCancel?: boolean; + fillOrKill?: boolean; + expirationTime?: string; + orderToReplace?: number; + memos?: Memo[]; // If enabled, the offer will not consume offers that exactly match it, and // instead becomes an Offer node in the ledger. It will still consume offers // that cross it. - passive?: boolean + passive?: boolean; } diff --git a/src/common/types/objects/queue_data.ts b/src/common/types/objects/queue_data.ts index 918f05a3..331dac51 100644 --- a/src/common/types/objects/queue_data.ts +++ b/src/common/types/objects/queue_data.ts @@ -1,16 +1,16 @@ export interface QueueTransaction { - auth_change: boolean - fee: string - fee_level: string - max_spend_drops: string - seq: number + auth_change: boolean; + fee: string; + fee_level: string; + max_spend_drops: string; + seq: number; } export interface QueueData { - txn_count: number - auth_change_queued?: boolean - lowest_sequence?: number - highest_sequence?: number - max_spend_drops_total?: string - transactions?: QueueTransaction[] + txn_count: number; + auth_change_queued?: boolean; + lowest_sequence?: number; + highest_sequence?: number; + max_spend_drops_total?: string; + transactions?: QueueTransaction[]; } diff --git a/src/common/types/objects/settings.ts b/src/common/types/objects/settings.ts index 69285898..754257c6 100644 --- a/src/common/types/objects/settings.ts +++ b/src/common/types/objects/settings.ts @@ -1,33 +1,33 @@ -import {Memo} from './memos' +import { Memo } from "./memos"; -export type WeightedSigner = { - address: string - weight: number +export interface WeightedSigner { + address: string; + weight: number; } -export type Signers = { - threshold?: number - weights: WeightedSigner[] +export interface Signers { + threshold?: number; + weights: WeightedSigner[]; } -export type FormattedSettings = { - defaultRipple?: boolean - depositAuth?: boolean - disableMasterKey?: boolean - disallowIncomingXRP?: boolean - domain?: string - emailHash?: string | null - walletLocator?: string | null - enableTransactionIDTracking?: boolean - globalFreeze?: boolean - memos?: Memo[] - messageKey?: string - noFreeze?: boolean - passwordSpent?: boolean - regularKey?: string - requireAuthorization?: boolean - requireDestinationTag?: boolean - signers?: Signers - transferRate?: number | null - tickSize?: number +export interface FormattedSettings { + defaultRipple?: boolean; + depositAuth?: boolean; + disableMasterKey?: boolean; + disallowIncomingXRP?: boolean; + domain?: string; + emailHash?: string | null; + walletLocator?: string | null; + enableTransactionIDTracking?: boolean; + globalFreeze?: boolean; + memos?: Memo[]; + messageKey?: string; + noFreeze?: boolean; + passwordSpent?: boolean; + regularKey?: string; + requireAuthorization?: boolean; + requireDestinationTag?: boolean; + signers?: Signers; + transferRate?: number | null; + tickSize?: number; } diff --git a/src/common/types/objects/signers.ts b/src/common/types/objects/signers.ts index 3c7d85dc..fdf869d5 100644 --- a/src/common/types/objects/signers.ts +++ b/src/common/types/objects/signers.ts @@ -1,6 +1,6 @@ export interface SignerEntry { SignerEntry: { - Account: string - SignerWeight: number - } + Account: string; + SignerWeight: number; + }; } diff --git a/src/common/types/objects/transactions.ts b/src/common/types/objects/transactions.ts index 70b860fa..14f1f563 100644 --- a/src/common/types/objects/transactions.ts +++ b/src/common/types/objects/transactions.ts @@ -1,27 +1,27 @@ -import {RippledAmount} from './amounts' -import {Memo} from './memos' +import { RippledAmount } from "./amounts"; +import { Memo } from "./memos"; export interface OfferCreateTransaction { - TransactionType: 'OfferCreate' - Account: string - AccountTxnID?: string - Fee: string - Field: any - Flags: number - LastLedgerSequence?: number - Sequence: number - Signers: any[] - SigningPubKey: string - SourceTag?: number - TakerGets: RippledAmount - TakerPays: RippledAmount - TxnSignature: string - Expiration?: number - Memos?: Memo[] - OfferSequence?: number + TransactionType: "OfferCreate"; + Account: string; + AccountTxnID?: string; + Fee: string; + Field: any; + Flags: number; + LastLedgerSequence?: number; + Sequence: number; + Signers: any[]; + SigningPubKey: string; + SourceTag?: number; + TakerGets: RippledAmount; + TakerPays: RippledAmount; + TxnSignature: string; + Expiration?: number; + Memos?: Memo[]; + OfferSequence?: number; } export interface SignedTransaction { - signedTransaction: string - id: string + signedTransaction: string; + id: string; } diff --git a/src/common/types/objects/trustlines.ts b/src/common/types/objects/trustlines.ts index 75be5ff4..d813eda0 100644 --- a/src/common/types/objects/trustlines.ts +++ b/src/common/types/objects/trustlines.ts @@ -1,42 +1,42 @@ -import {Memo} from './memos' +import { Memo } from "./memos"; export interface Trustline { - account: string - balance: string - currency: string - limit: string - limit_peer: string - quality_in: number - quality_out: number - no_ripple?: boolean - no_ripple_peer?: boolean - freeze?: boolean - freeze_peer?: boolean - authorized?: boolean - peer_authorized?: boolean + account: string; + balance: string; + currency: string; + limit: string; + limit_peer: string; + quality_in: number; + quality_out: number; + no_ripple?: boolean; + no_ripple_peer?: boolean; + freeze?: boolean; + freeze_peer?: boolean; + authorized?: boolean; + peer_authorized?: boolean; } -export type FormattedTrustlineSpecification = { - currency: string - counterparty: string - limit: string - qualityIn?: number - qualityOut?: number - ripplingDisabled?: boolean - authorized?: boolean - frozen?: boolean - memos?: Memo[] +export interface FormattedTrustlineSpecification { + currency: string; + counterparty: string; + limit: string; + qualityIn?: number; + qualityOut?: number; + ripplingDisabled?: boolean; + authorized?: boolean; + frozen?: boolean; + memos?: Memo[]; } -export type FormattedTrustline = { - specification: FormattedTrustlineSpecification +export interface FormattedTrustline { + specification: FormattedTrustlineSpecification; counterparty: { - limit: string - ripplingDisabled?: boolean - frozen?: boolean - authorized?: boolean - } + limit: string; + ripplingDisabled?: boolean; + frozen?: boolean; + authorized?: boolean; + }; state: { - balance: string - } + balance: string; + }; } diff --git a/src/common/validate.ts b/src/common/validate.ts index 145e4d65..7c97e422 100644 --- a/src/common/validate.ts +++ b/src/common/validate.ts @@ -1,9 +1,10 @@ -import _ from 'lodash' -import {ValidationError} from './errors' -import {schemaValidate} from './schema-validator' +import _ from "lodash"; + +import { ValidationError } from "./errors"; +import { schemaValidate } from "./schema-validator"; function error(text) { - return new ValidationError(text) + return new ValidationError(text); } function validateLedgerRange(options) { @@ -13,158 +14,161 @@ function validateLedgerRange(options) { options.maxLedgerVersion != null ) { if (Number(options.minLedgerVersion) > Number(options.maxLedgerVersion)) { - throw error('minLedgerVersion must not be greater than maxLedgerVersion') + throw error("minLedgerVersion must not be greater than maxLedgerVersion"); } } } function validateOptions(schema, instance) { - schemaValidate(schema, instance) - validateLedgerRange(instance.options) + schemaValidate(schema, instance); + validateLedgerRange(instance.options); } -export const getPaths = _.partial(schemaValidate, 'getPathsParameters') +export const getPaths = _.partial(schemaValidate, "getPathsParameters"); export const getTransactions = _.partial( validateOptions, - 'getTransactionsParameters' -) + "getTransactionsParameters" +); -export const getSettings = _.partial(validateOptions, 'getSettingsParameters') +export const getSettings = _.partial(validateOptions, "getSettingsParameters"); export const getAccountInfo = _.partial( validateOptions, - 'getAccountInfoParameters' -) + "getAccountInfoParameters" +); export const getTrustlines = _.partial( validateOptions, - 'getTrustlinesParameters' -) + "getTrustlinesParameters" +); -export const getBalances = _.partial(validateOptions, 'getBalancesParameters') +export const getBalances = _.partial(validateOptions, "getBalancesParameters"); export const getBalanceSheet = _.partial( validateOptions, - 'getBalanceSheetParameters' -) + "getBalanceSheetParameters" +); -export const getOrders = _.partial(validateOptions, 'getOrdersParameters') +export const getOrders = _.partial(validateOptions, "getOrdersParameters"); -export const getOrderbook = _.partial(validateOptions, 'getOrderbookParameters') +export const getOrderbook = _.partial( + validateOptions, + "getOrderbookParameters" +); export const getTransaction = _.partial( validateOptions, - 'getTransactionParameters' -) + "getTransactionParameters" +); export const getPaymentChannel = _.partial( validateOptions, - 'getPaymentChannelParameters' -) + "getPaymentChannelParameters" +); -export const getLedger = _.partial(validateOptions, 'getLedgerParameters') +export const getLedger = _.partial(validateOptions, "getLedgerParameters"); export const preparePayment = _.partial( schemaValidate, - 'preparePaymentParameters' -) + "preparePaymentParameters" +); -export const prepareOrder = _.partial(schemaValidate, 'prepareOrderParameters') +export const prepareOrder = _.partial(schemaValidate, "prepareOrderParameters"); export const prepareOrderCancellation = _.partial( schemaValidate, - 'prepareOrderCancellationParameters' -) + "prepareOrderCancellationParameters" +); export const prepareTrustline = _.partial( schemaValidate, - 'prepareTrustlineParameters' -) + "prepareTrustlineParameters" +); export const prepareSettings = _.partial( schemaValidate, - 'prepareSettingsParameters' -) + "prepareSettingsParameters" +); export const prepareEscrowCreation = _.partial( schemaValidate, - 'prepareEscrowCreationParameters' -) + "prepareEscrowCreationParameters" +); export const prepareEscrowCancellation = _.partial( schemaValidate, - 'prepareEscrowCancellationParameters' -) + "prepareEscrowCancellationParameters" +); export const prepareEscrowExecution = _.partial( schemaValidate, - 'prepareEscrowExecutionParameters' -) + "prepareEscrowExecutionParameters" +); export const preparePaymentChannelCreate = _.partial( schemaValidate, - 'preparePaymentChannelCreateParameters' -) + "preparePaymentChannelCreateParameters" +); export const preparePaymentChannelFund = _.partial( schemaValidate, - 'preparePaymentChannelFundParameters' -) + "preparePaymentChannelFundParameters" +); export const preparePaymentChannelClaim = _.partial( schemaValidate, - 'preparePaymentChannelClaimParameters' -) + "preparePaymentChannelClaimParameters" +); export const prepareCheckCreate = _.partial( schemaValidate, - 'prepareCheckCreateParameters' -) + "prepareCheckCreateParameters" +); export const prepareCheckCash = _.partial( schemaValidate, - 'prepareCheckCashParameters' -) + "prepareCheckCashParameters" +); export const prepareCheckCancel = _.partial( schemaValidate, - 'prepareCheckCancelParameters' -) + "prepareCheckCancelParameters" +); export const prepareTicketCreate = _.partial( schemaValidate, - 'prepareTicketParameters' -) + "prepareTicketParameters" +); -export const sign = _.partial(schemaValidate, 'signParameters') +export const sign = _.partial(schemaValidate, "signParameters"); -export const combine = _.partial(schemaValidate, 'combineParameters') +export const combine = _.partial(schemaValidate, "combineParameters"); -export const submit = _.partial(schemaValidate, 'submitParameters') +export const submit = _.partial(schemaValidate, "submitParameters"); export const computeLedgerHash = _.partial( schemaValidate, - 'computeLedgerHashParameters' -) + "computeLedgerHashParameters" +); export const generateAddress = _.partial( schemaValidate, - 'generateAddressParameters' -) + "generateAddressParameters" +); export const signPaymentChannelClaim = _.partial( schemaValidate, - 'signPaymentChannelClaimParameters' -) + "signPaymentChannelClaimParameters" +); export const verifyPaymentChannelClaim = _.partial( schemaValidate, - 'verifyPaymentChannelClaimParameters' -) + "verifyPaymentChannelClaimParameters" +); -export const apiOptions = _.partial(schemaValidate, 'api-options') +export const apiOptions = _.partial(schemaValidate, "api-options"); -export const instructions = _.partial(schemaValidate, 'instructions') +export const instructions = _.partial(schemaValidate, "instructions"); -export const tx_json = _.partial(schemaValidate, 'tx-json') +export const tx_json = _.partial(schemaValidate, "tx-json"); diff --git a/src/index.ts b/src/index.ts index a5e87fa7..c713324f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,14 +1,14 @@ -export {Client} from './client' +export { Client } from "./client"; -export * from './transaction/types' +export * from "./transaction/types"; -export * from './common/types/objects/ledger' +export * from "./common/types/objects/ledger"; -export * from './models/methods' +export * from "./models/methods"; -export * from './utils' +export * from "./utils"; // Broadcast client is experimental -export {BroadcastClient} from './client/broadcastClient' +export { BroadcastClient } from "./client/broadcastClient"; -export * from './Wallet' +export * from "./Wallet"; diff --git a/src/ledger/balances.ts b/src/ledger/balances.ts index db5b2975..d36cf0ad 100644 --- a/src/ledger/balances.ts +++ b/src/ledger/balances.ts @@ -1,42 +1,46 @@ -import * as utils from './utils' -import {validate, ensureClassicAddress} from '../common' -import {Connection} from '../client' -import {GetTrustlinesOptions} from './trustlines' -import {FormattedTrustline} from '../common/types/objects/trustlines' -import {Client} from '..' +import { Client } from ".."; +import { Connection } from "../client"; +import { validate, ensureClassicAddress } from "../common"; +import { FormattedTrustline } from "../common/types/objects/trustlines"; -export type Balance = { - value: string - currency: string - counterparty?: string +import { GetTrustlinesOptions } from "./trustlines"; +import * as utils from "./utils"; + +export interface Balance { + value: string; + currency: string; + counterparty?: string; } -export type GetBalances = Array +export type GetBalances = Balance[]; function getTrustlineBalanceAmount(trustline: FormattedTrustline): Balance { return { currency: trustline.specification.currency, counterparty: trustline.specification.counterparty, - value: trustline.state.balance - } + value: trustline.state.balance, + }; } -function formatBalances(options: GetTrustlinesOptions, balances: {xrp: string, trustlines: FormattedTrustline[]}) { - const result = balances.trustlines.map(getTrustlineBalanceAmount) +function formatBalances( + options: GetTrustlinesOptions, + balances: { xrp: string; trustlines: FormattedTrustline[] } +) { + const result = balances.trustlines.map(getTrustlineBalanceAmount); if ( - !(options.counterparty || (options.currency && options.currency !== 'XRP')) + !(options.counterparty || (options.currency && options.currency !== "XRP")) ) { const xrpBalance = { - currency: 'XRP', - value: balances.xrp - } - result.unshift(xrpBalance) + currency: "XRP", + value: balances.xrp, + }; + result.unshift(xrpBalance); } if (options.limit && result.length > options.limit) { - const toRemove = result.length - options.limit - result.splice(-toRemove, toRemove) + const toRemove = result.length - options.limit; + result.splice(-toRemove, toRemove); } - return result + return result; } function getLedgerVersionHelper( @@ -44,12 +48,14 @@ function getLedgerVersionHelper( optionValue?: number ): Promise { if (optionValue != null && optionValue !== null) { - return Promise.resolve(optionValue) + return Promise.resolve(optionValue); } - return connection.request({ - command: 'ledger', - ledger_index: 'validated' - }).then(response => response.result.ledger_index); + return connection + .request({ + command: "ledger", + ledger_index: "validated", + }) + .then((response) => response.result.ledger_index); } function getBalances( @@ -57,26 +63,23 @@ function getBalances( address: string, options: GetTrustlinesOptions = {} ): Promise { - validate.getTrustlines({address, options}) + validate.getTrustlines({ address, options }); // Only support retrieving balances without a tag, // since we currently do not calculate balances // on a per-tag basis. Apps must interpret and // use tags independent of the XRP Ledger, comparing // with the XRP Ledger's balance as an accounting check. - address = ensureClassicAddress(address) + address = ensureClassicAddress(address); return Promise.all([ - getLedgerVersionHelper( - this.connection, - options.ledgerVersion - ).then((ledgerVersion) => - utils.getXRPBalance(this, address, ledgerVersion) + getLedgerVersionHelper(this.connection, options.ledgerVersion).then( + (ledgerVersion) => utils.getXRPBalance(this, address, ledgerVersion) ), - this.getTrustlines(address, options) + this.getTrustlines(address, options), ]).then((results) => - formatBalances(options, {xrp: results[0], trustlines: results[1]}) - ) + formatBalances(options, { xrp: results[0], trustlines: results[1] }) + ); } -export default getBalances +export default getBalances; diff --git a/src/ledger/orderbook.ts b/src/ledger/orderbook.ts index 8bde6fe5..7a805a04 100644 --- a/src/ledger/orderbook.ts +++ b/src/ledger/orderbook.ts @@ -1,45 +1,46 @@ -import _ from 'lodash' -import * as utils from './utils' +import BigNumber from "bignumber.js"; +import _ from "lodash"; + +import type { Client } from "../client"; +import type { BookOffer } from "../common/types/commands"; +import type { Issue } from "../common/types/objects"; + import { parseOrderbookOrder, - FormattedOrderbookOrder -} from './parse/orderbook-order' -import {validate} from '../common' -import {Issue} from '../common/types/objects' -import {BookOffer} from '../common/types/commands' -import {Client} from '..' -import BigNumber from 'bignumber.js' + FormattedOrderbookOrder, +} from "./parse/orderbook-order"; +import * as utils from "./utils"; -export type FormattedOrderbook = { - bids: FormattedOrderbookOrder[] - asks: FormattedOrderbookOrder[] +export interface FormattedOrderbook { + bids: FormattedOrderbookOrder[]; + asks: FormattedOrderbookOrder[]; } function isSameIssue(a: Issue, b: Issue) { - return a.currency === b.currency && a.counterparty === b.counterparty + return a.currency === b.currency && a.counterparty === b.counterparty; } function directionFilter(direction: string, order: FormattedOrderbookOrder) { - return order.specification.direction === direction + return order.specification.direction === direction; } function flipOrder(order: FormattedOrderbookOrder) { - const specification = order.specification + const specification = order.specification; const flippedSpecification = { quantity: specification.totalPrice, totalPrice: specification.quantity, - direction: specification.direction === 'buy' ? 'sell' : 'buy' - } - const newSpecification = _.merge({}, specification, flippedSpecification) - return _.merge({}, order, {specification: newSpecification}) + direction: specification.direction === "buy" ? "sell" : "buy", + }; + const newSpecification = _.merge({}, specification, flippedSpecification); + return _.merge({}, order, { specification: newSpecification }); } function alignOrder( base: Issue, order: FormattedOrderbookOrder ): FormattedOrderbookOrder { - const quantity = order.specification.quantity - return isSameIssue(quantity, base) ? order : flipOrder(order) + const quantity = order.specification.quantity; + return isSameIssue(quantity, base) ? order : flipOrder(order); } export function formatBidsAndAsks( @@ -58,14 +59,17 @@ export function formatBidsAndAsks( // we sort the orders so that earlier orders are closer to mid-market const orders = offers .sort((a, b) => { - return new BigNumber(a.quality).comparedTo(b.quality) - }) - .map(parseOrderbookOrder) + const qualityA = a.quality ?? 0; + const qualityB = b.quality ?? 0; - const alignedOrders = orders.map(_.partial(alignOrder, orderbook.base)) - const bids = alignedOrders.filter(_.partial(directionFilter, 'buy')) - const asks = alignedOrders.filter(_.partial(directionFilter, 'sell')) - return {bids, asks} + return new BigNumber(qualityA).comparedTo(qualityB); + }) + .map(parseOrderbookOrder); + + const alignedOrders = orders.map(_.partial(alignOrder, orderbook.base)); + const bids = alignedOrders.filter(_.partial(directionFilter, "buy")); + const asks = alignedOrders.filter(_.partial(directionFilter, "sell")); + return { bids, asks }; } // account is to specify a "perspective", which affects which unfunded offers @@ -79,25 +83,26 @@ async function makeRequest( ) { const orderData = utils.renameCounterpartyToIssuerInOrder({ taker_gets: takerGets, - taker_pays: takerPays - }) - return client.requestAll({command: 'book_offers', + taker_pays: takerPays, + }); + return client.requestAll({ + command: "book_offers", taker_gets: orderData.taker_gets, taker_pays: orderData.taker_pays, - ledger_index: options.ledgerVersion || 'validated', + ledger_index: options.ledgerVersion || "validated", limit: options.limit, - taker - }) + taker, + }); } -export type GetOrderbookOptions = { - limit?: number - ledgerVersion?: number +export interface GetOrderbookOptions { + limit?: number; + ledgerVersion?: number; } -export type OrderbookInfo = { - base: Issue - counter: Issue +export interface OrderbookInfo { + base: Issue; + counter: Issue; } export async function getOrderbook( @@ -106,21 +111,19 @@ export async function getOrderbook( orderbook: OrderbookInfo, options: GetOrderbookOptions = {} ): Promise { - // 1. Validate - validate.getOrderbook({address, orderbook, options}) // 2. Make Request const [directOfferResults, reverseOfferResults] = await Promise.all([ makeRequest(this, address, options, orderbook.base, orderbook.counter), - makeRequest(this, address, options, orderbook.counter, orderbook.base) - ]) + makeRequest(this, address, options, orderbook.counter, orderbook.base), + ]); // 3. Return Formatted Response const directOffers = _.flatMap( directOfferResults, (directOfferResult) => directOfferResult.result.offers - ) + ); const reverseOffers = _.flatMap( reverseOfferResults, (reverseOfferResult) => reverseOfferResult.result.offers - ) - return formatBidsAndAsks(orderbook, [...directOffers, ...reverseOffers]) + ); + return formatBidsAndAsks(orderbook, [...directOffers, ...reverseOffers]); } diff --git a/src/ledger/parse/account-delete.ts b/src/ledger/parse/account-delete.ts index 9020f815..17625ab4 100644 --- a/src/ledger/parse/account-delete.ts +++ b/src/ledger/parse/account-delete.ts @@ -1,25 +1,28 @@ -import * as assert from 'assert' -import {removeUndefined} from '../../utils' -import {classicAddressToXAddress} from 'ripple-address-codec' -import {parseMemos} from './utils' +import * as assert from "assert"; -export type FormattedAccountDelete = { +import { classicAddressToXAddress } from "ripple-address-codec"; + +import { removeUndefined } from "../../utils"; + +import { parseMemos } from "./utils"; + +export interface FormattedAccountDelete { // account (address) of an account to receive any leftover XRP after deleting the sending account. // Must be a funded account in the ledger, and must not be the sending account. - destination: string + destination: string; // (Optional) Arbitrary destination tag that identifies a hosted recipient or other information // for the recipient of the deleted account's leftover XRP. NB: Ensure that the hosted recipient is // able to account for AccountDelete transactions; if not, your balance may not be properly credited. - destinationTag?: number + destinationTag?: number; // X-address of an account to receive any leftover XRP after deleting the sending account. // Must be a funded account in the ledger, and must not be the sending account. - destinationXAddress: string + destinationXAddress: string; } function parseAccountDelete(tx: any): FormattedAccountDelete { - assert.ok(tx.TransactionType === 'AccountDelete') + assert.ok(tx.TransactionType === "AccountDelete"); return removeUndefined({ memos: parseMemos(tx), @@ -29,8 +32,8 @@ function parseAccountDelete(tx: any): FormattedAccountDelete { tx.Destination, tx.DestinationTag == null ? false : tx.DestinationTag, false - ) - }) + ), + }); } -export default parseAccountDelete +export default parseAccountDelete; diff --git a/src/ledger/parse/account-order.ts b/src/ledger/parse/account-order.ts index d347c041..315c3343 100644 --- a/src/ledger/parse/account-order.ts +++ b/src/ledger/parse/account-order.ts @@ -1,23 +1,25 @@ -import BigNumber from 'bignumber.js' -import parseAmount from './amount' -import {parseTimestamp, adjustQualityForXRP} from './utils' -import {removeUndefined} from '../../utils' -import {orderFlags} from './flags' -import {FormattedOrderSpecification} from '../../common/types/objects' +import BigNumber from "bignumber.js"; -export type FormattedAccountOrder = { - specification: FormattedOrderSpecification +import { FormattedOrderSpecification } from "../../common/types/objects"; +import { removeUndefined } from "../../utils"; + +import parseAmount from "./amount"; +import { orderFlags } from "./flags"; +import { parseTimestamp, adjustQualityForXRP } from "./utils"; + +export interface FormattedAccountOrder { + specification: FormattedOrderSpecification; properties: { - maker: string - sequence: number - makerExchangeRate: string - } + maker: string; + sequence: number; + makerExchangeRate: string; + }; } // TODO: remove this function once rippled provides quality directly function computeQuality(takerGets, takerPays) { - const quotient = new BigNumber(takerPays.value).dividedBy(takerGets.value) - return quotient.precision(16, BigNumber.ROUND_HALF_UP).toString() + const quotient = new BigNumber(takerPays.value).dividedBy(takerGets.value); + return quotient.precision(16, BigNumber.ROUND_HALF_UP).toString(); } // rippled 'account_offers' returns a different format for orders than 'tx' @@ -26,22 +28,22 @@ export function parseAccountOrder( address: string, order: any ): FormattedAccountOrder { - const direction = (order.flags & orderFlags.Sell) === 0 ? 'buy' : 'sell' - const takerGetsAmount = parseAmount(order.taker_gets) - const takerPaysAmount = parseAmount(order.taker_pays) - const quantity = direction === 'buy' ? takerPaysAmount : takerGetsAmount - const totalPrice = direction === 'buy' ? takerGetsAmount : takerPaysAmount + const direction = (order.flags & orderFlags.Sell) === 0 ? "buy" : "sell"; + const takerGetsAmount = parseAmount(order.taker_gets); + const takerPaysAmount = parseAmount(order.taker_pays); + const quantity = direction === "buy" ? takerPaysAmount : takerGetsAmount; + const totalPrice = direction === "buy" ? takerGetsAmount : takerPaysAmount; // note: immediateOrCancel and fillOrKill orders cannot enter the order book // so we can omit those flags here const specification = removeUndefined({ - direction: direction, - quantity: quantity, - totalPrice: totalPrice, + direction, + quantity, + totalPrice, passive: (order.flags & orderFlags.Passive) !== 0 || undefined, // rippled currently does not provide "expiration" in account_offers - expirationTime: parseTimestamp(order.expiration) - }) + expirationTime: parseTimestamp(order.expiration), + }); const makerExchangeRate = order.quality ? adjustQualityForXRP( @@ -49,12 +51,12 @@ export function parseAccountOrder( takerGetsAmount.currency, takerPaysAmount.currency ) - : computeQuality(takerGetsAmount, takerPaysAmount) + : computeQuality(takerGetsAmount, takerPaysAmount); const properties = { maker: address, sequence: order.seq, - makerExchangeRate: makerExchangeRate - } + makerExchangeRate, + }; - return {specification, properties} + return { specification, properties }; } diff --git a/src/ledger/parse/account-trustline.ts b/src/ledger/parse/account-trustline.ts index 179d68bb..cc034ad4 100644 --- a/src/ledger/parse/account-trustline.ts +++ b/src/ledger/parse/account-trustline.ts @@ -1,9 +1,10 @@ -import {parseQuality} from './utils' -import {removeUndefined} from '../../utils' import { Trustline, - FormattedTrustline -} from '../../common/types/objects/trustlines' + FormattedTrustline, +} from "../../common/types/objects/trustlines"; +import { removeUndefined } from "../../utils"; + +import { parseQuality } from "./utils"; // rippled 'account_lines' returns a different format for // trustlines than 'tx' @@ -16,19 +17,19 @@ function parseAccountTrustline(trustline: Trustline): FormattedTrustline { qualityOut: parseQuality(trustline.quality_out) || undefined, ripplingDisabled: trustline.no_ripple, frozen: trustline.freeze, - authorized: trustline.authorized - }) + authorized: trustline.authorized, + }); // rippled doesn't provide the counterparty's qualities const counterparty = removeUndefined({ limit: trustline.limit_peer, ripplingDisabled: trustline.no_ripple_peer, frozen: trustline.freeze_peer, - authorized: trustline.peer_authorized - }) + authorized: trustline.peer_authorized, + }); const state = { - balance: trustline.balance - } - return {specification, counterparty, state} + balance: trustline.balance, + }; + return { specification, counterparty, state }; } -export default parseAccountTrustline +export default parseAccountTrustline; diff --git a/src/ledger/parse/amendment.ts b/src/ledger/parse/amendment.ts index 7c25cf75..01c22f74 100644 --- a/src/ledger/parse/amendment.ts +++ b/src/ledger/parse/amendment.ts @@ -1,7 +1,7 @@ function parseAmendment(tx: any) { return { - amendment: tx.Amendment - } + amendment: tx.Amendment, + }; } -export default parseAmendment +export default parseAmendment; diff --git a/src/ledger/parse/amount.ts b/src/ledger/parse/amount.ts index f8d696b9..91f853d3 100644 --- a/src/ledger/parse/amount.ts +++ b/src/ledger/parse/amount.ts @@ -1,18 +1,18 @@ -import {Amount, RippledAmount} from '../../common/types/objects' -import {dropsToXrp} from '../../utils' +import { Amount, RippledAmount } from "../../common/types/objects"; +import { dropsToXrp } from "../../utils"; function parseAmount(amount: RippledAmount): Amount { - if (typeof amount === 'string') { + if (typeof amount === "string") { return { - currency: 'XRP', - value: dropsToXrp(amount) - } + currency: "XRP", + value: dropsToXrp(amount), + }; } return { currency: amount.currency, value: amount.value, - counterparty: amount.issuer - } + counterparty: amount.issuer, + }; } -export default parseAmount +export default parseAmount; diff --git a/src/ledger/parse/cancellation.ts b/src/ledger/parse/cancellation.ts index 3fbff8f8..f94238ea 100644 --- a/src/ledger/parse/cancellation.ts +++ b/src/ledger/parse/cancellation.ts @@ -1,12 +1,13 @@ -import * as assert from 'assert' -import {parseMemos} from './utils' +import * as assert from "assert"; + +import { parseMemos } from "./utils"; function parseOrderCancellation(tx: any): object { - assert.ok(tx.TransactionType === 'OfferCancel') + assert.ok(tx.TransactionType === "OfferCancel"); return { memos: parseMemos(tx), - orderSequence: tx.OfferSequence - } + orderSequence: tx.OfferSequence, + }; } -export default parseOrderCancellation +export default parseOrderCancellation; diff --git a/src/ledger/parse/check-cancel.ts b/src/ledger/parse/check-cancel.ts index 81c18a22..3f357fb4 100644 --- a/src/ledger/parse/check-cancel.ts +++ b/src/ledger/parse/check-cancel.ts @@ -1,19 +1,21 @@ -import * as assert from 'assert' -import {removeUndefined} from '../../utils' -import {parseMemos} from './utils' +import * as assert from "assert"; -export type FormattedCheckCancel = { +import { removeUndefined } from "../../utils"; + +import { parseMemos } from "./utils"; + +export interface FormattedCheckCancel { // ID of the Check ledger object to cancel. - checkID: string + checkID: string; } function parseCheckCancel(tx: any): FormattedCheckCancel { - assert.ok(tx.TransactionType === 'CheckCancel') + assert.ok(tx.TransactionType === "CheckCancel"); return removeUndefined({ memos: parseMemos(tx), - checkID: tx.CheckID - }) + checkID: tx.CheckID, + }); } -export default parseCheckCancel +export default parseCheckCancel; diff --git a/src/ledger/parse/check-cash.ts b/src/ledger/parse/check-cash.ts index 0bf83c7e..43da3823 100644 --- a/src/ledger/parse/check-cash.ts +++ b/src/ledger/parse/check-cash.ts @@ -1,36 +1,38 @@ -import * as assert from 'assert' -import {removeUndefined} from '../../utils' -import parseAmount from './amount' -import {Amount} from '../../common/types/objects' -import {parseMemos} from './utils' +import * as assert from "assert"; -export type FormattedCheckCash = { +import { Amount } from "../../common/types/objects"; +import { removeUndefined } from "../../utils"; + +import parseAmount from "./amount"; +import { parseMemos } from "./utils"; + +export interface FormattedCheckCash { // ID of the Check ledger object to cash. - checkID: string + checkID: string; // (Optional) redeem the Check for exactly this amount, if possible. // The currency must match that of the `SendMax` of the corresponding // `CheckCreate` transaction. - amount: Amount + amount: Amount; // (Optional) redeem the Check for at least this amount and // for as much as possible. // The currency must match that of the `SendMax` of the corresponding // `CheckCreate` transaction. - deliverMin: Amount + deliverMin: Amount; // *must* include either Amount or DeliverMin, but not both. } function parseCheckCash(tx: any): FormattedCheckCash { - assert.ok(tx.TransactionType === 'CheckCash') + assert.ok(tx.TransactionType === "CheckCash"); return removeUndefined({ memos: parseMemos(tx), checkID: tx.CheckID, amount: tx.Amount && parseAmount(tx.Amount), - deliverMin: tx.DeliverMin && parseAmount(tx.DeliverMin) - }) + deliverMin: tx.DeliverMin && parseAmount(tx.DeliverMin), + }); } -export default parseCheckCash +export default parseCheckCash; diff --git a/src/ledger/parse/check-create.ts b/src/ledger/parse/check-create.ts index afecf78a..e7cc606c 100644 --- a/src/ledger/parse/check-create.ts +++ b/src/ledger/parse/check-create.ts @@ -1,30 +1,31 @@ -import * as assert from 'assert' -import {parseTimestamp} from './utils' -import {removeUndefined} from '../../utils' -import parseAmount from './amount' -import {Amount} from '../../common/types/objects' -import {parseMemos} from './utils' +import * as assert from "assert"; -export type FormattedCheckCreate = { +import { Amount } from "../../common/types/objects"; +import { removeUndefined } from "../../utils"; + +import parseAmount from "./amount"; +import { parseTimestamp, parseMemos } from "./utils"; + +export interface FormattedCheckCreate { // account that can cash the check. - destination: string + destination: string; // amount the check is allowed to debit the sender, // including transfer fees on non-XRP currencies. - sendMax: Amount + sendMax: Amount; // (Optional) identifies the reason for the check, or a hosted recipient. - destinationTag?: string + destinationTag?: string; // (Optional) time in seconds since the Ripple Epoch. - expiration?: string + expiration?: string; // (Optional) 256-bit hash representing a specific reason or identifier. - invoiceID?: string + invoiceID?: string; } function parseCheckCreate(tx: any): FormattedCheckCreate { - assert.ok(tx.TransactionType === 'CheckCreate') + assert.ok(tx.TransactionType === "CheckCreate"); return removeUndefined({ memos: parseMemos(tx), @@ -32,8 +33,8 @@ function parseCheckCreate(tx: any): FormattedCheckCreate { sendMax: parseAmount(tx.SendMax), destinationTag: tx.DestinationTag, expiration: tx.Expiration && parseTimestamp(tx.Expiration), - invoiceID: tx.InvoiceID - }) + invoiceID: tx.InvoiceID, + }); } -export default parseCheckCreate +export default parseCheckCreate; diff --git a/src/ledger/parse/deposit-preauth.ts b/src/ledger/parse/deposit-preauth.ts index 890033f5..680b26c8 100644 --- a/src/ledger/parse/deposit-preauth.ts +++ b/src/ledger/parse/deposit-preauth.ts @@ -1,23 +1,25 @@ -import * as assert from 'assert' -import {removeUndefined} from '../../utils' -import {parseMemos} from './utils' +import * as assert from "assert"; -export type FormattedDepositPreauth = { +import { removeUndefined } from "../../utils"; + +import { parseMemos } from "./utils"; + +export interface FormattedDepositPreauth { // account (address) of the sender to preauthorize - authorize: string + authorize: string; // account (address) of the sender whose preauthorization should be revoked - unauthorize: string + unauthorize: string; } function parseDepositPreauth(tx: any): FormattedDepositPreauth { - assert.ok(tx.TransactionType === 'DepositPreauth') + assert.ok(tx.TransactionType === "DepositPreauth"); return removeUndefined({ memos: parseMemos(tx), authorize: tx.Authorize, - unauthorize: tx.Unauthorize - }) + unauthorize: tx.Unauthorize, + }); } -export default parseDepositPreauth +export default parseDepositPreauth; diff --git a/src/ledger/parse/escrow-cancellation.ts b/src/ledger/parse/escrow-cancellation.ts index 1db6d589..c21a15ae 100644 --- a/src/ledger/parse/escrow-cancellation.ts +++ b/src/ledger/parse/escrow-cancellation.ts @@ -1,15 +1,17 @@ -import * as assert from 'assert' -import {parseMemos} from './utils' -import {removeUndefined} from '../../utils' +import * as assert from "assert"; + +import { removeUndefined } from "../../utils"; + +import { parseMemos } from "./utils"; function parseEscrowCancellation(tx: any): object { - assert.ok(tx.TransactionType === 'EscrowCancel') + assert.ok(tx.TransactionType === "EscrowCancel"); return removeUndefined({ memos: parseMemos(tx), owner: tx.Owner, - escrowSequence: tx.OfferSequence - }) + escrowSequence: tx.OfferSequence, + }); } -export default parseEscrowCancellation +export default parseEscrowCancellation; diff --git a/src/ledger/parse/escrow-creation.ts b/src/ledger/parse/escrow-creation.ts index b14a6894..f1cb839a 100644 --- a/src/ledger/parse/escrow-creation.ts +++ b/src/ledger/parse/escrow-creation.ts @@ -1,10 +1,12 @@ -import * as assert from 'assert' -import parseAmount from './amount' -import {parseTimestamp, parseMemos} from './utils' -import {removeUndefined} from '../../utils' +import * as assert from "assert"; + +import { removeUndefined } from "../../utils"; + +import parseAmount from "./amount"; +import { parseTimestamp, parseMemos } from "./utils"; function parseEscrowCreation(tx: any): object { - assert.ok(tx.TransactionType === 'EscrowCreate') + assert.ok(tx.TransactionType === "EscrowCreate"); return removeUndefined({ amount: parseAmount(tx.Amount).value, @@ -14,8 +16,8 @@ function parseEscrowCreation(tx: any): object { allowCancelAfter: parseTimestamp(tx.CancelAfter), allowExecuteAfter: parseTimestamp(tx.FinishAfter), sourceTag: tx.SourceTag, - destinationTag: tx.DestinationTag - }) + destinationTag: tx.DestinationTag, + }); } -export default parseEscrowCreation +export default parseEscrowCreation; diff --git a/src/ledger/parse/escrow-execution.ts b/src/ledger/parse/escrow-execution.ts index 2c2bf737..fedecdb9 100644 --- a/src/ledger/parse/escrow-execution.ts +++ b/src/ledger/parse/escrow-execution.ts @@ -1,17 +1,19 @@ -import * as assert from 'assert' -import {parseMemos} from './utils' -import {removeUndefined} from '../../utils' +import * as assert from "assert"; + +import { removeUndefined } from "../../utils"; + +import { parseMemos } from "./utils"; function parseEscrowExecution(tx: any): object { - assert.ok(tx.TransactionType === 'EscrowFinish') + assert.ok(tx.TransactionType === "EscrowFinish"); return removeUndefined({ memos: parseMemos(tx), owner: tx.Owner, escrowSequence: tx.OfferSequence, condition: tx.Condition, - fulfillment: tx.Fulfillment - }) + fulfillment: tx.Fulfillment, + }); } -export default parseEscrowExecution +export default parseEscrowExecution; diff --git a/src/ledger/parse/fee-update.ts b/src/ledger/parse/fee-update.ts index 7bf9e8a8..88937729 100644 --- a/src/ledger/parse/fee-update.ts +++ b/src/ledger/parse/fee-update.ts @@ -1,16 +1,18 @@ -import BigNumber from 'bignumber.js' -import {dropsToXrp} from '../../utils' -import {parseMemos} from './utils' +import BigNumber from "bignumber.js"; + +import { dropsToXrp } from "../../utils"; + +import { parseMemos } from "./utils"; function parseFeeUpdate(tx: any) { - const baseFeeDrops = new BigNumber(tx.BaseFee, 16).toString() + const baseFeeDrops = new BigNumber(tx.BaseFee, 16).toString(); return { memos: parseMemos(tx), baseFeeXRP: dropsToXrp(baseFeeDrops), referenceFeeUnits: tx.ReferenceFeeUnits, reserveBaseXRP: dropsToXrp(tx.ReserveBase), - reserveIncrementXRP: dropsToXrp(tx.ReserveIncrement) - } + reserveIncrementXRP: dropsToXrp(tx.ReserveIncrement), + }; } -export default parseFeeUpdate +export default parseFeeUpdate; diff --git a/src/ledger/parse/fields.ts b/src/ledger/parse/fields.ts index 05ec3130..cf01c8b1 100644 --- a/src/ledger/parse/fields.ts +++ b/src/ledger/parse/fields.ts @@ -1,52 +1,54 @@ -import _ from 'lodash' -import BigNumber from 'bignumber.js' -import {constants} from '../../common' -const AccountFields = constants.AccountFields +import BigNumber from "bignumber.js"; +import _ from "lodash"; + +import { constants } from "../../common"; + +const AccountFields = constants.AccountFields; function parseField(info, value) { - if (info.encoding === 'hex' && !info.length) { + if (info.encoding === "hex" && !info.length) { // e.g. "domain" - return Buffer.from(value, 'hex').toString('ascii') + return Buffer.from(value, "hex").toString("ascii"); } if (info.shift) { - return new BigNumber(value).shiftedBy(-info.shift).toNumber() + return new BigNumber(value).shiftedBy(-info.shift).toNumber(); } - return value + return value; } function parseFields(data: any): object { - const settings: any = {} + const settings: any = {}; for (const fieldName in AccountFields) { - const fieldValue = data[fieldName] + const fieldValue = data[fieldName]; if (fieldValue != null) { - const info = AccountFields[fieldName] - settings[info.name] = parseField(info, fieldValue) + const info = AccountFields[fieldName]; + settings[info.name] = parseField(info, fieldValue); } } if (data.RegularKey) { - settings.regularKey = data.RegularKey + settings.regularKey = data.RegularKey; } // Since an account can own at most one SignerList, // this array must have exactly one member if it is present. if (data.signer_lists && data.signer_lists.length === 1) { - settings.signers = {} + settings.signers = {}; if (data.signer_lists[0].SignerQuorum) { - settings.signers.threshold = data.signer_lists[0].SignerQuorum + settings.signers.threshold = data.signer_lists[0].SignerQuorum; } if (data.signer_lists[0].SignerEntries) { settings.signers.weights = data.signer_lists[0].SignerEntries.map( (entry: any) => { return { address: entry.SignerEntry.Account, - weight: entry.SignerEntry.SignerWeight - } + weight: entry.SignerEntry.SignerWeight, + }; } - ) + ); } } - return settings + return settings; } -export default parseFields +export default parseFields; diff --git a/src/ledger/parse/flags.ts b/src/ledger/parse/flags.ts index b6bd69af..ed9a14f3 100644 --- a/src/ledger/parse/flags.ts +++ b/src/ledger/parse/flags.ts @@ -1,7 +1,7 @@ const orderFlags = { Passive: 0x00010000, - Sell: 0x00020000 // offer was placed as a sell -} + Sell: 0x00020000, // offer was placed as a sell +}; const trustlineFlags = { LowReserve: 0x00010000, // entry counts toward reserve @@ -11,7 +11,7 @@ const trustlineFlags = { LowNoRipple: 0x00100000, HighNoRipple: 0x00200000, LowFreeze: 0x00400000, - HighFreeze: 0x00800000 -} + HighFreeze: 0x00800000, +}; -export {orderFlags, trustlineFlags} +export { orderFlags, trustlineFlags }; diff --git a/src/ledger/parse/ledger.ts b/src/ledger/parse/ledger.ts index 298f06d9..3218510f 100644 --- a/src/ledger/parse/ledger.ts +++ b/src/ledger/parse/ledger.ts @@ -1,87 +1,92 @@ -import _ from 'lodash' -import {removeUndefined, rippleTimeToISOTime} from '../../utils' -import parseTransaction from './transaction' -import { TransactionAndMetadata } from '../../models/transactions' +import _ from "lodash"; -export type FormattedLedger = { +import { TransactionAndMetadata } from "../../models/transactions"; +import { removeUndefined, rippleTimeToISOTime } from "../../utils"; + +import parseTransaction from "./transaction"; + +export interface FormattedLedger { // TODO: properties in type don't match response object. Fix! // closed: boolean, - stateHash: string - closeTime: string - closeTimeResolution: number - closeFlags: number - ledgerHash: string - ledgerVersion: number - parentLedgerHash: string - parentCloseTime: string - totalDrops: string - transactionHash: string - transactions?: Array - transactionHashes?: Array - rawState?: string - stateHashes?: Array + stateHash: string; + closeTime: string; + closeTimeResolution: number; + closeFlags: number; + ledgerHash: string; + ledgerVersion: number; + parentLedgerHash: string; + parentCloseTime: string; + totalDrops: string; + transactionHash: string; + transactions?: object[]; + transactionHashes?: string[]; + rawState?: string; + stateHashes?: string[]; } -function parseTransactionWrapper(ledgerVersion: number, tx: TransactionAndMetadata) { +function parseTransactionWrapper( + ledgerVersion: number, + tx: TransactionAndMetadata +) { // renames metaData to meta and adds ledger_index - const transaction = Object.assign({}, _.omit(tx, 'metadata'), { + const transaction = { + ..._.omit(tx, "metadata"), meta: tx.metadata, - ledger_index: ledgerVersion - }) - const result = parseTransaction(transaction, true) + ledger_index: ledgerVersion, + }; + const result = parseTransaction(transaction, true); if (!result.outcome.ledgerVersion) { - result.outcome.ledgerVersion = ledgerVersion + result.outcome.ledgerVersion = ledgerVersion; } - return result + return result; } -function parseTransactions(transactions: string[] | TransactionAndMetadata[], ledgerVersion: number) { +function parseTransactions( + transactions: string[] | TransactionAndMetadata[], + ledgerVersion: number +) { if (_.isEmpty(transactions)) { - return {} + return {}; } - if (typeof transactions[0] === 'string') { - return {transactionHashes: transactions as unknown as string[]} + if (typeof transactions[0] === "string") { + return { transactionHashes: transactions as unknown as string[] }; } return { transactions: (transactions as unknown as TransactionAndMetadata[]).map( _.partial(parseTransactionWrapper, ledgerVersion) - ) - } + ), + }; } function parseState(state) { if (_.isEmpty(state)) { - return {} + return {}; } - if (typeof state[0] === 'string') { - return {stateHashes: state} + if (typeof state[0] === "string") { + return { stateHashes: state }; } - return {rawState: JSON.stringify(state)} + return { rawState: JSON.stringify(state) }; } /** - * @param {Ledger} ledger must be a *closed* ledger with valid `close_time` and `parent_close_time` - * @returns {FormattedLedger} formatted ledger - * @throws RangeError: Invalid time value (rippleTimeToISOTime) + * @param ledger - Must be a *closed* ledger with valid `close_time` and `parent_close_time`. + * @returns Formatted ledger. + * @throws RangeError: Invalid time value (rippleTimeToISOTime). */ export function parseLedger(ledger): FormattedLedger { - const ledgerVersion = parseInt(ledger.ledger_index, 10) - return removeUndefined( - Object.assign( - { - stateHash: ledger.account_hash, - closeTime: rippleTimeToISOTime(ledger.close_time), - closeTimeResolution: ledger.close_time_resolution, - closeFlags: ledger.close_flags, - ledgerHash: ledger.ledger_hash, - ledgerVersion: ledgerVersion, - parentLedgerHash: ledger.parent_hash, - parentCloseTime: rippleTimeToISOTime(ledger.parent_close_time), - totalDrops: ledger.total_coins, - transactionHash: ledger.transaction_hash - }, - parseTransactions(ledger.transactions, ledgerVersion), - parseState(ledger.accountState) - ) - ) + const ledgerVersion = parseInt(ledger.ledger_index, 10); + return removeUndefined({ + stateHash: ledger.account_hash, + closeTime: rippleTimeToISOTime(ledger.close_time), + closeTimeResolution: ledger.close_time_resolution, + closeFlags: ledger.close_flags, + ledgerHash: ledger.ledger_hash, + ledgerVersion, + parentLedgerHash: ledger.parent_hash, + parentCloseTime: rippleTimeToISOTime(ledger.parent_close_time), + totalDrops: ledger.total_coins, + transactionHash: ledger.transaction_hash, + ...parseTransactions(ledger.transactions, ledgerVersion), + ...parseState(ledger.accountState), + }); } diff --git a/src/ledger/parse/order.ts b/src/ledger/parse/order.ts index 82ffd985..1f5e29c6 100644 --- a/src/ledger/parse/order.ts +++ b/src/ledger/parse/order.ts @@ -1,35 +1,36 @@ -import * as assert from 'assert' -import {parseTimestamp} from './utils' -import {parseMemos} from './utils' -import parseAmount from './amount' -import {removeUndefined} from '../../utils' -import {txFlags} from '../../common' +import * as assert from "assert"; + +import { txFlags } from "../../common"; import { FormattedOrderSpecification, - OfferCreateTransaction -} from '../../common/types/objects/index' + OfferCreateTransaction, +} from "../../common/types/objects/index"; +import { removeUndefined } from "../../utils"; -const flags = txFlags.OfferCreate +import parseAmount from "./amount"; +import { parseTimestamp, parseMemos } from "./utils"; + +const flags = txFlags.OfferCreate; function parseOrder(tx: OfferCreateTransaction): FormattedOrderSpecification { - assert.ok(tx.TransactionType === 'OfferCreate') + assert.ok(tx.TransactionType === "OfferCreate"); - const direction = (tx.Flags & flags.Sell) === 0 ? 'buy' : 'sell' - const takerGetsAmount = parseAmount(tx.TakerGets) - const takerPaysAmount = parseAmount(tx.TakerPays) - const quantity = direction === 'buy' ? takerPaysAmount : takerGetsAmount - const totalPrice = direction === 'buy' ? takerGetsAmount : takerPaysAmount + const direction = (tx.Flags & flags.Sell) === 0 ? "buy" : "sell"; + const takerGetsAmount = parseAmount(tx.TakerGets); + const takerPaysAmount = parseAmount(tx.TakerPays); + const quantity = direction === "buy" ? takerPaysAmount : takerGetsAmount; + const totalPrice = direction === "buy" ? takerGetsAmount : takerPaysAmount; return removeUndefined({ memos: parseMemos(tx), - direction: direction, - quantity: quantity, - totalPrice: totalPrice, + direction, + quantity, + totalPrice, passive: (tx.Flags & flags.Passive) !== 0 || undefined, immediateOrCancel: (tx.Flags & flags.ImmediateOrCancel) !== 0 || undefined, fillOrKill: (tx.Flags & flags.FillOrKill) !== 0 || undefined, - expirationTime: parseTimestamp(tx.Expiration) - }) + expirationTime: parseTimestamp(tx.Expiration), + }); } -export default parseOrder +export default parseOrder; diff --git a/src/ledger/parse/orderbook-order.ts b/src/ledger/parse/orderbook-order.ts index 9f0b5738..15a1b078 100644 --- a/src/ledger/parse/orderbook-order.ts +++ b/src/ledger/parse/orderbook-order.ts @@ -1,42 +1,50 @@ -import _ from 'lodash' -import {parseTimestamp, adjustQualityForXRP} from './utils' -import {removeUndefined} from '../../utils' +import _ from "lodash"; -import {orderFlags} from './flags' -import parseAmount from './amount' -import {BookOffer} from '../../common/types/commands' -import {Amount, FormattedOrderSpecification} from '../../common/types/objects' +import { BookOffer } from "../../common/types/commands"; +import { + Amount, + FormattedOrderSpecification, +} from "../../common/types/objects"; +import { removeUndefined } from "../../utils"; -export type FormattedOrderbookOrder = { - specification: FormattedOrderSpecification +import parseAmount from "./amount"; +import { orderFlags } from "./flags"; +import { parseTimestamp, adjustQualityForXRP } from "./utils"; + +export interface FormattedOrderbookOrder { + specification: FormattedOrderSpecification; properties: { - maker: string - sequence: number - makerExchangeRate: string - } + maker: string; + sequence: number; + makerExchangeRate: string; + }; state?: { - fundedAmount: Amount - priceOfFundedAmount: Amount - } - data: BookOffer + fundedAmount: Amount; + priceOfFundedAmount: Amount; + }; + data: BookOffer; } export function parseOrderbookOrder(data: BookOffer): FormattedOrderbookOrder { - const direction = (data.Flags & orderFlags.Sell) === 0 ? 'buy' : 'sell' - const takerGetsAmount = parseAmount(data.TakerGets) - const takerPaysAmount = parseAmount(data.TakerPays) - const quantity = direction === 'buy' ? takerPaysAmount : takerGetsAmount - const totalPrice = direction === 'buy' ? takerGetsAmount : takerPaysAmount + const direction = (data.Flags & orderFlags.Sell) === 0 ? "buy" : "sell"; + const takerGetsAmount = parseAmount(data.TakerGets); + const takerPaysAmount = parseAmount(data.TakerPays); + const quantity = direction === "buy" ? takerPaysAmount : takerGetsAmount; + const totalPrice = direction === "buy" ? takerGetsAmount : takerPaysAmount; // note: immediateOrCancel and fillOrKill orders cannot enter the order book // so we can omit those flags here const specification: FormattedOrderSpecification = removeUndefined({ - direction: direction, - quantity: quantity, - totalPrice: totalPrice, + direction, + quantity, + totalPrice, passive: (data.Flags & orderFlags.Passive) !== 0 || undefined, - expirationTime: parseTimestamp(data.Expiration) - }) + expirationTime: parseTimestamp(data.Expiration), + }); + + if (data.quality == null) { + throw new Error("parseOrderBookOrder: Could not find quality"); + } const properties = { maker: data.Account, @@ -45,19 +53,25 @@ export function parseOrderbookOrder(data: BookOffer): FormattedOrderbookOrder { data.quality, takerGetsAmount.currency, takerPaysAmount.currency - ) - } + ), + }; const takerGetsFunded = data.taker_gets_funded ? parseAmount(data.taker_gets_funded) - : undefined + : undefined; const takerPaysFunded = data.taker_pays_funded ? parseAmount(data.taker_pays_funded) - : undefined + : undefined; const available = removeUndefined({ fundedAmount: takerGetsFunded, - priceOfFundedAmount: takerPaysFunded - }) - const state = _.isEmpty(available) ? undefined : available - return removeUndefined({specification, properties, state, data}) + priceOfFundedAmount: takerPaysFunded, + }); + const state = _.isEmpty(available) ? undefined : available; + + return removeUndefined({ + specification, + properties, + state, + data, + }) as FormattedOrderbookOrder; } diff --git a/src/ledger/parse/pathfind.ts b/src/ledger/parse/pathfind.ts index 0320389a..f00be559 100644 --- a/src/ledger/parse/pathfind.ts +++ b/src/ledger/parse/pathfind.ts @@ -1,31 +1,33 @@ -import _ from 'lodash' -import parseAmount from './amount' -import {Amount, RippledAmount} from '../../common/types/objects' -import {Path, GetPaths, RippledPathsResponse} from '../pathfind-types' +import _ from "lodash"; + +import { Amount, RippledAmount } from "../../common/types/objects"; +import { Path, GetPaths, RippledPathsResponse } from "../pathfind-types"; + +import parseAmount from "./amount"; function parsePaths(paths) { return paths.map((steps) => - steps.map((step) => _.omit(step, ['type', 'type_hex'])) - ) + steps.map((step) => _.omit(step, ["type", "type_hex"])) + ); } function removeAnyCounterpartyEncoding(address: string, amount: Amount) { return amount.counterparty === address - ? _.omit(amount, 'counterparty') - : amount + ? _.omit(amount, "counterparty") + : amount; } function createAdjustment( address: string, adjustmentWithoutAddress: object ): any { - const amountKey = Object.keys(adjustmentWithoutAddress)[0] - const amount = adjustmentWithoutAddress[amountKey] + const amountKey = Object.keys(adjustmentWithoutAddress)[0]; + const amount = adjustmentWithoutAddress[amountKey]; return _.set( - {address: address}, + { address }, amountKey, removeAnyCounterpartyEncoding(address, amount) - ) + ); } function parseAlternative( @@ -39,28 +41,30 @@ function parseAlternative( const amounts = alternative.destination_amount != null ? { - source: {amount: parseAmount(alternative.source_amount)}, - destination: {minAmount: parseAmount(alternative.destination_amount)} + source: { amount: parseAmount(alternative.source_amount) }, + destination: { + minAmount: parseAmount(alternative.destination_amount), + }, } : { - source: {maxAmount: parseAmount(alternative.source_amount)}, - destination: {amount: parseAmount(destinationAmount)} - } + source: { maxAmount: parseAmount(alternative.source_amount) }, + destination: { amount: parseAmount(destinationAmount) }, + }; return { source: createAdjustment(sourceAddress, amounts.source), destination: createAdjustment(destinationAddress, amounts.destination), - paths: JSON.stringify(parsePaths(alternative.paths_computed)) - } + paths: JSON.stringify(parsePaths(alternative.paths_computed)), + }; } function parsePathfind(pathfindResult: RippledPathsResponse): GetPaths { - const sourceAddress = pathfindResult.source_account - const destinationAddress = pathfindResult.destination_account - const destinationAmount = pathfindResult.destination_amount + const sourceAddress = pathfindResult.source_account; + const destinationAddress = pathfindResult.destination_account; + const destinationAmount = pathfindResult.destination_amount; return pathfindResult.alternatives.map((alt) => parseAlternative(sourceAddress, destinationAddress, destinationAmount, alt) - ) + ); } -export default parsePathfind +export default parsePathfind; diff --git a/src/ledger/parse/payment-channel-claim.ts b/src/ledger/parse/payment-channel-claim.ts index 22175f9f..8a185937 100644 --- a/src/ledger/parse/payment-channel-claim.ts +++ b/src/ledger/parse/payment-channel-claim.ts @@ -1,12 +1,15 @@ -import * as assert from 'assert' -import {removeUndefined} from '../../utils' -import {txFlags} from '../../common' -import parseAmount from './amount' -import {parseMemos} from './utils' -const claimFlags = txFlags.PaymentChannelClaim +import * as assert from "assert"; + +import { txFlags } from "../../common"; +import { removeUndefined } from "../../utils"; + +import parseAmount from "./amount"; +import { parseMemos } from "./utils"; + +const claimFlags = txFlags.PaymentChannelClaim; function parsePaymentChannelClaim(tx: any): object { - assert.ok(tx.TransactionType === 'PaymentChannelClaim') + assert.ok(tx.TransactionType === "PaymentChannelClaim"); return removeUndefined({ memos: parseMemos(tx), @@ -16,8 +19,8 @@ function parsePaymentChannelClaim(tx: any): object { signature: tx.Signature, publicKey: tx.PublicKey, renew: Boolean(tx.Flags & claimFlags.Renew) || undefined, - close: Boolean(tx.Flags & claimFlags.Close) || undefined - }) + close: Boolean(tx.Flags & claimFlags.Close) || undefined, + }); } -export default parsePaymentChannelClaim +export default parsePaymentChannelClaim; diff --git a/src/ledger/parse/payment-channel-create.ts b/src/ledger/parse/payment-channel-create.ts index 08caf67f..95413838 100644 --- a/src/ledger/parse/payment-channel-create.ts +++ b/src/ledger/parse/payment-channel-create.ts @@ -1,10 +1,12 @@ -import * as assert from 'assert' -import {parseTimestamp,parseMemos} from './utils' -import {removeUndefined} from '../../utils' -import parseAmount from './amount' +import * as assert from "assert"; + +import { removeUndefined } from "../../utils"; + +import parseAmount from "./amount"; +import { parseTimestamp, parseMemos } from "./utils"; function parsePaymentChannelCreate(tx: any): object { - assert.ok(tx.TransactionType === 'PaymentChannelCreate') + assert.ok(tx.TransactionType === "PaymentChannelCreate"); return removeUndefined({ memos: parseMemos(tx), @@ -14,8 +16,8 @@ function parsePaymentChannelCreate(tx: any): object { publicKey: tx.PublicKey, cancelAfter: tx.CancelAfter && parseTimestamp(tx.CancelAfter), sourceTag: tx.SourceTag, - destinationTag: tx.DestinationTag - }) + destinationTag: tx.DestinationTag, + }); } -export default parsePaymentChannelCreate +export default parsePaymentChannelCreate; diff --git a/src/ledger/parse/payment-channel-fund.ts b/src/ledger/parse/payment-channel-fund.ts index ef371bb5..92720291 100644 --- a/src/ledger/parse/payment-channel-fund.ts +++ b/src/ledger/parse/payment-channel-fund.ts @@ -1,17 +1,19 @@ -import * as assert from 'assert' -import {parseTimestamp,parseMemos} from './utils' -import {removeUndefined} from '../../utils' -import parseAmount from './amount' +import * as assert from "assert"; + +import { removeUndefined } from "../../utils"; + +import parseAmount from "./amount"; +import { parseTimestamp, parseMemos } from "./utils"; function parsePaymentChannelFund(tx: any): object { - assert.ok(tx.TransactionType === 'PaymentChannelFund') + assert.ok(tx.TransactionType === "PaymentChannelFund"); return removeUndefined({ memos: parseMemos(tx), channel: tx.Channel, amount: parseAmount(tx.Amount).value, - expiration: tx.Expiration && parseTimestamp(tx.Expiration) - }) + expiration: tx.Expiration && parseTimestamp(tx.Expiration), + }); } -export default parsePaymentChannelFund +export default parsePaymentChannelFund; diff --git a/src/ledger/parse/payment-channel.ts b/src/ledger/parse/payment-channel.ts index 92b79d5e..c02cd141 100644 --- a/src/ledger/parse/payment-channel.ts +++ b/src/ledger/parse/payment-channel.ts @@ -1,25 +1,24 @@ -import {parseTimestamp, parseMemos} from './utils' -import {removeUndefined, dropsToXrp} from '../../utils' -import { PayChannel } from '../../models/ledger' +import { PayChannel } from "../../models/ledger"; +import { removeUndefined, dropsToXrp } from "../../utils"; -export type FormattedPaymentChannel = { - account: string - amount: string - balance: string - publicKey: string - destination: string - settleDelay: number - expiration?: string - cancelAfter?: string - sourceTag?: number - destinationTag?: number - previousAffectingTransactionID: string - previousAffectingTransactionLedgerVersion: number +import { parseTimestamp, parseMemos } from "./utils"; + +export interface FormattedPaymentChannel { + account: string; + amount: string; + balance: string; + publicKey: string; + destination: string; + settleDelay: number; + expiration?: string; + cancelAfter?: string; + sourceTag?: number; + destinationTag?: number; + previousAffectingTransactionID: string; + previousAffectingTransactionLedgerVersion: number; } -export function parsePaymentChannel( - data: PayChannel -): FormattedPaymentChannel { +export function parsePaymentChannel(data: PayChannel): FormattedPaymentChannel { return removeUndefined({ memos: parseMemos(data), account: data.Account, @@ -33,6 +32,6 @@ export function parsePaymentChannel( sourceTag: data.SourceTag, destinationTag: data.DestinationTag, previousAffectingTransactionID: data.PreviousTxnID, - previousAffectingTransactionLedgerVersion: data.PreviousTxnLgrSeq - }) + previousAffectingTransactionLedgerVersion: data.PreviousTxnLgrSeq, + }); } diff --git a/src/ledger/parse/payment.ts b/src/ledger/parse/payment.ts index 015c7f7a..a48e0a5e 100644 --- a/src/ledger/parse/payment.ts +++ b/src/ledger/parse/payment.ts @@ -1,27 +1,30 @@ -import _ from 'lodash' -import * as assert from 'assert' -import * as utils from './utils' -import {txFlags} from '../../common' -import {removeUndefined} from '../../utils' -import parseAmount from './amount' +import * as assert from "assert"; + +import _ from "lodash"; + +import { txFlags } from "../../common"; +import { removeUndefined } from "../../utils"; + +import parseAmount from "./amount"; +import * as utils from "./utils"; function isNoDirectRipple(tx) { - return (tx.Flags & txFlags.Payment.NoRippleDirect) !== 0 + return (tx.Flags & txFlags.Payment.NoRippleDirect) !== 0; } function isQualityLimited(tx) { - return (tx.Flags & txFlags.Payment.LimitQuality) !== 0 + return (tx.Flags & txFlags.Payment.LimitQuality) !== 0; } function removeGenericCounterparty(amount, address) { return amount.counterparty === address - ? _.omit(amount, 'counterparty') - : amount + ? _.omit(amount, "counterparty") + : amount; } // Payment specification function parsePayment(tx: any): object { - assert.ok(tx.TransactionType === 'Payment') + assert.ok(tx.TransactionType === "Payment"); const source = { address: tx.Account, @@ -29,17 +32,17 @@ function parsePayment(tx: any): object { parseAmount(tx.SendMax || tx.Amount), tx.Account ), - tag: tx.SourceTag - } + tag: tx.SourceTag, + }; const destination: { - address: string - tag: number | undefined + address: string; + tag: number | undefined; } = { address: tx.Destination, - tag: tx.DestinationTag + tag: tx.DestinationTag, // Notice that `amount` is omitted to prevent misinterpretation - } + }; return removeUndefined({ source: removeUndefined(source), @@ -49,8 +52,8 @@ function parsePayment(tx: any): object { paths: tx.Paths ? JSON.stringify(tx.Paths) : undefined, allowPartialPayment: utils.isPartialPayment(tx) || undefined, noDirectRipple: isNoDirectRipple(tx) || undefined, - limitQuality: isQualityLimited(tx) || undefined - }) + limitQuality: isQualityLimited(tx) || undefined, + }); } -export default parsePayment +export default parsePayment; diff --git a/src/ledger/parse/settings.ts b/src/ledger/parse/settings.ts index 6cba47f7..da99b8b1 100644 --- a/src/ledger/parse/settings.ts +++ b/src/ledger/parse/settings.ts @@ -1,65 +1,69 @@ -import _ from 'lodash' -import * as assert from 'assert' -import {constants} from '../../common' -const AccountFlags = constants.AccountFlags -import parseFields from './fields' +import * as assert from "assert"; + +import _ from "lodash"; + +import { constants } from "../../common"; + +import parseFields from "./fields"; + +const AccountFlags = constants.AccountFlags; function getAccountRootModifiedNode(tx: any) { const modifiedNodes = tx.meta.AffectedNodes.filter( - (node) => node.ModifiedNode.LedgerEntryType === 'AccountRoot' - ) - assert.ok(modifiedNodes.length === 1) - return modifiedNodes[0].ModifiedNode + (node) => node.ModifiedNode.LedgerEntryType === "AccountRoot" + ); + assert.ok(modifiedNodes.length === 1); + return modifiedNodes[0].ModifiedNode; } function parseFlags(tx: any): any { - const settings: any = {} - if (tx.TransactionType !== 'AccountSet') { - return settings + const settings: any = {}; + if (tx.TransactionType !== "AccountSet") { + return settings; } - const node = getAccountRootModifiedNode(tx) - const oldFlags = _.get(node.PreviousFields, 'Flags') - const newFlags = _.get(node.FinalFields, 'Flags') + const node = getAccountRootModifiedNode(tx); + const oldFlags = _.get(node.PreviousFields, "Flags"); + const newFlags = _.get(node.FinalFields, "Flags"); if (oldFlags != null && newFlags != null) { - const changedFlags = oldFlags ^ newFlags - const setFlags = newFlags & changedFlags - const clearedFlags = oldFlags & changedFlags - Object.entries(AccountFlags).forEach(entry => { + const changedFlags = oldFlags ^ newFlags; + const setFlags = newFlags & changedFlags; + const clearedFlags = oldFlags & changedFlags; + Object.entries(AccountFlags).forEach((entry) => { const [flagName, flagValue] = entry; if (setFlags & flagValue) { - settings[flagName] = true + settings[flagName] = true; } else if (clearedFlags & flagValue) { - settings[flagName] = false + settings[flagName] = false; } - }) + }); } // enableTransactionIDTracking requires a special case because it // does not affect the Flags field; instead it adds/removes a field called // "AccountTxnID" to/from the account root. - const oldField = _.get(node.PreviousFields, 'AccountTxnID') - const newField = _.get(node.FinalFields, 'AccountTxnID') + const oldField = _.get(node.PreviousFields, "AccountTxnID"); + const newField = _.get(node.FinalFields, "AccountTxnID"); if (newField && !oldField) { - settings.enableTransactionIDTracking = true + settings.enableTransactionIDTracking = true; } else if (oldField && !newField) { - settings.enableTransactionIDTracking = false + settings.enableTransactionIDTracking = false; } - return settings + return settings; } function parseSettings(tx: any) { - const txType = tx.TransactionType + const txType = tx.TransactionType; assert.ok( - txType === 'AccountSet' || - txType === 'SetRegularKey' || - txType === 'SignerListSet' - ) + txType === "AccountSet" || + txType === "SetRegularKey" || + txType === "SignerListSet" + ); - return Object.assign({}, parseFlags(tx), parseFields(tx)) + return { ...parseFlags(tx), ...parseFields(tx) }; } -export default parseSettings +export default parseSettings; diff --git a/src/ledger/parse/ticket-create.ts b/src/ledger/parse/ticket-create.ts index c949ab45..b193e48f 100644 --- a/src/ledger/parse/ticket-create.ts +++ b/src/ledger/parse/ticket-create.ts @@ -1,13 +1,15 @@ -import * as assert from 'assert' -import {removeUndefined} from '../../utils' -import {parseMemos} from './utils' +import * as assert from "assert"; + +import { removeUndefined } from "../../utils"; + +import { parseMemos } from "./utils"; function parseTicketCreate(tx: any): object { - assert.ok(tx.TransactionType === 'TicketCreate') + assert.ok(tx.TransactionType === "TicketCreate"); return removeUndefined({ memos: parseMemos(tx), - ticketCount: tx.TicketCount - }) + ticketCount: tx.TicketCount, + }); } -export default parseTicketCreate +export default parseTicketCreate; diff --git a/src/ledger/parse/transaction.ts b/src/ledger/parse/transaction.ts index 557ac136..34292034 100644 --- a/src/ledger/parse/transaction.ts +++ b/src/ledger/parse/transaction.ts @@ -1,59 +1,58 @@ -import {parseOutcome} from './utils' -import {removeUndefined} from '../../utils' +import { removeUndefined } from "../../utils"; -import parseSettings from './settings' -import parseAccountDelete from './account-delete' -import parseCheckCancel from './check-cancel' -import parseCheckCash from './check-cash' -import parseCheckCreate from './check-create' -import parseDepositPreauth from './deposit-preauth' -import parseEscrowCancellation from './escrow-cancellation' -import parseEscrowCreation from './escrow-creation' -import parseEscrowExecution from './escrow-execution' -import parseOrderCancellation from './cancellation' -import parseOrder from './order' -import parsePayment from './payment' -import parsePaymentChannelClaim from './payment-channel-claim' -import parsePaymentChannelCreate from './payment-channel-create' -import parsePaymentChannelFund from './payment-channel-fund' -import parseTicketCreate from './ticket-create' -import parseTrustline from './trustline' - -import parseAmendment from './amendment' // pseudo-transaction -import parseFeeUpdate from './fee-update' // pseudo-transaction +import parseAccountDelete from "./account-delete"; +import parseAmendment from "./amendment"; // pseudo-transaction +import parseOrderCancellation from "./cancellation"; +import parseCheckCancel from "./check-cancel"; +import parseCheckCash from "./check-cash"; +import parseCheckCreate from "./check-create"; +import parseDepositPreauth from "./deposit-preauth"; +import parseEscrowCancellation from "./escrow-cancellation"; +import parseEscrowCreation from "./escrow-creation"; +import parseEscrowExecution from "./escrow-execution"; +import parseFeeUpdate from "./fee-update"; // pseudo-transaction +import parseOrder from "./order"; +import parsePayment from "./payment"; +import parsePaymentChannelClaim from "./payment-channel-claim"; +import parsePaymentChannelCreate from "./payment-channel-create"; +import parsePaymentChannelFund from "./payment-channel-fund"; +import parseSettings from "./settings"; +import parseTicketCreate from "./ticket-create"; +import parseTrustline from "./trustline"; +import { parseOutcome } from "./utils"; function parseTransactionType(type) { // Ordering matches https://developers.ripple.com/transaction-types.html const mapping = { - AccountSet: 'settings', - AccountDelete: 'accountDelete', - CheckCancel: 'checkCancel', - CheckCash: 'checkCash', - CheckCreate: 'checkCreate', - DepositPreauth: 'depositPreauth', - EscrowCancel: 'escrowCancellation', - EscrowCreate: 'escrowCreation', - EscrowFinish: 'escrowExecution', - OfferCancel: 'orderCancellation', - OfferCreate: 'order', - Payment: 'payment', - PaymentChannelClaim: 'paymentChannelClaim', - PaymentChannelCreate: 'paymentChannelCreate', - PaymentChannelFund: 'paymentChannelFund', - SetRegularKey: 'settings', - SignerListSet: 'settings', - TicketCreate: 'ticketCreate', - TrustSet: 'trustline', + AccountSet: "settings", + AccountDelete: "accountDelete", + CheckCancel: "checkCancel", + CheckCash: "checkCash", + CheckCreate: "checkCreate", + DepositPreauth: "depositPreauth", + EscrowCancel: "escrowCancellation", + EscrowCreate: "escrowCreation", + EscrowFinish: "escrowExecution", + OfferCancel: "orderCancellation", + OfferCreate: "order", + Payment: "payment", + PaymentChannelClaim: "paymentChannelClaim", + PaymentChannelCreate: "paymentChannelCreate", + PaymentChannelFund: "paymentChannelFund", + SetRegularKey: "settings", + SignerListSet: "settings", + TicketCreate: "ticketCreate", + TrustSet: "trustline", - EnableAmendment: 'amendment', // pseudo-transaction - SetFee: 'feeUpdate' // pseudo-transaction - } - return mapping[type] || null + EnableAmendment: "amendment", // pseudo-transaction + SetFee: "feeUpdate", // pseudo-transaction + }; + return mapping[type] || null; } // includeRawTransaction: undefined by default (getTransaction) function parseTransaction(tx: any, includeRawTransaction: boolean): any { - const type = parseTransactionType(tx.TransactionType) + const type = parseTransactionType(tx.TransactionType); const mapping = { settings: parseSettings, accountDelete: parseAccountDelete, @@ -74,31 +73,31 @@ function parseTransaction(tx: any, includeRawTransaction: boolean): any { trustline: parseTrustline, amendment: parseAmendment, // pseudo-transaction - feeUpdate: parseFeeUpdate // pseudo-transaction - } - const parser: Function = mapping[type] + feeUpdate: parseFeeUpdate, // pseudo-transaction + }; + const parser: Function = mapping[type]; const specification = parser ? parser(tx) : { - UNAVAILABLE: 'Unrecognized transaction type.', + UNAVAILABLE: "Unrecognized transaction type.", SEE_RAW_TRANSACTION: - 'Since this type is unrecognized, `rawTransaction` is included in this response.' - } + "Since this type is unrecognized, `rawTransaction` is included in this response.", + }; if (!parser) { - includeRawTransaction = true + includeRawTransaction = true; } - const outcome = parseOutcome(tx) + const outcome = parseOutcome(tx); return removeUndefined({ - type: type, + type, address: tx.Account, sequence: tx.Sequence, id: tx.hash, specification: removeUndefined(specification), outcome: outcome ? removeUndefined(outcome) : undefined, - rawTransaction: includeRawTransaction ? JSON.stringify(tx) : undefined - }) + rawTransaction: includeRawTransaction ? JSON.stringify(tx) : undefined, + }); } -export default parseTransaction +export default parseTransaction; diff --git a/src/ledger/parse/trustline.ts b/src/ledger/parse/trustline.ts index 513d30d5..fbbbd5a9 100644 --- a/src/ledger/parse/trustline.ts +++ b/src/ledger/parse/trustline.ts @@ -1,21 +1,24 @@ -import * as assert from 'assert' -import {parseQuality, parseMemos} from './utils' -import {txFlags} from '../../common' -import {removeUndefined} from '../../utils' -const flags = txFlags.TrustSet +import * as assert from "assert"; + +import { txFlags } from "../../common"; +import { removeUndefined } from "../../utils"; + +import { parseQuality, parseMemos } from "./utils"; + +const flags = txFlags.TrustSet; function parseFlag(flagsValue, trueValue, falseValue) { if (flagsValue & trueValue) { - return true + return true; } if (flagsValue & falseValue) { - return false + return false; } - return undefined + return undefined; } function parseTrustline(tx: any): object { - assert.ok(tx.TransactionType === 'TrustSet') + assert.ok(tx.TransactionType === "TrustSet"); return removeUndefined({ limit: tx.LimitAmount.value, @@ -30,8 +33,8 @@ function parseTrustline(tx: any): object { flags.ClearNoRipple ), frozen: parseFlag(tx.Flags, flags.SetFreeze, flags.ClearFreeze), - authorized: parseFlag(tx.Flags, flags.SetAuth, 0) - }) + authorized: parseFlag(tx.Flags, flags.SetAuth, 0), + }); } -export default parseTrustline +export default parseTrustline; diff --git a/src/ledger/parse/utils.ts b/src/ledger/parse/utils.ts index 98f62e4b..3f34e605 100644 --- a/src/ledger/parse/utils.ts +++ b/src/ledger/parse/utils.ts @@ -1,32 +1,33 @@ -import transactionParser from 'ripple-lib-transactionparser' -import BigNumber from 'bignumber.js' -import parseAmount from './amount' +import BigNumber from "bignumber.js"; +import transactionParser from "ripple-lib-transactionparser"; -import {Amount, Memo} from '../../common/types/objects' -import {txFlags} from '../../common' -import {removeUndefined, dropsToXrp, rippleTimeToISOTime} from '../../utils' +import { txFlags } from "../../common"; +import { Amount, Memo } from "../../common/types/objects"; +import { removeUndefined, dropsToXrp, rippleTimeToISOTime } from "../../utils"; -type OfferDescription = { - direction: string, - quantity: any, - totalPrice: any, - sequence: number, - status: string, - makerExchangeRate: string +import parseAmount from "./amount"; + +interface OfferDescription { + direction: string; + quantity: any; + totalPrice: any; + sequence: number; + status: string; + makerExchangeRate: string; } -type Orderbook = { - [key: string]: OfferDescription[] +interface Orderbook { + [key: string]: OfferDescription[]; } -type BalanceSheetItem = { - counterparty: string, - currency: string, - value: string +interface BalanceSheetItem { + counterparty: string; + currency: string; + value: string; } -type BalanceSheet = { - [key: string]: BalanceSheetItem[] +interface BalanceSheet { + [key: string]: BalanceSheetItem[]; } function adjustQualityForXRP( @@ -36,77 +37,79 @@ function adjustQualityForXRP( ) { // quality = takerPays.value/takerGets.value // using drops (1e-6 XRP) for XRP values - const numeratorShift = takerPaysCurrency === 'XRP' ? -6 : 0 - const denominatorShift = takerGetsCurrency === 'XRP' ? -6 : 0 - const shift = numeratorShift - denominatorShift + const numeratorShift = takerPaysCurrency === "XRP" ? -6 : 0; + const denominatorShift = takerGetsCurrency === "XRP" ? -6 : 0; + const shift = numeratorShift - denominatorShift; return shift === 0 ? quality - : new BigNumber(quality).shiftedBy(shift).toString() + : new BigNumber(quality).shiftedBy(shift).toString(); } function parseQuality(quality?: number | null): number | undefined { - if (typeof quality !== 'number') { - return undefined + if (typeof quality !== "number") { + return undefined; } - return new BigNumber(quality).shiftedBy(-9).toNumber() + return new BigNumber(quality).shiftedBy(-9).toNumber(); } function parseTimestamp(rippleTime?: number | null): string | undefined { - if (typeof rippleTime !== 'number') { - return undefined + if (typeof rippleTime !== "number") { + return undefined; } - return rippleTimeToISOTime(rippleTime) + return rippleTimeToISOTime(rippleTime); } function removeEmptyCounterparty(amount) { - if (amount.counterparty === '') { - delete amount.counterparty + if (amount.counterparty === "") { + delete amount.counterparty; } } function removeEmptyCounterpartyInBalanceChanges(balanceChanges: BalanceSheet) { Object.entries(balanceChanges).forEach(([_, changes]) => { - changes.forEach(removeEmptyCounterparty) - }) + changes.forEach(removeEmptyCounterparty); + }); } -function removeEmptyCounterpartyInOrderbookChanges(orderbookChanges: Orderbook) { +function removeEmptyCounterpartyInOrderbookChanges( + orderbookChanges: Orderbook +) { Object.entries(orderbookChanges).forEach(([_, changes]) => { changes.forEach((change) => { - Object.entries(change).forEach(removeEmptyCounterparty) - }) - }) + Object.entries(change).forEach(removeEmptyCounterparty); + }); + }); } function isPartialPayment(tx: any) { - return (tx.Flags & txFlags.Payment.PartialPayment) !== 0 + return (tx.Flags & txFlags.Payment.PartialPayment) !== 0; } function parseDeliveredAmount(tx: any): Amount | void { if ( - tx.TransactionType !== 'Payment' || - tx.meta.TransactionResult !== 'tesSUCCESS' + tx.TransactionType !== "Payment" || + tx.meta.TransactionResult !== "tesSUCCESS" ) { - return undefined + return undefined; } - if (tx.meta.delivered_amount && tx.meta.delivered_amount === 'unavailable') { - return undefined + if (tx.meta.delivered_amount && tx.meta.delivered_amount === "unavailable") { + return undefined; } // parsable delivered_amount if (tx.meta.delivered_amount) { - return parseAmount(tx.meta.delivered_amount) + return parseAmount(tx.meta.delivered_amount); } // DeliveredAmount only present on partial payments if (tx.meta.DeliveredAmount) { - return parseAmount(tx.meta.DeliveredAmount) + return parseAmount(tx.meta.DeliveredAmount); } // no partial payment flag, use tx.Amount if (tx.Amount && !isPartialPayment(tx)) { - return parseAmount(tx.Amount) + return parseAmount(tx.Amount); } // DeliveredAmount field was introduced at @@ -116,52 +119,52 @@ function parseDeliveredAmount(tx: any): Amount | void { // transferred with a partial payment before // that date must be derived from metadata. if (tx.Amount && tx.ledger_index > 4594094) { - return parseAmount(tx.Amount) + return parseAmount(tx.Amount); } - return undefined + return undefined; } function parseOutcome(tx: any): any | undefined { - const metadata = tx.meta || tx.metaData + const metadata = tx.meta || tx.metaData; if (!metadata) { - return undefined + return undefined; } - const balanceChanges = transactionParser.parseBalanceChanges(metadata) - const orderbookChanges = transactionParser.parseOrderbookChanges(metadata) - const channelChanges = transactionParser.parseChannelChanges(metadata) + const balanceChanges = transactionParser.parseBalanceChanges(metadata); + const orderbookChanges = transactionParser.parseOrderbookChanges(metadata); + const channelChanges = transactionParser.parseChannelChanges(metadata); - removeEmptyCounterpartyInBalanceChanges(balanceChanges) - removeEmptyCounterpartyInOrderbookChanges(orderbookChanges) + removeEmptyCounterpartyInBalanceChanges(balanceChanges); + removeEmptyCounterpartyInOrderbookChanges(orderbookChanges); return removeUndefined({ result: tx.meta.TransactionResult, timestamp: parseTimestamp(tx.date), fee: dropsToXrp(tx.Fee), - balanceChanges: balanceChanges, - orderbookChanges: orderbookChanges, - channelChanges: channelChanges, + balanceChanges, + orderbookChanges, + channelChanges, ledgerVersion: tx.ledger_index, indexInLedger: tx.meta.TransactionIndex, - deliveredAmount: parseDeliveredAmount(tx) - }) + deliveredAmount: parseDeliveredAmount(tx), + }); } function hexToString(hex: string): string | undefined { - return hex ? Buffer.from(hex, 'hex').toString('utf-8') : undefined + return hex ? Buffer.from(hex, "hex").toString("utf-8") : undefined; } -function parseMemos(tx: any): Array | undefined { +function parseMemos(tx: any): Memo[] | undefined { if (!Array.isArray(tx.Memos) || tx.Memos.length === 0) { - return undefined + return undefined; } return tx.Memos.map((m) => { return removeUndefined({ type: m.Memo.parsed_memo_type || hexToString(m.Memo.MemoType), format: m.Memo.parsed_memo_format || hexToString(m.Memo.MemoFormat), - data: m.Memo.parsed_memo_data || hexToString(m.Memo.MemoData) - }) - }) + data: m.Memo.parsed_memo_data || hexToString(m.Memo.MemoData), + }); + }); } export { @@ -171,5 +174,5 @@ export { hexToString, parseTimestamp, adjustQualityForXRP, - isPartialPayment -} + isPartialPayment, +}; diff --git a/src/ledger/pathfind-types.ts b/src/ledger/pathfind-types.ts index 76df0610..8612567f 100644 --- a/src/ledger/pathfind-types.ts +++ b/src/ledger/pathfind-types.ts @@ -3,64 +3,64 @@ import { RippledAmount, Adjustment, MaxAdjustment, - MinAdjustment -} from '../common/types/objects' + MinAdjustment, +} from "../common/types/objects"; // Amount where counterparty and value are optional -export type LaxLaxAmount = { - currency: string - value?: string - issuer?: string - counterparty?: string +export interface LaxLaxAmount { + currency: string; + value?: string; + issuer?: string; + counterparty?: string; } -export type Path = { - source: Adjustment | MaxAdjustment - destination: Adjustment | MinAdjustment - paths: string +export interface Path { + source: Adjustment | MaxAdjustment; + destination: Adjustment | MinAdjustment; + paths: string; } -export type GetPaths = Array +export type GetPaths = Path[]; -export type PathFind = { +export interface PathFind { source: { - address: string - amount?: Amount - currencies?: Array<{currency: string; counterparty?: string}> - } + address: string; + amount?: Amount; + currencies?: Array<{ currency: string; counterparty?: string }>; + }; destination: { - address: string - amount: LaxLaxAmount - } + address: string; + amount: LaxLaxAmount; + }; } -export type PathFindRequest = { - command: string - source_account: string - destination_amount: RippledAmount - destination_account: string - source_currencies?: {currency: string; issuer?: string}[] - send_max?: RippledAmount +export interface PathFindRequest { + command: string; + source_account: string; + destination_amount: RippledAmount; + destination_account: string; + source_currencies?: Array<{ currency: string; issuer?: string }>; + send_max?: RippledAmount; } -export type RippledPathsResponse = { +export interface RippledPathsResponse { alternatives: Array<{ paths_computed: Array< Array<{ - type: number - type_hex: string - account?: string - issuer?: string - currency?: string + type: number; + type_hex: string; + account?: string; + issuer?: string; + currency?: string; }> - > - source_amount: RippledAmount - }> - type: string - destination_account: string - destination_amount: RippledAmount - destination_currencies?: Array - source_account: string - source_currencies?: Array<{currency: string}> - full_reply?: boolean + >; + source_amount: RippledAmount; + }>; + type: string; + destination_account: string; + destination_amount: RippledAmount; + destination_currencies?: string[]; + source_account: string; + source_currencies?: Array<{ currency: string }>; + full_reply?: boolean; } diff --git a/src/ledger/pathfind.ts b/src/ledger/pathfind.ts index ba5dfbfa..3347eb5a 100644 --- a/src/ledger/pathfind.ts +++ b/src/ledger/pathfind.ts @@ -1,87 +1,90 @@ -import _ from 'lodash' -import BigNumber from 'bignumber.js' -import {getXRPBalance, renameCounterpartyToIssuer} from './utils' -import { - validate, - errors -} from '../common' -import {toRippledAmount, xrpToDrops, dropsToXrp} from '../utils' -import {Connection} from '../client' -import parsePathfind from './parse/pathfind' -import {RippledAmount, Amount} from '../common/types/objects' +import BigNumber from "bignumber.js"; +import _ from "lodash"; + +import type { Client } from ".."; +import { Connection } from "../client"; +import { validate, errors } from "../common"; +import { RippledAmount, Amount } from "../common/types/objects"; +import { RipplePathFindRequest } from "../models/methods"; +import { toRippledAmount, xrpToDrops, dropsToXrp } from "../utils"; + +import parsePathfind from "./parse/pathfind"; import { GetPaths, PathFind, RippledPathsResponse, - PathFindRequest -} from './pathfind-types' -import {Client} from '..' -import { RipplePathFindRequest } from '../models/methods' -const NotFoundError = errors.NotFoundError -const ValidationError = errors.ValidationError + PathFindRequest, +} from "./pathfind-types"; +import { getXRPBalance, renameCounterpartyToIssuer } from "./utils"; + +const NotFoundError = errors.NotFoundError; +const ValidationError = errors.ValidationError; function addParams( request: PathFindRequest, result: RippledPathsResponse ): RippledPathsResponse { return _.defaults( - Object.assign({}, result, { + { + ...result, source_account: request.source_account, - source_currencies: request.source_currencies - }), - {destination_amount: request.destination_amount} - ) + source_currencies: request.source_currencies, + }, + { destination_amount: request.destination_amount } + ); } function requestPathFind( connection: Connection, pathfind: PathFind ): Promise { - const destinationAmount: Amount = Object.assign( - { - // This is converted back to drops by toRippledAmount() - value: - pathfind.destination.amount.currency === 'XRP' ? dropsToXrp('-1') : '-1' - }, - pathfind.destination.amount - ) + const destinationAmount: Amount = { + // This is converted back to drops by toRippledAmount() + value: + pathfind.destination.amount.currency === "XRP" ? dropsToXrp("-1") : "-1", + ...pathfind.destination.amount, + }; const request: RipplePathFindRequest = { - command: 'ripple_path_find', + command: "ripple_path_find", source_account: pathfind.source.address, destination_account: pathfind.destination.address, - // @ts-ignore - destination_amount: destinationAmount - } + // @ts-expect-error + destination_amount: destinationAmount, + }; if ( - typeof request.destination_amount === 'object' && + typeof request.destination_amount === "object" && !request.destination_amount.issuer ) { // Convert blank issuer to sender's address // (Ripple convention for 'any issuer') // https://developers.ripple.com/payment.html#special-issuer-values-for-sendmax-and-amount - request.destination_amount.issuer = request.destination_account + request.destination_amount.issuer = request.destination_account; } if (pathfind.source.currencies && pathfind.source.currencies.length > 0) { - // @ts-ignore + // @ts-expect-error request.source_currencies = pathfind.source.currencies.map((amount) => renameCounterpartyToIssuer(amount) - ) + ); } if (pathfind.source.amount) { if (pathfind.destination.amount.value != null) { throw new ValidationError( - 'Cannot specify both source.amount' + - ' and destination.amount.value in getPaths' - ) + "Cannot specify both source.amount" + + " and destination.amount.value in getPaths" + ); } - // @ts-ignore - request.send_max = toRippledAmount(pathfind.source.amount) - if (typeof request.send_max !== 'string' && !request.send_max.issuer) { - request.send_max.issuer = pathfind.source.address + // @ts-expect-error + request.send_max = toRippledAmount(pathfind.source.amount); + if ( + request.send_max != null && + typeof request.send_max !== "string" && + !request.send_max.issuer + ) { + request.send_max.issuer = pathfind.source.address; } } - // @ts-ignore - return connection.request(request).then((paths) => addParams(request, paths)) + // @ts-expect-error + return connection.request(request).then((paths) => addParams(request, paths)); } function addDirectXrpPath( @@ -89,22 +92,22 @@ function addDirectXrpPath( xrpBalance: string ): RippledPathsResponse { // Add XRP "path" only if the source acct has enough XRP to make the payment - const destinationAmount = paths.destination_amount - // @ts-ignore: destinationAmount can be a currency amount object! Fix! + const destinationAmount = paths.destination_amount; + // @ts-expect-error: destinationAmount can be a currency amount object! Fix! if (new BigNumber(xrpBalance).isGreaterThanOrEqualTo(destinationAmount)) { paths.alternatives.unshift({ paths_computed: [], - source_amount: paths.destination_amount - }) + source_amount: paths.destination_amount, + }); } - return paths + return paths; } function isRippledIOUAmount(amount: RippledAmount) { // rippled XRP amounts are specified as decimal strings return ( - typeof amount === 'object' && amount.currency && amount.currency !== 'XRP' - ) + typeof amount === "object" && amount.currency && amount.currency !== "XRP" + ); } function conditionallyAddDirectXRPPath( @@ -114,13 +117,14 @@ function conditionallyAddDirectXRPPath( ): Promise { if ( isRippledIOUAmount(paths.destination_amount) || - !paths.destination_currencies.includes('XRP') + (paths.destination_currencies && + !paths.destination_currencies.includes("XRP")) ) { - return Promise.resolve(paths) + return Promise.resolve(paths); } return getXRPBalance(client, address, undefined).then((xrpBalance) => addDirectXrpPath(paths, xrpBalance) - ) + ); } function filterSourceFundsLowPaths( @@ -129,74 +133,72 @@ function filterSourceFundsLowPaths( ): RippledPathsResponse { if ( pathfind.source.amount && - pathfind.destination.amount.value == null && - paths.alternatives + paths.alternatives && + pathfind.destination.amount.value == null ) { paths.alternatives = paths.alternatives.filter((alt) => { if (!alt.source_amount) { - return false + return false; } + if (pathfind.source.amount === undefined) { + return false; + } + const pathfindSourceAmountValue = new BigNumber( - pathfind.source.amount.currency === 'XRP' + pathfind.source.amount.currency === "XRP" ? xrpToDrops(pathfind.source.amount.value) : pathfind.source.amount.value - ) + ); const altSourceAmountValue = new BigNumber( - typeof alt.source_amount === 'string' + typeof alt.source_amount === "string" ? alt.source_amount : alt.source_amount.value - ) - return altSourceAmountValue.eq(pathfindSourceAmountValue) - }) + ); + return altSourceAmountValue.eq(pathfindSourceAmountValue); + }); } - return paths + return paths; } function formatResponse(pathfind: PathFind, paths: RippledPathsResponse) { if (paths.alternatives && paths.alternatives.length > 0) { - return parsePathfind(paths) + return parsePathfind(paths); } if ( paths.destination_currencies != null && - !paths.destination_currencies.includes( - pathfind.destination.amount.currency - ) + !paths.destination_currencies.includes(pathfind.destination.amount.currency) ) { throw new NotFoundError( - 'No paths found. ' + - 'The destination_account does not accept ' + - pathfind.destination.amount.currency + - ', they only accept: ' + - paths.destination_currencies.join(', ') - ) + `${"No paths found. " + "The destination_account does not accept "}${ + pathfind.destination.amount.currency + }, they only accept: ${paths.destination_currencies.join(", ")}` + ); } else if (paths.source_currencies && paths.source_currencies.length > 0) { throw new NotFoundError( - 'No paths found. Please ensure' + - ' that the source_account has sufficient funds to execute' + - ' the payment in one of the specified source_currencies. If it does' + - ' there may be insufficient liquidity in the network to execute' + - ' this payment right now' - ) + "No paths found. Please ensure" + + " that the source_account has sufficient funds to execute" + + " the payment in one of the specified source_currencies. If it does" + + " there may be insufficient liquidity in the network to execute" + + " this payment right now" + ); } else { throw new NotFoundError( - 'No paths found.' + - ' Please ensure that the source_account has sufficient funds to' + - ' execute the payment. If it does there may be insufficient liquidity' + - ' in the network to execute this payment right now' - ) + "No paths found." + + " Please ensure that the source_account has sufficient funds to" + + " execute the payment. If it does there may be insufficient liquidity" + + " in the network to execute this payment right now" + ); } } function getPaths(this: Client, pathfind: PathFind): Promise { - validate.getPaths({pathfind}) + validate.getPaths({ pathfind }); - const address = pathfind.source.address + const address = pathfind.source.address; return requestPathFind(this.connection, pathfind) - .then((paths) => - conditionallyAddDirectXRPPath(this, address, paths) - ) + .then((paths) => conditionallyAddDirectXRPPath(this, address, paths)) .then((paths) => filterSourceFundsLowPaths(pathfind, paths)) - .then((paths) => formatResponse(pathfind, paths)) + .then((paths) => formatResponse(pathfind, paths)); } -export default getPaths +export default getPaths; diff --git a/src/ledger/trustlines.ts b/src/ledger/trustlines.ts index e3ec5888..00f21019 100644 --- a/src/ledger/trustlines.ts +++ b/src/ledger/trustlines.ts @@ -1,18 +1,23 @@ -import _ from 'lodash' -import {validate, ensureClassicAddress} from '../common' -import parseAccountTrustline from './parse/account-trustline' -import {Client} from '..' -import {FormattedTrustline} from '../common/types/objects/trustlines' +import _ from "lodash"; -export type GetTrustlinesOptions = { - counterparty?: string - currency?: string - limit?: number - ledgerVersion?: number +import type { Client } from ".."; +import { validate, ensureClassicAddress } from "../common"; +import { FormattedTrustline } from "../common/types/objects"; + +import parseAccountTrustline from "./parse/account-trustline"; + +export interface GetTrustlinesOptions { + counterparty?: string; + currency?: string; + limit?: number; + ledgerVersion?: number; } -function currencyFilter(currency: string, trustline: FormattedTrustline) { - return currency === null || trustline.specification.currency === currency +function currencyFilter( + currency: string | null, + trustline: FormattedTrustline +) { + return currency === null || trustline.specification.currency === currency; } async function getTrustlines( @@ -21,25 +26,26 @@ async function getTrustlines( options: GetTrustlinesOptions = {} ): Promise { // 1. Validate - validate.getTrustlines({address, options}) + validate.getTrustlines({ address, options }); // Only support retrieving trustlines without a tag, // since it does not make sense to filter trustlines // by tag. - address = ensureClassicAddress(address) + address = ensureClassicAddress(address); // 2. Make Request - const responses = await this.requestAll({command: 'account_lines', + const responses = await this.requestAll({ + command: "account_lines", account: address, - ledger_index: options.ledgerVersion ?? 'validated', + ledger_index: options.ledgerVersion ?? "validated", limit: options.limit, - peer: options.counterparty - }) + peer: options.counterparty, + }); // 3. Return Formatted Response - const trustlines = _.flatMap(responses, (response) => response.result.lines) + const trustlines = _.flatMap(responses, (response) => response.result.lines); return trustlines.map(parseAccountTrustline).filter((trustline) => { - return currencyFilter(options.currency || null, trustline) - }) + return currencyFilter(options.currency ?? null, trustline); + }); } -export default getTrustlines +export default getTrustlines; diff --git a/src/ledger/utils.ts b/src/ledger/utils.ts index 52b48e08..038dead9 100644 --- a/src/ledger/utils.ts +++ b/src/ledger/utils.ts @@ -1,23 +1,27 @@ -import _ from 'lodash' -import * as assert from 'assert' -import * as common from '../common' -import {Connection} from '../client' -import {FormattedTransactionType} from '../transaction/types' -import {Issue} from '../common/types/objects' -import {Client} from '..' -import {AccountInfoRequest} from '../models/methods' -import {dropsToXrp} from '..' +import * as assert from "assert"; -export type RecursiveData = { - marker: string - results: Array +import _ from "lodash"; + +import { Client, dropsToXrp } from ".."; +import { Connection } from "../client"; +import * as common from "../common"; +import { Issue } from "../common/types/objects"; +import { AccountInfoRequest } from "../models/methods"; +import { FormattedTransactionType } from "../transaction/types"; + +export interface RecursiveData { + marker: string; + results: any[]; } -export type Getter = (marker?: string, limit?: number) => Promise +export type Getter = ( + marker?: string, + limit?: number +) => Promise; function clamp(value: number, min: number, max: number): number { - assert.ok(min <= max, 'Illegal clamp bounds') - return Math.min(Math.max(value, min), max) + assert.ok(min <= max, "Illegal clamp bounds"); + return Math.min(Math.max(value, min), max); } async function getXRPBalance( @@ -26,13 +30,12 @@ async function getXRPBalance( ledgerVersion?: number ): Promise { const request: AccountInfoRequest = { - command: 'account_info', + command: "account_info", account: address, - ledger_index: ledgerVersion - } - const data = await client - .request(request) - return dropsToXrp(data.result.account_data.Balance) + ledger_index: ledgerVersion, + }; + const data = await client.request(request); + return dropsToXrp(data.result.account_data.Balance); } // If the marker is omitted from a response, you have reached the end @@ -40,64 +43,71 @@ async function getRecursiveRecur( getter: Getter, marker: string | undefined, limit: number -): Promise> { - const data = await getter(marker, limit) - const remaining = limit - data.results.length +): Promise { + const data = await getter(marker, limit); + const remaining = limit - data.results.length; if (remaining > 0 && data.marker != null) { - return getRecursiveRecur(getter, data.marker, remaining).then((results) => data.results.concat(results) - ) + return getRecursiveRecur(getter, data.marker, remaining).then((results) => + data.results.concat(results) + ); } - return data.results.slice(0, limit) + return data.results.slice(0, limit); } -function getRecursive(getter: Getter, limit?: number): Promise> { - return getRecursiveRecur(getter, undefined, limit || Infinity) +function getRecursive(getter: Getter, limit?: number): Promise { + return getRecursiveRecur(getter, undefined, limit || Infinity); } function renameCounterpartyToIssuer( - obj: T & {counterparty?: string; issuer?: string} -): T & {issuer?: string} { + obj: T & { counterparty?: string; issuer?: string } +): T & { issuer?: string } { const issuer = obj.counterparty != null ? obj.counterparty : obj.issuer != null ? obj.issuer - : undefined - const withIssuer = Object.assign({}, obj, {issuer}) - delete withIssuer.counterparty - return withIssuer + : undefined; + const withIssuer = { ...obj, issuer }; + delete withIssuer.counterparty; + return withIssuer; } -export type RequestBookOffersArgs = {taker_gets: Issue; taker_pays: Issue} +export interface RequestBookOffersArgs { + taker_gets: Issue; + taker_pays: Issue; +} function renameCounterpartyToIssuerInOrder(order: RequestBookOffersArgs) { - const taker_gets = renameCounterpartyToIssuer(order.taker_gets) - const taker_pays = renameCounterpartyToIssuer(order.taker_pays) - const changes = {taker_gets, taker_pays} - return Object.assign({}, order, _.omitBy(changes, value => value == null)) + const taker_gets = renameCounterpartyToIssuer(order.taker_gets); + const taker_pays = renameCounterpartyToIssuer(order.taker_pays); + const changes = { taker_gets, taker_pays }; + return { ...order, ..._.omitBy(changes, (value) => value == null) }; } function signum(num) { - return num === 0 ? 0 : num > 0 ? 1 : -1 + return num === 0 ? 0 : num > 0 ? 1 : -1; } /** - * Order two rippled transactions based on their ledger_index. - * If two transactions took place in the same ledger, sort - * them based on TransactionIndex - * See: https://developers.ripple.com/transaction-metadata.html + * Order two rippled transactions based on their ledger_index. + * If two transactions took place in the same ledger, sort + * them based on TransactionIndex + * See: https://developers.ripple.com/transaction-metadata.html. + * + * @param first + * @param second */ function compareTransactions( first: FormattedTransactionType, second: FormattedTransactionType ): number { if (!first.outcome || !second.outcome) { - return 0 + return 0; } if (first.outcome.ledgerVersion === second.outcome.ledgerVersion) { - return signum(first.outcome.indexInLedger - second.outcome.indexInLedger) + return signum(first.outcome.indexInLedger - second.outcome.indexInLedger); } - return first.outcome.ledgerVersion < second.outcome.ledgerVersion ? -1 : 1 + return first.outcome.ledgerVersion < second.outcome.ledgerVersion ? -1 : 1; } async function isPendingLedgerVersion( @@ -105,27 +115,30 @@ async function isPendingLedgerVersion( maxLedgerVersion?: number ): Promise { const response = await client.request({ - command: 'ledger', - ledger_index: 'validated' - }) - const ledgerVersion = response.result.ledger_index - return ledgerVersion < (maxLedgerVersion || 0) + command: "ledger", + ledger_index: "validated", + }); + const ledgerVersion = response.result.ledger_index; + return ledgerVersion < (maxLedgerVersion || 0); } -async function ensureLedgerVersion(this: Client, options: any): Promise { +async function ensureLedgerVersion( + this: Client, + options: any +): Promise { if ( Boolean(options) && options.ledgerVersion != null && options.ledgerVersion !== null ) { - return Promise.resolve(options) + return Promise.resolve(options); } const response = await this.request({ - command: 'ledger', - ledger_index: 'validated' - }) - const ledgerVersion = response.result.ledger_index - return Object.assign({}, options, { ledgerVersion }) + command: "ledger", + ledger_index: "validated", + }); + const ledgerVersion = response.result.ledger_index; + return { ...options, ledgerVersion }; } export { @@ -138,5 +151,5 @@ export { isPendingLedgerVersion, clamp, common, - Connection -} + Connection, +}; diff --git a/src/models/common/index.ts b/src/models/common/index.ts index 158910b2..9f4eb704 100644 --- a/src/models/common/index.ts +++ b/src/models/common/index.ts @@ -1,23 +1,29 @@ -export type LedgerIndex = number | ('validated' | 'closed' | 'current') +export type LedgerIndex = number | ("validated" | "closed" | "current"); -export type AccountObjectType = 'check' | 'escrow' | 'offer' | 'payment_channel' | 'signer_list' | 'state' +export type AccountObjectType = + | "check" + | "escrow" + | "offer" + | "payment_channel" + | "signer_list" + | "state"; export interface XRP { - currency: "XRP" + currency: "XRP"; } export interface IssuedCurrency { - currency: string - issuer: string + currency: string; + issuer: string; } -export type Currency = IssuedCurrency | XRP +export type Currency = IssuedCurrency | XRP; export interface IssuedCurrencyAmount extends IssuedCurrency { - value: string + value: string; } -export type Amount = IssuedCurrencyAmount | string +export type Amount = IssuedCurrencyAmount | string; export interface Signer { Account: string; @@ -31,17 +37,25 @@ export interface Memo { MemoFormat?: string; } -export type StreamType = "consensus" | "ledger" | "manifests" | "peer_status" | "transactions" | "transactions_proposed" | "server" | "validations" +export type StreamType = + | "consensus" + | "ledger" + | "manifests" + | "peer_status" + | "transactions" + | "transactions_proposed" + | "server" + | "validations"; interface PathStep { - account?: string - currency?: string - issuer?: string + account?: string; + currency?: string; + issuer?: string; } -export type Path = PathStep[] +export type Path = PathStep[]; export interface SignerEntry { Account: string; SignerWeight: number; -} \ No newline at end of file +} diff --git a/src/models/common/metadata.ts b/src/models/common/metadata.ts index cca41c10..10b79e25 100644 --- a/src/models/common/metadata.ts +++ b/src/models/common/metadata.ts @@ -1,38 +1,38 @@ import { Amount } from "."; interface CreatedNode { - CreatedNode: { - LedgerEntryType: string - LedgerIndex: string - NewFields: {[field: string]: any} - } + CreatedNode: { + LedgerEntryType: string; + LedgerIndex: string; + NewFields: { [field: string]: any }; + }; } interface ModifiedNode { - ModifiedNode: { - LedgerEntryType: string - LedgerIndex: string - FinalFields: {[field: string]: any} - PreviousFields: {[field: string]: any} - PreviousTxnID?: string - PreviouTxnLgrSeq?: number - } + ModifiedNode: { + LedgerEntryType: string; + LedgerIndex: string; + FinalFields: { [field: string]: any }; + PreviousFields: { [field: string]: any }; + PreviousTxnID?: string; + PreviouTxnLgrSeq?: number; + }; } interface DeletedNode { - DeletedNode: { - LedgerEntryType: string - LedgerIndex: string - FinalFields: {[field: string]: any} - } + DeletedNode: { + LedgerEntryType: string; + LedgerIndex: string; + FinalFields: { [field: string]: any }; + }; } -type Node = CreatedNode | ModifiedNode | DeletedNode +type Node = CreatedNode | ModifiedNode | DeletedNode; export default interface Metadata { - AffectedNodes: Node[] - DeliveredAmount?: Amount - delivered_amount?: Amount - TransactionIndex: number - TransactionResult: string -} \ No newline at end of file + AffectedNodes: Node[]; + DeliveredAmount?: Amount; + delivered_amount?: Amount; + TransactionIndex: number; + TransactionResult: string; +} diff --git a/src/models/common/transaction.ts b/src/models/common/transaction.ts index 69e2550d..79a6e6ea 100644 --- a/src/models/common/transaction.ts +++ b/src/models/common/transaction.ts @@ -1,38 +1,38 @@ import { Amount } from "."; interface CreatedNode { - CreatedNode: { - LedgerEntryType: string - LedgerIndex: string - NewFields: {[field: string]: any} - } + CreatedNode: { + LedgerEntryType: string; + LedgerIndex: string; + NewFields: { [field: string]: any }; + }; } interface ModifiedNode { - ModifiedNode: { - LedgerEntryType: string - LedgerIndex: string - FinalFields: {[field: string]: any} - PreviousFields: {[field: string]: any} - PreviousTxnID?: string - PreviouTxnLgrSeq?: number - } + ModifiedNode: { + LedgerEntryType: string; + LedgerIndex: string; + FinalFields: { [field: string]: any }; + PreviousFields: { [field: string]: any }; + PreviousTxnID?: string; + PreviouTxnLgrSeq?: number; + }; } interface DeletedNode { - DeletedNode: { - LedgerEntryType: string - LedgerIndex: string - FinalFields: {[field: string]: any} - } + DeletedNode: { + LedgerEntryType: string; + LedgerIndex: string; + FinalFields: { [field: string]: any }; + }; } -type Node = CreatedNode | ModifiedNode | DeletedNode +type Node = CreatedNode | ModifiedNode | DeletedNode; export interface TransactionMetadata { - AffectedNodes: Node[] - DeliveredAmount?: Amount - delivered_amount?: Amount - TransactionIndex: number - TransactionResult: string -} \ No newline at end of file + AffectedNodes: Node[]; + DeliveredAmount?: Amount; + delivered_amount?: Amount; + TransactionIndex: number; + TransactionResult: string; +} diff --git a/src/models/ledger/accountRoot.ts b/src/models/ledger/accountRoot.ts index 8d12e388..7b5c2950 100644 --- a/src/models/ledger/accountRoot.ts +++ b/src/models/ledger/accountRoot.ts @@ -1,20 +1,20 @@ import { BaseLedgerEntry } from "./baseLedgerEntry"; -export interface AccountRoot extends BaseLedgerEntry{ - LedgerEntryType: 'AccountRoot' - Account: string - Balance: string - Flags: number - OwnerCount: number - PreviousTxnID: string - PreviousTxnLgrSeq: number - Sequence: number - AccountTxnID?: string - Domain?: string - EmailHash?: string - MessageKey?: string - RegularKey?: string - TicketCount?: number - TickSize?: number - TransferRate?: number - } \ No newline at end of file +export interface AccountRoot extends BaseLedgerEntry { + LedgerEntryType: "AccountRoot"; + Account: string; + Balance: string; + Flags: number; + OwnerCount: number; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; + Sequence: number; + AccountTxnID?: string; + Domain?: string; + EmailHash?: string; + MessageKey?: string; + RegularKey?: string; + TicketCount?: number; + TickSize?: number; + TransferRate?: number; +} diff --git a/src/models/ledger/amendments.ts b/src/models/ledger/amendments.ts index 79bd3f04..3427b34d 100644 --- a/src/models/ledger/amendments.ts +++ b/src/models/ledger/amendments.ts @@ -2,14 +2,14 @@ import { BaseLedgerEntry } from "./baseLedgerEntry"; interface Majority { Majority: { - Amendment: string - CloseTime: number - } + Amendment: string; + CloseTime: number; + }; } export interface Amendments extends BaseLedgerEntry { - LedgerEntryType: 'Amendments' - Amendments?: string[] - Majorities?: Majority[] - Flags: 0 -} \ No newline at end of file + LedgerEntryType: "Amendments"; + Amendments?: string[]; + Majorities?: Majority[]; + Flags: 0; +} diff --git a/src/models/ledger/baseLedgerEntry.ts b/src/models/ledger/baseLedgerEntry.ts index d322ccac..ab70beb6 100644 --- a/src/models/ledger/baseLedgerEntry.ts +++ b/src/models/ledger/baseLedgerEntry.ts @@ -1,3 +1,3 @@ export interface BaseLedgerEntry { - index: string -} \ No newline at end of file + index: string; +} diff --git a/src/models/ledger/check.ts b/src/models/ledger/check.ts index 6c6d6209..b10f2756 100644 --- a/src/models/ledger/check.ts +++ b/src/models/ledger/check.ts @@ -1,19 +1,20 @@ import { Amount } from "../common"; + import { BaseLedgerEntry } from "./baseLedgerEntry"; export interface Check extends BaseLedgerEntry { - LedgerEntryType: 'Check' - Account: string - Destination: string - Flags: 0 - OwnerNode: string - PreviousTxnID: string - PreviousTxnLgrSeq: number - SendMax: Amount - Sequence: number - DestinationNode?: string - DestinationTag?: number - Expiration?: number - InvoiceID?: string - SourceTag?: number - } \ No newline at end of file + LedgerEntryType: "Check"; + Account: string; + Destination: string; + Flags: 0; + OwnerNode: string; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; + SendMax: Amount; + Sequence: number; + DestinationNode?: string; + DestinationTag?: number; + Expiration?: number; + InvoiceID?: string; + SourceTag?: number; +} diff --git a/src/models/ledger/depositPreauth.ts b/src/models/ledger/depositPreauth.ts index d10ab671..0d48caf2 100644 --- a/src/models/ledger/depositPreauth.ts +++ b/src/models/ledger/depositPreauth.ts @@ -1,11 +1,11 @@ import { BaseLedgerEntry } from "./baseLedgerEntry"; export interface DepositPreauth extends BaseLedgerEntry { - LedgerEntryType: 'DepositPreauth' - Account: string - Authorize: string - Flags: 0 - OwnerNode: string - PreviousTxnID: string - PreviousTxnLgrSeq: number - } \ No newline at end of file + LedgerEntryType: "DepositPreauth"; + Account: string; + Authorize: string; + Flags: 0; + OwnerNode: string; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; +} diff --git a/src/models/ledger/directoryNode.ts b/src/models/ledger/directoryNode.ts index 295c46e1..f0e0b8ee 100644 --- a/src/models/ledger/directoryNode.ts +++ b/src/models/ledger/directoryNode.ts @@ -1,15 +1,15 @@ import { BaseLedgerEntry } from "./baseLedgerEntry"; export interface DirectoryNode extends BaseLedgerEntry { - LedgerEntryType: 'DirectoryNode' - Flags: number - RootIndex: string - Indexes: string[] - IndexNext?: number - IndexPrevious?: number - Owner?: string - TakerPaysCurrency?: string - TakerPaysIssuer?: string - TakerGetsCurrency?: string - TakerGetsIssuer?: string -} \ No newline at end of file + LedgerEntryType: "DirectoryNode"; + Flags: number; + RootIndex: string; + Indexes: string[]; + IndexNext?: number; + IndexPrevious?: number; + Owner?: string; + TakerPaysCurrency?: string; + TakerPaysIssuer?: string; + TakerGetsCurrency?: string; + TakerGetsIssuer?: string; +} diff --git a/src/models/ledger/escrow.ts b/src/models/ledger/escrow.ts index 264da1ba..6ff0a299 100644 --- a/src/models/ledger/escrow.ts +++ b/src/models/ledger/escrow.ts @@ -1,18 +1,18 @@ import { BaseLedgerEntry } from "./baseLedgerEntry"; export interface Escrow extends BaseLedgerEntry { - LedgerEntryType: 'Escrow' - Account: string - Destination: string - Amount: string - Condition?: string - CancelAfter?: number - FinishAfter?: number - Flags: number - SourceTag?: number - DestinationTag?: number - OwnerNode: string - DestinationNode?: string - PreviousTxnID: string - PreviousTxnLgrSeq: number - } \ No newline at end of file + LedgerEntryType: "Escrow"; + Account: string; + Destination: string; + Amount: string; + Condition?: string; + CancelAfter?: number; + FinishAfter?: number; + Flags: number; + SourceTag?: number; + DestinationTag?: number; + OwnerNode: string; + DestinationNode?: string; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; +} diff --git a/src/models/ledger/feeSettings.ts b/src/models/ledger/feeSettings.ts index c00b69c4..a29168b8 100644 --- a/src/models/ledger/feeSettings.ts +++ b/src/models/ledger/feeSettings.ts @@ -1,10 +1,10 @@ import { BaseLedgerEntry } from "./baseLedgerEntry"; export interface FeeSettings extends BaseLedgerEntry { - LedgerEntryType: 'FeeSettings' - BaseFee: string - ReferenceFeeUnits: number - ReserveBase: number - ReserveIncrement: number - Flags: number - } \ No newline at end of file + LedgerEntryType: "FeeSettings"; + BaseFee: string; + ReferenceFeeUnits: number; + ReserveBase: number; + ReserveIncrement: number; + Flags: number; +} diff --git a/src/models/ledger/index.ts b/src/models/ledger/index.ts index fb6ebf88..340de5da 100644 --- a/src/models/ledger/index.ts +++ b/src/models/ledger/index.ts @@ -14,35 +14,36 @@ import { RippleState } from "./rippleState"; import { SignerList } from "./signerList"; import { Ticket } from "./ticket"; -export type LedgerEntry = AccountRoot - | Amendments - | Check - | DepositPreauth - | DirectoryNode - | Escrow - | FeeSettings - | LedgerHashes - | NegativeUNL - | Offer - | PayChannel - | RippleState - | SignerList - | Ticket +export type LedgerEntry = + | AccountRoot + | Amendments + | Check + | DepositPreauth + | DirectoryNode + | Escrow + | FeeSettings + | LedgerHashes + | NegativeUNL + | Offer + | PayChannel + | RippleState + | SignerList + | Ticket; export { - AccountRoot, - Amendments, - Check, - DepositPreauth, - DirectoryNode, - Escrow, - FeeSettings, - LedgerHashes, - NegativeUNL, - Offer, - PayChannel, - RippleState, - SignerList, - Ticket, - Ledger -} + AccountRoot, + Amendments, + Check, + DepositPreauth, + DirectoryNode, + Escrow, + FeeSettings, + LedgerHashes, + NegativeUNL, + Offer, + PayChannel, + RippleState, + SignerList, + Ticket, + Ledger, +}; diff --git a/src/models/ledger/ledger.ts b/src/models/ledger/ledger.ts index b1f36a7d..ea9e8106 100644 --- a/src/models/ledger/ledger.ts +++ b/src/models/ledger/ledger.ts @@ -1,19 +1,20 @@ -import { LedgerEntry } from "."; import { Transaction } from "../transactions"; +import { LedgerEntry } from "."; + export interface Ledger { - account_hash: string - accountState?: LedgerEntry[] - close_flags: number - close_time: number - close_time_human: string - close_time_resolution: number - closed: boolean - ledger_hash: string - ledger_index: string - parent_close_time: number - parent_hash: string - total_coins: string - transaction_hash: string - transactions?: Transaction[] - } + account_hash: string; + accountState?: LedgerEntry[]; + close_flags: number; + close_time: number; + close_time_human: string; + close_time_resolution: number; + closed: boolean; + ledger_hash: string; + ledger_index: string; + parent_close_time: number; + parent_hash: string; + total_coins: string; + transaction_hash: string; + transactions?: Transaction[]; +} diff --git a/src/models/ledger/ledgerHashes.ts b/src/models/ledger/ledgerHashes.ts index 51292a90..999d574e 100644 --- a/src/models/ledger/ledgerHashes.ts +++ b/src/models/ledger/ledgerHashes.ts @@ -1,8 +1,8 @@ import { BaseLedgerEntry } from "./baseLedgerEntry"; export interface LedgerHashes extends BaseLedgerEntry { - LedgerEntryType: 'LedgerHashes' - LastLedgerSequence?: number - Hashes: string[] - Flags: number - } \ No newline at end of file + LedgerEntryType: "LedgerHashes"; + LastLedgerSequence?: number; + Hashes: string[]; + Flags: number; +} diff --git a/src/models/ledger/negativeUNL.ts b/src/models/ledger/negativeUNL.ts index eff7106d..82dd61f8 100644 --- a/src/models/ledger/negativeUNL.ts +++ b/src/models/ledger/negativeUNL.ts @@ -1,13 +1,13 @@ import { BaseLedgerEntry } from "./baseLedgerEntry"; interface DisabledValidator { - FirstLedgerSequence: number - PublicKey: string + FirstLedgerSequence: number; + PublicKey: string; } export interface NegativeUNL extends BaseLedgerEntry { - LedgerEntryType: "NegativeUNL" - DisabledValidators?: DisabledValidator[] - ValidatorToDisable?: string - ValidatorToReEnable?: string -} \ No newline at end of file + LedgerEntryType: "NegativeUNL"; + DisabledValidators?: DisabledValidator[]; + ValidatorToDisable?: string; + ValidatorToReEnable?: string; +} diff --git a/src/models/ledger/offer.ts b/src/models/ledger/offer.ts index 138af70f..7684cbcb 100644 --- a/src/models/ledger/offer.ts +++ b/src/models/ledger/offer.ts @@ -1,17 +1,18 @@ import { Amount } from "../common"; + import { BaseLedgerEntry } from "./baseLedgerEntry"; export interface Offer extends BaseLedgerEntry { - LedgerEntryType: 'Offer' - Flags: number - Account: string - Sequence: number - TakerPays: Amount - TakerGets: Amount - BookDirectory: string - BookNode: string - OwnerNode: string - PreviousTxnID: string - PreviousTxnLgrSeq: number - Expiration?: number - } \ No newline at end of file + LedgerEntryType: "Offer"; + Flags: number; + Account: string; + Sequence: number; + TakerPays: Amount; + TakerGets: Amount; + BookDirectory: string; + BookNode: string; + OwnerNode: string; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; + Expiration?: number; +} diff --git a/src/models/ledger/payChannel.ts b/src/models/ledger/payChannel.ts index 3ab97a83..8ec31f59 100644 --- a/src/models/ledger/payChannel.ts +++ b/src/models/ledger/payChannel.ts @@ -1,20 +1,20 @@ import { BaseLedgerEntry } from "./baseLedgerEntry"; export interface PayChannel extends BaseLedgerEntry { - LedgerEntryType: 'PayChannel' - Account: string - Destination: string - Amount: string - Balance: string - PublicKey: string - SettleDelay: number - OwnerNode: string - PreviousTxnID: string - PreviousTxnLgrSeq: number - Flags: number - Expiration?: number - CancelAfter?: number - SourceTag?: number - DestinationTag?: number - DestinationNode?: string -} \ No newline at end of file + LedgerEntryType: "PayChannel"; + Account: string; + Destination: string; + Amount: string; + Balance: string; + PublicKey: string; + SettleDelay: number; + OwnerNode: string; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; + Flags: number; + Expiration?: number; + CancelAfter?: number; + SourceTag?: number; + DestinationTag?: number; + DestinationNode?: string; +} diff --git a/src/models/ledger/rippleState.ts b/src/models/ledger/rippleState.ts index 7648b3eb..6a839a06 100644 --- a/src/models/ledger/rippleState.ts +++ b/src/models/ledger/rippleState.ts @@ -1,18 +1,19 @@ -import { BaseLedgerEntry } from "./baseLedgerEntry"; import { IssuedCurrencyAmount } from "../common"; +import { BaseLedgerEntry } from "./baseLedgerEntry"; + export interface RippleState extends BaseLedgerEntry { - LedgerEntryType: 'RippleState' - Flags: number - Balance: IssuedCurrencyAmount - LowLimit: IssuedCurrencyAmount - HighLimit: IssuedCurrencyAmount - PreviousTxnID: string - PreviousTxnLgrSeq: number - LowNode?: string - HighNode?: string - LowQualityIn?: number - LowQualityOut?: number - HighQualityIn?: number - HighQualityOut?: number -} \ No newline at end of file + LedgerEntryType: "RippleState"; + Flags: number; + Balance: IssuedCurrencyAmount; + LowLimit: IssuedCurrencyAmount; + HighLimit: IssuedCurrencyAmount; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; + LowNode?: string; + HighNode?: string; + LowQualityIn?: number; + LowQualityOut?: number; + HighQualityIn?: number; + HighQualityOut?: number; +} diff --git a/src/models/ledger/signerList.ts b/src/models/ledger/signerList.ts index 6ba41cf3..bdd68561 100644 --- a/src/models/ledger/signerList.ts +++ b/src/models/ledger/signerList.ts @@ -2,18 +2,18 @@ import { BaseLedgerEntry } from "./baseLedgerEntry"; interface SignerEntry { SignerEntry: { - Account: string - SignerWeight: number - } + Account: string; + SignerWeight: number; + }; } export interface SignerList extends BaseLedgerEntry { - LedgerEntryType: 'SignerList' - Flags: number - PreviousTxnID: string - PreviousTxnLgrSeq: number - OwnerNode: string - SignerEntries: SignerEntry[] - SignerListID: number - SignerQuorum: number -} \ No newline at end of file + LedgerEntryType: "SignerList"; + Flags: number; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; + OwnerNode: string; + SignerEntries: SignerEntry[]; + SignerListID: number; + SignerQuorum: number; +} diff --git a/src/models/ledger/ticket.ts b/src/models/ledger/ticket.ts index 0ae5c754..b6050753 100644 --- a/src/models/ledger/ticket.ts +++ b/src/models/ledger/ticket.ts @@ -1,11 +1,11 @@ import { BaseLedgerEntry } from "./baseLedgerEntry"; export interface Ticket extends BaseLedgerEntry { - LedgerEntryType: "Ticket" - Account: string - Flags: number - OwnerNode: string - PreviousTxnID: string - PreviousTxnLgrSeq: number - TicketSequence: number -} \ No newline at end of file + LedgerEntryType: "Ticket"; + Account: string; + Flags: number; + OwnerNode: string; + PreviousTxnID: string; + PreviousTxnLgrSeq: number; + TicketSequence: number; +} diff --git a/src/models/methods/accountChannels.ts b/src/models/methods/accountChannels.ts index c5a3371a..b6efc276 100644 --- a/src/models/methods/accountChannels.ts +++ b/src/models/methods/accountChannels.ts @@ -1,39 +1,40 @@ -import { BaseRequest, BaseResponse } from './baseMethod' -import { LedgerIndex } from "../common" +import { LedgerIndex } from "../common"; + +import { BaseRequest, BaseResponse } from "./baseMethod"; interface Channel { - account: string - amount: string - balance: string - channel_id: string - destination_account: string - settle_delay: number - public_key?: string - public_key_hex?: string - expiration?: number - cancel_after?: number - source_tab?: number - destination_tag?: number + account: string; + amount: string; + balance: string; + channel_id: string; + destination_account: string; + settle_delay: number; + public_key?: string; + public_key_hex?: string; + expiration?: number; + cancel_after?: number; + source_tab?: number; + destination_tag?: number; } - + export interface AccountChannelsRequest extends BaseRequest { - command: "account_channels" - account: string - destination_account?: string - ledger_hash?: string - ledger_index?: LedgerIndex - limit: number - marker?: any + command: "account_channels"; + account: string; + destination_account?: string; + ledger_hash?: string; + ledger_index?: LedgerIndex; + limit: number; + marker?: any; } export interface AccountChannelsResponse extends BaseResponse { - result: { - account: string - channels: Channel[] - ledger_hash: string - ledger_index: number - validated?: boolean - limit?: number - marker?: any - } + result: { + account: string; + channels: Channel[]; + ledger_hash: string; + ledger_index: number; + validated?: boolean; + limit?: number; + marker?: any; + }; } diff --git a/src/models/methods/accountCurrencies.ts b/src/models/methods/accountCurrencies.ts index 1151cad4..8aa88834 100644 --- a/src/models/methods/accountCurrencies.ts +++ b/src/models/methods/accountCurrencies.ts @@ -1,21 +1,22 @@ -import { BaseRequest, BaseResponse } from './baseMethod' -import { LedgerIndex } from "../common" - +import { LedgerIndex } from "../common"; + +import { BaseRequest, BaseResponse } from "./baseMethod"; + export interface AccountCurrenciesRequest extends BaseRequest { - command: "account_currencies" - account: string - destination_account?: string - ledger_hash?: string - ledger_index?: LedgerIndex - strict?: boolean + command: "account_currencies"; + account: string; + destination_account?: string; + ledger_hash?: string; + ledger_index?: LedgerIndex; + strict?: boolean; } export interface AccountCurrenciesResponse extends BaseResponse { - result: { - ledger_hash?: string - ledger_index: number - receive_currencies: string[] - send_currencies: string[] - validated: boolean - } + result: { + ledger_hash?: string; + ledger_index: number; + receive_currencies: string[]; + send_currencies: string[]; + validated: boolean; + }; } diff --git a/src/models/methods/accountInfo.ts b/src/models/methods/accountInfo.ts index bc7d0eb9..4a249984 100644 --- a/src/models/methods/accountInfo.ts +++ b/src/models/methods/accountInfo.ts @@ -1,41 +1,42 @@ -import { BaseRequest, BaseResponse } from './baseMethod' -import { LedgerIndex } from "../common" -import { AccountRoot, SignerList } from "../ledger" - +import { LedgerIndex } from "../common"; +import { AccountRoot, SignerList } from "../ledger"; + +import { BaseRequest, BaseResponse } from "./baseMethod"; + export interface AccountInfoRequest extends BaseRequest { - command: "account_info" - account: string - ledger_hash?: string - ledger_index?: LedgerIndex - queue?: boolean - signer_lists?: boolean - strict?: boolean + command: "account_info"; + account: string; + ledger_hash?: string; + ledger_index?: LedgerIndex; + queue?: boolean; + signer_lists?: boolean; + strict?: boolean; } interface QueueTransaction { - auth_change: boolean - fee: string - fee_level: string - max_spend_drops: string - seq: number + auth_change: boolean; + fee: string; + fee_level: string; + max_spend_drops: string; + seq: number; } interface QueueData { - txn_count: number - auth_change_queued?: boolean - lowest_sequence?: number - highest_sequence?: number - max_spend_drops_total?: string - transactions?: QueueTransaction[] + txn_count: number; + auth_change_queued?: boolean; + lowest_sequence?: number; + highest_sequence?: number; + max_spend_drops_total?: string; + transactions?: QueueTransaction[]; } export interface AccountInfoResponse extends BaseResponse { result: { - account_data: AccountRoot - signer_lists?: SignerList[] - ledger_current_index?: number - ledger_index?: number - queue_data?: QueueData - validated?: boolean - } -} \ No newline at end of file + account_data: AccountRoot; + signer_lists?: SignerList[]; + ledger_current_index?: number; + ledger_index?: number; + queue_data?: QueueData; + validated?: boolean; + }; +} diff --git a/src/models/methods/accountLines.ts b/src/models/methods/accountLines.ts index 2b15614f..f5144c0c 100644 --- a/src/models/methods/accountLines.ts +++ b/src/models/methods/accountLines.ts @@ -1,39 +1,40 @@ -import { BaseRequest, BaseResponse } from './baseMethod' -import { LedgerIndex } from "../common" +import { LedgerIndex } from "../common"; + +import { BaseRequest, BaseResponse } from "./baseMethod"; interface Trustline { - account: string - balance: string - currency: string - limit: string - limit_peer: string - quality_in: number - quality_out: number - no_ripple?: boolean - no_ripple_peer?: boolean - authorized?: boolean - peer_authorized?: boolean - freeze?: boolean - freeze_peer?: boolean + account: string; + balance: string; + currency: string; + limit: string; + limit_peer: string; + quality_in: number; + quality_out: number; + no_ripple?: boolean; + no_ripple_peer?: boolean; + authorized?: boolean; + peer_authorized?: boolean; + freeze?: boolean; + freeze_peer?: boolean; } export interface AccountLinesRequest extends BaseRequest { - command: "account_lines" - account: string - ledger_hash?: string - ledger_index?: LedgerIndex - peer?: string - limit?: number - marker?: any + command: "account_lines"; + account: string; + ledger_hash?: string; + ledger_index?: LedgerIndex; + peer?: string; + limit?: number; + marker?: any; } export interface AccountLinesResponse extends BaseResponse { result: { - account: string - lines: Trustline[] - ledger_current_index?: number - ledger_index?: number - ledger_hash?: string - marker?: any - } + account: string; + lines: Trustline[]; + ledger_current_index?: number; + ledger_index?: number; + ledger_hash?: string; + marker?: any; + }; } diff --git a/src/models/methods/accountObjects.ts b/src/models/methods/accountObjects.ts index 80eb546b..29509242 100644 --- a/src/models/methods/accountObjects.ts +++ b/src/models/methods/accountObjects.ts @@ -1,29 +1,47 @@ -import { BaseRequest, BaseResponse } from './baseMethod' -import { AccountObjectType, LedgerIndex } from "../common" -import { Check, DepositPreauth, Escrow, Offer, PayChannel, RippleState, SignerList, Ticket } from "../ledger" - +import { AccountObjectType, LedgerIndex } from "../common"; +import { + Check, + DepositPreauth, + Escrow, + Offer, + PayChannel, + RippleState, + SignerList, + Ticket, +} from "../ledger"; + +import { BaseRequest, BaseResponse } from "./baseMethod"; + export interface AccountObjectsRequest extends BaseRequest { - command: "account_objects" - account: string - type?: AccountObjectType - deletion_blockers_only?: boolean - ledger_hash?: string - ledger_index?: LedgerIndex - limit?: number - marker?: any + command: "account_objects"; + account: string; + type?: AccountObjectType; + deletion_blockers_only?: boolean; + ledger_hash?: string; + ledger_index?: LedgerIndex; + limit?: number; + marker?: any; } -type AccountObject = Check | DepositPreauth | Escrow | Offer | PayChannel | SignerList | Ticket | RippleState +type AccountObject = + | Check + | DepositPreauth + | Escrow + | Offer + | PayChannel + | SignerList + | Ticket + | RippleState; export interface AccountObjectsResponse extends BaseResponse { result: { - account: string - account_objects: AccountObject[] - ledger_hash?: string - ledger_index?: number - ledger_current_index?: number - limit?: number - marker?: string - validated?: boolean - } -} \ No newline at end of file + account: string; + account_objects: AccountObject[]; + ledger_hash?: string; + ledger_index?: number; + ledger_current_index?: number; + limit?: number; + marker?: string; + validated?: boolean; + }; +} diff --git a/src/models/methods/accountOffers.ts b/src/models/methods/accountOffers.ts index 2e89be37..5516eeba 100644 --- a/src/models/methods/accountOffers.ts +++ b/src/models/methods/accountOffers.ts @@ -1,32 +1,33 @@ import { Amount, LedgerIndex } from "../common"; + import { BaseRequest, BaseResponse } from "./baseMethod"; export interface AccountOffersRequest extends BaseRequest { - command: "account_offers" - account: string - ledger_hash?: string - ledger_index?: LedgerIndex - limit?: number - marker?: any - strict?: boolean + command: "account_offers"; + account: string; + ledger_hash?: string; + ledger_index?: LedgerIndex; + limit?: number; + marker?: any; + strict?: boolean; } interface AccountOffer { - flags: number - seq: number - taker_gets: Amount - taker_pays: Amount - quality: string - expiration?: number + flags: number; + seq: number; + taker_gets: Amount; + taker_pays: Amount; + quality: string; + expiration?: number; } export interface AccountOffersResponse extends BaseResponse { result: { - account: string - offers?: AccountOffer[] - ledger_current_index?: number - ledger_index?: number - ledger_hash?: string - marker?: any - } + account: string; + offers?: AccountOffer[]; + ledger_current_index?: number; + ledger_index?: number; + ledger_hash?: string; + marker?: any; + }; } diff --git a/src/models/methods/accountTx.ts b/src/models/methods/accountTx.ts index 09b9debb..e0abb1d5 100644 --- a/src/models/methods/accountTx.ts +++ b/src/models/methods/accountTx.ts @@ -1,36 +1,37 @@ import { LedgerIndex } from "../common"; import Metadata from "../common/metadata"; + import { BaseRequest, BaseResponse } from "./baseMethod"; export interface AccountTxRequest extends BaseRequest { - command: "account_tx" - account: string - ledger_index_min?: number - ledger_index_max?: number - ledger_hash?: string - ledger_index?: LedgerIndex - binary?: boolean - forward?: boolean - limit?: number - marker?: any + command: "account_tx"; + account: string; + ledger_index_min?: number; + ledger_index_max?: number; + ledger_hash?: string; + ledger_index?: LedgerIndex; + binary?: boolean; + forward?: boolean; + limit?: number; + marker?: any; } interface AccountTransaction { - ledger_index: number - meta: string | Metadata - tx?: any // TODO: replace when transaction objects are done - tx_blob?: string - validated: boolean + ledger_index: number; + meta: string | Metadata; + tx?: any; // TODO: replace when transaction objects are done + tx_blob?: string; + validated: boolean; } export interface AccountTxResponse extends BaseResponse { result: { - account: string - ledger_index_min: number - ledger_index_max: number - limit: number - marker?: any - transactions: AccountTransaction[] - validated?: boolean - } + account: string; + ledger_index_min: number; + ledger_index_max: number; + limit: number; + marker?: any; + transactions: AccountTransaction[]; + validated?: boolean; + }; } diff --git a/src/models/methods/baseMethod.ts b/src/models/methods/baseMethod.ts index 7c55da9f..0d1af5c0 100644 --- a/src/models/methods/baseMethod.ts +++ b/src/models/methods/baseMethod.ts @@ -1,27 +1,27 @@ import { Response } from "."; export interface BaseRequest { - id?: number | string - command: string - api_version?: number + id?: number | string; + command: string; + api_version?: number; } interface Warning { - id: number - message: string - details?: {[key: string]: string} + id: number; + message: string; + details?: { [key: string]: string }; } export interface BaseResponse { - id: number | string - status: "success" | "error" | string - type: "response" | string - result: any - warning?: "load" - warnings?: Warning[] - forwarded?: boolean - error?: string - error_message?: string - request?: Response - api_version?: number -} \ No newline at end of file + id: number | string; + status: "success" | "error" | string; + type: "response" | string; + result: any; + warning?: "load"; + warnings?: Warning[]; + forwarded?: boolean; + error?: string; + error_message?: string; + request?: Response; + api_version?: number; +} diff --git a/src/models/methods/bookOffers.ts b/src/models/methods/bookOffers.ts index 1222ebf3..3f9381d6 100644 --- a/src/models/methods/bookOffers.ts +++ b/src/models/methods/bookOffers.ts @@ -1,34 +1,35 @@ -import { Amount, LedgerIndex } from '../common'; -import { Offer } from '../ledger'; -import { BaseRequest, BaseResponse } from './baseMethod'; +import { Amount, LedgerIndex } from "../common"; +import { Offer } from "../ledger"; + +import { BaseRequest, BaseResponse } from "./baseMethod"; interface TakerAmount { - currency: string - issuer?: string + currency: string; + issuer?: string; } export interface BookOffersRequest extends BaseRequest { - command: "book_offers" - ledger_hash?: string - ledger_index?: LedgerIndex - limit?: number - taker?: string - taker_gets: TakerAmount - taker_pays: TakerAmount + command: "book_offers"; + ledger_hash?: string; + ledger_index?: LedgerIndex; + limit?: number; + taker?: string; + taker_gets: TakerAmount; + taker_pays: TakerAmount; } interface BookOffer extends Offer { - owner_funds?: string - taker_gets_funded?: Amount - taker_pays_funded?: Amount - quality?: string + owner_funds?: string; + taker_gets_funded?: Amount; + taker_pays_funded?: Amount; + quality?: string; } export interface BookOffersResponse extends BaseResponse { result: { - ledger_current_index?: number - ledger_index?: number - ledger_hash?: string - offers: BookOffer[] - } + ledger_current_index?: number; + ledger_index?: number; + ledger_hash?: string; + offers: BookOffer[]; + }; } diff --git a/src/models/methods/channelVerify.ts b/src/models/methods/channelVerify.ts index 4eb96566..c86b39bb 100644 --- a/src/models/methods/channelVerify.ts +++ b/src/models/methods/channelVerify.ts @@ -1,15 +1,15 @@ -import {BaseRequest, BaseResponse} from './baseMethod' +import { BaseRequest, BaseResponse } from "./baseMethod"; export interface ChannelVerifyRequest extends BaseRequest { - command: 'channel_verify' - amount: string - channel_id: string - public_key: string - signature: string + command: "channel_verify"; + amount: string; + channel_id: string; + public_key: string; + signature: string; } export interface ChannelVerifyResponse extends BaseResponse { result: { - signature_verified: boolean - } + signature_verified: boolean; + }; } diff --git a/src/models/methods/depositAuthorized.ts b/src/models/methods/depositAuthorized.ts index 686c3d39..94fc5ab9 100644 --- a/src/models/methods/depositAuthorized.ts +++ b/src/models/methods/depositAuthorized.ts @@ -1,22 +1,23 @@ -import { LedgerIndex } from '../common'; -import { BaseRequest, BaseResponse } from './baseMethod'; +import { LedgerIndex } from "../common"; + +import { BaseRequest, BaseResponse } from "./baseMethod"; export interface DepositAuthorizedRequest extends BaseRequest { - command: "deposit_authorized" - source_account: string - destination_account: string - ledger_hash?: string - ledger_index?: LedgerIndex + command: "deposit_authorized"; + source_account: string; + destination_account: string; + ledger_hash?: string; + ledger_index?: LedgerIndex; } export interface DepositAuthorizedResponse extends BaseResponse { result: { - deposit_authorized: boolean - destination_account: string - ledger_hash?: string - ledger_index?: number - ledger_current_index?: number - source_account: string - validated?: boolean - } + deposit_authorized: boolean; + destination_account: string; + ledger_hash?: string; + ledger_index?: number; + ledger_current_index?: number; + source_account: string; + validated?: boolean; + }; } diff --git a/src/models/methods/fee.ts b/src/models/methods/fee.ts index 7b57fe1f..aa5c9c61 100644 --- a/src/models/methods/fee.ts +++ b/src/models/methods/fee.ts @@ -1,27 +1,27 @@ import { BaseRequest, BaseResponse } from "./baseMethod"; export interface FeeRequest extends BaseRequest { - command: "fee" + command: "fee"; } export interface FeeResponse extends BaseResponse { - result: { - current_ledger_size: string - current_queue_size: string - drops: { - base_fee: string - median_fee: string - minimum_fee: string - open_ledger_fee: string - } - expected_ledger_size: string - ledger_current_index: number - levels: { - median_level: string - minimum_level: string - open_ledger_level: string - reference_level: string - } - max_queue_size: string - } -} \ No newline at end of file + result: { + current_ledger_size: string; + current_queue_size: string; + drops: { + base_fee: string; + median_fee: string; + minimum_fee: string; + open_ledger_fee: string; + }; + expected_ledger_size: string; + ledger_current_index: number; + levels: { + median_level: string; + minimum_level: string; + open_ledger_level: string; + reference_level: string; + }; + max_queue_size: string; + }; +} diff --git a/src/models/methods/gatewayBalances.ts b/src/models/methods/gatewayBalances.ts index b9da2d2d..a960bb1c 100644 --- a/src/models/methods/gatewayBalances.ts +++ b/src/models/methods/gatewayBalances.ts @@ -1,28 +1,29 @@ -import { LedgerIndex } from '../common' -import { BaseRequest, BaseResponse } from './baseMethod'; +import { LedgerIndex } from "../common"; + +import { BaseRequest, BaseResponse } from "./baseMethod"; export interface GatewayBalancesRequest extends BaseRequest { - command: "gateway_balances" - account: string - strict?: boolean - hotwallet: string | string[] - ledger_hash?: string - ledger_index?: LedgerIndex + command: "gateway_balances"; + account: string; + strict?: boolean; + hotwallet: string | string[]; + ledger_hash?: string; + ledger_index?: LedgerIndex; } interface Balance { - currency: string - value: string + currency: string; + value: string; } export interface GatewayBalancesResponse extends BaseResponse { result: { - account: string - obligations?: {[currency: string]: string} - balances?: {[address: string]: Balance[]} - assets?: {[address: string]: Balance[]} - ledger_hash?: string - ledger_current_index?: number - ledger_index?: number - } + account: string; + obligations?: { [currency: string]: string }; + balances?: { [address: string]: Balance[] }; + assets?: { [address: string]: Balance[] }; + ledger_hash?: string; + ledger_current_index?: number; + ledger_index?: number; + }; } diff --git a/src/models/methods/index.ts b/src/models/methods/index.ts index daf45968..4a8897be 100644 --- a/src/models/methods/index.ts +++ b/src/models/methods/index.ts @@ -1,195 +1,227 @@ -import { AccountChannelsRequest, AccountChannelsResponse } from "./accountChannels"; -import { AccountCurrenciesRequest, AccountCurrenciesResponse } from "./accountCurrencies"; +import { + AccountChannelsRequest, + AccountChannelsResponse, +} from "./accountChannels"; +import { + AccountCurrenciesRequest, + AccountCurrenciesResponse, +} from "./accountCurrencies"; import { AccountInfoRequest, AccountInfoResponse } from "./accountInfo"; import { AccountLinesRequest, AccountLinesResponse } from "./accountLines"; -import { AccountObjectsRequest, AccountObjectsResponse } from "./accountObjects"; +import { + AccountObjectsRequest, + AccountObjectsResponse, +} from "./accountObjects"; import { AccountOffersRequest, AccountOffersResponse } from "./accountOffers"; import { AccountTxRequest, AccountTxResponse } from "./accountTx"; import { BookOffersRequest, BookOffersResponse } from "./bookOffers"; import { ChannelVerifyRequest, ChannelVerifyResponse } from "./channelVerify"; -import { DepositAuthorizedRequest, DepositAuthorizedResponse } from "./depositAuthorized"; +import { + DepositAuthorizedRequest, + DepositAuthorizedResponse, +} from "./depositAuthorized"; import { FeeRequest, FeeResponse } from "./fee"; -import { GatewayBalancesRequest, GatewayBalancesResponse } from "./gatewayBalances"; +import { + GatewayBalancesRequest, + GatewayBalancesResponse, +} from "./gatewayBalances"; +import { LedgerRequest, LedgerResponse } from "./ledger"; +import { LedgerClosedRequest, LedgerClosedResponse } from "./ledgerClosed"; +import { LedgerCurrentRequest, LedgerCurrentResponse } from "./ledgerCurrent"; +import { LedgerDataRequest, LedgerDataResponse } from "./ledgerData"; +import { LedgerEntryRequest, LedgerEntryResponse } from "./ledgerEntry"; import { ManifestRequest, ManifestResponse } from "./manifest"; import { NoRippleCheckRequest, NoRippleCheckResponse } from "./norippleCheck"; -import { ConsensusStream, LedgerStream, OrderBookStream, PeerStatusStream, Stream, SubscribeRequest, SubscribeResponse, TransactionStream, ValidationStream } from "./subscribe"; -import { UnsubscribeRequest, UnsubscribeResponse } from "./unsubscribe"; import { PathFindRequest, PathFindResponse } from "./pathFind"; import { PingRequest, PingResponse } from "./ping"; import { RandomRequest, RandomResponse } from "./random"; -import { RipplePathFindRequest, RipplePathFindResponse } from "./ripplePathFind"; -import { LedgerRequest, LedgerResponse } from "./ledger"; -import { LedgerClosedRequest, LedgerClosedResponse } from "./ledgerClosed"; -import { LedgerDataRequest, LedgerDataResponse } from "./ledgerData"; -import { LedgerEntryRequest, LedgerEntryResponse } from "./ledgerEntry"; -import { LedgerCurrentRequest, LedgerCurrentResponse } from "./ledgerCurrent"; +import { + RipplePathFindRequest, + RipplePathFindResponse, +} from "./ripplePathFind"; import { ServerInfoRequest, ServerInfoResponse } from "./serverInfo"; import { ServerStateRequest, ServerStateResponse } from "./serverState"; import { SubmitRequest, SubmitResponse } from "./submit"; -import { SubmitMultisignedRequest, SubmitMultisignedResponse } from "./submitMultisigned"; -import { TransactionEntryRequest, TransactionEntryResponse } from "./transactionEntry"; +import { + SubmitMultisignedRequest, + SubmitMultisignedResponse, +} from "./submitMultisigned"; +import { + ConsensusStream, + LedgerStream, + OrderBookStream, + PeerStatusStream, + Stream, + SubscribeRequest, + SubscribeResponse, + TransactionStream, + ValidationStream, +} from "./subscribe"; +import { + TransactionEntryRequest, + TransactionEntryResponse, +} from "./transactionEntry"; import { TxRequest, TxResponse } from "./tx"; +import { UnsubscribeRequest, UnsubscribeResponse } from "./unsubscribe"; -type Request = // account methods - AccountChannelsRequest - | AccountCurrenciesRequest - | AccountInfoRequest - | AccountLinesRequest - | AccountObjectsRequest - | AccountOffersRequest - | AccountTxRequest - | GatewayBalancesRequest - | NoRippleCheckRequest - // ledger methods - | LedgerRequest - | LedgerClosedRequest - | LedgerCurrentRequest - | LedgerDataRequest - | LedgerEntryRequest - // transaction methods - | SubmitRequest - | SubmitMultisignedRequest - | TransactionEntryRequest - | TxRequest - // path and order book methods - | BookOffersRequest - | DepositAuthorizedRequest - | PathFindRequest - | RipplePathFindRequest - // payment channel methods - | ChannelVerifyRequest - // subscription methods - | SubscribeRequest - | UnsubscribeRequest - // server info methods - | FeeRequest - | ManifestRequest - | ServerInfoRequest - | ServerStateRequest - // utility methods - | PingRequest - | RandomRequest - - -type Response = // account methods - AccountChannelsResponse - | AccountCurrenciesResponse - | AccountInfoResponse - | AccountLinesResponse - | AccountObjectsResponse - | AccountOffersResponse - | AccountTxResponse - | GatewayBalancesResponse - | NoRippleCheckResponse - // ledger methods - | LedgerResponse - | LedgerClosedResponse - | LedgerCurrentResponse - | LedgerDataResponse - | LedgerEntryResponse - // transaction methods - | SubmitResponse - | SubmitMultisignedResponse - | TransactionEntryResponse - | TxResponse - // path and order book methods - | BookOffersResponse - | DepositAuthorizedResponse - | PathFindResponse - | RipplePathFindResponse - // payment channel methods - | ChannelVerifyResponse - // subscription methods - | SubscribeResponse - | UnsubscribeResponse - // server info methods - | FeeResponse - | ManifestResponse - | ServerInfoResponse - | ServerStateResponse - // utility methods - | PingResponse - | RandomResponse +type Request = // account methods + | AccountChannelsRequest + | AccountCurrenciesRequest + | AccountInfoRequest + | AccountLinesRequest + | AccountObjectsRequest + | AccountOffersRequest + | AccountTxRequest + | GatewayBalancesRequest + | NoRippleCheckRequest + // ledger methods + | LedgerRequest + | LedgerClosedRequest + | LedgerCurrentRequest + | LedgerDataRequest + | LedgerEntryRequest + // transaction methods + | SubmitRequest + | SubmitMultisignedRequest + | TransactionEntryRequest + | TxRequest + // path and order book methods + | BookOffersRequest + | DepositAuthorizedRequest + | PathFindRequest + | RipplePathFindRequest + // payment channel methods + | ChannelVerifyRequest + // subscription methods + | SubscribeRequest + | UnsubscribeRequest + // server info methods + | FeeRequest + | ManifestRequest + | ServerInfoRequest + | ServerStateRequest + // utility methods + | PingRequest + | RandomRequest; +type Response = // account methods + | AccountChannelsResponse + | AccountCurrenciesResponse + | AccountInfoResponse + | AccountLinesResponse + | AccountObjectsResponse + | AccountOffersResponse + | AccountTxResponse + | GatewayBalancesResponse + | NoRippleCheckResponse + // ledger methods + | LedgerResponse + | LedgerClosedResponse + | LedgerCurrentResponse + | LedgerDataResponse + | LedgerEntryResponse + // transaction methods + | SubmitResponse + | SubmitMultisignedResponse + | TransactionEntryResponse + | TxResponse + // path and order book methods + | BookOffersResponse + | DepositAuthorizedResponse + | PathFindResponse + | RipplePathFindResponse + // payment channel methods + | ChannelVerifyResponse + // subscription methods + | SubscribeResponse + | UnsubscribeResponse + // server info methods + | FeeResponse + | ManifestResponse + | ServerInfoResponse + | ServerStateResponse + // utility methods + | PingResponse + | RandomResponse; export { - Request, - Response, - // account methods - AccountChannelsRequest, - AccountChannelsResponse, - AccountCurrenciesRequest, - AccountCurrenciesResponse, - AccountInfoRequest, - AccountInfoResponse, - AccountLinesRequest, - AccountLinesResponse, - AccountObjectsRequest, - AccountObjectsResponse, - AccountOffersRequest, - AccountOffersResponse, - AccountTxRequest, - AccountTxResponse, - GatewayBalancesRequest, - GatewayBalancesResponse, - NoRippleCheckRequest, - NoRippleCheckResponse, - // ledger methods - LedgerRequest, - LedgerResponse, - LedgerClosedRequest, - LedgerClosedResponse, - LedgerCurrentRequest, - LedgerCurrentResponse, - LedgerDataRequest, - LedgerDataResponse, - LedgerEntryRequest, - LedgerEntryResponse, - // transaction methods - SubmitRequest, - SubmitResponse, - SubmitMultisignedRequest, - SubmitMultisignedResponse, - TransactionEntryRequest, - TransactionEntryResponse, - TxRequest, - TxResponse, - // path and order book methods - BookOffersRequest, - BookOffersResponse, - DepositAuthorizedRequest, - DepositAuthorizedResponse, - PathFindRequest, - PathFindResponse, - RipplePathFindRequest, - RipplePathFindResponse, - // payment channel methods - ChannelVerifyRequest, - ChannelVerifyResponse, - // Subscribe methods/streams - SubscribeRequest, - SubscribeResponse, - Stream, - LedgerStream, - ValidationStream, - TransactionStream, - PeerStatusStream, - OrderBookStream, - ConsensusStream, - UnsubscribeRequest, - UnsubscribeResponse, - // server info methods - FeeRequest, - FeeResponse, - ManifestRequest, - ManifestResponse, - ServerInfoRequest, - ServerInfoResponse, - ServerStateRequest, - ServerStateResponse, - // utility methods - PingRequest, - PingResponse, - RandomRequest, - RandomResponse -} + Request, + Response, + // account methods + AccountChannelsRequest, + AccountChannelsResponse, + AccountCurrenciesRequest, + AccountCurrenciesResponse, + AccountInfoRequest, + AccountInfoResponse, + AccountLinesRequest, + AccountLinesResponse, + AccountObjectsRequest, + AccountObjectsResponse, + AccountOffersRequest, + AccountOffersResponse, + AccountTxRequest, + AccountTxResponse, + GatewayBalancesRequest, + GatewayBalancesResponse, + NoRippleCheckRequest, + NoRippleCheckResponse, + // ledger methods + LedgerRequest, + LedgerResponse, + LedgerClosedRequest, + LedgerClosedResponse, + LedgerCurrentRequest, + LedgerCurrentResponse, + LedgerDataRequest, + LedgerDataResponse, + LedgerEntryRequest, + LedgerEntryResponse, + // transaction methods + SubmitRequest, + SubmitResponse, + SubmitMultisignedRequest, + SubmitMultisignedResponse, + TransactionEntryRequest, + TransactionEntryResponse, + TxRequest, + TxResponse, + // path and order book methods + BookOffersRequest, + BookOffersResponse, + DepositAuthorizedRequest, + DepositAuthorizedResponse, + PathFindRequest, + PathFindResponse, + RipplePathFindRequest, + RipplePathFindResponse, + // payment channel methods + ChannelVerifyRequest, + ChannelVerifyResponse, + // Subscribe methods/streams + SubscribeRequest, + SubscribeResponse, + Stream, + LedgerStream, + ValidationStream, + TransactionStream, + PeerStatusStream, + OrderBookStream, + ConsensusStream, + UnsubscribeRequest, + UnsubscribeResponse, + // server info methods + FeeRequest, + FeeResponse, + ManifestRequest, + ManifestResponse, + ServerInfoRequest, + ServerInfoResponse, + ServerStateRequest, + ServerStateResponse, + // utility methods + PingRequest, + PingResponse, + RandomRequest, + RandomResponse, +}; diff --git a/src/models/methods/ledger.ts b/src/models/methods/ledger.ts index ef22ffa3..59c7ebd2 100644 --- a/src/models/methods/ledger.ts +++ b/src/models/methods/ledger.ts @@ -1,46 +1,48 @@ import { LedgerIndex } from "../common"; import { Ledger } from "../ledger"; + import { BaseRequest, BaseResponse } from "./baseMethod"; export interface LedgerRequest extends BaseRequest { - command: "ledger" - ledger_hash?: string, - ledger_index?: LedgerIndex - full?: boolean - accounts?: boolean - transactions?: boolean - expand?: boolean - owner_funds?: boolean - binary?: boolean - queue?: boolean + command: "ledger"; + ledger_hash?: string; + ledger_index?: LedgerIndex; + full?: boolean; + accounts?: boolean; + transactions?: boolean; + expand?: boolean; + owner_funds?: boolean; + binary?: boolean; + queue?: boolean; } interface LedgerQueueData { - account: string - // TODO: Retype tx once we have transaction types - // Also include tx_blob as possible type: https://xrpl.org/ledger.html - // Also handle the special case where 'owner_funds: string' is a field of OfferCreate sometimes - https://xrpl.org/ledger.html#response-format - tx: any - retries_remaining: number - preflight_result: string - last_result?: string - auth_change?: boolean - fee?: string - fee_level?: string - max_spend_drops?: string + account: string; + // TODO: Retype tx once we have transaction types + // Also include tx_blob as possible type: https://xrpl.org/ledger.html + // Also handle the special case where 'owner_funds: string' is a field of OfferCreate sometimes - https://xrpl.org/ledger.html#response-format + tx: any; + retries_remaining: number; + preflight_result: string; + last_result?: string; + auth_change?: boolean; + fee?: string; + fee_level?: string; + max_spend_drops?: string; } -interface BinaryLedger extends Omit, 'accountState'> { - accountState?: string[] - transactions?: string[] +interface BinaryLedger + extends Omit, "accountState"> { + accountState?: string[]; + transactions?: string[]; } export interface LedgerResponse extends BaseResponse { - result: { - ledger: Ledger | BinaryLedger - ledger_hash: string - ledger_index: number - queue_data?: (LedgerQueueData | string)[] - validated: boolean //TODO: Figure out if the example is correct, or the documentation for this field - https://xrpl.org/ledger.html#response-format - } -} \ No newline at end of file + result: { + ledger: Ledger | BinaryLedger; + ledger_hash: string; + ledger_index: number; + queue_data?: Array; + validated: boolean; // TODO: Figure out if the example is correct, or the documentation for this field - https://xrpl.org/ledger.html#response-format + }; +} diff --git a/src/models/methods/ledgerClosed.ts b/src/models/methods/ledgerClosed.ts index 4b6d23eb..bf89459a 100644 --- a/src/models/methods/ledgerClosed.ts +++ b/src/models/methods/ledgerClosed.ts @@ -1,12 +1,12 @@ import { BaseRequest, BaseResponse } from "./baseMethod"; export interface LedgerClosedRequest extends BaseRequest { - command: "ledger_closed" + command: "ledger_closed"; } export interface LedgerClosedResponse extends BaseResponse { - result: { - ledger_hash: string - ledger_index: number - } -} \ No newline at end of file + result: { + ledger_hash: string; + ledger_index: number; + }; +} diff --git a/src/models/methods/ledgerCurrent.ts b/src/models/methods/ledgerCurrent.ts index 33624bf8..1507ff78 100644 --- a/src/models/methods/ledgerCurrent.ts +++ b/src/models/methods/ledgerCurrent.ts @@ -1,11 +1,11 @@ import { BaseRequest, BaseResponse } from "./baseMethod"; export interface LedgerCurrentRequest extends BaseRequest { - command: "ledger_current" + command: "ledger_current"; } export interface LedgerCurrentResponse extends BaseResponse { - result: { - ledger_current_index: number - } -} \ No newline at end of file + result: { + ledger_current_index: number; + }; +} diff --git a/src/models/methods/ledgerData.ts b/src/models/methods/ledgerData.ts index c647d539..88bd98c0 100644 --- a/src/models/methods/ledgerData.ts +++ b/src/models/methods/ledgerData.ts @@ -1,27 +1,30 @@ import { LedgerIndex } from "../common"; import { LedgerEntry } from "../ledger"; + import { BaseRequest, BaseResponse } from "./baseMethod"; export interface LedgerDataRequest extends BaseRequest { - command: "ledger_data" - ledger_hash?: string - ledger_index?: LedgerIndex - binary?: boolean - limit?: number - marker?: any + command: "ledger_data"; + ledger_hash?: string; + ledger_index?: LedgerIndex; + binary?: boolean; + limit?: number; + marker?: any; } -type LabeledLedgerEntry = ({ledgerEntryType: string} & LedgerEntry) +type LabeledLedgerEntry = { ledgerEntryType: string } & LedgerEntry; -type BinaryLedgerEntry = {data: string} +interface BinaryLedgerEntry { + data: string; +} -type State = {index: string} & (BinaryLedgerEntry | LabeledLedgerEntry) +type State = { index: string } & (BinaryLedgerEntry | LabeledLedgerEntry); export interface LedgerDataResponse extends BaseResponse { - result: { - ledger_index: number - ledger_hash: string - state: State[] - marker?: any - } -} \ No newline at end of file + result: { + ledger_index: number; + ledger_hash: string; + state: State[]; + marker?: any; + }; +} diff --git a/src/models/methods/ledgerEntry.ts b/src/models/methods/ledgerEntry.ts index 99c57160..3c015a6c 100644 --- a/src/models/methods/ledgerEntry.ts +++ b/src/models/methods/ledgerEntry.ts @@ -1,61 +1,72 @@ -import { BaseRequest, BaseResponse } from "./baseMethod"; -import { LedgerEntry } from "../ledger"; import { LedgerIndex } from "../common"; +import { LedgerEntry } from "../ledger"; + +import { BaseRequest, BaseResponse } from "./baseMethod"; export interface LedgerEntryRequest extends BaseRequest { - command: "ledger_entry" - binary?: boolean - ledger_hash?: string - ledger_index?: LedgerIndex + command: "ledger_entry"; + binary?: boolean; + ledger_hash?: string; + ledger_index?: LedgerIndex; - // Only one of the following properties should be defined in a single request - // https://xrpl.org/ledger_entry.html + // Only one of the following properties should be defined in a single request + // https://xrpl.org/ledger_entry.html - index?: string - - account_root?: string - - directory?: { - sub_index?: number - dir_root?: string - owner?: string - } | string + index?: string; - offer?: { - account: string - seq: number - } | string + account_root?: string; - ripple_state?: { - accounts: string[] - currency: string - } - - check?: string + directory?: + | { + sub_index?: number; + dir_root?: string; + owner?: string; + } + | string; - escrow?: { - owner: string - seq: number - } | string + offer?: + | { + account: string; + seq: number; + } + | string; - payment_channel?: string + ripple_state?: { + accounts: string[]; + currency: string; + }; - deposit_preauth?: { - owner: string - authorized: string - } | string - - ticket?: { - owner: string - ticket_sequence: number - } | string + check?: string; + + escrow?: + | { + owner: string; + seq: number; + } + | string; + + payment_channel?: string; + + deposit_preauth?: + | { + owner: string; + authorized: string; + } + | string; + + ticket?: + | { + owner: string; + ticket_sequence: number; + } + | string; } export interface LedgerEntryResponse extends BaseResponse { - result: { - index: string - ledger_index: number - node?: LedgerEntry - node_binary?: string - } -} \ No newline at end of file + result: { + index: string; + ledger_index: number; + node?: LedgerEntry; + node_binary?: string; + }; +} diff --git a/src/models/methods/manifest.ts b/src/models/methods/manifest.ts index 10851a42..0081fb5c 100644 --- a/src/models/methods/manifest.ts +++ b/src/models/methods/manifest.ts @@ -1,19 +1,19 @@ import { BaseRequest, BaseResponse } from "./baseMethod"; export interface ManifestRequest extends BaseRequest { - command: "manifest" - public_key: string + command: "manifest"; + public_key: string; } export interface ManifestResponse extends BaseResponse { - result: { - details?: { - domain: string - ephemeral_key: string - master_key: string - seq: number - } - manifest?: string - requested: string - } -} \ No newline at end of file + result: { + details?: { + domain: string; + ephemeral_key: string; + master_key: string; + seq: number; + }; + manifest?: string; + requested: string; + }; +} diff --git a/src/models/methods/norippleCheck.ts b/src/models/methods/norippleCheck.ts index 75d28cee..62628fb8 100644 --- a/src/models/methods/norippleCheck.ts +++ b/src/models/methods/norippleCheck.ts @@ -1,19 +1,20 @@ -import { LedgerIndex } from '../common' -import { BaseRequest, BaseResponse } from './baseMethod'; +import { LedgerIndex } from "../common"; + +import { BaseRequest, BaseResponse } from "./baseMethod"; export interface NoRippleCheckRequest extends BaseRequest { - command: "noripple_check" - account: string - role: "gateway" | "user" - transactions?: boolean - ledger_hash?: string - ledger_index?: LedgerIndex + command: "noripple_check"; + account: string; + role: "gateway" | "user"; + transactions?: boolean; + ledger_hash?: string; + ledger_index?: LedgerIndex; } export interface NoRippleCheckResponse extends BaseResponse { result: { - ledger_current_index: number - problems: string[] - transactions: any[] // TODO: fix once transaction objects are implemented - } + ledger_current_index: number; + problems: string[]; + transactions: any[]; // TODO: fix once transaction objects are implemented + }; } diff --git a/src/models/methods/pathFind.ts b/src/models/methods/pathFind.ts index 57efdf58..2d65858a 100644 --- a/src/models/methods/pathFind.ts +++ b/src/models/methods/pathFind.ts @@ -1,46 +1,50 @@ -import { Amount, Path } from '../common' -import { BaseRequest, BaseResponse } from './baseMethod'; +import { Amount, Path } from "../common"; + +import { BaseRequest, BaseResponse } from "./baseMethod"; interface BasePathFindRequest extends BaseRequest { - command: "path_find" - subcommand: string + command: "path_find"; + subcommand: string; } export interface PathFindCreateRequest extends BasePathFindRequest { - subcommand: "create" - source_account: string - destination_account: string - destination_amount: Amount - send_max?: Amount - paths?: Path[] + subcommand: "create"; + source_account: string; + destination_account: string; + destination_amount: Amount; + send_max?: Amount; + paths?: Path[]; } interface PathFindCloseRequest extends BasePathFindRequest { - subcommand: "close" + subcommand: "close"; } interface PathFindStatusRequest extends BasePathFindRequest { - subcommand: "status" + subcommand: "status"; } -export type PathFindRequest = PathFindCreateRequest | PathFindCloseRequest | PathFindStatusRequest +export type PathFindRequest = + | PathFindCreateRequest + | PathFindCloseRequest + | PathFindStatusRequest; interface PathOption { - paths_computed: Path[] - source_amount: Amount + paths_computed: Path[]; + source_amount: Amount; } export interface PathFindResponse extends BaseResponse { result: { - alternatives: PathOption[] - destination_account: string - destination_amount: Amount - source_account: string - full_reply: boolean - id?: number | string - closed?: true - status?: true - } + alternatives: PathOption[]; + destination_account: string; + destination_amount: Amount; + source_account: string; + full_reply: boolean; + id?: number | string; + closed?: true; + status?: true; + }; } // TODO: figure out where to put the path_find asynchronous follow-ups diff --git a/src/models/methods/ping.ts b/src/models/methods/ping.ts index a8de40d4..113c7eb6 100644 --- a/src/models/methods/ping.ts +++ b/src/models/methods/ping.ts @@ -1,9 +1,9 @@ import { BaseRequest, BaseResponse } from "./baseMethod"; export interface PingRequest extends BaseRequest { - command: "ping" + command: "ping"; } export interface PingResponse extends BaseResponse { - result: {} + result: {}; } diff --git a/src/models/methods/random.ts b/src/models/methods/random.ts index d474d9bf..af00c3d6 100644 --- a/src/models/methods/random.ts +++ b/src/models/methods/random.ts @@ -1,11 +1,11 @@ import { BaseRequest, BaseResponse } from "./baseMethod"; export interface RandomRequest extends BaseRequest { - command: "random" + command: "random"; } export interface RandomResponse extends BaseResponse { result: { - random: string - } + random: string; + }; } diff --git a/src/models/methods/ripplePathFind.ts b/src/models/methods/ripplePathFind.ts index 7e1721eb..d4c5e99f 100644 --- a/src/models/methods/ripplePathFind.ts +++ b/src/models/methods/ripplePathFind.ts @@ -1,31 +1,32 @@ import { Amount, LedgerIndex, Path } from "../common"; + import { BaseRequest, BaseResponse } from "./baseMethod"; interface SourceCurrencyAmount { - currency: string - issuer?: string - } + currency: string; + issuer?: string; +} export interface RipplePathFindRequest extends BaseRequest { - command: "ripple_path_find" - source_account: string - destination_account: string - destination_amount: Amount - send_max?: Amount - source_currencies?: SourceCurrencyAmount - ledger_hash?: string - ledger_index?: LedgerIndex + command: "ripple_path_find"; + source_account: string; + destination_account: string; + destination_amount: Amount; + send_max?: Amount; + source_currencies?: SourceCurrencyAmount; + ledger_hash?: string; + ledger_index?: LedgerIndex; } interface PathOption { - paths_computed: Path[] - source_amount: Amount + paths_computed: Path[]; + source_amount: Amount; } export interface RipplePathFindResponse extends BaseResponse { - result: { - alternatives: PathOption[] - destination_account: string - destination_currencies: string[] - } -} \ No newline at end of file + result: { + alternatives: PathOption[]; + destination_account: string; + destination_currencies: string[]; + }; +} diff --git a/src/models/methods/serverInfo.ts b/src/models/methods/serverInfo.ts index 503554f5..c7ed1879 100644 --- a/src/models/methods/serverInfo.ts +++ b/src/models/methods/serverInfo.ts @@ -1,75 +1,82 @@ import { BaseRequest, BaseResponse } from "./baseMethod"; export interface ServerInfoRequest extends BaseRequest { - command: "server_info" + command: "server_info"; } -export type ServerState = "disconnected" | "connected" | "syncing" | "tracking" | "full" | "validating" | "proposing" +export type ServerState = + | "disconnected" + | "connected" + | "syncing" + | "tracking" + | "full" + | "validating" + | "proposing"; export interface StateAccounting { - duration_us: string - transitions: number + duration_us: string; + transitions: number; } export interface JobType { - job_type: string - per_second: number - peak_time?: number - avg_time?: number - in_progress?: number + job_type: string; + per_second: number; + peak_time?: number; + avg_time?: number; + in_progress?: number; } export interface ServerInfoResponse extends BaseResponse { - result: { - info: { - amendment_blocked?: boolean - build_version: string - closed_ledger?: { - age: number - base_fee_xrp: number - hash: string - reserve_base_xrp: number - reserve_inc_xrp: number - seq: number - } - complete_ledgers: string - hostid: string - io_latency_ms: number - jq_trans_overflow: string - last_close: { - converge_time_s: number - proposers: number - } - load?: { - job_types: JobType[] - threads: number - } - load_factor: number - load_factor_local?: number - load_factor_net?: number - load_factor_cluster?: number - load_factor_fee_escalation?: number - load_factor_fee_queue?: number - load_factor_server?: number - network_ledger?: "waiting" - peers: number - pubkey_node: string - pubkey_validator?: string - server_state: ServerState - server_state_duration_us: number - state_accounting: Record - time: string - uptime: number - validated_ledger?: { - age: number - base_fee_xrp: number - hash: string - reserve_base_xrp: number - reserve_inc_xrp: number - seq: number - } - validation_quorum: number - validator_list_expires?: string - } - } -} \ No newline at end of file + result: { + info: { + amendment_blocked?: boolean; + build_version: string; + closed_ledger?: { + age: number; + base_fee_xrp: number; + hash: string; + reserve_base_xrp: number; + reserve_inc_xrp: number; + seq: number; + }; + complete_ledgers: string; + hostid: string; + io_latency_ms: number; + jq_trans_overflow: string; + last_close: { + converge_time_s: number; + proposers: number; + }; + load?: { + job_types: JobType[]; + threads: number; + }; + load_factor: number; + load_factor_local?: number; + load_factor_net?: number; + load_factor_cluster?: number; + load_factor_fee_escalation?: number; + load_factor_fee_queue?: number; + load_factor_server?: number; + network_ledger?: "waiting"; + peers: number; + pubkey_node: string; + pubkey_validator?: string; + server_state: ServerState; + server_state_duration_us: number; + state_accounting: Record; + time: string; + uptime: number; + validated_ledger?: { + age: number; + base_fee_xrp: number; + hash: string; + reserve_base_xrp: number; + reserve_inc_xrp: number; + seq: number; + }; + validation_quorum: number; + validator_list_expires?: string; + }; + }; +} diff --git a/src/models/methods/serverState.ts b/src/models/methods/serverState.ts index 3ae12194..20969a87 100644 --- a/src/models/methods/serverState.ts +++ b/src/models/methods/serverState.ts @@ -2,56 +2,56 @@ import { BaseRequest, BaseResponse } from "./baseMethod"; import { JobType, ServerState, StateAccounting } from "./serverInfo"; export interface ServerStateRequest extends BaseRequest { - command: "server_state" + command: "server_state"; } export interface ServerStateResponse extends BaseResponse { - result: { - state: { - amendment_blocked?: boolean - build_version: string - complete_ledgers: string - closed_ledger?: { - age: number - base_fee: number - hash: string - reserve_base: number - reserve_inc: number - seq: number - } - io_latency_ms: number - jq_trans_overflow: string - last_close: { - converge_time_s: number - proposers: number - } - load?: { - job_types: JobType[] - threads: number - } - load_base: number - load_factor: number - load_factor_fee_escalation?: number - load_factor_fee_queue?: number - load_factor_fee_reference?: number - load_factor_server?: number - peers: number - pubkey_node: string - pubkey_validator?: string - server_state: ServerState - server_state_duration_us: number - state_accounting: Record - time: string - uptime: number - validated_ledger?: { - age: number - base_fee: number - hash: string - reserve_base: number - reserve_inc: number - seq: number - } - validation_quorum: number - validator_list_expires?: string - } - } -} \ No newline at end of file + result: { + state: { + amendment_blocked?: boolean; + build_version: string; + complete_ledgers: string; + closed_ledger?: { + age: number; + base_fee: number; + hash: string; + reserve_base: number; + reserve_inc: number; + seq: number; + }; + io_latency_ms: number; + jq_trans_overflow: string; + last_close: { + converge_time_s: number; + proposers: number; + }; + load?: { + job_types: JobType[]; + threads: number; + }; + load_base: number; + load_factor: number; + load_factor_fee_escalation?: number; + load_factor_fee_queue?: number; + load_factor_fee_reference?: number; + load_factor_server?: number; + peers: number; + pubkey_node: string; + pubkey_validator?: string; + server_state: ServerState; + server_state_duration_us: number; + state_accounting: Record; + time: string; + uptime: number; + validated_ledger?: { + age: number; + base_fee: number; + hash: string; + reserve_base: number; + reserve_inc: number; + seq: number; + }; + validation_quorum: number; + validator_list_expires?: string; + }; + }; +} diff --git a/src/models/methods/submit.ts b/src/models/methods/submit.ts index c5e9f911..95ef6a5a 100644 --- a/src/models/methods/submit.ts +++ b/src/models/methods/submit.ts @@ -1,26 +1,26 @@ import { BaseRequest, BaseResponse } from "./baseMethod"; export interface SubmitRequest extends BaseRequest { - command: "submit" - tx_blob: string - fail_hard?: boolean + command: "submit"; + tx_blob: string; + fail_hard?: boolean; } export interface SubmitResponse extends BaseResponse { result: { - engine_result: string - engine_result_code: number - engine_result_message: string - tx_blob: string - tx_json: any // TODO: type this properly when we have Transaction types - accepted: boolean - account_sequence_available: number - account_sequence_next: number - applied: boolean - broadcast: boolean - kept: boolean - queued: boolean - open_ledger_cost: string - validated_ledger_index: number - } + engine_result: string; + engine_result_code: number; + engine_result_message: string; + tx_blob: string; + tx_json: any; // TODO: type this properly when we have Transaction types + accepted: boolean; + account_sequence_available: number; + account_sequence_next: number; + applied: boolean; + broadcast: boolean; + kept: boolean; + queued: boolean; + open_ledger_cost: string; + validated_ledger_index: number; + }; } diff --git a/src/models/methods/submitMultisigned.ts b/src/models/methods/submitMultisigned.ts index ec51d240..4a147f4d 100644 --- a/src/models/methods/submitMultisigned.ts +++ b/src/models/methods/submitMultisigned.ts @@ -1,17 +1,17 @@ import { BaseRequest, BaseResponse } from "./baseMethod"; export interface SubmitMultisignedRequest extends BaseRequest { - command: "submit_multisigned" - tx_json: any // TODO: type this properly when we have Transaction types - fail_hard?: boolean + command: "submit_multisigned"; + tx_json: any; // TODO: type this properly when we have Transaction types + fail_hard?: boolean; } export interface SubmitMultisignedResponse extends BaseResponse { result: { - engine_result: string - engine_result_code: number - engine_result_message: string - tx_blob: string - tx_json: any // TODO: type this properly when we have Transaction types - } + engine_result: string; + engine_result_code: number; + engine_result_message: string; + tx_blob: string; + tx_json: any; // TODO: type this properly when we have Transaction types + }; } diff --git a/src/models/methods/subscribe.ts b/src/models/methods/subscribe.ts index 3c3220eb..c598e852 100644 --- a/src/models/methods/subscribe.ts +++ b/src/models/methods/subscribe.ts @@ -1,107 +1,118 @@ -import { BaseRequest, BaseResponse } from './baseMethod' -import { Currency, StreamType } from "../common" -import { TransactionMetadata } from '../common/transaction' +import { Currency, StreamType } from "../common"; +import { TransactionMetadata } from "../common/transaction"; + +import { BaseRequest, BaseResponse } from "./baseMethod"; interface Book { - taker_gets: Currency - taker_pays: Currency - taker: string - snapshot?: boolean - both?: boolean + taker_gets: Currency; + taker_pays: Currency; + taker: string; + snapshot?: boolean; + both?: boolean; } - + export interface SubscribeRequest extends BaseRequest { - command: "subscribe" - streams?: StreamType[] - accounts?: string[] - accounts_proposed?: string[] - books?: Book[] - url?: string - url_username?: string - url_password?: string + command: "subscribe"; + streams?: StreamType[]; + accounts?: string[]; + accounts_proposed?: string[]; + books?: Book[]; + url?: string; + url_username?: string; + url_password?: string; } export interface SubscribeResponse extends BaseResponse { - result: any + result: any; } interface BaseStream { - type: string + type: string; } export interface LedgerStream extends BaseStream { - type: "ledgerClosed" - fee_base: number - fee_ref: number - ledger_hash: string - ledger_index: number - ledger_time: number - reserve_base: number - reserve_inc: number - txn_count: number - validated_ledgers?: string + type: "ledgerClosed"; + fee_base: number; + fee_ref: number; + ledger_hash: string; + ledger_index: number; + ledger_time: number; + reserve_base: number; + reserve_inc: number; + txn_count: number; + validated_ledgers?: string; } export interface ValidationStream extends BaseStream { - type: "validationReceived" - amendments?: string[] - base_fee?: number - flags: number - full: boolean - ledger_hash: string - ledger_index: string - load_fee?: number - master_key?: string - reserve_base?: number - reserve_inc?: number - signature: string - signing_time: number - validation_public_key: string + type: "validationReceived"; + amendments?: string[]; + base_fee?: number; + flags: number; + full: boolean; + ledger_hash: string; + ledger_index: string; + load_fee?: number; + master_key?: string; + reserve_base?: number; + reserve_inc?: number; + signature: string; + signing_time: number; + validation_public_key: string; } export interface TransactionStream extends BaseStream { - status: string - type: "transaction" - engine_result: string - engine_result_code: number - engine_result_message: string - ledger_current_index?: number - ledger_hash?: string - ledger_index?: number - meta?: TransactionMetadata - transaction: any // TODO: replace when we have types for transactions - validated?: boolean + status: string; + type: "transaction"; + engine_result: string; + engine_result_code: number; + engine_result_message: string; + ledger_current_index?: number; + ledger_hash?: string; + ledger_index?: number; + meta?: TransactionMetadata; + transaction: any; // TODO: replace when we have types for transactions + validated?: boolean; } export interface PeerStatusStream extends BaseStream { - type: "peerStatusChange" - action: "CLOSING_LEDGER" | "ACCEPTED_LEDGER" | "SWITCHED_LEDGER" | "LOST_SYNC" - date: number - ledger_hash?: string - ledger_index?: number - ledger_index_max?: number - ledger_index_min?: number + type: "peerStatusChange"; + action: + | "CLOSING_LEDGER" + | "ACCEPTED_LEDGER" + | "SWITCHED_LEDGER" + | "LOST_SYNC"; + date: number; + ledger_hash?: string; + ledger_index?: number; + ledger_index_max?: number; + ledger_index_min?: number; } export interface OrderBookStream extends BaseStream { - status: string - type: "transaction" - engine_result: string - engine_result_code: number - engine_result_message: string - ledger_current_index?: number - ledger_hash?: string - ledger_index?: number - meta: TransactionMetadata - transaction: any // TODO: replace when we have types for transactions - // TODO: transactions for this object have a special case for OfferCreate - // https://xrpl.org/subscribe.html#order-book-streams - validated: boolean + status: string; + type: "transaction"; + engine_result: string; + engine_result_code: number; + engine_result_message: string; + ledger_current_index?: number; + ledger_hash?: string; + ledger_index?: number; + meta: TransactionMetadata; + transaction: any; // TODO: replace when we have types for transactions + // TODO: transactions for this object have a special case for OfferCreate + // https://xrpl.org/subscribe.html#order-book-streams + validated: boolean; } export interface ConsensusStream extends BaseStream { - type: "consensusPhase" - consensus: "open" | "establish" | "accepted" + type: "consensusPhase"; + consensus: "open" | "establish" | "accepted"; } -export type Stream = LedgerStream | ValidationStream | TransactionStream | PeerStatusStream | OrderBookStream | ConsensusStream \ No newline at end of file +export type Stream = + | LedgerStream + | ValidationStream + | TransactionStream + | PeerStatusStream + | OrderBookStream + | ConsensusStream; diff --git a/src/models/methods/transactionEntry.ts b/src/models/methods/transactionEntry.ts index ef006aca..3dd82ea6 100644 --- a/src/models/methods/transactionEntry.ts +++ b/src/models/methods/transactionEntry.ts @@ -1,19 +1,20 @@ import { LedgerIndex } from "../common"; import { TransactionMetadata } from "../common/transaction"; + import { BaseRequest, BaseResponse } from "./baseMethod"; export interface TransactionEntryRequest extends BaseRequest { - command: "transaction_entry" - ledger_hash?: string - ledger_index?: LedgerIndex - tx_hash: string + command: "transaction_entry"; + ledger_hash?: string; + ledger_index?: LedgerIndex; + tx_hash: string; } export interface TransactionEntryResponse extends BaseResponse { result: { - ledger_hash: string - ledger_index: number - metadata: TransactionMetadata - tx_json: any // TODO: type this properly when we have Transaction types - } + ledger_hash: string; + ledger_index: number; + metadata: TransactionMetadata; + tx_json: any; // TODO: type this properly when we have Transaction types + }; } diff --git a/src/models/methods/tx.ts b/src/models/methods/tx.ts index 48137886..78c1d843 100644 --- a/src/models/methods/tx.ts +++ b/src/models/methods/tx.ts @@ -1,20 +1,21 @@ import { TransactionMetadata } from "../common/transaction"; + import { BaseRequest, BaseResponse } from "./baseMethod"; export interface TxRequest extends BaseRequest { - command: "tx" - transaction: string - binary?: boolean - min_ledger?: number - max_ledger?: number + command: "tx"; + transaction: string; + binary?: boolean; + min_ledger?: number; + max_ledger?: number; } export interface TxResponse extends BaseResponse { result: { - hash: string - ledger_index: number - meta: TransactionMetadata | string - validated?: boolean - } // TODO: needs to be `& Transaction` once that type is available - searched_all?: boolean + hash: string; + ledger_index: number; + meta: TransactionMetadata | string; + validated?: boolean; + }; // TODO: needs to be `& Transaction` once that type is available + searched_all?: boolean; } diff --git a/src/models/methods/unsubscribe.ts b/src/models/methods/unsubscribe.ts index 2cadae10..d9e67044 100644 --- a/src/models/methods/unsubscribe.ts +++ b/src/models/methods/unsubscribe.ts @@ -1,20 +1,21 @@ import { Currency, StreamType } from "../common"; + import { BaseRequest, BaseResponse } from "./baseMethod"; interface Book { - taker_gets: Currency - taker_pays: Currency - both?: boolean + taker_gets: Currency; + taker_pays: Currency; + both?: boolean; } - + export interface UnsubscribeRequest extends BaseRequest { - command: "unsubscribe" - streams?: StreamType[] - accounts?: string[] - accounts_proposed?: string[] - books?: Book[] + command: "unsubscribe"; + streams?: StreamType[]; + accounts?: string[]; + accounts_proposed?: string[]; + books?: Book[]; } export interface UnsubscribeResponse extends BaseResponse { - result: {} -} \ No newline at end of file + result: {}; +} diff --git a/src/models/transactions/accountDelete.ts b/src/models/transactions/accountDelete.ts index 4b9a7efd..e3f465e6 100644 --- a/src/models/transactions/accountDelete.ts +++ b/src/models/transactions/accountDelete.ts @@ -1,28 +1,35 @@ import { ValidationError } from "../../common/errors"; + import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface AccountDelete extends BaseTransaction { - TransactionType: "AccountDelete"; - Destination: string; - DestinationTag?: number; + TransactionType: "AccountDelete"; + Destination: string; + DestinationTag?: number; } /** * Verify the form and type of an AccountDelete at runtime. - * - * @param tx - An AccountDelete Transaction - * @returns - Void. - * @throws - When the AccountDelete is Malformed. + * + * @param tx - An AccountDelete Transaction. + * @returns Void. + * @throws When the AccountDelete is Malformed. */ - export function verifyAccountDelete(tx: AccountDelete): void { - verifyBaseTransaction(tx) +export function verifyAccountDelete(tx: AccountDelete): void { + verifyBaseTransaction(tx); - if (tx.Destination === undefined) - throw new ValidationError("AccountDelete: missing field Destination") - - if (typeof tx.Destination !== 'string') - throw new ValidationError("AccountDelete: invalid Destination") + if (tx.Destination === undefined) { + throw new ValidationError("AccountDelete: missing field Destination"); + } - if (tx.DestinationTag !== undefined && typeof tx.DestinationTag !== 'number') - throw new ValidationError("AccountDelete: invalid DestinationTag") -} \ No newline at end of file + if (typeof tx.Destination !== "string") { + throw new ValidationError("AccountDelete: invalid Destination"); + } + + if ( + tx.DestinationTag !== undefined && + typeof tx.DestinationTag !== "number" + ) { + throw new ValidationError("AccountDelete: invalid DestinationTag"); + } +} diff --git a/src/models/transactions/accountSet.ts b/src/models/transactions/accountSet.ts index cfe6dce8..c72a36cc 100644 --- a/src/models/transactions/accountSet.ts +++ b/src/models/transactions/accountSet.ts @@ -1,69 +1,80 @@ -import { ValidationError } from "../../common/errors" -import { BaseTransaction, verifyBaseTransaction } from "./common" +import { ValidationError } from "../../common/errors"; + +import { BaseTransaction, verifyBaseTransaction } from "./common"; enum AccountSetFlagEnum { - asfRequireDest = 1, - asfRequireAuth = 2, - asfDisallowXRP = 3, - asfDisableMaster = 4, - asfAccountTxnID = 5, - asfNoFreeze = 6, - asfGlobalFreeze = 7, - asfDefaultRipple = 8, - asfDepositAuth = 9, + asfRequireDest = 1, + asfRequireAuth = 2, + asfDisallowXRP = 3, + asfDisableMaster = 4, + asfAccountTxnID = 5, + asfNoFreeze = 6, + asfGlobalFreeze = 7, + asfDefaultRipple = 8, + asfDepositAuth = 9, } export interface AccountSet extends BaseTransaction { - TransactionType: "AccountSet" - ClearFlag?: number - Domain?: string - EmailHash?: string - MessageKey?: string - SetFlag?: AccountSetFlagEnum - TransferRate?: number - TickSize?: number + TransactionType: "AccountSet"; + ClearFlag?: number; + Domain?: string; + EmailHash?: string; + MessageKey?: string; + SetFlag?: AccountSetFlagEnum; + TransferRate?: number; + TickSize?: number; } /** * Verify the form and type of an AccountSet at runtime. - * - * @param tx - An AccountSet Transaction - * @returns - Void. - * @throws - When the AccountSet is Malformed. + * + * @param tx - An AccountSet Transaction. + * @returns Void. + * @throws When the AccountSet is Malformed. */ - export function verifyAccountSet(tx: AccountSet): void { - verifyBaseTransaction(tx) +export function verifyAccountSet(tx: AccountSet): void { + verifyBaseTransaction(tx); - if (tx.ClearFlag !== undefined){ - if (typeof tx.ClearFlag !== 'number') - throw new ValidationError("AccountSet: invalid ClearFlag") - if (!Object.values(AccountSetFlagEnum).includes(tx.ClearFlag)) - throw new ValidationError("AccountSet: invalid ClearFlag") + if (tx.ClearFlag !== undefined) { + if (typeof tx.ClearFlag !== "number") { + throw new ValidationError("AccountSet: invalid ClearFlag"); } - - if (tx.Domain !== undefined && typeof tx.Domain !== 'string') - throw new ValidationError("AccountSet: invalid Domain") - - if (tx.EmailHash !== undefined && typeof tx.EmailHash !== 'string') - throw new ValidationError("AccountSet: invalid EmailHash") - - if (tx.MessageKey !== undefined && typeof tx.MessageKey !== 'string') - throw new ValidationError("AccountSet: invalid MessageKey") - - if (tx.SetFlag !== undefined){ - if (typeof tx.SetFlag !== 'number') - throw new ValidationError("AccountSet: invalid SetFlag") - if (!Object.values(AccountSetFlagEnum).includes(tx.SetFlag)) - throw new ValidationError("AccountSet: invalid SetFlag") + if (!Object.values(AccountSetFlagEnum).includes(tx.ClearFlag)) { + throw new ValidationError("AccountSet: invalid ClearFlag"); } + } - if (tx.TransferRate !== undefined && typeof tx.TransferRate !== 'number') - throw new ValidationError("AccountSet: invalid TransferRate") - - if (tx.TickSize !== undefined){ - if (typeof tx.TickSize !== 'number') - throw new ValidationError("AccountSet: invalid TickSize") - if (tx.TickSize !== 0 && (3 > tx.TickSize || tx.TickSize > 15)) - throw new ValidationError("AccountSet: invalid TickSize") + if (tx.Domain !== undefined && typeof tx.Domain !== "string") { + throw new ValidationError("AccountSet: invalid Domain"); + } + + if (tx.EmailHash !== undefined && typeof tx.EmailHash !== "string") { + throw new ValidationError("AccountSet: invalid EmailHash"); + } + + if (tx.MessageKey !== undefined && typeof tx.MessageKey !== "string") { + throw new ValidationError("AccountSet: invalid MessageKey"); + } + + if (tx.SetFlag !== undefined) { + if (typeof tx.SetFlag !== "number") { + throw new ValidationError("AccountSet: invalid SetFlag"); } + if (!Object.values(AccountSetFlagEnum).includes(tx.SetFlag)) { + throw new ValidationError("AccountSet: invalid SetFlag"); + } + } + + if (tx.TransferRate !== undefined && typeof tx.TransferRate !== "number") { + throw new ValidationError("AccountSet: invalid TransferRate"); + } + + if (tx.TickSize !== undefined) { + if (typeof tx.TickSize !== "number") { + throw new ValidationError("AccountSet: invalid TickSize"); + } + if (tx.TickSize !== 0 && (tx.TickSize < 3 || tx.TickSize > 15)) { + throw new ValidationError("AccountSet: invalid TickSize"); + } + } } diff --git a/src/models/transactions/checkCancel.ts b/src/models/transactions/checkCancel.ts index be14edad..af365142 100644 --- a/src/models/transactions/checkCancel.ts +++ b/src/models/transactions/checkCancel.ts @@ -1,21 +1,23 @@ import { ValidationError } from "../../common/errors"; + import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface CheckCancel extends BaseTransaction { - TransactionType: "CheckCancel"; - CheckID: string; + TransactionType: "CheckCancel"; + CheckID: string; } /** * Verify the form and type of an CheckCancel at runtime. - * - * @param tx - An CheckCancel Transaction - * @returns - Void. - * @throws - When the CheckCancel is Malformed. + * + * @param tx - An CheckCancel Transaction. + * @returns Void. + * @throws When the CheckCancel is Malformed. */ - export function verifyCheckCancel(tx: CheckCancel): void { - verifyBaseTransaction(tx) +export function verifyCheckCancel(tx: CheckCancel): void { + verifyBaseTransaction(tx); - if (tx.CheckID !== undefined && typeof tx.CheckID !== 'string') - throw new ValidationError("CheckCancel: invalid CheckID") -} \ No newline at end of file + if (tx.CheckID !== undefined && typeof tx.CheckID !== "string") { + throw new ValidationError("CheckCancel: invalid CheckID"); + } +} diff --git a/src/models/transactions/checkCash.ts b/src/models/transactions/checkCash.ts index 558e86b6..48044f64 100644 --- a/src/models/transactions/checkCash.ts +++ b/src/models/transactions/checkCash.ts @@ -1,36 +1,54 @@ import { ValidationError } from "../../common/errors"; import { Amount } from "../common"; + import { BaseTransaction, verifyBaseTransaction, isAmount } from "./common"; export interface CheckCash extends BaseTransaction { - TransactionType: "CheckCash"; - CheckID: string; - Amount?: Amount; - DeliverMin?: Amount; + TransactionType: "CheckCash"; + CheckID: string; + Amount?: Amount; + DeliverMin?: Amount; } /** * Verify the form and type of an CheckCash at runtime. - * - * @param tx - An CheckCash Transaction - * @returns - Void. - * @throws - When the CheckCash is Malformed. + * + * @param tx - An CheckCash Transaction. + * @returns Void. + * @throws When the CheckCash is Malformed. */ - export function verifyCheckCash(tx: CheckCash): void { - verifyBaseTransaction(tx) +export function verifyCheckCash(tx: CheckCash): void { + verifyBaseTransaction(tx); - if (tx.hasOwnProperty('Amount') && tx.hasOwnProperty('DeliverMin')) - throw new ValidationError("CheckCash: cannot have both Amount and DeliverMin") - - if (!tx.hasOwnProperty('Amount') && !tx.hasOwnProperty('DeliverMin')) - throw new ValidationError("CheckCash: must have either Amount or DeliverMin") + if (!tx.hasOwnProperty("Amount") && !tx.hasOwnProperty("DeliverMin")) { + throw new ValidationError( + "CheckCash: must have either Amount or DeliverMin" + ); + } - if (tx.hasOwnProperty('Amount') && tx.Amount !== undefined && !isAmount(tx.Amount)) - throw new ValidationError("CheckCash: invalid Amount") + if (tx.hasOwnProperty("Amount") && tx.hasOwnProperty("DeliverMin")) { + throw new ValidationError( + "CheckCash: cannot have both Amount and DeliverMin" + ); + } - if (tx.hasOwnProperty('DeliverMin') && tx.DeliverMin !== undefined && !isAmount(tx.DeliverMin)) - throw new ValidationError("CheckCash: invalid DeliverMin") + if ( + tx.hasOwnProperty("Amount") && + tx.Amount !== undefined && + !isAmount(tx.Amount) + ) { + throw new ValidationError("CheckCash: invalid Amount"); + } - if (tx.CheckID !== undefined && typeof tx.CheckID !== 'string') - throw new ValidationError("CheckCash: invalid CheckID") -} \ No newline at end of file + if ( + tx.hasOwnProperty("DeliverMin") && + tx.DeliverMin !== undefined && + !isAmount(tx.DeliverMin) + ) { + throw new ValidationError("CheckCash: invalid DeliverMin"); + } + + if (tx.CheckID !== undefined && typeof tx.CheckID !== "string") { + throw new ValidationError("CheckCash: invalid CheckID"); + } +} diff --git a/src/models/transactions/checkCreate.ts b/src/models/transactions/checkCreate.ts index f09756c9..5dfc6947 100644 --- a/src/models/transactions/checkCreate.ts +++ b/src/models/transactions/checkCreate.ts @@ -1,51 +1,64 @@ import { ValidationError } from "../../common/errors"; import { Amount, IssuedCurrencyAmount } from "../common"; + import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface CheckCreate extends BaseTransaction { - TransactionType: "CheckCreate"; - Destination: string; - SendMax: Amount; - DestinationTag?: number; - Expiration?: number; - InvoiceID?: string + TransactionType: "CheckCreate"; + Destination: string; + SendMax: Amount; + DestinationTag?: number; + Expiration?: number; + InvoiceID?: string; } /** * Verify the form and type of an CheckCreate at runtime. - * - * @param tx - An CheckCreate Transaction - * @returns - Void. - * @throws - When the CheckCreate is Malformed. + * + * @param tx - An CheckCreate Transaction. + * @returns Void. + * @throws When the CheckCreate is Malformed. */ - export function verifyCheckCreate(tx: CheckCreate): void { - verifyBaseTransaction(tx) +export function verifyCheckCreate(tx: CheckCreate): void { + verifyBaseTransaction(tx); - if (tx.SendMax === undefined) - throw new ValidationError("CheckCreate: missing field SendMax") + if (tx.SendMax === undefined) { + throw new ValidationError("CheckCreate: missing field SendMax"); + } - if (tx.Destination === undefined) - throw new ValidationError("CheckCreate: missing field Destination") + if (tx.Destination === undefined) { + throw new ValidationError("CheckCreate: missing field Destination"); + } - const isIssuedCurrency = (obj: IssuedCurrencyAmount): boolean => { - return Object.keys(obj).length === 3 - && typeof obj.value === 'string' - && typeof obj.issuer === 'string' - && typeof obj.currency === 'string' - } + const isIssuedCurrency = (obj: IssuedCurrencyAmount): boolean => { + return ( + Object.keys(obj).length === 3 && + typeof obj.value === "string" && + typeof obj.issuer === "string" && + typeof obj.currency === "string" + ); + }; - if (typeof tx.SendMax !== 'string' && !isIssuedCurrency(tx.SendMax)) - throw new ValidationError("CheckCreate: invalid SendMax") + if (typeof tx.SendMax !== "string" && !isIssuedCurrency(tx.SendMax)) { + throw new ValidationError("CheckCreate: invalid SendMax"); + } - if (typeof tx.Destination !== 'string') - throw new ValidationError("CheckCreate: invalid Destination") + if (typeof tx.Destination !== "string") { + throw new ValidationError("CheckCreate: invalid Destination"); + } - if (tx.DestinationTag !== undefined && typeof tx.DestinationTag !== 'number') - throw new ValidationError("CheckCreate: invalid DestinationTag") + if ( + tx.DestinationTag !== undefined && + typeof tx.DestinationTag !== "number" + ) { + throw new ValidationError("CheckCreate: invalid DestinationTag"); + } - if (tx.Expiration !== undefined && typeof tx.Expiration !== 'number') - throw new ValidationError("CheckCreate: invalid Expiration") + if (tx.Expiration !== undefined && typeof tx.Expiration !== "number") { + throw new ValidationError("CheckCreate: invalid Expiration"); + } - if (tx.InvoiceID !== undefined && typeof tx.InvoiceID !== 'string') - throw new ValidationError("CheckCreate: invalid InvoiceID") -} \ No newline at end of file + if (tx.InvoiceID !== undefined && typeof tx.InvoiceID !== "string") { + throw new ValidationError("CheckCreate: invalid InvoiceID"); + } +} diff --git a/src/models/transactions/common.ts b/src/models/transactions/common.ts index 151e6135..1763a1d7 100644 --- a/src/models/transactions/common.ts +++ b/src/models/transactions/common.ts @@ -1,66 +1,73 @@ -import { ValidationError } from "../../common/errors" -import { Amount, Memo, Signer, IssuedCurrencyAmount } from "../common" -import { onlyHasFields } from "../utils" +import { ValidationError } from "../../common/errors"; +import { Amount, Memo, Signer, IssuedCurrencyAmount } from "../common"; +import { onlyHasFields } from "../utils"; const transactionTypes = [ - "AccountSet", - "AccountDelete", - "CheckCancel", - "CheckCash", - "CheckCreate", - "DepositPreauth", - "EscrowCancel", - "EscrowCreate", - "EscrowFinish", - "OfferCancel", - "OfferCreate", - "Payment", - "PaymentChannelClaim", - "PaymentChannelCreate", - "PaymentChannelFund", - "SetRegularKey", - "SignerListSet", - "TicketCreate", - "TrustSet", -] + "AccountSet", + "AccountDelete", + "CheckCancel", + "CheckCash", + "CheckCreate", + "DepositPreauth", + "EscrowCancel", + "EscrowCreate", + "EscrowFinish", + "OfferCancel", + "OfferCreate", + "Payment", + "PaymentChannelClaim", + "PaymentChannelCreate", + "PaymentChannelFund", + "SetRegularKey", + "SignerListSet", + "TicketCreate", + "TrustSet", +]; -const isMemo = (obj: {Memo: Memo}): boolean => { - const memo = obj.Memo - const size = Object.keys(memo).length - const validData = memo.MemoData === undefined - || typeof memo.MemoData === 'string' - const validFormat = memo.MemoFormat === undefined - || typeof memo.MemoData === 'string' - const validType = memo.MemoType === undefined - || typeof memo.MemoType === 'string' +const isMemo = (obj: { Memo: Memo }): boolean => { + const memo = obj.Memo; + const size = Object.keys(memo).length; + const validData = + memo.MemoData === undefined || typeof memo.MemoData === "string"; + const validFormat = + memo.MemoFormat === undefined || typeof memo.MemoData === "string"; + const validType = + memo.MemoType === undefined || typeof memo.MemoType === "string"; - return (1 <= size && size <= 3) - && validData - && validFormat - && validType - && onlyHasFields(memo, ["MemoFormat", "MemoData", "MemoType"]) -} + return ( + size >= 1 && + size <= 3 && + validData && + validFormat && + validType && + onlyHasFields(memo, ["MemoFormat", "MemoData", "MemoType"]) + ); +}; const isSigner = (signer: Signer): boolean => { - return Object.keys(signer).length === 3 - && typeof signer.Account === 'string' - && typeof signer.TxnSignature === 'string' - && typeof signer.SigningPubKey === 'string' -} + return ( + Object.keys(signer).length === 3 && + typeof signer.Account === "string" && + typeof signer.TxnSignature === "string" && + typeof signer.SigningPubKey === "string" + ); +}; -export function isIssuedCurrency (obj: IssuedCurrencyAmount): boolean { - return Object.keys(obj).length === 3 - && typeof obj.value === 'string' - && typeof obj.issuer === 'string' - && typeof obj.currency === 'string' +export function isIssuedCurrency(obj: IssuedCurrencyAmount): boolean { + return ( + Object.keys(obj).length === 3 && + typeof obj.value === "string" && + typeof obj.issuer === "string" && + typeof obj.currency === "string" + ); } export function isAmount(amount: Amount): boolean { - return typeof amount === 'string' || isIssuedCurrency(amount); + return typeof amount === "string" || isIssuedCurrency(amount); } export interface GlobalFlags { - tfFullyCanonicalSig: boolean, + tfFullyCanonicalSig: boolean; } export interface BaseTransaction { @@ -72,7 +79,7 @@ export interface BaseTransaction { Flags?: number | GlobalFlags; LastLedgerSequence?: number; Memos?: Array<{ Memo: Memo }>; - Signers?: Array; + Signers?: Signer[]; SourceTag?: number; SigningPubKey?: string; TicketSequence?: number; @@ -80,64 +87,93 @@ export interface BaseTransaction { } /** - * verify the common fields of a transaction. The verify functionality will be + * Verify the common fields of a transaction. The verify functionality will be * optional, and will check transaction form at runtime. This should be called * any time a transaction will be verified. - * - * @param common - An interface w/ common transaction fields - * @returns - Void - * @throws - When the common param is malformed. + * + * @param common - An interface w/ common transaction fields. + * @returns Void. + * @throws When the common param is malformed. */ export function verifyBaseTransaction(common: BaseTransaction): void { - if (common.Account === undefined) - throw new ValidationError("BaseTransaction: missing field Account") - - if (typeof common.Account !== 'string') - throw new ValidationError("BaseTransaction: Account not string") + if (common.Account === undefined) { + throw new ValidationError("BaseTransaction: missing field Account"); + } - if (common.TransactionType === undefined) - throw new ValidationError("BaseTransaction: missing field TransactionType") + if (typeof common.Account !== "string") { + throw new ValidationError("BaseTransaction: Account not string"); + } - if (typeof common.TransactionType !== 'string') - throw new ValidationError("BaseTransaction: TransactionType not string") + if (common.TransactionType === undefined) { + throw new ValidationError("BaseTransaction: missing field TransactionType"); + } - if (!transactionTypes.includes(common.TransactionType)) - throw new ValidationError("BaseTransaction: Unknown TransactionType") + if (typeof common.TransactionType !== "string") { + throw new ValidationError("BaseTransaction: TransactionType not string"); + } - if (common.Fee !== undefined && typeof common.Fee !== 'string') - throw new ValidationError("BaseTransaction: invalid Fee") + if (!transactionTypes.includes(common.TransactionType)) { + throw new ValidationError("BaseTransaction: Unknown TransactionType"); + } - if (common.Sequence !== undefined && typeof common.Sequence !== 'number') - throw new ValidationError("BaseTransaction: invalid Sequence") + if (common.Fee !== undefined && typeof common.Fee !== "string") { + throw new ValidationError("BaseTransaction: invalid Fee"); + } - if (common.AccountTxnID !== undefined - && typeof common.AccountTxnID !== 'string') - throw new ValidationError("BaseTransaction: invalid AccountTxnID") + if (common.Sequence !== undefined && typeof common.Sequence !== "number") { + throw new ValidationError("BaseTransaction: invalid Sequence"); + } - if (common.LastLedgerSequence !== undefined - && typeof common.LastLedgerSequence !== 'number') - throw new ValidationError("BaseTransaction: invalid LastLedgerSequence") + if ( + common.AccountTxnID !== undefined && + typeof common.AccountTxnID !== "string" + ) { + throw new ValidationError("BaseTransaction: invalid AccountTxnID"); + } - if (common.Memos !== undefined - && (common.Memos.length === 0 || !common.Memos.every(isMemo))) - throw new ValidationError("BaseTransaction: invalid Memos") + if ( + common.LastLedgerSequence !== undefined && + typeof common.LastLedgerSequence !== "number" + ) { + throw new ValidationError("BaseTransaction: invalid LastLedgerSequence"); + } - if (common.Signers !== undefined - && (common.Signers.length === 0 || !common.Signers.every(isSigner))) - throw new ValidationError("BaseTransaction: invalid Signers") + if ( + common.Memos !== undefined && + (common.Memos.length === 0 || !common.Memos.every(isMemo)) + ) { + throw new ValidationError("BaseTransaction: invalid Memos"); + } - if (common.SourceTag !== undefined && typeof common.SourceTag !== 'number') - throw new ValidationError("BaseTransaction: invalid SourceTag") + if ( + common.Signers !== undefined && + (common.Signers.length === 0 || !common.Signers.every(isSigner)) + ) { + throw new ValidationError("BaseTransaction: invalid Signers"); + } - if (common.SigningPubKey !== undefined - && typeof common.SigningPubKey !== 'string') - throw new ValidationError("BaseTransaction: invalid SigningPubKey") + if (common.SourceTag !== undefined && typeof common.SourceTag !== "number") { + throw new ValidationError("BaseTransaction: invalid SourceTag"); + } - if (common.TicketSequence !== undefined - && typeof common.TicketSequence !== 'number') - throw new ValidationError("BaseTransaction: invalid TicketSequence") + if ( + common.SigningPubKey !== undefined && + typeof common.SigningPubKey !== "string" + ) { + throw new ValidationError("BaseTransaction: invalid SigningPubKey"); + } - if (common.TxnSignature !== undefined - && typeof common.TxnSignature !== 'string') - throw new ValidationError("BaseTransaction: invalid TxnSignature") -} \ No newline at end of file + if ( + common.TicketSequence !== undefined && + typeof common.TicketSequence !== "number" + ) { + throw new ValidationError("BaseTransaction: invalid TicketSequence"); + } + + if ( + common.TxnSignature !== undefined && + typeof common.TxnSignature !== "string" + ) { + throw new ValidationError("BaseTransaction: invalid TxnSignature"); + } +} diff --git a/src/models/transactions/depositPreauth.ts b/src/models/transactions/depositPreauth.ts index eaa98a1d..73379c11 100644 --- a/src/models/transactions/depositPreauth.ts +++ b/src/models/transactions/depositPreauth.ts @@ -1,46 +1,55 @@ -import { ValidationError } from '../../common/errors' -import { BaseTransaction, verifyBaseTransaction } from './common' +import { ValidationError } from "../../common/errors"; + +import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface DepositPreauth extends BaseTransaction { - TransactionType: 'DepositPreauth' - Authorize?: string - Unauthorize?: string + TransactionType: "DepositPreauth"; + Authorize?: string; + Unauthorize?: string; } /** - * - * @param {DepositPreauth} tx A DepositPreauth Transaction. - * @returns {void} + * + * @param tx - A DepositPreauth Transaction. + * @returns * @throws {ValidationError} When the DepositPreauth is malformed. */ export function verifyDepositPreauth(tx: DepositPreauth): void { - verifyBaseTransaction(tx) + verifyBaseTransaction(tx); - if (tx.Authorize !== undefined && tx.Unauthorize !== undefined) { - throw new ValidationError("DepositPreauth: can't provide both Authorize and Unauthorize fields") + if (tx.Authorize !== undefined && tx.Unauthorize !== undefined) { + throw new ValidationError( + "DepositPreauth: can't provide both Authorize and Unauthorize fields" + ); + } + + if (tx.Authorize === undefined && tx.Unauthorize === undefined) { + throw new ValidationError( + "DepositPreauth: must provide either Authorize or Unauthorize field" + ); + } + + if (tx.Authorize !== undefined) { + if (typeof tx.Authorize !== "string") { + throw new ValidationError("DepositPreauth: Authorize must be a string"); } - if (tx.Authorize === undefined && tx.Unauthorize === undefined) { - throw new ValidationError('DepositPreauth: must provide either Authorize or Unauthorize field') + if (tx.Account === tx.Authorize) { + throw new ValidationError( + "DepositPreauth: Account can't preauthorize its own address" + ); + } + } + + if (tx.Unauthorize !== undefined) { + if (typeof tx.Unauthorize !== "string") { + throw new ValidationError("DepositPreauth: Unauthorize must be a string"); } - if (tx.Authorize !== undefined) { - if (typeof tx.Authorize !== 'string') { - throw new ValidationError('DepositPreauth: Authorize must be a string') - } - - if (tx.Account === tx.Authorize) { - throw new ValidationError("DepositPreauth: Account can't preauthorize its own address") - } - } - - if (tx.Unauthorize !== undefined) { - if (typeof tx.Unauthorize !== 'string') { - throw new ValidationError("DepositPreauth: Unauthorize must be a string") - } - - if (tx.Account === tx.Unauthorize) { - throw new ValidationError("DepositPreauth: Account can't unauthorize its own address") - } + if (tx.Account === tx.Unauthorize) { + throw new ValidationError( + "DepositPreauth: Account can't unauthorize its own address" + ); } + } } diff --git a/src/models/transactions/escrowCancel.ts b/src/models/transactions/escrowCancel.ts index d0c204f9..87dfcfed 100644 --- a/src/models/transactions/escrowCancel.ts +++ b/src/models/transactions/escrowCancel.ts @@ -1,31 +1,36 @@ -import { ValidationError } from "../../common/errors" -import { BaseTransaction, verifyBaseTransaction } from "./common" +import { ValidationError } from "../../common/errors"; + +import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface EscrowCancel extends BaseTransaction { - TransactionType: "EscrowCancel" - Owner: string - OfferSequence: number + TransactionType: "EscrowCancel"; + Owner: string; + OfferSequence: number; } /** * Verify the form and type of an EscrowCancel at runtime. - * - * @param tx - An EscrowCancel Transaction - * @returns - Void. - * @throws - When the EscrowCancel is Malformed. + * + * @param tx - An EscrowCancel Transaction. + * @returns Void. + * @throws When the EscrowCancel is Malformed. */ - export function verifyEscrowCancel(tx: EscrowCancel): void { - verifyBaseTransaction(tx) +export function verifyEscrowCancel(tx: EscrowCancel): void { + verifyBaseTransaction(tx); - if (tx.Owner === undefined) - throw new ValidationError('EscrowCancel: missing Owner') + if (tx.Owner === undefined) { + throw new ValidationError("EscrowCancel: missing Owner"); + } - if (typeof tx.Owner !== 'string') - throw new ValidationError('EscrowCancel: Owner must be a string') + if (typeof tx.Owner !== "string") { + throw new ValidationError("EscrowCancel: Owner must be a string"); + } - if (tx.OfferSequence === undefined) - throw new ValidationError('EscrowCancel: missing OfferSequence') + if (tx.OfferSequence === undefined) { + throw new ValidationError("EscrowCancel: missing OfferSequence"); + } - if (typeof tx.OfferSequence !== 'number') - throw new ValidationError('EscrowCancel: OfferSequence must be a number') -} \ No newline at end of file + if (typeof tx.OfferSequence !== "number") { + throw new ValidationError("EscrowCancel: OfferSequence must be a number"); + } +} diff --git a/src/models/transactions/escrowCreate.ts b/src/models/transactions/escrowCreate.ts index 10c5038d..bdc7acbd 100644 --- a/src/models/transactions/escrowCreate.ts +++ b/src/models/transactions/escrowCreate.ts @@ -1,53 +1,71 @@ -import { ValidationError } from "../../common/errors" -import { BaseTransaction, verifyBaseTransaction } from "./common" +import { ValidationError } from "../../common/errors"; + +import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface EscrowCreate extends BaseTransaction { - TransactionType: "EscrowCreate" - Amount: string - Destination: string - CancelAfter?: number - FinishAfter?: number - Condition?: string - DestinationTag?: number + TransactionType: "EscrowCreate"; + Amount: string; + Destination: string; + CancelAfter?: number; + FinishAfter?: number; + Condition?: string; + DestinationTag?: number; } /** * Verify the form and type of an EscrowCreate at runtime. - * - * @param tx - An EscrowCreate Transaction - * @returns - Void. - * @throws - When the EscrowCreate is Malformed. + * + * @param tx - An EscrowCreate Transaction. + * @returns Void. + * @throws When the EscrowCreate is Malformed. */ - export function verifyEscrowCreate(tx: EscrowCreate): void { - verifyBaseTransaction(tx) +export function verifyEscrowCreate(tx: EscrowCreate): void { + verifyBaseTransaction(tx); - if (tx.Amount === undefined) - throw new ValidationError("EscrowCreate: missing field Amount") + if (tx.Amount === undefined) { + throw new ValidationError("EscrowCreate: missing field Amount"); + } - if (typeof tx.Amount !== 'string') - throw new ValidationError("EscrowCreate: Amount must be a string") + if (typeof tx.Amount !== "string") { + throw new ValidationError("EscrowCreate: Amount must be a string"); + } - if (tx.Destination === undefined) - throw new ValidationError("EscrowCreate: missing field Destination") + if (tx.Destination === undefined) { + throw new ValidationError("EscrowCreate: missing field Destination"); + } - if (typeof tx.Destination !== 'string') - throw new ValidationError("EscrowCreate: Destination must be a string") + if (typeof tx.Destination !== "string") { + throw new ValidationError("EscrowCreate: Destination must be a string"); + } - if (tx.CancelAfter === undefined && tx.FinishAfter === undefined) - throw new ValidationError("EscrowCreate: Either CancelAfter or FinishAfter must be specified") + if (tx.CancelAfter === undefined && tx.FinishAfter === undefined) { + throw new ValidationError( + "EscrowCreate: Either CancelAfter or FinishAfter must be specified" + ); + } - if (tx.FinishAfter === undefined && tx.Condition === undefined) - throw new ValidationError("EscrowCreate: Either Condition or FinishAfter must be specified") + if (tx.FinishAfter === undefined && tx.Condition === undefined) { + throw new ValidationError( + "EscrowCreate: Either Condition or FinishAfter must be specified" + ); + } - if (tx.CancelAfter !== undefined && typeof tx.CancelAfter !== 'number') - throw new ValidationError("EscrowCreate: CancelAfter must be a number") + if (tx.CancelAfter !== undefined && typeof tx.CancelAfter !== "number") { + throw new ValidationError("EscrowCreate: CancelAfter must be a number"); + } - if (tx.FinishAfter !== undefined && typeof tx.FinishAfter !== 'number') - throw new ValidationError("EscrowCreate: FinishAfter must be a number") + if (tx.FinishAfter !== undefined && typeof tx.FinishAfter !== "number") { + throw new ValidationError("EscrowCreate: FinishAfter must be a number"); + } - if (tx.Condition !== undefined && typeof tx.Condition !== 'string') - throw new ValidationError("EscrowCreate: Condition must be a string") + if (tx.Condition !== undefined && typeof tx.Condition !== "string") { + throw new ValidationError("EscrowCreate: Condition must be a string"); + } - if (tx.DestinationTag !== undefined && typeof tx.DestinationTag !== 'number') - throw new ValidationError("EscrowCreate: DestinationTag must be a number") -} \ No newline at end of file + if ( + tx.DestinationTag !== undefined && + typeof tx.DestinationTag !== "number" + ) { + throw new ValidationError("EscrowCreate: DestinationTag must be a number"); + } +} diff --git a/src/models/transactions/escrowFinish.ts b/src/models/transactions/escrowFinish.ts index 7d3c329f..72f339df 100644 --- a/src/models/transactions/escrowFinish.ts +++ b/src/models/transactions/escrowFinish.ts @@ -1,39 +1,46 @@ -import { ValidationError } from "../../common/errors" -import { BaseTransaction, verifyBaseTransaction } from "./common" +import { ValidationError } from "../../common/errors"; + +import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface EscrowFinish extends BaseTransaction { - TransactionType: "EscrowFinish" - Owner: string - OfferSequence: number - Condition?: string - Fulfillment?: string + TransactionType: "EscrowFinish"; + Owner: string; + OfferSequence: number; + Condition?: string; + Fulfillment?: string; } /** * Verify the form and type of an EscrowFinish at runtime. - * - * @param tx - An EscrowFinish Transaction - * @returns - Void. - * @throws - When the EscrowFinish is Malformed. + * + * @param tx - An EscrowFinish Transaction. + * @returns Void. + * @throws When the EscrowFinish is Malformed. */ - export function verifyEscrowFinish(tx: EscrowFinish): void { - verifyBaseTransaction(tx) +export function verifyEscrowFinish(tx: EscrowFinish): void { + verifyBaseTransaction(tx); - if (tx.Owner === undefined) - throw new ValidationError("EscrowFinish: missing field Owner") + if (tx.Owner === undefined) { + throw new ValidationError("EscrowFinish: missing field Owner"); + } - if (typeof tx.Owner !== 'string') - throw new ValidationError("EscrowFinish: Owner must be a string") + if (typeof tx.Owner !== "string") { + throw new ValidationError("EscrowFinish: Owner must be a string"); + } - if (tx.OfferSequence === undefined) - throw new ValidationError("EscrowFinish: missing field OfferSequence") + if (tx.OfferSequence === undefined) { + throw new ValidationError("EscrowFinish: missing field OfferSequence"); + } - if (typeof tx.OfferSequence !== 'number') - throw new ValidationError("EscrowFinish: OfferSequence must be a number") + if (typeof tx.OfferSequence !== "number") { + throw new ValidationError("EscrowFinish: OfferSequence must be a number"); + } - if (tx.Condition !== undefined && typeof tx.Condition !== 'string') - throw new ValidationError("EscrowFinish: Condition must be a string") + if (tx.Condition !== undefined && typeof tx.Condition !== "string") { + throw new ValidationError("EscrowFinish: Condition must be a string"); + } - if (tx.Fulfillment !== undefined && typeof tx.Fulfillment !== 'string') - throw new ValidationError("EscrowFinish: Fulfillment must be a string") -} \ No newline at end of file + if (tx.Fulfillment !== undefined && typeof tx.Fulfillment !== "string") { + throw new ValidationError("EscrowFinish: Fulfillment must be a string"); + } +} diff --git a/src/models/transactions/index.ts b/src/models/transactions/index.ts index 84117b52..a87c32e8 100644 --- a/src/models/transactions/index.ts +++ b/src/models/transactions/index.ts @@ -1,20 +1,20 @@ -export * from './transaction' -export * from './accountSet' -export * from './accountDelete' -export * from './checkCancel' -export * from './checkCash' -export * from './checkCreate' -export * from './depositPreauth' -export * from './escrowCancel' -export * from './escrowCreate' -export * from './escrowFinish' -export * from './offerCancel' -export * from './offerCreate' -export * from './paymentTransaction' -export * from './paymentChannelClaim' -export * from './paymentChannelCreate' -export * from './paymentChannelFund' -export * from './setRegularKey' -export * from './signerListSet' -export * from './ticketCreate' -export * from './trustSet' +export * from "./transaction"; +export * from "./accountSet"; +export * from "./accountDelete"; +export * from "./checkCancel"; +export * from "./checkCash"; +export * from "./checkCreate"; +export * from "./depositPreauth"; +export * from "./escrowCancel"; +export * from "./escrowCreate"; +export * from "./escrowFinish"; +export * from "./offerCancel"; +export * from "./offerCreate"; +export * from "./paymentTransaction"; +export * from "./paymentChannelClaim"; +export * from "./paymentChannelCreate"; +export * from "./paymentChannelFund"; +export * from "./setRegularKey"; +export * from "./signerListSet"; +export * from "./ticketCreate"; +export * from "./trustSet"; diff --git a/src/models/transactions/offerCancel.ts b/src/models/transactions/offerCancel.ts index 622f81be..c4615747 100644 --- a/src/models/transactions/offerCancel.ts +++ b/src/models/transactions/offerCancel.ts @@ -1,24 +1,27 @@ -import { ValidationError } from "../../common/errors" -import { BaseTransaction, verifyBaseTransaction } from "./common" +import { ValidationError } from "../../common/errors"; + +import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface OfferCancel extends BaseTransaction { - TransactionType: "OfferCancel" - OfferSequence: number + TransactionType: "OfferCancel"; + OfferSequence: number; } /** * Verify the form and type of an OfferCancel at runtime. - * - * @param tx - An OfferCancel Transaction - * @returns - Void. - * @throws - When the OfferCancel is Malformed. + * + * @param tx - An OfferCancel Transaction. + * @returns Void. + * @throws When the OfferCancel is Malformed. */ - export function verifyOfferCancel(tx: OfferCancel): void { - verifyBaseTransaction(tx) +export function verifyOfferCancel(tx: OfferCancel): void { + verifyBaseTransaction(tx); - if (tx.OfferSequence === undefined) - throw new ValidationError("OfferCancel: missing field OfferSequence") + if (tx.OfferSequence === undefined) { + throw new ValidationError("OfferCancel: missing field OfferSequence"); + } - if (typeof tx.OfferSequence !== 'number') - throw new ValidationError("OfferCancel: OfferSequence must be a number") -} \ No newline at end of file + if (typeof tx.OfferSequence !== "number") { + throw new ValidationError("OfferCancel: OfferSequence must be a number"); + } +} diff --git a/src/models/transactions/offerCreate.ts b/src/models/transactions/offerCreate.ts index a3763149..b926f269 100644 --- a/src/models/transactions/offerCreate.ts +++ b/src/models/transactions/offerCreate.ts @@ -1,48 +1,60 @@ import { ValidationError } from "../../common/errors"; import { Amount } from "../common"; -import { BaseTransaction, GlobalFlags, verifyBaseTransaction, isAmount } from "./common"; + +import { + BaseTransaction, + GlobalFlags, + verifyBaseTransaction, + isAmount, +} from "./common"; export interface OfferCreateFlags extends GlobalFlags { - tfPassive?: boolean; - tfImmediateOrCancel?: boolean; - tfFillOrKill?: boolean; - tfSell?: boolean; + tfPassive?: boolean; + tfImmediateOrCancel?: boolean; + tfFillOrKill?: boolean; + tfSell?: boolean; } export interface OfferCreate extends BaseTransaction { - TransactionType: "OfferCreate"; - Flags?: number | OfferCreateFlags - Expiration?: number; - OfferSequence?: number; - TakerGets: Amount; - TakerPays: Amount; + TransactionType: "OfferCreate"; + Flags?: number | OfferCreateFlags; + Expiration?: number; + OfferSequence?: number; + TakerGets: Amount; + TakerPays: Amount; } /** * Verify the form and type of an OfferCreate at runtime. - * - * @param tx - An OfferCreate Transaction - * @returns - Void. - * @throws - When the OfferCreate is Malformed. + * + * @param tx - An OfferCreate Transaction. + * @returns Void. + * @throws When the OfferCreate is Malformed. */ - export function verifyOfferCreate(tx: OfferCreate): void { - verifyBaseTransaction(tx) +export function verifyOfferCreate(tx: OfferCreate): void { + verifyBaseTransaction(tx); - if (tx.TakerGets === undefined) - throw new ValidationError("OfferCreate: missing field TakerGets") + if (tx.TakerGets === undefined) { + throw new ValidationError("OfferCreate: missing field TakerGets"); + } - if (tx.TakerPays === undefined) - throw new ValidationError("OfferCreate: missing field TakerPays") + if (tx.TakerPays === undefined) { + throw new ValidationError("OfferCreate: missing field TakerPays"); + } - if (typeof tx.TakerGets !== 'string' && !isAmount(tx.TakerGets)) - throw new ValidationError("OfferCreate: invalid TakerGets") + if (typeof tx.TakerGets !== "string" && !isAmount(tx.TakerGets)) { + throw new ValidationError("OfferCreate: invalid TakerGets"); + } - if (typeof tx.TakerPays !== 'string' && !isAmount(tx.TakerPays)) - throw new ValidationError("OfferCreate: invalid TakerPays") + if (typeof tx.TakerPays !== "string" && !isAmount(tx.TakerPays)) { + throw new ValidationError("OfferCreate: invalid TakerPays"); + } - if (tx.Expiration !== undefined && typeof tx.Expiration !== 'number') - throw new ValidationError("OfferCreate: invalid Expiration") + if (tx.Expiration !== undefined && typeof tx.Expiration !== "number") { + throw new ValidationError("OfferCreate: invalid Expiration"); + } - if (tx.OfferSequence !== undefined && typeof tx.OfferSequence !== 'number') - throw new ValidationError("OfferCreate: invalid OfferSequence") -} \ No newline at end of file + if (tx.OfferSequence !== undefined && typeof tx.OfferSequence !== "number") { + throw new ValidationError("OfferCreate: invalid OfferSequence"); + } +} diff --git a/src/models/transactions/paymentChannelClaim.ts b/src/models/transactions/paymentChannelClaim.ts index 1d27d148..a8a6b8fe 100644 --- a/src/models/transactions/paymentChannelClaim.ts +++ b/src/models/transactions/paymentChannelClaim.ts @@ -1,46 +1,57 @@ import { ValidationError } from "../../common/errors"; + import { BaseTransaction, GlobalFlags, verifyBaseTransaction } from "./common"; export interface PaymentChannelClaimFlags extends GlobalFlags { - tfRenew?: boolean; - tfClose?: boolean; + tfRenew?: boolean; + tfClose?: boolean; } export interface PaymentChannelClaim extends BaseTransaction { - TransactionType: "PaymentChannelClaim"; - Flags?: number | PaymentChannelClaimFlags - Channel: string; - Balance?: string; - Amount?: string; - Signature?: string; - PublicKey?: string; + TransactionType: "PaymentChannelClaim"; + Flags?: number | PaymentChannelClaimFlags; + Channel: string; + Balance?: string; + Amount?: string; + Signature?: string; + PublicKey?: string; } /** * Verify the form and type of an PaymentChannelClaim at runtime. - * - * @param tx - An PaymentChannelClaim Transaction - * @returns - Void. - * @throws - When the PaymentChannelClaim is Malformed. + * + * @param tx - An PaymentChannelClaim Transaction. + * @returns Void. + * @throws When the PaymentChannelClaim is Malformed. */ - export function verifyPaymentChannelClaim(tx: PaymentChannelClaim): void { - verifyBaseTransaction(tx) +export function verifyPaymentChannelClaim(tx: PaymentChannelClaim): void { + verifyBaseTransaction(tx); - if (tx.Channel === undefined) - throw new ValidationError("PaymentChannelClaim: missing Channel") + if (tx.Channel === undefined) { + throw new ValidationError("PaymentChannelClaim: missing Channel"); + } - if (typeof tx.Channel !== 'string') - throw new ValidationError("PaymentChannelClaim: Channel must be a string") + if (typeof tx.Channel !== "string") { + throw new ValidationError("PaymentChannelClaim: Channel must be a string"); + } - if (tx.Balance !== undefined && typeof tx.Balance !== 'string') - throw new ValidationError("PaymentChannelClaim: Balance must be a string") + if (tx.Balance !== undefined && typeof tx.Balance !== "string") { + throw new ValidationError("PaymentChannelClaim: Balance must be a string"); + } - if (tx.Amount !== undefined && typeof tx.Amount !== 'string') - throw new ValidationError("PaymentChannelClaim: Amount must be a string") + if (tx.Amount !== undefined && typeof tx.Amount !== "string") { + throw new ValidationError("PaymentChannelClaim: Amount must be a string"); + } - if (tx.Signature !== undefined && typeof tx.Signature !== 'string') - throw new ValidationError("PaymentChannelClaim: Signature must be a string") + if (tx.Signature !== undefined && typeof tx.Signature !== "string") { + throw new ValidationError( + "PaymentChannelClaim: Signature must be a string" + ); + } - if (tx.PublicKey !== undefined && typeof tx.PublicKey !== 'string') - throw new ValidationError("PaymentChannelClaim: PublicKey must be a string") -} \ No newline at end of file + if (tx.PublicKey !== undefined && typeof tx.PublicKey !== "string") { + throw new ValidationError( + "PaymentChannelClaim: PublicKey must be a string" + ); + } +} diff --git a/src/models/transactions/paymentChannelCreate.ts b/src/models/transactions/paymentChannelCreate.ts index 4feebf0f..56ae2424 100644 --- a/src/models/transactions/paymentChannelCreate.ts +++ b/src/models/transactions/paymentChannelCreate.ts @@ -1,53 +1,77 @@ -import { ValidationError } from "../../common/errors" -import { BaseTransaction, verifyBaseTransaction } from "./common" +import { ValidationError } from "../../common/errors"; + +import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface PaymentChannelCreate extends BaseTransaction { - TransactionType: "PaymentChannelCreate" - Amount: string - Destination: string - SettleDelay: number - PublicKey: string - CancelAfter?: number - DestinationTag?: number + TransactionType: "PaymentChannelCreate"; + Amount: string; + Destination: string; + SettleDelay: number; + PublicKey: string; + CancelAfter?: number; + DestinationTag?: number; } /** * Verify the form and type of an PaymentChannelCreate at runtime. - * - * @param tx - An PaymentChannelCreate Transaction - * @returns - Void. - * @throws - When the PaymentChannelCreate is Malformed. + * + * @param tx - An PaymentChannelCreate Transaction. + * @returns Void. + * @throws When the PaymentChannelCreate is Malformed. */ - export function verifyPaymentChannelCreate(tx: PaymentChannelCreate): void { - verifyBaseTransaction(tx) +export function verifyPaymentChannelCreate(tx: PaymentChannelCreate): void { + verifyBaseTransaction(tx); - if (tx.Amount === undefined) - throw new ValidationError("PaymentChannelCreate: missing Amount") + if (tx.Amount === undefined) { + throw new ValidationError("PaymentChannelCreate: missing Amount"); + } - if (typeof tx.Amount !== 'string') - throw new ValidationError("PaymentChannelCreate: Amount must be a string") + if (typeof tx.Amount !== "string") { + throw new ValidationError("PaymentChannelCreate: Amount must be a string"); + } - if (tx.Destination === undefined) - throw new ValidationError("PaymentChannelCreate: missing Destination") + if (tx.Destination === undefined) { + throw new ValidationError("PaymentChannelCreate: missing Destination"); + } - if (typeof tx.Destination !== 'string') - throw new ValidationError("PaymentChannelCreate: Destination must be a string") + if (typeof tx.Destination !== "string") { + throw new ValidationError( + "PaymentChannelCreate: Destination must be a string" + ); + } - if (tx.SettleDelay === undefined) - throw new ValidationError("PaymentChannelCreate: missing SettleDelay") + if (tx.SettleDelay === undefined) { + throw new ValidationError("PaymentChannelCreate: missing SettleDelay"); + } - if (typeof tx.SettleDelay !== 'number') - throw new ValidationError("PaymentChannelCreate: SettleDelay must be a number") - - if (tx.PublicKey === undefined) - throw new ValidationError("PaymentChannelCreate: missing PublicKey") + if (typeof tx.SettleDelay !== "number") { + throw new ValidationError( + "PaymentChannelCreate: SettleDelay must be a number" + ); + } - if (typeof tx.PublicKey !== 'string') - throw new ValidationError("PaymentChannelCreate: PublicKey must be a string") + if (tx.PublicKey === undefined) { + throw new ValidationError("PaymentChannelCreate: missing PublicKey"); + } - if (tx.CancelAfter !== undefined && typeof tx.CancelAfter !== 'number') - throw new ValidationError("PaymentChannelCreate: CancelAfter must be a number") + if (typeof tx.PublicKey !== "string") { + throw new ValidationError( + "PaymentChannelCreate: PublicKey must be a string" + ); + } - if (tx.DestinationTag !== undefined && typeof tx.DestinationTag !== 'number') - throw new ValidationError("PaymentChannelCreate: DestinationTag must be a number") -} \ No newline at end of file + if (tx.CancelAfter !== undefined && typeof tx.CancelAfter !== "number") { + throw new ValidationError( + "PaymentChannelCreate: CancelAfter must be a number" + ); + } + + if ( + tx.DestinationTag !== undefined && + typeof tx.DestinationTag !== "number" + ) { + throw new ValidationError( + "PaymentChannelCreate: DestinationTag must be a number" + ); + } +} diff --git a/src/models/transactions/paymentChannelFund.ts b/src/models/transactions/paymentChannelFund.ts index 8eb9fc82..320e2957 100644 --- a/src/models/transactions/paymentChannelFund.ts +++ b/src/models/transactions/paymentChannelFund.ts @@ -1,35 +1,43 @@ import { ValidationError } from "../../common/errors"; + import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface PaymentChannelFund extends BaseTransaction { - TransactionType: "PaymentChannelFund"; - Channel: string; - Amount: string; - Expiration?: number; + TransactionType: "PaymentChannelFund"; + Channel: string; + Amount: string; + Expiration?: number; } /** * Verify the form and type of an PaymentChannelFund at runtime. - * - * @param tx - An PaymentChannelFund Transaction - * @returns - Void. - * @throws - When the PaymentChannelFund is Malformed. + * + * @param tx - An PaymentChannelFund Transaction. + * @returns Void. + * @throws When the PaymentChannelFund is Malformed. */ - export function verifyPaymentChannelFund(tx: PaymentChannelFund): void { - verifyBaseTransaction(tx) +export function verifyPaymentChannelFund(tx: PaymentChannelFund): void { + verifyBaseTransaction(tx); - if (tx.Channel === undefined) - throw new ValidationError("PaymentChannelFund: missing Channel") + if (tx.Channel === undefined) { + throw new ValidationError("PaymentChannelFund: missing Channel"); + } - if (typeof tx.Channel !== 'string') - throw new ValidationError("PaymentChannelFund: Channel must be a string") + if (typeof tx.Channel !== "string") { + throw new ValidationError("PaymentChannelFund: Channel must be a string"); + } - if (tx.Amount === undefined) - throw new ValidationError("PaymentChannelFund: missing Amount") + if (tx.Amount === undefined) { + throw new ValidationError("PaymentChannelFund: missing Amount"); + } - if (typeof tx.Amount !== 'string') - throw new ValidationError("PaymentChannelFund: Amount must be a string") + if (typeof tx.Amount !== "string") { + throw new ValidationError("PaymentChannelFund: Amount must be a string"); + } - if (tx.Expiration !== undefined && typeof tx.Expiration !== 'number') - throw new ValidationError("PaymentChannelFund: Expiration must be a number") -} \ No newline at end of file + if (tx.Expiration !== undefined && typeof tx.Expiration !== "number") { + throw new ValidationError( + "PaymentChannelFund: Expiration must be a number" + ); + } +} diff --git a/src/models/transactions/paymentTransaction.ts b/src/models/transactions/paymentTransaction.ts index f56284bf..7797a1ea 100644 --- a/src/models/transactions/paymentTransaction.ts +++ b/src/models/transactions/paymentTransaction.ts @@ -1,109 +1,123 @@ -import { ValidationError } from '../../common/errors' -import { Amount, Path } from '../common' -import { isFlagEnabled } from '../utils' -import { BaseTransaction, isAmount, GlobalFlags, verifyBaseTransaction } from './common' +import { ValidationError } from "../../common/errors"; +import { Amount, Path } from "../common"; +import { isFlagEnabled } from "../utils"; + +import { + BaseTransaction, + isAmount, + GlobalFlags, + verifyBaseTransaction, +} from "./common"; export enum PaymentTransactionFlagsEnum { - tfNoDirectRipple = 0x00010000, - tfPartialPayment = 0x00020000, - tfLimitQuality = 0x00040000, + tfNoDirectRipple = 0x00010000, + tfPartialPayment = 0x00020000, + tfLimitQuality = 0x00040000, } export interface PaymentTransactionFlags extends GlobalFlags { - tfNoDirectRipple?: boolean - tfPartialPayment?: boolean - tfLimitQuality?: boolean + tfNoDirectRipple?: boolean; + tfPartialPayment?: boolean; + tfLimitQuality?: boolean; } export interface PaymentTransaction extends BaseTransaction { - TransactionType: 'Payment' - Amount: Amount - Destination: string - DestinationTag?: number - InvoiceID?: string - Paths?: Path[] - SendMax?: Amount - DeliverMin?: Amount - Flags?: number | PaymentTransactionFlags + TransactionType: "Payment"; + Amount: Amount; + Destination: string; + DestinationTag?: number; + InvoiceID?: string; + Paths?: Path[]; + SendMax?: Amount; + DeliverMin?: Amount; + Flags?: number | PaymentTransactionFlags; } /** - * @param {PaymentTransaction} tx A Payment Transaction. - * @returns {void} + * @param tx - A Payment Transaction. + * @returns * @throws {ValidationError} When the PaymentTransaction is malformed. */ export function verifyPaymentTransaction(tx: PaymentTransaction): void { - verifyBaseTransaction(tx) - - if (tx.Amount === undefined) { - throw new ValidationError('PaymentTransaction: missing field Amount') - } - - if (!isAmount(tx.Amount)) { - throw new ValidationError('PaymentTransaction: invalid Amount') - } - - if (tx.Destination === undefined) { - throw new ValidationError('PaymentTransaction: missing field Destination') + verifyBaseTransaction(tx); + + if (tx.Amount === undefined) { + throw new ValidationError("PaymentTransaction: missing field Amount"); + } + + if (!isAmount(tx.Amount)) { + throw new ValidationError("PaymentTransaction: invalid Amount"); + } + + if (tx.Destination === undefined) { + throw new ValidationError("PaymentTransaction: missing field Destination"); + } + + if (!isAmount(tx.Destination)) { + throw new ValidationError("PaymentTransaction: invalid Destination"); + } + + if ( + tx.DestinationTag !== undefined && + typeof tx.DestinationTag !== "number" + ) { + throw new ValidationError( + "PaymentTransaction: DestinationTag must be a number" + ); + } + + if (tx.InvoiceID !== undefined && typeof tx.InvoiceID !== "string") { + throw new ValidationError("PaymentTransaction: InvoiceID must be a string"); + } + + if (tx.Paths !== undefined && !isPaths(tx.Paths)) { + throw new ValidationError("PaymentTransaction: invalid Paths"); + } + + if (tx.SendMax !== undefined && !isAmount(tx.SendMax)) { + throw new ValidationError("PaymentTransaction: invalid SendMax"); + } + + if (tx.DeliverMin !== undefined) { + const isTfPartialPayment = + typeof tx.Flags === "number" + ? isFlagEnabled(tx.Flags, PaymentTransactionFlagsEnum.tfPartialPayment) + : tx.Flags?.tfPartialPayment ?? false; + + if (!isTfPartialPayment) { + throw new ValidationError( + "PaymentTransaction: tfPartialPayment flag required with DeliverMin" + ); } - if (!isAmount(tx.Destination)) { - throw new ValidationError('PaymentTransaction: invalid Destination') - } - - if (tx.DestinationTag !== undefined && typeof tx.DestinationTag !== 'number') { - throw new ValidationError('PaymentTransaction: DestinationTag must be a number') - } - - if (tx.InvoiceID !== undefined && typeof tx.InvoiceID !== 'string') { - throw new ValidationError('PaymentTransaction: InvoiceID must be a string') - } - - if (tx.Paths !== undefined && !isPaths(tx.Paths)) { - throw new ValidationError('PaymentTransaction: invalid Paths') - } - - if (tx.SendMax !== undefined && !isAmount(tx.SendMax)) { - throw new ValidationError('PaymentTransaction: invalid SendMax') - } - - if (tx.DeliverMin !== undefined) { - const isTfPartialPayment = typeof tx.Flags === 'number' ? - isFlagEnabled(tx.Flags, PaymentTransactionFlagsEnum.tfPartialPayment) : - tx.Flags?.tfPartialPayment ?? false - - if (!isTfPartialPayment) { - throw new ValidationError('PaymentTransaction: tfPartialPayment flag required with DeliverMin') - } - - if (!isAmount(tx.DeliverMin)) { - throw new ValidationError('PaymentTransaction: invalid DeliverMin') - } + if (!isAmount(tx.DeliverMin)) { + throw new ValidationError("PaymentTransaction: invalid DeliverMin"); } + } } function isPaths(paths: Path[]): boolean { - if (!Array.isArray(paths) || paths.length === 0) { - return false - } - - for (const i in paths) { - const path = paths[i] - if (!Array.isArray(path) || path.length === 0) { - return false - } - - for (const j in path) { - const pathStep = path[j] - const { account, currency, issuer } = pathStep - if ( - (account !== undefined && typeof account !== 'string') || - (currency !== undefined && typeof currency !== 'string') || - (issuer !== undefined && typeof issuer !== 'string') - ) { - return false - } - } + if (!Array.isArray(paths) || paths.length === 0) { + return false; + } + + for (const i in paths) { + const path = paths[i]; + if (!Array.isArray(path) || path.length === 0) { + return false; } - return true; + for (const j in path) { + const pathStep = path[j]; + const { account, currency, issuer } = pathStep; + if ( + (account !== undefined && typeof account !== "string") || + (currency !== undefined && typeof currency !== "string") || + (issuer !== undefined && typeof issuer !== "string") + ) { + return false; + } + } + } + + return true; } diff --git a/src/models/transactions/setRegularKey.ts b/src/models/transactions/setRegularKey.ts index d01caa36..5bbd9f28 100644 --- a/src/models/transactions/setRegularKey.ts +++ b/src/models/transactions/setRegularKey.ts @@ -1,19 +1,21 @@ -import { ValidationError } from "../../common/errors" -import { BaseTransaction, verifyBaseTransaction } from "./common" +import { ValidationError } from "../../common/errors"; + +import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface SetRegularKey extends BaseTransaction { - TransactionType: "SetRegularKey" - RegularKey?: string + TransactionType: "SetRegularKey"; + RegularKey?: string; } /** - * @param {SetRegularKey} tx A Payment Transaction. - * @returns {void} + * @param tx - A Payment Transaction. + * @returns * @throws {ValidationError} When the SetRegularKey is malformed. */ - export function verifySetRegularKey(tx: SetRegularKey): void { - verifyBaseTransaction(tx) +export function verifySetRegularKey(tx: SetRegularKey): void { + verifyBaseTransaction(tx); - if (tx.RegularKey !== undefined && typeof tx.RegularKey !== 'string') - throw new ValidationError("SetRegularKey: RegularKey must be a string") -} \ No newline at end of file + if (tx.RegularKey !== undefined && typeof tx.RegularKey !== "string") { + throw new ValidationError("SetRegularKey: RegularKey must be a string"); + } +} diff --git a/src/models/transactions/signerListSet.ts b/src/models/transactions/signerListSet.ts index a93bc2b4..245e814a 100644 --- a/src/models/transactions/signerListSet.ts +++ b/src/models/transactions/signerListSet.ts @@ -1,38 +1,49 @@ -import { ValidationError } from "../../common/errors" -import { SignerEntry } from "../common" -import { BaseTransaction, verifyBaseTransaction } from "./common" +import { ValidationError } from "../../common/errors"; +import { SignerEntry } from "../common"; + +import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface SignerListSet extends BaseTransaction { - TransactionType: "SignerListSet" - SignerQuorum: number - SignerEntries: SignerEntry[] + TransactionType: "SignerListSet"; + SignerQuorum: number; + SignerEntries: SignerEntry[]; } /** * Verify the form and type of an SignerListSet at runtime. - * - * @param tx - An SignerListSet Transaction - * @returns - Void. - * @throws - When the SignerListSet is Malformed. + * + * @param tx - An SignerListSet Transaction. + * @returns Void. + * @throws When the SignerListSet is Malformed. */ - export function verifySignerListSet(tx: SignerListSet): void { - verifyBaseTransaction(tx) +export function verifySignerListSet(tx: SignerListSet): void { + verifyBaseTransaction(tx); - if (tx.SignerQuorum === undefined) - throw new ValidationError("SignerListSet: missing field SignerQuorum") + if (tx.SignerQuorum === undefined) { + throw new ValidationError("SignerListSet: missing field SignerQuorum"); + } - if (typeof tx.SignerQuorum !== 'number') - throw new ValidationError("SignerListSet: invalid SignerQuorum") + if (typeof tx.SignerQuorum !== "number") { + throw new ValidationError("SignerListSet: invalid SignerQuorum"); + } - if (tx.SignerEntries === undefined) - throw new ValidationError("SignerListSet: missing field SignerEntries") + if (tx.SignerEntries === undefined) { + throw new ValidationError("SignerListSet: missing field SignerEntries"); + } - if (!Array.isArray(tx.SignerEntries)) - throw new ValidationError("SignerListSet: invalid SignerEntries") + if (!Array.isArray(tx.SignerEntries)) { + throw new ValidationError("SignerListSet: invalid SignerEntries"); + } - if (tx.SignerEntries.length === 0) - throw new ValidationError("SignerListSet: need atleast 1 member in SignerEntries") - - if (tx.SignerEntries.length > 8) - throw new ValidationError("SignerListSet: maximum of 8 members allowed in SignerEntries") -} \ No newline at end of file + if (tx.SignerEntries.length === 0) { + throw new ValidationError( + "SignerListSet: need atleast 1 member in SignerEntries" + ); + } + + if (tx.SignerEntries.length > 8) { + throw new ValidationError( + "SignerListSet: maximum of 8 members allowed in SignerEntries" + ); + } +} diff --git a/src/models/transactions/ticketCreate.ts b/src/models/transactions/ticketCreate.ts index fd2e8779..109f69f3 100644 --- a/src/models/transactions/ticketCreate.ts +++ b/src/models/transactions/ticketCreate.ts @@ -1,30 +1,33 @@ -import { ValidationError } from '../../common/errors' -import { BaseTransaction, verifyBaseTransaction } from './common' +import { ValidationError } from "../../common/errors"; + +import { BaseTransaction, verifyBaseTransaction } from "./common"; export interface TicketCreate extends BaseTransaction { - TransactionType: 'TicketCreate' - TicketCount: number + TransactionType: "TicketCreate"; + TicketCount: number; } /** - * - * @param {TicketCreate} tx A TicketCreate Transaction. - * @returns {void} + * + * @param tx - A TicketCreate Transaction. + * @returns * @throws {ValidationError} When the TicketCreate is malformed. */ - export function verifyTicketCreate(tx: TicketCreate): void { - verifyBaseTransaction(tx) - const { TicketCount } = tx +export function verifyTicketCreate(tx: TicketCreate): void { + verifyBaseTransaction(tx); + const { TicketCount } = tx; - if (TicketCount === undefined) { - throw new ValidationError('TicketCreate: missing field TicketCount') - } + if (TicketCount === undefined) { + throw new ValidationError("TicketCreate: missing field TicketCount"); + } - if (typeof TicketCount !== 'number') { - throw new ValidationError('TicketCreate: TicketCount must be a number') - } + if (typeof TicketCount !== "number") { + throw new ValidationError("TicketCreate: TicketCount must be a number"); + } - if (!Number.isInteger(TicketCount) || TicketCount < 1 || TicketCount > 250) { - throw new ValidationError('TicketCreate: TicketCount must be an integer from 1 to 250') - } + if (!Number.isInteger(TicketCount) || TicketCount < 1 || TicketCount > 250) { + throw new ValidationError( + "TicketCreate: TicketCount must be an integer from 1 to 250" + ); + } } diff --git a/src/models/transactions/transaction.ts b/src/models/transactions/transaction.ts index 22c8600a..0ed240a7 100644 --- a/src/models/transactions/transaction.ts +++ b/src/models/transactions/transaction.ts @@ -1,46 +1,47 @@ import Metadata from "../common/metadata"; + import { AccountDelete } from "./accountDelete"; import { AccountSet } from "./accountSet"; import { CheckCancel } from "./checkCancel"; import { CheckCash } from "./checkCash"; import { CheckCreate } from "./checkCreate"; -import { DepositPreauth } from "./depositPreauth" -import { EscrowCreate } from "./escrowCreate" -import { EscrowCancel } from './escrowCancel' -import { EscrowFinish } from "./escrowFinish" -import { OfferCancel } from "./offerCancel" -import { OfferCreate } from "./offerCreate" -import { PaymentTransaction } from "./paymentTransaction" -import { PaymentChannelClaim } from './paymentChannelClaim' -import { PaymentChannelCreate } from "./paymentChannelCreate" -import { PaymentChannelFund } from "./paymentChannelFund" +import { DepositPreauth } from "./depositPreauth"; +import { EscrowCancel } from "./escrowCancel"; +import { EscrowCreate } from "./escrowCreate"; +import { EscrowFinish } from "./escrowFinish"; +import { OfferCancel } from "./offerCancel"; +import { OfferCreate } from "./offerCreate"; +import { PaymentChannelClaim } from "./paymentChannelClaim"; +import { PaymentChannelCreate } from "./paymentChannelCreate"; +import { PaymentChannelFund } from "./paymentChannelFund"; +import { PaymentTransaction } from "./paymentTransaction"; import { SetRegularKey } from "./setRegularKey"; -import { SignerListSet } from "./signerListSet" -import { TicketCreate } from "./ticketCreate" -import { TrustSet } from "./trustSet" +import { SignerListSet } from "./signerListSet"; +import { TicketCreate } from "./ticketCreate"; +import { TrustSet } from "./trustSet"; export type Transaction = - AccountDelete - | AccountSet - | CheckCancel - | CheckCash - | CheckCreate - | DepositPreauth - | EscrowCancel - | EscrowCreate - | EscrowFinish - | OfferCancel - | OfferCreate - | PaymentTransaction - | PaymentChannelClaim - | PaymentChannelCreate - | PaymentChannelFund - | SetRegularKey - | SignerListSet - | TicketCreate - | TrustSet + | AccountDelete + | AccountSet + | CheckCancel + | CheckCash + | CheckCreate + | DepositPreauth + | EscrowCancel + | EscrowCreate + | EscrowFinish + | OfferCancel + | OfferCreate + | PaymentTransaction + | PaymentChannelClaim + | PaymentChannelCreate + | PaymentChannelFund + | SetRegularKey + | SignerListSet + | TicketCreate + | TrustSet; export interface TransactionAndMetadata { - transaction: Transaction - metadata: Metadata + transaction: Transaction; + metadata: Metadata; } diff --git a/src/models/transactions/trustSet.ts b/src/models/transactions/trustSet.ts index 4bdca574..e43c31ac 100644 --- a/src/models/transactions/trustSet.ts +++ b/src/models/transactions/trustSet.ts @@ -1,54 +1,60 @@ -import { ValidationError } from '../../common/errors' -import { Amount } from '../common' -import { BaseTransaction, GlobalFlags, isAmount, verifyBaseTransaction } from './common' +import { ValidationError } from "../../common/errors"; +import { Amount } from "../common"; + +import { + BaseTransaction, + GlobalFlags, + isAmount, + verifyBaseTransaction, +} from "./common"; export enum TrustSetFlagsEnum { - tfSetfAuth = 0x00010000, - tfSetNoRipple = 0x00020000, - tfClearNoRipple = 0x00040000, - tfSetFreeze = 0x00100000, - tfClearFreeze = 0x00200000, + tfSetfAuth = 0x00010000, + tfSetNoRipple = 0x00020000, + tfClearNoRipple = 0x00040000, + tfSetFreeze = 0x00100000, + tfClearFreeze = 0x00200000, } export interface TrustSetFlags extends GlobalFlags { - tfSetfAuth?: boolean - tfSetNoRipple?: boolean - tfClearNoRipple?: boolean - tfSetFreeze?: boolean - tfClearFreeze?: boolean + tfSetfAuth?: boolean; + tfSetNoRipple?: boolean; + tfClearNoRipple?: boolean; + tfSetFreeze?: boolean; + tfClearFreeze?: boolean; } export interface TrustSet extends BaseTransaction { - TransactionType: 'TrustSet' - LimitAmount: Amount - QualityIn?: number - QualityOut?: number - Flags?: number | TrustSetFlags + TransactionType: "TrustSet"; + LimitAmount: Amount; + QualityIn?: number; + QualityOut?: number; + Flags?: number | TrustSetFlags; } /** - * - * @param tx A TrustSet Transaction. - * @returns {void} + * + * @param tx - A TrustSet Transaction. + * @returns * @throws {ValidationError} When the TrustSet is malformed. */ export function verifyTrustSet(tx: TrustSet): void { - verifyBaseTransaction(tx) - const { LimitAmount, QualityIn, QualityOut } = tx + verifyBaseTransaction(tx); + const { LimitAmount, QualityIn, QualityOut } = tx; - if (LimitAmount === undefined) { - throw new ValidationError('TrustSet: missing field LimitAmount') - } + if (LimitAmount === undefined) { + throw new ValidationError("TrustSet: missing field LimitAmount"); + } - if (!isAmount(LimitAmount)) { - throw new ValidationError('TrustSet: invalid LimitAmount') - } + if (!isAmount(LimitAmount)) { + throw new ValidationError("TrustSet: invalid LimitAmount"); + } - if (QualityIn !== undefined && typeof QualityIn !== 'number') { - throw new ValidationError('TrustSet: QualityIn must be a number') - } + if (QualityIn !== undefined && typeof QualityIn !== "number") { + throw new ValidationError("TrustSet: QualityIn must be a number"); + } - if (QualityOut !== undefined && typeof QualityOut !== 'number') { - throw new ValidationError('TrustSet: QualityOut must be a number') - } + if (QualityOut !== undefined && typeof QualityOut !== "number") { + throw new ValidationError("TrustSet: QualityOut must be a number"); + } } diff --git a/src/models/utils/index.ts b/src/models/utils/index.ts index d6f2ac18..4901c1ae 100644 --- a/src/models/utils/index.ts +++ b/src/models/utils/index.ts @@ -1,21 +1,21 @@ /** - * Verify that all fields of an object are in fields - * - * @param obj Object to verify fields - * @param fields Fields to verify - * @returns True if keys in object are all in fields + * Verify that all fields of an object are in fields. + * + * @param obj - Object to verify fields. + * @param fields - Fields to verify. + * @returns True if keys in object are all in fields. */ -export function onlyHasFields(obj: object, fields: Array): boolean { - return Object.keys(obj).every((key:string) => fields.includes(key)) +export function onlyHasFields(obj: object, fields: string[]): boolean { + return Object.keys(obj).every((key: string) => fields.includes(key)); } /** * Perform bitwise AND (&) to check if a flag is enabled within Flags (as a number). - * - * @param {number} Flags A number that represents flags enabled. - * @param {number} checkFlag A specific flag to check if it's enabled within Flags. - * @returns {boolean} True if checkFlag is enabled within Flags. + * + * @param Flags - A number that represents flags enabled. + * @param checkFlag - A specific flag to check if it's enabled within Flags. + * @returns True if checkFlag is enabled within Flags. */ export function isFlagEnabled(Flags: number, checkFlag: number): boolean { - return (checkFlag & Flags) === checkFlag + return (checkFlag & Flags) === checkFlag; } diff --git a/src/transaction/check-cancel.ts b/src/transaction/check-cancel.ts index 02ac839b..223e47d5 100644 --- a/src/transaction/check-cancel.ts +++ b/src/transaction/check-cancel.ts @@ -1,10 +1,11 @@ -import {prepareTransaction} from './utils' -import {validate} from '../common' -import {Instructions, Prepare, TransactionJSON} from './types' -import {Client} from '..' +import { Client } from ".."; +import { validate } from "../common"; -export type CheckCancelParameters = { - checkID: string +import { Instructions, Prepare, TransactionJSON } from "./types"; +import { prepareTransaction } from "./utils"; + +export interface CheckCancelParameters { + checkID: string; } function createCheckCancelTransaction( @@ -13,11 +14,11 @@ function createCheckCancelTransaction( ): TransactionJSON { const txJSON = { Account: account, - TransactionType: 'CheckCancel', - CheckID: cancel.checkID - } + TransactionType: "CheckCancel", + CheckID: cancel.checkID, + }; - return txJSON + return txJSON; } function prepareCheckCancel( @@ -27,12 +28,12 @@ function prepareCheckCancel( instructions: Instructions = {} ): Promise { try { - validate.prepareCheckCancel({address, checkCancel, instructions}) - const txJSON = createCheckCancelTransaction(address, checkCancel) - return prepareTransaction(txJSON, this, instructions) + validate.prepareCheckCancel({ address, checkCancel, instructions }); + const txJSON = createCheckCancelTransaction(address, checkCancel); + return prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default prepareCheckCancel +export default prepareCheckCancel; diff --git a/src/transaction/check-cash.ts b/src/transaction/check-cash.ts index 239d877c..33db67ca 100644 --- a/src/transaction/check-cash.ts +++ b/src/transaction/check-cash.ts @@ -1,15 +1,16 @@ -import * as utils from './utils' -import {validate} from '../common' -import {Instructions, Prepare, TransactionJSON} from './types' -import {Amount} from '../common/types/objects' -import {Client} from '..' -import {toRippledAmount} from '../utils' -import {ValidationError} from '../common/errors' +import { Client } from ".."; +import { validate } from "../common"; +import { ValidationError } from "../common/errors"; +import { Amount } from "../common/types/objects"; +import { toRippledAmount } from "../utils"; -export type CheckCashParameters = { - checkID: string - amount?: Amount - deliverMin?: Amount +import { Instructions, Prepare, TransactionJSON } from "./types"; +import * as utils from "./utils"; + +export interface CheckCashParameters { + checkID: string; + amount?: Amount; + deliverMin?: Amount; } function createCheckCashTransaction( @@ -19,25 +20,25 @@ function createCheckCashTransaction( if (checkCash.amount && checkCash.deliverMin) { throw new ValidationError( '"amount" and "deliverMin" properties on ' + - 'CheckCash are mutually exclusive' - ) + "CheckCash are mutually exclusive" + ); } const txJSON: any = { Account: account, - TransactionType: 'CheckCash', - CheckID: checkCash.checkID - } + TransactionType: "CheckCash", + CheckID: checkCash.checkID, + }; if (checkCash.amount != null) { - txJSON.Amount = toRippledAmount(checkCash.amount) + txJSON.Amount = toRippledAmount(checkCash.amount); } if (checkCash.deliverMin != null) { - txJSON.DeliverMin = toRippledAmount(checkCash.deliverMin) + txJSON.DeliverMin = toRippledAmount(checkCash.deliverMin); } - return txJSON + return txJSON; } function prepareCheckCash( @@ -47,12 +48,12 @@ function prepareCheckCash( instructions: Instructions = {} ): Promise { try { - validate.prepareCheckCash({address, checkCash, instructions}) - const txJSON = createCheckCashTransaction(address, checkCash) - return utils.prepareTransaction(txJSON, this, instructions) + validate.prepareCheckCash({ address, checkCash, instructions }); + const txJSON = createCheckCashTransaction(address, checkCash); + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default prepareCheckCash +export default prepareCheckCash; diff --git a/src/transaction/check-create.ts b/src/transaction/check-create.ts index d024dd8c..78dbe7d0 100644 --- a/src/transaction/check-create.ts +++ b/src/transaction/check-create.ts @@ -1,16 +1,17 @@ -import * as utils from './utils' -import {validate} from '../common' -import {ISOTimeToRippleTime, toRippledAmount} from '../utils' -import {Instructions, Prepare, TransactionJSON} from './types' -import {Amount} from '../common/types/objects' -import {Client} from '..' +import { Client } from ".."; +import { validate } from "../common"; +import { Amount } from "../common/types/objects"; +import { ISOTimeToRippleTime, toRippledAmount } from "../utils"; -export type CheckCreateParameters = { - destination: string - sendMax: Amount - destinationTag?: number - expiration?: string - invoiceID?: string +import { Instructions, Prepare, TransactionJSON } from "./types"; +import * as utils from "./utils"; + +export interface CheckCreateParameters { + destination: string; + sendMax: Amount; + destinationTag?: number; + expiration?: string; + invoiceID?: string; } function createCheckCreateTransaction( @@ -19,24 +20,24 @@ function createCheckCreateTransaction( ): TransactionJSON { const txJSON: any = { Account: account, - TransactionType: 'CheckCreate', + TransactionType: "CheckCreate", Destination: check.destination, - SendMax: toRippledAmount(check.sendMax) - } + SendMax: toRippledAmount(check.sendMax), + }; if (check.destinationTag != null) { - txJSON.DestinationTag = check.destinationTag + txJSON.DestinationTag = check.destinationTag; } if (check.expiration != null) { - txJSON.Expiration = ISOTimeToRippleTime(check.expiration) + txJSON.Expiration = ISOTimeToRippleTime(check.expiration); } if (check.invoiceID != null) { - txJSON.InvoiceID = check.invoiceID + txJSON.InvoiceID = check.invoiceID; } - return txJSON + return txJSON; } function prepareCheckCreate( @@ -46,12 +47,12 @@ function prepareCheckCreate( instructions: Instructions = {} ): Promise { try { - validate.prepareCheckCreate({address, checkCreate, instructions}) - const txJSON = createCheckCreateTransaction(address, checkCreate) - return utils.prepareTransaction(txJSON, this, instructions) + validate.prepareCheckCreate({ address, checkCreate, instructions }); + const txJSON = createCheckCreateTransaction(address, checkCreate); + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default prepareCheckCreate +export default prepareCheckCreate; diff --git a/src/transaction/combine.ts b/src/transaction/combine.ts index e0a5d0c3..9be01079 100644 --- a/src/transaction/combine.ts +++ b/src/transaction/combine.ts @@ -1,66 +1,85 @@ -import _ from 'lodash' -import binary from 'ripple-binary-codec' -import BigNumber from 'bignumber.js' -import {ValidationError} from '../common/errors' -import {decodeAccountID} from 'ripple-address-codec' -import {validate} from '../common' -import {computeBinaryTransactionHash} from '../utils/hashes' -import {JsonObject} from 'ripple-binary-codec/dist/types/serialized-type' +import BigNumber from "bignumber.js"; +import _ from "lodash"; +import { decodeAccountID } from "ripple-address-codec"; +import binary from "ripple-binary-codec"; +import { JsonObject } from "ripple-binary-codec/dist/types/serialized-type"; + +import { validate } from "../common"; +import { ValidationError } from "../common/errors"; +import { computeBinaryTransactionHash } from "../utils/hashes"; /** - * The transactions should all be equal except for the 'Signers' field. + * The transactions should all be equal except for the 'Signers' field. + * + * @param transactions */ - function validateTransactionEquivalence(transactions: Array) { - const exampleTransaction = JSON.stringify({...transactions[0], Signers: null}) - if (transactions.slice(1).some(tx => JSON.stringify({...tx, Signers: null}) !== exampleTransaction)) { - throw new ValidationError('txJSON is not the same for all signedTransactions') +function validateTransactionEquivalence(transactions: JsonObject[]) { + const exampleTransaction = JSON.stringify({ + ...transactions[0], + Signers: null, + }); + if ( + transactions + .slice(1) + .some( + (tx) => JSON.stringify({ ...tx, Signers: null }) !== exampleTransaction + ) + ) { + throw new ValidationError( + "txJSON is not the same for all signedTransactions" + ); } } function addressToBigNumber(address) { - const hex = Buffer.from(decodeAccountID(address)).toString('hex') - return new BigNumber(hex, 16) + const hex = Buffer.from(decodeAccountID(address)).toString("hex"); + return new BigNumber(hex, 16); } /** - * If presented in binary form, the Signers array must be sorted based on - * the numeric value of the signer addresses, with the lowest value first. + * If presented in binary form, the Signers array must be sorted based on + * the numeric value of the signer addresses, with the lowest value first. * (If submitted as JSON, the submit_multisigned method handles this automatically.) - * https://xrpl.org/multi-signing.html + * https://xrpl.org/multi-signing.html. + * + * @param a + * @param b */ function compareSigners(a, b) { return addressToBigNumber(a.Signer.Account).comparedTo( addressToBigNumber(b.Signer.Account) - ) + ); } -function getTransactionWithAllSigners(transactions: Array): JsonObject { +function getTransactionWithAllSigners(transactions: JsonObject[]): JsonObject { // Signers must be sorted - see compareSigners for more details - const sortedSigners = _.flatMap(transactions, tx => tx.Signers) - .filter(signer => signer) - .sort(compareSigners) + const sortedSigners = _.flatMap(transactions, (tx) => tx.Signers) + .filter((signer) => signer) + .sort(compareSigners); - return {...transactions[0], Signers: sortedSigners} + return { ...transactions[0], Signers: sortedSigners }; } /** - * - * @param signedTransactions A collection of the same transaction signed by different signers. The only difference + * + * @param signedTransactions - A collection of the same transaction signed by different signers. The only difference * between the elements of signedTransactions should be the Signers field. * @returns An object with the combined transaction (now having a sorted list of all signers) which is encoded, along * with a transaction id based on the combined transaction. */ -function combine(signedTransactions: Array): object { - validate.combine({signedTransactions}) +function combine(signedTransactions: string[]): object { + validate.combine({ signedTransactions }); const transactions: JsonObject[] = signedTransactions.map(binary.decode); - validateTransactionEquivalence(transactions) + validateTransactionEquivalence(transactions); - const signedTransaction = binary.encode(getTransactionWithAllSigners(transactions)) + const signedTransaction = binary.encode( + getTransactionWithAllSigners(transactions) + ); return { - signedTransaction: signedTransaction, - id: computeBinaryTransactionHash(signedTransaction) - } + signedTransaction, + id: computeBinaryTransactionHash(signedTransaction), + }; } -export default combine +export default combine; diff --git a/src/transaction/escrow-cancellation.ts b/src/transaction/escrow-cancellation.ts index 4feb0537..4fa95e39 100644 --- a/src/transaction/escrow-cancellation.ts +++ b/src/transaction/escrow-cancellation.ts @@ -1,16 +1,18 @@ -import * as utils from './utils' -const validate = utils.common.validate -import {Instructions, Prepare, TransactionJSON} from './types' -import {Memo} from '../common/types/objects' -import {Client} from '..' +import { Client } from ".."; +import { Memo } from "../common/types/objects"; -export type EscrowCancellation = { - owner: string - escrowSequence: number +import { Instructions, Prepare, TransactionJSON } from "./types"; +import * as utils from "./utils"; + +const validate = utils.common.validate; + +export interface EscrowCancellation { + owner: string; + escrowSequence: number; // TODO: This ripple-lib memo format should be deprecated in favor of rippled's format. // If necessary, expose a public method for converting between the two formats. - memos?: Array + memos?: Memo[]; } function createEscrowCancellationTransaction( @@ -18,15 +20,15 @@ function createEscrowCancellationTransaction( payment: EscrowCancellation ): TransactionJSON { const txJSON: any = { - TransactionType: 'EscrowCancel', + TransactionType: "EscrowCancel", Account: account, Owner: payment.owner, - OfferSequence: payment.escrowSequence - } + OfferSequence: payment.escrowSequence, + }; if (payment.memos != null) { - txJSON.Memos = payment.memos.map(utils.convertMemo) + txJSON.Memos = payment.memos.map(utils.convertMemo); } - return txJSON + return txJSON; } function prepareEscrowCancellation( @@ -38,13 +40,13 @@ function prepareEscrowCancellation( validate.prepareEscrowCancellation({ address, escrowCancellation, - instructions - }) + instructions, + }); const txJSON = createEscrowCancellationTransaction( address, escrowCancellation - ) - return utils.prepareTransaction(txJSON, this, instructions) + ); + return utils.prepareTransaction(txJSON, this, instructions); } -export default prepareEscrowCancellation +export default prepareEscrowCancellation; diff --git a/src/transaction/escrow-creation.ts b/src/transaction/escrow-creation.ts index 35be8df7..6fc03c28 100644 --- a/src/transaction/escrow-creation.ts +++ b/src/transaction/escrow-creation.ts @@ -1,20 +1,22 @@ -import * as utils from './utils' -import {validate} from '../common' -import {ISOTimeToRippleTime, xrpToDrops} from '../utils' -const ValidationError = utils.common.errors.ValidationError -import {Instructions, Prepare, TransactionJSON} from './types' -import {Memo} from '../common/types/objects' -import {Client} from '..' +import { Client } from ".."; +import { validate } from "../common"; +import { Memo } from "../common/types/objects"; +import { ISOTimeToRippleTime, xrpToDrops } from "../utils"; -export type EscrowCreation = { - amount: string - destination: string - memos?: Array - condition?: string - allowCancelAfter?: string - allowExecuteAfter?: string - sourceTag?: number - destinationTag?: number +import { Instructions, Prepare, TransactionJSON } from "./types"; +import * as utils from "./utils"; + +const ValidationError = utils.common.errors.ValidationError; + +export interface EscrowCreation { + amount: string; + destination: string; + memos?: Memo[]; + condition?: string; + allowCancelAfter?: string; + allowExecuteAfter?: string; + sourceTag?: number; + destinationTag?: number; } function createEscrowCreationTransaction( @@ -22,29 +24,29 @@ function createEscrowCreationTransaction( payment: EscrowCreation ): TransactionJSON { const txJSON: any = { - TransactionType: 'EscrowCreate', + TransactionType: "EscrowCreate", Account: account, Destination: payment.destination, - Amount: xrpToDrops(payment.amount) - } + Amount: xrpToDrops(payment.amount), + }; if (payment.condition != null) { - txJSON.Condition = payment.condition + txJSON.Condition = payment.condition; } if (payment.allowCancelAfter != null) { - txJSON.CancelAfter = ISOTimeToRippleTime(payment.allowCancelAfter) + txJSON.CancelAfter = ISOTimeToRippleTime(payment.allowCancelAfter); } if (payment.allowExecuteAfter != null) { - txJSON.FinishAfter = ISOTimeToRippleTime(payment.allowExecuteAfter) + txJSON.FinishAfter = ISOTimeToRippleTime(payment.allowExecuteAfter); } if (payment.sourceTag != null) { - txJSON.SourceTag = payment.sourceTag + txJSON.SourceTag = payment.sourceTag; } if (payment.destinationTag != null) { - txJSON.DestinationTag = payment.destinationTag + txJSON.DestinationTag = payment.destinationTag; } if (payment.memos != null) { - txJSON.Memos = payment.memos.map(utils.convertMemo) + txJSON.Memos = payment.memos.map(utils.convertMemo); } if ( Boolean(payment.allowCancelAfter) && @@ -52,11 +54,11 @@ function createEscrowCreationTransaction( txJSON.CancelAfter <= txJSON.FinishAfter ) { throw new ValidationError( - 'prepareEscrowCreation: ' + + "prepareEscrowCreation: " + '"allowCancelAfter" must be after "allowExecuteAfter"' - ) + ); } - return txJSON + return txJSON; } function prepareEscrowCreation( @@ -66,12 +68,12 @@ function prepareEscrowCreation( instructions: Instructions = {} ): Promise { try { - validate.prepareEscrowCreation({address, escrowCreation, instructions}) - const txJSON = createEscrowCreationTransaction(address, escrowCreation) - return utils.prepareTransaction(txJSON, this, instructions) + validate.prepareEscrowCreation({ address, escrowCreation, instructions }); + const txJSON = createEscrowCreationTransaction(address, escrowCreation); + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default prepareEscrowCreation +export default prepareEscrowCreation; diff --git a/src/transaction/escrow-execution.ts b/src/transaction/escrow-execution.ts index f7065895..55df790f 100644 --- a/src/transaction/escrow-execution.ts +++ b/src/transaction/escrow-execution.ts @@ -1,16 +1,18 @@ -import * as utils from './utils' -const validate = utils.common.validate -const ValidationError = utils.common.errors.ValidationError -import {Instructions, Prepare, TransactionJSON} from './types' -import {Memo} from '../common/types/objects' -import {Client} from '..' +import { Client } from ".."; +import { Memo } from "../common/types/objects"; -export type EscrowExecution = { - owner: string - escrowSequence: number - memos?: Array - condition?: string - fulfillment?: string +import { Instructions, Prepare, TransactionJSON } from "./types"; +import * as utils from "./utils"; + +const validate = utils.common.validate; +const ValidationError = utils.common.errors.ValidationError; + +export interface EscrowExecution { + owner: string; + escrowSequence: number; + memos?: Memo[]; + condition?: string; + fulfillment?: string; } function createEscrowExecutionTransaction( @@ -18,29 +20,29 @@ function createEscrowExecutionTransaction( payment: EscrowExecution ): TransactionJSON { const txJSON: any = { - TransactionType: 'EscrowFinish', + TransactionType: "EscrowFinish", Account: account, Owner: payment.owner, - OfferSequence: payment.escrowSequence - } + OfferSequence: payment.escrowSequence, + }; if (Boolean(payment.condition) !== Boolean(payment.fulfillment)) { throw new ValidationError( '"condition" and "fulfillment" fields on' + - ' EscrowFinish must only be specified together.' - ) + " EscrowFinish must only be specified together." + ); } if (payment.condition != null) { - txJSON.Condition = payment.condition + txJSON.Condition = payment.condition; } if (payment.fulfillment != null) { - txJSON.Fulfillment = payment.fulfillment + txJSON.Fulfillment = payment.fulfillment; } if (payment.memos != null) { - txJSON.Memos = payment.memos.map(utils.convertMemo) + txJSON.Memos = payment.memos.map(utils.convertMemo); } - return txJSON + return txJSON; } function prepareEscrowExecution( @@ -50,12 +52,12 @@ function prepareEscrowExecution( instructions: Instructions = {} ): Promise { try { - validate.prepareEscrowExecution({address, escrowExecution, instructions}) - const txJSON = createEscrowExecutionTransaction(address, escrowExecution) - return utils.prepareTransaction(txJSON, this, instructions) + validate.prepareEscrowExecution({ address, escrowExecution, instructions }); + const txJSON = createEscrowExecutionTransaction(address, escrowExecution); + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default prepareEscrowExecution +export default prepareEscrowExecution; diff --git a/src/transaction/order.ts b/src/transaction/order.ts index dcbff55b..7972842c 100644 --- a/src/transaction/order.ts +++ b/src/transaction/order.ts @@ -1,51 +1,54 @@ -import * as utils from './utils' -const offerFlags = utils.common.txFlags.OfferCreate -import {validate} from '../common' -import {ISOTimeToRippleTime, toRippledAmount} from '../utils' -import {Instructions, Prepare, OfferCreateTransaction} from './types' -import {FormattedOrderSpecification} from '../common/types/objects/index' -import {Client} from '..' +import { Client } from ".."; +import { validate } from "../common"; +import { FormattedOrderSpecification } from "../common/types/objects/index"; +import { ISOTimeToRippleTime, toRippledAmount } from "../utils"; + +import { Instructions, Prepare, OfferCreateTransaction } from "./types"; +import * as utils from "./utils"; + +const offerFlags = utils.common.txFlags.OfferCreate; function createOrderTransaction( account: string, order: FormattedOrderSpecification ): OfferCreateTransaction { const takerPays = toRippledAmount( - order.direction === 'buy' ? order.quantity : order.totalPrice - ) + order.direction === "buy" ? order.quantity : order.totalPrice + ); const takerGets = toRippledAmount( - order.direction === 'buy' ? order.totalPrice : order.quantity - ) + order.direction === "buy" ? order.totalPrice : order.quantity + ); const txJSON: Partial = { - TransactionType: 'OfferCreate', + TransactionType: "OfferCreate", Account: account, TakerGets: takerGets, TakerPays: takerPays, - Flags: 0 + }; + + txJSON.Flags = 0; + if (order.direction === "sell") { + txJSON.Flags |= offerFlags.Sell; } - if (order.direction === 'sell') { - txJSON.Flags |= offerFlags.Sell + if (order.passive) { + txJSON.Flags |= offerFlags.Passive; } - if (order.passive === true) { - txJSON.Flags |= offerFlags.Passive + if (order.immediateOrCancel) { + txJSON.Flags |= offerFlags.ImmediateOrCancel; } - if (order.immediateOrCancel === true) { - txJSON.Flags |= offerFlags.ImmediateOrCancel - } - if (order.fillOrKill === true) { - txJSON.Flags |= offerFlags.FillOrKill + if (order.fillOrKill) { + txJSON.Flags |= offerFlags.FillOrKill; } if (order.expirationTime != null) { - txJSON.Expiration = ISOTimeToRippleTime(order.expirationTime) + txJSON.Expiration = ISOTimeToRippleTime(order.expirationTime); } if (order.orderToReplace != null) { - txJSON.OfferSequence = order.orderToReplace + txJSON.OfferSequence = order.orderToReplace; } if (order.memos != null) { - txJSON.Memos = order.memos.map(utils.convertMemo) + txJSON.Memos = order.memos.map(utils.convertMemo); } - return txJSON as OfferCreateTransaction + return txJSON as OfferCreateTransaction; } function prepareOrder( @@ -55,12 +58,12 @@ function prepareOrder( instructions: Instructions = {} ): Promise { try { - validate.prepareOrder({address, order, instructions}) - const txJSON = createOrderTransaction(address, order) - return utils.prepareTransaction(txJSON, this, instructions) + validate.prepareOrder({ address, order, instructions }); + const txJSON = createOrderTransaction(address, order); + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default prepareOrder +export default prepareOrder; diff --git a/src/transaction/ordercancellation.ts b/src/transaction/ordercancellation.ts index 0aed83fc..0f7d38f4 100644 --- a/src/transaction/ordercancellation.ts +++ b/src/transaction/ordercancellation.ts @@ -1,21 +1,23 @@ -import * as utils from './utils' -const validate = utils.common.validate -import {Instructions, Prepare, TransactionJSON} from './types' -import {Client} from '..' +import { Client } from ".."; + +import { Instructions, Prepare, TransactionJSON } from "./types"; +import * as utils from "./utils"; + +const validate = utils.common.validate; function createOrderCancellationTransaction( account: string, orderCancellation: any ): TransactionJSON { const txJSON: any = { - TransactionType: 'OfferCancel', + TransactionType: "OfferCancel", Account: account, - OfferSequence: orderCancellation.orderSequence - } + OfferSequence: orderCancellation.orderSequence, + }; if (orderCancellation.memos != null) { - txJSON.Memos = orderCancellation.memos.map(utils.convertMemo) + txJSON.Memos = orderCancellation.memos.map(utils.convertMemo); } - return txJSON + return txJSON; } function prepareOrderCancellation( @@ -28,16 +30,16 @@ function prepareOrderCancellation( validate.prepareOrderCancellation({ address, orderCancellation, - instructions - }) + instructions, + }); const txJSON = createOrderCancellationTransaction( address, orderCancellation - ) - return utils.prepareTransaction(txJSON, this, instructions) + ); + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default prepareOrderCancellation +export default prepareOrderCancellation; diff --git a/src/transaction/payment-channel-claim.ts b/src/transaction/payment-channel-claim.ts index 676d3fb8..c61f8859 100644 --- a/src/transaction/payment-channel-claim.ts +++ b/src/transaction/payment-channel-claim.ts @@ -1,19 +1,21 @@ -import * as utils from './utils' -const ValidationError = utils.common.errors.ValidationError -const claimFlags = utils.common.txFlags.PaymentChannelClaim -import {validate} from '../common' -import {xrpToDrops} from '../utils' -import {Instructions, Prepare, TransactionJSON} from './types' -import {Client} from '..' +import { Client } from ".."; +import { validate } from "../common"; +import { xrpToDrops } from "../utils"; -export type PaymentChannelClaim = { - channel: string - balance?: string - amount?: string - signature?: string - publicKey?: string - renew?: boolean - close?: boolean +import { Instructions, Prepare, TransactionJSON } from "./types"; +import * as utils from "./utils"; + +const ValidationError = utils.common.errors.ValidationError; +const claimFlags = utils.common.txFlags.PaymentChannelClaim; + +export interface PaymentChannelClaim { + channel: string; + balance?: string; + amount?: string; + signature?: string; + publicKey?: string; + renew?: boolean; + close?: boolean; } function createPaymentChannelClaimTransaction( @@ -22,47 +24,48 @@ function createPaymentChannelClaimTransaction( ): TransactionJSON { const txJSON: TransactionJSON = { Account: account, - TransactionType: 'PaymentChannelClaim', + TransactionType: "PaymentChannelClaim", Channel: claim.channel, - Flags: 0 - } + Flags: 0, + }; if (claim.balance != null) { - txJSON.Balance = xrpToDrops(claim.balance) + txJSON.Balance = xrpToDrops(claim.balance); } if (claim.amount != null) { - txJSON.Amount = xrpToDrops(claim.amount) + txJSON.Amount = xrpToDrops(claim.amount); } if (Boolean(claim.signature) !== Boolean(claim.publicKey)) { throw new ValidationError( '"signature" and "publicKey" fields on' + - ' PaymentChannelClaim must only be specified together.' - ) + " PaymentChannelClaim must only be specified together." + ); } if (claim.signature != null) { - txJSON.Signature = claim.signature + txJSON.Signature = claim.signature; } if (claim.publicKey != null) { - txJSON.PublicKey = claim.publicKey + txJSON.PublicKey = claim.publicKey; } - if (claim.renew === true && claim.close === true) { + if (claim.renew && claim.close) { throw new ValidationError( '"renew" and "close" flags on PaymentChannelClaim' + - ' are mutually exclusive' - ) + " are mutually exclusive" + ); } - if (claim.renew === true) { - txJSON.Flags |= claimFlags.Renew + txJSON.Flags = 0; + if (claim.renew) { + txJSON.Flags |= claimFlags.Renew; } - if (claim.close === true) { - txJSON.Flags |= claimFlags.Close + if (claim.close) { + txJSON.Flags |= claimFlags.Close; } - return txJSON + return txJSON; } function preparePaymentChannelClaim( @@ -75,16 +78,16 @@ function preparePaymentChannelClaim( validate.preparePaymentChannelClaim({ address, paymentChannelClaim, - instructions - }) + instructions, + }); const txJSON = createPaymentChannelClaimTransaction( address, paymentChannelClaim - ) - return utils.prepareTransaction(txJSON, this, instructions) + ); + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default preparePaymentChannelClaim +export default preparePaymentChannelClaim; diff --git a/src/transaction/payment-channel-create.ts b/src/transaction/payment-channel-create.ts index 591572dd..6557e07e 100644 --- a/src/transaction/payment-channel-create.ts +++ b/src/transaction/payment-channel-create.ts @@ -1,17 +1,18 @@ -import * as utils from './utils' -import {validate} from '../common' -import {ISOTimeToRippleTime, xrpToDrops} from '../utils' -import {Instructions, Prepare, TransactionJSON} from './types' -import {Client} from '..' +import { Client } from ".."; +import { validate } from "../common"; +import { ISOTimeToRippleTime, xrpToDrops } from "../utils"; -export type PaymentChannelCreate = { - amount: string - destination: string - settleDelay: number - publicKey: string - cancelAfter?: string - sourceTag?: number - destinationTag?: number +import { Instructions, Prepare, TransactionJSON } from "./types"; +import * as utils from "./utils"; + +export interface PaymentChannelCreate { + amount: string; + destination: string; + settleDelay: number; + publicKey: string; + cancelAfter?: string; + sourceTag?: number; + destinationTag?: number; } function createPaymentChannelCreateTransaction( @@ -20,24 +21,24 @@ function createPaymentChannelCreateTransaction( ): TransactionJSON { const txJSON: any = { Account: account, - TransactionType: 'PaymentChannelCreate', + TransactionType: "PaymentChannelCreate", Amount: xrpToDrops(paymentChannel.amount), Destination: paymentChannel.destination, SettleDelay: paymentChannel.settleDelay, - PublicKey: paymentChannel.publicKey.toUpperCase() - } + PublicKey: paymentChannel.publicKey.toUpperCase(), + }; if (paymentChannel.cancelAfter != null) { - txJSON.CancelAfter = ISOTimeToRippleTime(paymentChannel.cancelAfter) + txJSON.CancelAfter = ISOTimeToRippleTime(paymentChannel.cancelAfter); } if (paymentChannel.sourceTag != null) { - txJSON.SourceTag = paymentChannel.sourceTag + txJSON.SourceTag = paymentChannel.sourceTag; } if (paymentChannel.destinationTag != null) { - txJSON.DestinationTag = paymentChannel.destinationTag + txJSON.DestinationTag = paymentChannel.destinationTag; } - return txJSON + return txJSON; } function preparePaymentChannelCreate( @@ -50,16 +51,16 @@ function preparePaymentChannelCreate( validate.preparePaymentChannelCreate({ address, paymentChannelCreate, - instructions - }) + instructions, + }); const txJSON = createPaymentChannelCreateTransaction( address, paymentChannelCreate - ) - return utils.prepareTransaction(txJSON, this, instructions) + ); + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default preparePaymentChannelCreate +export default preparePaymentChannelCreate; diff --git a/src/transaction/payment-channel-fund.ts b/src/transaction/payment-channel-fund.ts index 6192be54..1b68cafa 100644 --- a/src/transaction/payment-channel-fund.ts +++ b/src/transaction/payment-channel-fund.ts @@ -1,13 +1,14 @@ -import * as utils from './utils' -import {validate} from '../common' -import {ISOTimeToRippleTime, xrpToDrops} from '../utils' -import {Instructions, Prepare, TransactionJSON} from './types' -import {Client} from '..' +import { Client } from ".."; +import { validate } from "../common"; +import { ISOTimeToRippleTime, xrpToDrops } from "../utils"; -export type PaymentChannelFund = { - channel: string - amount: string - expiration?: string +import { Instructions, Prepare, TransactionJSON } from "./types"; +import * as utils from "./utils"; + +export interface PaymentChannelFund { + channel: string; + amount: string; + expiration?: string; } function createPaymentChannelFundTransaction( @@ -16,16 +17,16 @@ function createPaymentChannelFundTransaction( ): TransactionJSON { const txJSON: TransactionJSON = { Account: account, - TransactionType: 'PaymentChannelFund', + TransactionType: "PaymentChannelFund", Channel: fund.channel, - Amount: xrpToDrops(fund.amount) - } + Amount: xrpToDrops(fund.amount), + }; if (fund.expiration != null) { - txJSON.Expiration = ISOTimeToRippleTime(fund.expiration) + txJSON.Expiration = ISOTimeToRippleTime(fund.expiration); } - return txJSON + return txJSON; } function preparePaymentChannelFund( @@ -38,16 +39,16 @@ function preparePaymentChannelFund( validate.preparePaymentChannelFund({ address, paymentChannelFund, - instructions - }) + instructions, + }); const txJSON = createPaymentChannelFundTransaction( address, paymentChannelFund - ) - return utils.prepareTransaction(txJSON, this, instructions) + ); + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default preparePaymentChannelFund +export default preparePaymentChannelFund; diff --git a/src/transaction/payment.ts b/src/transaction/payment.ts index bd87490a..59338cbe 100644 --- a/src/transaction/payment.ts +++ b/src/transaction/payment.ts @@ -1,74 +1,77 @@ -import _ from 'lodash' -import * as utils from './utils' -const validate = utils.common.validate -const paymentFlags = utils.common.txFlags.Payment -const ValidationError = utils.common.errors.ValidationError -import {Instructions, Prepare, TransactionJSON} from './types' +import _ from "lodash"; + +import type { Client } from "../client"; import { Amount, Adjustment, MaxAdjustment, MinAdjustment, - Memo -} from '../common/types/objects' -import {toRippledAmount, xrpToDrops} from '../utils' -import {Client} from '..' -import {getClassicAccountAndTag, ClassicAccountAndTag} from './utils' + Memo, +} from "../common/types/objects"; +import { toRippledAmount, xrpToDrops } from "../utils"; + +import { Instructions, Prepare, TransactionJSON } from "./types"; +import * as utils from "./utils"; +import { getClassicAccountAndTag, ClassicAccountAndTag } from "./utils"; + +const validate = utils.common.validate; +const paymentFlags = utils.common.txFlags.Payment; +const ValidationError = utils.common.errors.ValidationError; export interface Payment { - source: Adjustment | MaxAdjustment - destination: Adjustment | MinAdjustment - paths?: string - memos?: Array + source: Adjustment | MaxAdjustment; + destination: Adjustment | MinAdjustment; + paths?: string; + memos?: Memo[]; // A 256-bit hash that can be used to identify a particular payment - invoiceID?: string + invoiceID?: string; // A boolean that, if set to true, indicates that this payment should go // through even if the whole amount cannot be delivered because of a lack of // liquidity or funds in the source_account account - allowPartialPayment?: boolean + allowPartialPayment?: boolean; // A boolean that can be set to true if paths are specified and the sender // would like the Ripple Network to disregard any direct paths from // the source_account to the destination_account. This may be used to take // advantage of an arbitrage opportunity or by gateways wishing to issue // balances from a hot wallet to a user who has mistakenly set a trustline // directly to the hot wallet - noDirectRipple?: boolean - limitQuality?: boolean + noDirectRipple?: boolean; + limitQuality?: boolean; } function isMaxAdjustment( source: Adjustment | MaxAdjustment ): source is MaxAdjustment { - return (source as MaxAdjustment).maxAmount != null + return (source as MaxAdjustment).maxAmount != null; } function isMinAdjustment( destination: Adjustment | MinAdjustment ): destination is MinAdjustment { - return (destination as MinAdjustment).minAmount != null + return (destination as MinAdjustment).minAmount != null; } function isXRPToXRPPayment(payment: Payment): boolean { - const {source, destination} = payment + const { source, destination } = payment; const sourceCurrency = isMaxAdjustment(source) ? source.maxAmount.currency - : source.amount.currency + : source.amount.currency; const destinationCurrency = isMinAdjustment(destination) ? destination.minAmount.currency - : destination.amount.currency + : destination.amount.currency; return ( - (sourceCurrency === 'XRP' || sourceCurrency === 'drops') && - (destinationCurrency === 'XRP' || destinationCurrency === 'drops') - ) + (sourceCurrency === "XRP" || sourceCurrency === "drops") && + (destinationCurrency === "XRP" || destinationCurrency === "drops") + ); } function isIOUWithoutCounterparty(amount: Amount): boolean { return ( amount && - amount.currency !== 'XRP' && - amount.currency !== 'drops' && + amount.currency !== "XRP" && + amount.currency !== "drops" && amount.counterparty == null - ) + ); } function applyAnyCounterpartyEncoding(payment: Payment): void { @@ -76,32 +79,32 @@ function applyAnyCounterpartyEncoding(payment: Payment): void { // (Ripple convention for 'any counterparty') // https://developers.ripple.com/payment.html#special-issuer-values-for-sendmax-and-amount [payment.source, payment.destination].forEach((adjustment) => { - ['amount', 'minAmount', 'maxAmount'].forEach((key) => { + ["amount", "minAmount", "maxAmount"].forEach((key) => { if (isIOUWithoutCounterparty(adjustment[key])) { - adjustment[key].counterparty = adjustment.address + adjustment[key].counterparty = adjustment.address; } - }) - }) + }); + }); } function createMaximalAmount(amount: Amount): Amount { - const maxXRPValue = '100000000000' + const maxXRPValue = "100000000000"; // Equivalent to '9999999999999999e80' but we cannot use that because sign() // now checks that the encoded representation exactly matches the transaction // as it was originally provided. const maxIOUValue = - '999999999999999900000000000000000000000000000000000000000000000000000000000000000000000000000000' + "999999999999999900000000000000000000000000000000000000000000000000000000000000000000000000000000"; - let maxValue - if (amount.currency === 'XRP') { - maxValue = maxXRPValue - } else if (amount.currency === 'drops') { - maxValue = xrpToDrops(maxXRPValue) + let maxValue; + if (amount.currency === "XRP") { + maxValue = maxXRPValue; + } else if (amount.currency === "drops") { + maxValue = xrpToDrops(maxXRPValue); } else { - maxValue = maxIOUValue + maxValue = maxIOUValue; } - return Object.assign({}, amount, {value: maxValue}) + return { ...amount, value: maxValue }; } /** @@ -113,40 +116,43 @@ function createMaximalAmount(amount: Amount): Amount { * 3. If we do not want to use a tag in this case, * set the tag in the return value to `undefined`. * - * @param address The address to parse. - * @param expectedTag If provided, and the `Account` is an X-address, + * @param address - The address to parse. + * @param expectedTag - If provided, and the `Account` is an X-address, * this method throws an error if `expectedTag` * does not match the tag of the X-address. - * @returns {ClassicAccountAndTag} + * @returns * The classic account and tag. */ function validateAndNormalizeAddress( address: string, expectedTag: number | undefined ): ClassicAccountAndTag { - const classicAddress = getClassicAccountAndTag(address, expectedTag) + const classicAddress = getClassicAccountAndTag(address, expectedTag); classicAddress.tag = - classicAddress.tag === false ? undefined : classicAddress.tag - return classicAddress + classicAddress.tag === false ? undefined : classicAddress.tag; + return classicAddress; } function createPaymentTransaction( address: string, paymentArgument: Payment ): TransactionJSON { - const payment = _.cloneDeep(paymentArgument) - applyAnyCounterpartyEncoding(payment) + const payment = _.cloneDeep(paymentArgument); + applyAnyCounterpartyEncoding(payment); const sourceAddressAndTag = validateAndNormalizeAddress( payment.source.address, payment.source.tag - ) - const addressToVerifyAgainst = validateAndNormalizeAddress(address, undefined) + ); + const addressToVerifyAgainst = validateAndNormalizeAddress( + address, + undefined + ); if ( addressToVerifyAgainst.classicAccount !== sourceAddressAndTag.classicAccount ) { - throw new ValidationError('address must match payment.source.address') + throw new ValidationError("address must match payment.source.address"); } if ( @@ -155,31 +161,31 @@ function createPaymentTransaction( addressToVerifyAgainst.tag !== sourceAddressAndTag.tag ) { throw new ValidationError( - 'address includes a tag that does not match payment.source.tag' - ) + "address includes a tag that does not match payment.source.tag" + ); } const destinationAddressAndTag = validateAndNormalizeAddress( payment.destination.address, payment.destination.tag - ) + ); if ( (isMaxAdjustment(payment.source) && isMinAdjustment(payment.destination)) || (!isMaxAdjustment(payment.source) && !isMinAdjustment(payment.destination)) ) { throw new ValidationError( - 'payment must specify either (source.maxAmount ' + - 'and destination.amount) or (source.amount and destination.minAmount)' - ) + "payment must specify either (source.maxAmount " + + "and destination.amount) or (source.amount and destination.minAmount)" + ); } const destinationAmount = isMinAdjustment(payment.destination) ? payment.destination.minAmount - : payment.destination.amount + : payment.destination.amount; const sourceAmount = isMaxAdjustment(payment.source) ? payment.source.maxAmount - : payment.source.amount + : payment.source.amount; // when using destination.minAmount, rippled still requires that we set // a destination amount in addition to DeliverMin. the destination amount @@ -190,33 +196,33 @@ function createPaymentTransaction( const amount = isMinAdjustment(payment.destination) && !isXRPToXRPPayment(payment) ? createMaximalAmount(destinationAmount) - : destinationAmount + : destinationAmount; const txJSON: any = { - TransactionType: 'Payment', + TransactionType: "Payment", Account: sourceAddressAndTag.classicAccount, Destination: destinationAddressAndTag.classicAccount, Amount: toRippledAmount(amount), - Flags: 0 - } + Flags: 0, + }; if (payment.invoiceID != null) { - txJSON.InvoiceID = payment.invoiceID + txJSON.InvoiceID = payment.invoiceID; } if (sourceAddressAndTag.tag != null) { - txJSON.SourceTag = sourceAddressAndTag.tag + txJSON.SourceTag = sourceAddressAndTag.tag; } if (destinationAddressAndTag.tag != null) { - txJSON.DestinationTag = destinationAddressAndTag.tag + txJSON.DestinationTag = destinationAddressAndTag.tag; } if (payment.memos != null) { - txJSON.Memos = payment.memos.map(utils.convertMemo) + txJSON.Memos = payment.memos.map(utils.convertMemo); } - if (payment.noDirectRipple === true) { - txJSON.Flags |= paymentFlags.NoRippleDirect + if (payment.noDirectRipple) { + txJSON.Flags |= paymentFlags.NoRippleDirect; } - if (payment.limitQuality === true) { - txJSON.Flags |= paymentFlags.LimitQuality + if (payment.limitQuality) { + txJSON.Flags |= paymentFlags.LimitQuality; } if (!isXRPToXRPPayment(payment)) { // Don't set SendMax for XRP->XRP payment @@ -224,23 +230,23 @@ function createPaymentTransaction( // https://github.com/ripple/rippled/commit/ // c522ffa6db2648f1d8a987843e7feabf1a0b7de8/ if (payment.allowPartialPayment || isMinAdjustment(payment.destination)) { - txJSON.Flags |= paymentFlags.PartialPayment + txJSON.Flags |= paymentFlags.PartialPayment; } - txJSON.SendMax = toRippledAmount(sourceAmount) + txJSON.SendMax = toRippledAmount(sourceAmount); if (isMinAdjustment(payment.destination)) { - txJSON.DeliverMin = toRippledAmount(destinationAmount) + txJSON.DeliverMin = toRippledAmount(destinationAmount); } if (payment.paths != null) { - txJSON.Paths = JSON.parse(payment.paths) + txJSON.Paths = JSON.parse(payment.paths); } - } else if (payment.allowPartialPayment === true) { - throw new ValidationError('XRP to XRP payments cannot be partial payments') + } else if (payment.allowPartialPayment) { + throw new ValidationError("XRP to XRP payments cannot be partial payments"); } - return txJSON + return txJSON; } function preparePayment( @@ -250,12 +256,12 @@ function preparePayment( instructions: Instructions = {} ): Promise { try { - validate.preparePayment({address, payment, instructions}) - const txJSON = createPaymentTransaction(address, payment) - return utils.prepareTransaction(txJSON, this, instructions) + validate.preparePayment({ address, payment, instructions }); + const txJSON = createPaymentTransaction(address, payment); + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default preparePayment +export default preparePayment; diff --git a/src/transaction/settings.ts b/src/transaction/settings.ts index 0f8fe99f..648a4f0e 100644 --- a/src/transaction/settings.ts +++ b/src/transaction/settings.ts @@ -1,35 +1,41 @@ -import * as assert from 'assert' -import BigNumber from 'bignumber.js' -import * as utils from './utils' -const validate = utils.common.validate -const AccountSetFlags = utils.common.constants.AccountSetFlags -const AccountFields = utils.common.constants.AccountFields +import * as assert from "assert"; + +import BigNumber from "bignumber.js"; + +import { Client } from ".."; +import { FormattedSettings, WeightedSigner } from "../common/types/objects"; + import { Instructions, Prepare, SettingsTransaction, - TransactionJSON -} from './types' -import {FormattedSettings, WeightedSigner} from '../common/types/objects' -import {Client} from '..' + TransactionJSON, +} from "./types"; +import * as utils from "./utils"; + +const validate = utils.common.validate; +const AccountSetFlags = utils.common.constants.AccountSetFlags; +const AccountFields = utils.common.constants.AccountFields; function setTransactionFlags( txJSON: TransactionJSON, values: FormattedSettings ) { - const keys = Object.keys(values).filter((key) => AccountSetFlags[key] != null) + const keys = Object.keys(values).filter( + (key) => AccountSetFlags[key] != null + ); assert.ok( keys.length <= 1, - 'ERROR: can only set one setting per transaction' - ) - const flagName = keys[0] - const value = values[flagName] - const index = AccountSetFlags[flagName] + "ERROR: can only set one setting per transaction" + ); + const flagName = keys[0]; + const value = values[flagName]; + const index = AccountSetFlags[flagName]; if (index != null) { if (value) { - txJSON.SetFlag = index + txJSON.SetFlag = index; } else { - txJSON.ClearFlag = index + txJSON.ClearFlag = index; } } } @@ -39,26 +45,26 @@ function setTransactionFields( txJSON: TransactionJSON, input: FormattedSettings ) { - const fieldSchema = AccountFields + const fieldSchema = AccountFields; for (const fieldName in fieldSchema) { - const field = fieldSchema[fieldName] - let value = input[field.name] + const field = fieldSchema[fieldName]; + let value = input[field.name]; if (value === undefined) { - continue + continue; } // The value required to clear an account root field varies - if (value === null && field.hasOwnProperty('defaults')) { - value = field.defaults + if (value === null && field.hasOwnProperty("defaults")) { + value = field.defaults; } - if (field.encoding === 'hex' && !field.length) { + if (field.encoding === "hex" && !field.length) { // This is currently only used for Domain field - value = Buffer.from(value, 'ascii').toString('hex').toUpperCase() + value = Buffer.from(value, "ascii").toString("hex").toUpperCase(); } - txJSON[fieldName] = value + txJSON[fieldName] = value; } } @@ -67,25 +73,25 @@ function setTransactionFields( * destination to receive 100%. * The transfer rate is specified as the input amount as fraction of 1. * To specify the default rate of 0%, a 100% input amount, specify 1. - * To specify a rate of 1%, a 101% input amount, specify 1.01 + * To specify a rate of 1%, a 101% input amount, specify 1.01. * * @param {Number|String} transferRate * - * @returns {Number|String} numbers will be converted while strings - * are returned + * @returns {Number|String} Numbers will be converted while strings + * are returned. */ function convertTransferRate(transferRate: number): number { - return new BigNumber(transferRate).shiftedBy(9).toNumber() + return new BigNumber(transferRate).shiftedBy(9).toNumber(); } function formatSignerEntry(signer: WeightedSigner): object { return { SignerEntry: { Account: signer.address, - SignerWeight: signer.weight - } - } + SignerWeight: signer.weight, + }, + }; } function createSettingsTransactionWithoutMemos( @@ -94,58 +100,55 @@ function createSettingsTransactionWithoutMemos( ): SettingsTransaction { if (settings.regularKey !== undefined) { const removeRegularKey = { - TransactionType: 'SetRegularKey', - Account: account - } + TransactionType: "SetRegularKey", + Account: account, + }; if (settings.regularKey === null) { - return removeRegularKey + return removeRegularKey; } - return Object.assign({}, removeRegularKey, { - RegularKey: settings.regularKey - }) + return { ...removeRegularKey, RegularKey: settings.regularKey }; } if (settings.signers != null) { - const setSignerList = { - TransactionType: 'SignerListSet', + const setSignerList: SettingsTransaction = { + TransactionType: "SignerListSet", Account: account, SignerEntries: [], - SignerQuorum: settings.signers.threshold - } + SignerQuorum: settings.signers.threshold, + }; if (settings.signers.weights != null) { - setSignerList.SignerEntries = settings.signers.weights.map( - formatSignerEntry - ) + setSignerList.SignerEntries = + settings.signers.weights.map(formatSignerEntry); } - return setSignerList + return setSignerList; } const txJSON: SettingsTransaction = { - TransactionType: 'AccountSet', - Account: account - } + TransactionType: "AccountSet", + Account: account, + }; - const settingsWithoutMemos = Object.assign({}, settings) - delete settingsWithoutMemos.memos - setTransactionFlags(txJSON, settingsWithoutMemos) - setTransactionFields(txJSON, settings) // Sets `null` fields to their `default`. + const settingsWithoutMemos = { ...settings }; + delete settingsWithoutMemos.memos; + setTransactionFlags(txJSON, settingsWithoutMemos); + setTransactionFields(txJSON, settings); // Sets `null` fields to their `default`. if (txJSON.TransferRate != null) { - txJSON.TransferRate = convertTransferRate(txJSON.TransferRate) + txJSON.TransferRate = convertTransferRate(txJSON.TransferRate); } - return txJSON + return txJSON; } function createSettingsTransaction( account: string, settings: FormattedSettings ): SettingsTransaction { - const txJSON = createSettingsTransactionWithoutMemos(account, settings) + const txJSON = createSettingsTransactionWithoutMemos(account, settings); if (settings.memos != null) { - txJSON.Memos = settings.memos.map(utils.convertMemo) + txJSON.Memos = settings.memos.map(utils.convertMemo); } - return txJSON + return txJSON; } function prepareSettings( @@ -155,12 +158,13 @@ function prepareSettings( instructions: Instructions = {} ): Promise { try { - validate.prepareSettings({address, settings, instructions}) - const txJSON = createSettingsTransaction(address, settings) - return utils.prepareTransaction(txJSON, this, instructions) + validate.prepareSettings({ address, settings, instructions }); + const txJSON = createSettingsTransaction(address, settings); + + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default prepareSettings +export default prepareSettings; diff --git a/src/transaction/sign.ts b/src/transaction/sign.ts index 5f6336ad..33a42afa 100644 --- a/src/transaction/sign.ts +++ b/src/transaction/sign.ts @@ -1,48 +1,50 @@ -import _ from 'lodash' -import * as utils from './utils' -import keypairs from 'ripple-keypairs' -import binaryCodec from 'ripple-binary-codec' -import {computeBinaryTransactionHash} from '../utils/hashes' -import {SignOptions, KeyPair, TransactionJSON} from './types' -import BigNumber from 'bignumber.js' -import {xrpToDrops} from '../utils' -import {Client} from '..' -import Wallet from '../Wallet' -import {SignedTransaction} from '../common/types/objects' -const validate = utils.common.validate +import BigNumber from "bignumber.js"; +import _ from "lodash"; +import binaryCodec from "ripple-binary-codec"; +import keypairs from "ripple-keypairs"; + +import { Client } from ".."; +import { SignedTransaction } from "../common/types/objects"; +import { xrpToDrops } from "../utils"; +import { computeBinaryTransactionHash } from "../utils/hashes"; +import Wallet from "../Wallet"; + +import { SignOptions, KeyPair, TransactionJSON } from "./types"; +import * as utils from "./utils"; + +const validate = utils.common.validate; function computeSignature(tx: object, privateKey: string, signAs?: string) { const signingData = signAs ? binaryCodec.encodeForMultisigning(tx, signAs) - : binaryCodec.encodeForSigning(tx) - return keypairs.sign(signingData, privateKey) + : binaryCodec.encodeForSigning(tx); + return keypairs.sign(signingData, privateKey); } function signWithKeypair( - client: Client, + client: Client | null, txJSON: string, keypair: KeyPair, options: SignOptions = { - signAs: '' + signAs: "", } ): SignedTransaction { - validate.sign({txJSON, keypair}) - const isOnline = !!client; + validate.sign({ txJSON, keypair }); - const tx = JSON.parse(txJSON) + const tx = JSON.parse(txJSON); if (tx.TxnSignature || tx.Signers) { throw new utils.common.errors.ValidationError( 'txJSON must not contain "TxnSignature" or "Signers" properties' - ) + ); } - if (isOnline) { - checkFee(client, tx.Fee) + if (client != null) { + checkFee(client, tx.Fee); } - const txToSignAndEncode = Object.assign({}, tx) + const txToSignAndEncode = { ...tx }; - txToSignAndEncode.SigningPubKey = options.signAs ? '' : keypair.publicKey + txToSignAndEncode.SigningPubKey = options.signAs ? "" : keypair.publicKey; if (options.signAs) { const signer = { @@ -52,74 +54,74 @@ function signWithKeypair( txToSignAndEncode, keypair.privateKey, options.signAs - ) - } - txToSignAndEncode.Signers = [{Signer: signer}] + ), + }; + txToSignAndEncode.Signers = [{ Signer: signer }]; } else { txToSignAndEncode.TxnSignature = computeSignature( txToSignAndEncode, keypair.privateKey - ) + ); } - const serialized = binaryCodec.encode(txToSignAndEncode) - checkTxSerialization(serialized, tx) + const serialized = binaryCodec.encode(txToSignAndEncode); + checkTxSerialization(serialized, tx); return { signedTransaction: serialized, - id: computeBinaryTransactionHash(serialized) - } + id: computeBinaryTransactionHash(serialized), + }; } /** * Compares two objects and creates a diff. * - * @param a An object to compare. - * @param b The other object to compare with. + * @param a - An object to compare. + * @param b - The other object to compare with. * * @returns An object containing the differences between the two objects. */ function objectDiff(a: object, b: object): object { - const diffs = {} + const diffs = {}; // Compare two items and push non-matches to object const compare = function (i1: any, i2: any, k: string): void { - const type1 = Object.prototype.toString.call(i1) - const type2 = Object.prototype.toString.call(i2) - if (type2 === '[object Undefined]') { - diffs[k] = null // Indicate that the item has been removed - return + const type1 = Object.prototype.toString.call(i1); + const type2 = Object.prototype.toString.call(i2); + if (type2 === "[object Undefined]") { + diffs[k] = null; // Indicate that the item has been removed + return; } if (type1 !== type2) { - diffs[k] = i2 // Indicate that the item has changed types - return + diffs[k] = i2; // Indicate that the item has changed types + return; } - if (type1 === '[object Object]') { - const objDiff = objectDiff(i1, i2) + if (type1 === "[object Object]") { + const objDiff = objectDiff(i1, i2); if (Object.keys(objDiff).length > 0) { - diffs[k] = objDiff + diffs[k] = objDiff; } - return + return; } - if (type1 === '[object Array]') { + if (type1 === "[object Array]") { if (!_.isEqual(i1, i2)) { - diffs[k] = i2 // If arrays do not match, add second item to diffs + diffs[k] = i2; // If arrays do not match, add second item to diffs } - return + return; } - if (type1 === '[object Function]') { + if (type1 === "[object Function]") { if (i1.toString() !== i2.toString()) { - diffs[k] = i2 // If functions differ, add second one to diffs + diffs[k] = i2; // If functions differ, add second one to diffs } - return + return; } if (i1 !== i2) { - diffs[k] = i2 + diffs[k] = i2; } - } + }; // Check items in first object for (const key in a) { if (a.hasOwnProperty(key)) { - compare(a[key], b[key], key) + compare(a[key], b[key], key); } } @@ -127,94 +129,94 @@ function objectDiff(a: object, b: object): object { for (const key in b) { if (b.hasOwnProperty(key)) { if (!a[key] && a[key] !== b[key]) { - diffs[key] = b[key] + diffs[key] = b[key]; } } } - return diffs + return diffs; } /** * Decode a serialized transaction, remove the fields that are added during the signing process, * and verify that it matches the transaction prior to signing. * - * @param {string} serialized A signed and serialized transaction. - * @param {TransactionJSON} tx The transaction prior to signing. + * @param serialized - A signed and serialized transaction. + * @param tx - The transaction prior to signing. * - * @returns {void} This method does not return a value, but throws an error if the check fails. + * @returns This method does not return a value, but throws an error if the check fails. */ function checkTxSerialization(serialized: string, tx: TransactionJSON): void { // Decode the serialized transaction: - const decoded = binaryCodec.decode(serialized) + const decoded = binaryCodec.decode(serialized); // ...And ensure it is equal to the original tx, except: // - It must have a TxnSignature or Signers (multisign). if (!decoded.TxnSignature && !decoded.Signers) { throw new utils.common.errors.ValidationError( - 'Serialized transaction must have a TxnSignature or Signers property' - ) + "Serialized transaction must have a TxnSignature or Signers property" + ); } // - We know that the original tx did not have TxnSignature, so we should delete it: - delete decoded.TxnSignature + delete decoded.TxnSignature; // - We know that the original tx did not have Signers, so if it exists, we should delete it: - delete decoded.Signers + delete decoded.Signers; // - If SigningPubKey was not in the original tx, then we should delete it. // But if it was in the original tx, then we should ensure that it has not been changed. if (!tx.SigningPubKey) { - delete decoded.SigningPubKey + delete decoded.SigningPubKey; } - // - Memos have exclusively hex data which should ignore case. + // - Memos have exclusively hex data which should ignore case. // Since decode goes to upper case, we set all tx memos to be uppercase for the comparison. - tx.Memos?.map(memo => { - if(memo?.Memo?.MemoData) { + tx.Memos?.map((memo) => { + if (memo.Memo.MemoData) { memo.Memo.MemoData = memo.Memo.MemoData.toUpperCase(); } - if(memo?.Memo?.MemoType) { + if (memo.Memo.MemoType) { memo.Memo.MemoType = memo.Memo.MemoType.toUpperCase(); } - - if(memo?.Memo?.MemoFormat) { + + if (memo.Memo.MemoFormat) { memo.Memo.MemoFormat = memo.Memo.MemoFormat.toUpperCase(); } - return memo - }) + return memo; + }); if (!_.isEqual(decoded, tx)) { const error = new utils.common.errors.ValidationError( - 'Serialized transaction does not match original txJSON. See `error.data`' - ) + "Serialized transaction does not match original txJSON. See `error.data`" + ); error.data = { decoded, tx, - diff: objectDiff(tx, decoded) - } - throw error + diff: objectDiff(tx, decoded), + }; + throw error; } } /** * Check that a given transaction fee does not exceed maxFeeXRP (in drops). * - * See https://xrpl.org/rippleapi-reference.html#parameters + * See https://xrpl.org/rippleapi-reference.html#parameters. * - * @param {Client} client A Client instance. - * @param {string} txFee The transaction fee in drops, encoded as a string. + * @param client - A Client instance. + * @param txFee - The transaction fee in drops, encoded as a string. * - * @returns {void} This method does not return a value, but throws an error if the check fails. + * @returns This method does not return a value, but throws an error if the check fails. */ function checkFee(client: Client, txFee: string): void { - const fee = new BigNumber(txFee) - const maxFeeDrops = xrpToDrops(client._maxFeeXRP) + const fee = new BigNumber(txFee); + const maxFeeDrops = xrpToDrops(client._maxFeeXRP); if (fee.isGreaterThan(maxFeeDrops)) { throw new utils.common.errors.ValidationError( `"Fee" should not exceed "${maxFeeDrops}". ` + - 'To use a higher fee, set `maxFeeXRP` in the Client constructor.' - ) + "To use a higher fee, set `maxFeeXRP` in the Client constructor." + ); } } @@ -225,40 +227,34 @@ function sign( options?: SignOptions, keypair?: KeyPair ): SignedTransaction { - if (typeof secret === 'string') { + if (typeof secret === "string") { // we can't validate that the secret matches the account because // the secret could correspond to the regular key - validate.sign({txJSON, secret}) + validate.sign({ txJSON, secret }); return signWithKeypair( this, txJSON, keypairs.deriveKeypair(secret), options - ) - } else { - if (!keypair && !secret) { - // Clearer message than 'ValidationError: instance is not exactly one from [subschema 0],[subschema 1]' - throw new utils.common.errors.ValidationError( - 'sign: Missing secret or keypair.' - ) - } - return signWithKeypair(this, txJSON, keypair ? keypair : secret, options) + ); } + if (!keypair && !secret) { + // Clearer message than 'ValidationError: instance is not exactly one from [subschema 0],[subschema 1]' + throw new utils.common.errors.ValidationError( + "sign: Missing secret or keypair." + ); + } + return signWithKeypair(this, txJSON, keypair || secret, options); } // TODO: move this to Wallet class function signOffline( wallet: Wallet, txJSON: string, - options?: SignOptions, + options?: SignOptions ): SignedTransaction { - const {publicKey, privateKey} = wallet - return signWithKeypair( - null, - txJSON, - {publicKey, privateKey}, - options, - ) + const { publicKey, privateKey } = wallet; + return signWithKeypair(null, txJSON, { publicKey, privateKey }, options); } -export {sign, signOffline} +export { sign, signOffline }; diff --git a/src/transaction/ticket.ts b/src/transaction/ticket.ts index 127ef359..a0223c13 100644 --- a/src/transaction/ticket.ts +++ b/src/transaction/ticket.ts @@ -1,30 +1,33 @@ -import _ from 'lodash' -import * as utils from './utils' -import {Prepare, TransactionJSON, Instructions} from './types' -import {Client} from '..' +import _ from "lodash"; -const validate = utils.common.validate -const ValidationError = utils.common.errors.ValidationError +import type { Client } from ".."; + +import { Prepare, TransactionJSON, Instructions } from "./types"; +import * as utils from "./utils"; + +const validate = utils.common.validate; +const ValidationError = utils.common.errors.ValidationError; export interface Ticket { - account: string - sequence: number + account: string; + sequence: number; } function createTicketTransaction( account: string, ticketCount: number ): TransactionJSON { - if (!ticketCount || ticketCount === 0) - throw new ValidationError('Ticket count must be greater than 0.') - - const txJSON: any = { - TransactionType: 'TicketCreate', - Account: account, - TicketCount: ticketCount + if (!ticketCount || ticketCount === 0) { + throw new ValidationError("Ticket count must be greater than 0."); } - return txJSON + const txJSON: any = { + TransactionType: "TicketCreate", + Account: account, + TicketCount: ticketCount, + }; + + return txJSON; } function prepareTicketCreate( @@ -34,12 +37,12 @@ function prepareTicketCreate( instructions: Instructions = {} ): Promise { try { - validate.prepareTicketCreate({address, ticketCount, instructions}) - const txJSON = createTicketTransaction(address, ticketCount) - return utils.prepareTransaction(txJSON, this, instructions) + validate.prepareTicketCreate({ address, ticketCount, instructions }); + const txJSON = createTicketTransaction(address, ticketCount); + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default prepareTicketCreate +export default prepareTicketCreate; diff --git a/src/transaction/trustline.ts b/src/transaction/trustline.ts index 3120303c..794b8483 100644 --- a/src/transaction/trustline.ts +++ b/src/transaction/trustline.ts @@ -1,16 +1,19 @@ -import BigNumber from 'bignumber.js' -import * as utils from './utils' -const validate = utils.common.validate -const trustlineFlags = utils.common.txFlags.TrustSet -import {Instructions, Prepare, TransactionJSON} from './types' -import {FormattedTrustlineSpecification} from '../common/types/objects/trustlines' -import {Client} from '..' +import BigNumber from "bignumber.js"; + +import { Client } from ".."; +import { FormattedTrustlineSpecification } from "../common/types/objects/trustlines"; + +import { Instructions, Prepare, TransactionJSON } from "./types"; +import * as utils from "./utils"; + +const validate = utils.common.validate; +const trustlineFlags = utils.common.txFlags.TrustSet; function convertQuality(quality) { return new BigNumber(quality) .shiftedBy(9) .integerValue(BigNumber.ROUND_DOWN) - .toNumber() + .toNumber(); } function createTrustlineTransaction( @@ -20,38 +23,38 @@ function createTrustlineTransaction( const limit = { currency: trustline.currency, issuer: trustline.counterparty, - value: trustline.limit - } + value: trustline.limit, + }; const txJSON: any = { - TransactionType: 'TrustSet', + TransactionType: "TrustSet", Account: account, LimitAmount: limit, - Flags: 0 - } + Flags: 0, + }; if (trustline.qualityIn != null) { - txJSON.QualityIn = convertQuality(trustline.qualityIn) + txJSON.QualityIn = convertQuality(trustline.qualityIn); } if (trustline.qualityOut != null) { - txJSON.QualityOut = convertQuality(trustline.qualityOut) + txJSON.QualityOut = convertQuality(trustline.qualityOut); } - if (trustline.authorized === true) { - txJSON.Flags |= trustlineFlags.SetAuth + if (trustline.authorized) { + txJSON.Flags |= trustlineFlags.SetAuth; } if (trustline.ripplingDisabled != null) { txJSON.Flags |= trustline.ripplingDisabled ? trustlineFlags.NoRipple - : trustlineFlags.ClearNoRipple + : trustlineFlags.ClearNoRipple; } if (trustline.frozen != null) { txJSON.Flags |= trustline.frozen ? trustlineFlags.SetFreeze - : trustlineFlags.ClearFreeze + : trustlineFlags.ClearFreeze; } if (trustline.memos != null) { - txJSON.Memos = trustline.memos.map(utils.convertMemo) + txJSON.Memos = trustline.memos.map(utils.convertMemo); } - return txJSON + return txJSON; } function prepareTrustline( @@ -61,12 +64,12 @@ function prepareTrustline( instructions: Instructions = {} ): Promise { try { - validate.prepareTrustline({address, trustline, instructions}) - const txJSON = createTrustlineTransaction(address, trustline) - return utils.prepareTransaction(txJSON, this, instructions) + validate.prepareTrustline({ address, trustline, instructions }); + const txJSON = createTrustlineTransaction(address, trustline); + return utils.prepareTransaction(txJSON, this, instructions); } catch (e) { - return Promise.reject(e) + return Promise.reject(e); } } -export default prepareTrustline +export default prepareTrustline; diff --git a/src/transaction/types.ts b/src/transaction/types.ts index bb6f10cb..3eabc39e 100644 --- a/src/transaction/types.ts +++ b/src/transaction/types.ts @@ -4,155 +4,156 @@ import { Adjustment, RippledAmount, Memo, - FormattedSettings -} from '../common/types/objects' -import {ApiMemo} from './utils' + FormattedSettings, +} from "../common/types/objects"; -export type TransactionJSON = { - Account: string - TransactionType: string - Memos?: {Memo: ApiMemo}[] - Flags?: number - Fulfillment?: string - [Field: string]: string | number | Array | RippledAmount | undefined +import { ApiMemo } from "./utils"; + +export interface TransactionJSON { + Account: string; + TransactionType: string; + Memos?: Array<{ Memo: ApiMemo }>; + Flags?: number; + Fulfillment?: string; + [Field: string]: string | number | any[] | RippledAmount | undefined; } -export type Instructions = { - sequence?: number - ticketSequence?: number - fee?: string +export interface Instructions { + sequence?: number; + ticketSequence?: number; + fee?: string; // @deprecated - maxFee?: string - maxLedgerVersion?: number - maxLedgerVersionOffset?: number - signersCount?: number + maxFee?: string; + maxLedgerVersion?: number; + maxLedgerVersionOffset?: number; + signersCount?: number; } -export type Prepare = { - txJSON: string +export interface Prepare { + txJSON: string; instructions: { - fee: string - sequence?: number - ticketSequence?: number - maxLedgerVersion?: number - } + fee: string; + sequence?: number; + ticketSequence?: number; + maxLedgerVersion?: number; + }; } -export type Submit = { - success: boolean - engineResult: string - engineResultCode: number - engineResultMessage?: string - txBlob?: string - txJson?: object +export interface Submit { + success: boolean; + engineResult: string; + engineResultCode: number; + engineResultMessage?: string; + txBlob?: string; + txJson?: object; } export interface OfferCreateTransaction extends TransactionJSON { - TransactionType: 'OfferCreate' - Account: string - Fee: string - Flags: number - LastLedgerSequence: number - Sequence: number - TakerGets: RippledAmount - TakerPays: RippledAmount - Expiration?: number - OfferSequence?: number - Memos?: {Memo: ApiMemo}[] + TransactionType: "OfferCreate"; + Account: string; + Fee: string; + Flags: number; + LastLedgerSequence: number; + Sequence: number; + TakerGets: RippledAmount; + TakerPays: RippledAmount; + Expiration?: number; + OfferSequence?: number; + Memos?: Array<{ Memo: ApiMemo }>; } export interface SettingsTransaction extends TransactionJSON { - TransferRate?: number + TransferRate?: number; } -export type KeyPair = { - publicKey: string - privateKey: string +export interface KeyPair { + publicKey: string; + privateKey: string; } -export type SignOptions = { - signAs: string +export interface SignOptions { + signAs: string; } -export type Outcome = { - result: string - ledgerVersion: number - indexInLedger: number - fee: string +export interface Outcome { + result: string; + ledgerVersion: number; + indexInLedger: number; + fee: string; balanceChanges: { - [key: string]: { - currency: string - counterparty?: string - value: string - }[] - } - orderbookChanges: object + [key: string]: Array<{ + currency: string; + counterparty?: string; + value: string; + }>; + }; + orderbookChanges: object; deliveredAmount?: { - currency: string - counterparty?: string - value: string - } - timestamp?: string + currency: string; + counterparty?: string; + value: string; + }; + timestamp?: string; } -export type FormattedOrderCancellation = { - orderSequence: number +export interface FormattedOrderCancellation { + orderSequence: number; } -export type FormattedPayment = { - source: Adjustment - destination: Adjustment - paths?: string - memos?: Array - invoiceID?: string - allowPartialPayment?: boolean - noDirectRipple?: boolean - limitQuality?: boolean +export interface FormattedPayment { + source: Adjustment; + destination: Adjustment; + paths?: string; + memos?: Memo[]; + invoiceID?: string; + allowPartialPayment?: boolean; + noDirectRipple?: boolean; + limitQuality?: boolean; } -export type FormattedPaymentTransaction = { - type: string - specification: FormattedPayment - outcome: Outcome - id: string - address: string - sequence: number +export interface FormattedPaymentTransaction { + type: string; + specification: FormattedPayment; + outcome: Outcome; + id: string; + address: string; + sequence: number; } -export type FormattedOrderTransaction = { - type: string - specification: FormattedOrderSpecification - outcome: Outcome - id: string - address: string - sequence: number +export interface FormattedOrderTransaction { + type: string; + specification: FormattedOrderSpecification; + outcome: Outcome; + id: string; + address: string; + sequence: number; } -export type FormattedOrderCancellationTransaction = { - type: string - specification: FormattedOrderCancellation - outcome: Outcome - id: string - address: string - sequence: number +export interface FormattedOrderCancellationTransaction { + type: string; + specification: FormattedOrderCancellation; + outcome: Outcome; + id: string; + address: string; + sequence: number; } -export type FormattedTrustlineTransaction = { - type: string - specification: FormattedTrustlineSpecification - outcome: Outcome - id: string - address: string - sequence: number +export interface FormattedTrustlineTransaction { + type: string; + specification: FormattedTrustlineSpecification; + outcome: Outcome; + id: string; + address: string; + sequence: number; } -export type FormattedSettingsTransaction = { - type: string - specification: FormattedSettings - outcome: Outcome - id: string - address: string - sequence: number +export interface FormattedSettingsTransaction { + type: string; + specification: FormattedSettings; + outcome: Outcome; + id: string; + address: string; + sequence: number; } export type FormattedTransactionType = @@ -160,4 +161,4 @@ export type FormattedTransactionType = | FormattedOrderTransaction | FormattedOrderCancellationTransaction | FormattedTrustlineTransaction - | FormattedSettingsTransaction + | FormattedSettingsTransaction; diff --git a/src/transaction/utils.ts b/src/transaction/utils.ts index ce4079b7..1ae18366 100644 --- a/src/transaction/utils.ts +++ b/src/transaction/utils.ts @@ -1,63 +1,77 @@ -import BigNumber from 'bignumber.js' -import * as common from '../common' -import {Memo} from '../common/types/objects' -import {Instructions, Prepare, TransactionJSON} from './types' -import {toRippledAmount, dropsToXrp, removeUndefined, xrpToDrops} from '../utils' -import {Client} from '..' -import {ValidationError} from '../common/errors' -import {xAddressToClassicAddress, isValidXAddress} from 'ripple-address-codec' +import BigNumber from "bignumber.js"; +import { + xAddressToClassicAddress, + isValidXAddress, +} from "ripple-address-codec"; -const txFlags = common.txFlags +import { Client } from ".."; +import * as common from "../common"; +import { ValidationError } from "../common/errors"; +import { Memo } from "../common/types/objects"; +import { + toRippledAmount, + dropsToXrp, + removeUndefined, + xrpToDrops, +} from "../utils"; + +import { Instructions, Prepare, TransactionJSON } from "./types"; + +const txFlags = common.txFlags; const TRANSACTION_TYPES_WITH_DESTINATION_TAG_FIELD = [ - 'Payment', - 'CheckCreate', - 'EscrowCreate', - 'PaymentChannelCreate' -] + "Payment", + "CheckCreate", + "EscrowCreate", + "PaymentChannelCreate", +]; -export type ApiMemo = { - MemoData?: string - MemoType?: string - MemoFormat?: string +export interface ApiMemo { + MemoData?: string; + MemoType?: string; + MemoFormat?: string; } function formatPrepareResponse(txJSON: any): Prepare { - const instructions = { + const instructions: any = { fee: dropsToXrp(txJSON.Fee), maxLedgerVersion: - txJSON.LastLedgerSequence == null ? null : txJSON.LastLedgerSequence - } + txJSON.LastLedgerSequence == null ? null : txJSON.LastLedgerSequence, + }; if (txJSON.TicketSequence != null) { - instructions['ticketSequence'] = txJSON.TicketSequence + instructions.ticketSequence = txJSON.TicketSequence; } else { - instructions['sequence'] = txJSON.Sequence + instructions.sequence = txJSON.Sequence; } return { txJSON: JSON.stringify(txJSON), - instructions - } + instructions, + }; } /** * Set the `tfFullyCanonicalSig` flag on a transaction. * - * See https://xrpl.org/transaction-malleability.html + * See https://xrpl.org/transaction-malleability.html. * - * @param {TransactionJSON} txJSON The transaction object to modify. + * @param txJSON - The transaction object to modify. * This method will modify object's `Flags` property, or add it if it does not exist. * - * @returns {void} This method mutates the original txJSON and does not return a value. + * @returns This method mutates the original txJSON and does not return a value. */ function setCanonicalFlag(txJSON: TransactionJSON): void { - txJSON.Flags |= txFlags.Universal.FullyCanonicalSig + if (txJSON.Flags == null) { + txJSON.Flags = 0; + } + + txJSON.Flags |= txFlags.Universal.FullyCanonicalSig; // JavaScript converts operands to 32-bit signed ints before doing bitwise // operations. We need to convert it back to an unsigned int. - txJSON.Flags = txJSON.Flags >>> 0 + txJSON.Flags >>>= 0; } function scaleValue(value, multiplier, extra = 0) { - return new BigNumber(value).times(multiplier).plus(extra).toString() + return new BigNumber(value).times(multiplier).plus(extra).toString(); } /** @@ -68,8 +82,8 @@ function scaleValue(value, multiplier, extra = 0) { * `undefined` if the input could not specify whether a tag should be used. */ export interface ClassicAccountAndTag { - classicAccount: string - tag: number | false | undefined + classicAccount: string; + tag: number | false | undefined; } /** @@ -78,11 +92,11 @@ export interface ClassicAccountAndTag { * 1. If the `Account` is an X-address, validate that the tags match. * 2. If the `Account` is a classic address, return `expectedTag` as the tag. * - * @param Account The address to parse. - * @param expectedTag If provided, and the `Account` is an X-address, + * @param Account - The address to parse. + * @param expectedTag - If provided, and the `Account` is an X-address, * this method throws an error if `expectedTag` * does not match the tag of the X-address. - * @returns {ClassicAccountAndTag} + * @returns * The classic account and tag. */ function getClassicAccountAndTag( @@ -90,22 +104,21 @@ function getClassicAccountAndTag( expectedTag?: number ): ClassicAccountAndTag { if (isValidXAddress(Account)) { - const classic = xAddressToClassicAddress(Account) + const classic = xAddressToClassicAddress(Account); if (expectedTag != null && classic.tag !== expectedTag) { throw new ValidationError( - 'address includes a tag that does not match the tag specified in the transaction' - ) + "address includes a tag that does not match the tag specified in the transaction" + ); } return { classicAccount: classic.classicAddress, - tag: classic.tag - } - } else { - return { - classicAccount: Account, - tag: expectedTag - } + tag: classic.tag, + }; } + return { + classicAccount: Account, + tag: expectedTag, + }; } function prepareTransaction( @@ -113,66 +126,62 @@ function prepareTransaction( client: Client, instructions: Instructions ): Promise { - common.validate.instructions(instructions) - common.validate.tx_json(txJSON) + common.validate.instructions(instructions); + common.validate.tx_json(txJSON); // We allow 0 values in the Sequence schema to support the Tickets feature // When a ticketSequence is used, sequence has to be 0 // We validate that a sequence with value 0 is not passed even if the json schema allows it if (instructions.sequence != null && instructions.sequence === 0) { - return Promise.reject(new ValidationError('`sequence` cannot be 0')) + return Promise.reject(new ValidationError("`sequence` cannot be 0")); } const disallowedFieldsInTxJSON = [ - 'maxLedgerVersion', - 'maxLedgerVersionOffset', - 'fee', - 'sequence', - 'ticketSequence' - ] - const badFields = disallowedFieldsInTxJSON.filter((field) => txJSON[field]) + "maxLedgerVersion", + "maxLedgerVersionOffset", + "fee", + "sequence", + "ticketSequence", + ]; + const badFields = disallowedFieldsInTxJSON.filter((field) => txJSON[field]); if (badFields.length) { return Promise.reject( new ValidationError( - 'txJSON additionalProperty "' + - badFields[0] + - '" exists in instance when not allowed' + `txJSON additionalProperty "${badFields[0]}" exists in instance when not allowed` ) - ) + ); } - const newTxJSON = Object.assign({}, txJSON) + const newTxJSON = { ...txJSON }; // To remove the signer list, `SignerEntries` field should be omitted. - if (txJSON['SignerQuorum'] === 0) { - delete newTxJSON.SignerEntries + if (txJSON.SignerQuorum === 0) { + delete newTxJSON.SignerEntries; } // Sender: - const {classicAccount, tag: sourceTag} = getClassicAccountAndTag( + const { classicAccount, tag: sourceTag } = getClassicAccountAndTag( txJSON.Account - ) - newTxJSON.Account = classicAccount + ); + newTxJSON.Account = classicAccount; if (sourceTag != null) { if (txJSON.SourceTag && txJSON.SourceTag !== sourceTag) { return Promise.reject( new ValidationError( - 'The `SourceTag`, if present, must match the tag of the `Account` X-address' + "The `SourceTag`, if present, must match the tag of the `Account` X-address" ) - ) + ); } if (sourceTag) { - newTxJSON.SourceTag = sourceTag + newTxJSON.SourceTag = sourceTag; } } // Destination: - if (typeof txJSON.Destination === 'string') { - const { - classicAccount: destinationAccount, - tag: destinationTag - } = getClassicAccountAndTag(txJSON.Destination) - newTxJSON.Destination = destinationAccount + if (typeof txJSON.Destination === "string") { + const { classicAccount: destinationAccount, tag: destinationTag } = + getClassicAccountAndTag(txJSON.Destination); + newTxJSON.Destination = destinationAccount; if (destinationTag != null) { if ( TRANSACTION_TYPES_WITH_DESTINATION_TAG_FIELD.includes( @@ -182,58 +191,61 @@ function prepareTransaction( if (txJSON.DestinationTag && txJSON.DestinationTag !== destinationTag) { return Promise.reject( new ValidationError( - 'The Payment `DestinationTag`, if present, must match the tag of the `Destination` X-address' + "The Payment `DestinationTag`, if present, must match the tag of the `Destination` X-address" ) - ) + ); } if (destinationTag) { - newTxJSON.DestinationTag = destinationTag + newTxJSON.DestinationTag = destinationTag; } } } } function convertToClassicAccountIfPresent(fieldName: string): void { - const account = txJSON[fieldName] - if (typeof account === 'string') { - const {classicAccount: ca} = getClassicAccountAndTag(account) - newTxJSON[fieldName] = ca + const account = txJSON[fieldName]; + if (typeof account === "string") { + const { classicAccount: ca } = getClassicAccountAndTag(account); + newTxJSON[fieldName] = ca; } } function convertIssuedCurrencyToAccountIfPresent(fieldName: string): void { - const amount = txJSON[fieldName] - if (typeof amount === 'number' - || amount instanceof Array - || amount == null) - return + const amount = txJSON[fieldName]; + if ( + typeof amount === "number" || + amount instanceof Array || + amount == null + ) { + return; + } - newTxJSON[fieldName] = toRippledAmount(amount) + newTxJSON[fieldName] = toRippledAmount(amount); } // DepositPreauth: - convertToClassicAccountIfPresent('Authorize') - convertToClassicAccountIfPresent('Unauthorize') + convertToClassicAccountIfPresent("Authorize"); + convertToClassicAccountIfPresent("Unauthorize"); // EscrowCancel, EscrowFinish: - convertToClassicAccountIfPresent('Owner') + convertToClassicAccountIfPresent("Owner"); // SetRegularKey: - convertToClassicAccountIfPresent('RegularKey') + convertToClassicAccountIfPresent("RegularKey"); // Payment - convertIssuedCurrencyToAccountIfPresent('Amount') - convertIssuedCurrencyToAccountIfPresent('SendMax') - convertIssuedCurrencyToAccountIfPresent('DeliverMin') + convertIssuedCurrencyToAccountIfPresent("Amount"); + convertIssuedCurrencyToAccountIfPresent("SendMax"); + convertIssuedCurrencyToAccountIfPresent("DeliverMin"); // OfferCreate - convertIssuedCurrencyToAccountIfPresent('TakerPays') - convertIssuedCurrencyToAccountIfPresent('TakerGets') + convertIssuedCurrencyToAccountIfPresent("TakerPays"); + convertIssuedCurrencyToAccountIfPresent("TakerGets"); // TrustSet - convertIssuedCurrencyToAccountIfPresent('LimitAmount') + convertIssuedCurrencyToAccountIfPresent("LimitAmount"); - setCanonicalFlag(newTxJSON) + setCanonicalFlag(newTxJSON); function prepareMaxLedgerVersion(): Promise { // Up to one of the following is allowed: @@ -243,38 +255,38 @@ function prepareTransaction( if (newTxJSON.LastLedgerSequence && instructions.maxLedgerVersion) { return Promise.reject( new ValidationError( - '`LastLedgerSequence` in txJSON and `maxLedgerVersion`' + - ' in `instructions` cannot both be set' + "`LastLedgerSequence` in txJSON and `maxLedgerVersion`" + + " in `instructions` cannot both be set" ) - ) + ); } if (newTxJSON.LastLedgerSequence && instructions.maxLedgerVersionOffset) { return Promise.reject( new ValidationError( - '`LastLedgerSequence` in txJSON and `maxLedgerVersionOffset`' + - ' in `instructions` cannot both be set' + "`LastLedgerSequence` in txJSON and `maxLedgerVersionOffset`" + + " in `instructions` cannot both be set" ) - ) + ); } if (newTxJSON.LastLedgerSequence) { - return Promise.resolve() + return Promise.resolve(); } if (instructions.maxLedgerVersion !== undefined) { if (instructions.maxLedgerVersion !== null) { - newTxJSON.LastLedgerSequence = instructions.maxLedgerVersion + newTxJSON.LastLedgerSequence = instructions.maxLedgerVersion; } - return Promise.resolve() + return Promise.resolve(); } const offset = instructions.maxLedgerVersionOffset != null ? instructions.maxLedgerVersionOffset - : 3 - return client.request({command: 'ledger_current'}) - .then(response => response.result.ledger_current_index) - .then((ledgerVersion) => { - newTxJSON.LastLedgerSequence = ledgerVersion + offset - return - }) + : 3; + return client + .request({ command: "ledger_current" }) + .then((response) => response.result.ledger_current_index) + .then((ledgerVersion) => { + newTxJSON.LastLedgerSequence = ledgerVersion + offset; + }); } function prepareFee(): Promise { @@ -286,62 +298,56 @@ function prepareTransaction( if (newTxJSON.Fee && instructions.fee) { return Promise.reject( new ValidationError( - '`Fee` in txJSON and `fee` in `instructions` cannot both be set' + "`Fee` in txJSON and `fee` in `instructions` cannot both be set" ) - ) + ); } if (newTxJSON.Fee) { // txJSON.Fee is set. Use this value and do not scale it. - return Promise.resolve() + return Promise.resolve(); } const multiplier = - instructions.signersCount == null - ? 1 - : instructions.signersCount + 1 + instructions.signersCount == null ? 1 : instructions.signersCount + 1; if (instructions.fee != null) { - const fee = new BigNumber(instructions.fee) + const fee = new BigNumber(instructions.fee); if (fee.isGreaterThan(client._maxFeeXRP)) { return Promise.reject( new ValidationError( `Fee of ${fee.toString(10)} XRP exceeds ` + `max of ${client._maxFeeXRP} XRP. To use this fee, increase ` + - '`maxFeeXRP` in the Client constructor.' + "`maxFeeXRP` in the Client constructor." ) - ) + ); } - newTxJSON.Fee = scaleValue( - xrpToDrops(instructions.fee), - multiplier - ) - return Promise.resolve() + newTxJSON.Fee = scaleValue(xrpToDrops(instructions.fee), multiplier); + return Promise.resolve(); } - const cushion = client._feeCushion + const cushion = client._feeCushion; return client.getFee(cushion).then((fee) => { - return client.request({command: 'fee'}) - .then(response => Number(response.result.drops.minimum_fee)) - .then((feeRef) => { - // feeRef is the reference transaction cost in "fee units" - const extraFee = - newTxJSON.TransactionType !== 'EscrowFinish' || - newTxJSON.Fulfillment == null - ? 0 - : cushion * - feeRef * - (32 + - Math.floor( - Buffer.from(newTxJSON.Fulfillment, 'hex').length / 16 - )) - const feeDrops = xrpToDrops(fee) - const maxFeeXRP = instructions.maxFee - ? BigNumber.min(client._maxFeeXRP, instructions.maxFee) - : client._maxFeeXRP - const maxFeeDrops = xrpToDrops(maxFeeXRP) - const normalFee = scaleValue(feeDrops, multiplier, extraFee) - newTxJSON.Fee = BigNumber.min(normalFee, maxFeeDrops).toString(10) - - return - }) - }) + return client + .request({ command: "fee" }) + .then((response) => Number(response.result.drops.minimum_fee)) + .then((feeRef) => { + // feeRef is the reference transaction cost in "fee units" + const extraFee = + newTxJSON.TransactionType !== "EscrowFinish" || + newTxJSON.Fulfillment == null + ? 0 + : cushion * + feeRef * + (32 + + Math.floor( + Buffer.from(newTxJSON.Fulfillment, "hex").length / 16 + )); + const feeDrops = xrpToDrops(fee); + const maxFeeXRP = instructions.maxFee + ? BigNumber.min(client._maxFeeXRP, instructions.maxFee) + : client._maxFeeXRP; + const maxFeeDrops = xrpToDrops(maxFeeXRP); + const normalFee = scaleValue(feeDrops, multiplier, extraFee); + newTxJSON.Fee = BigNumber.min(normalFee, maxFeeDrops).toString(10); + }); + }); } async function prepareSequence(): Promise { @@ -350,60 +356,60 @@ function prepareTransaction( newTxJSON.Sequence == null || instructions.sequence === newTxJSON.Sequence ) { - newTxJSON.Sequence = instructions.sequence - return Promise.resolve() - } else { - // Both txJSON.Sequence and instructions.sequence are defined, and they are NOT equal - return Promise.reject( - new ValidationError( - '`Sequence` in txJSON must match `sequence` in `instructions`' - ) - ) + newTxJSON.Sequence = instructions.sequence; + return Promise.resolve(); } + // Both txJSON.Sequence and instructions.sequence are defined, and they are NOT equal + return Promise.reject( + new ValidationError( + "`Sequence` in txJSON must match `sequence` in `instructions`" + ) + ); } if (newTxJSON.Sequence != null) { - return Promise.resolve() + return Promise.resolve(); } // Ticket Sequence if (instructions.ticketSequence != null) { - newTxJSON.Sequence = 0 - newTxJSON.TicketSequence = instructions.ticketSequence - return Promise.resolve() + newTxJSON.Sequence = 0; + newTxJSON.TicketSequence = instructions.ticketSequence; + return Promise.resolve(); } try { - const response = await client.request({command: 'account_info', + const response = await client.request({ + command: "account_info", account: classicAccount, - ledger_index: 'current' // Fix #999 - }) - newTxJSON.Sequence = response.result.account_data.Sequence - return Promise.resolve() + ledger_index: "current", // Fix #999 + }); + newTxJSON.Sequence = response.result.account_data.Sequence; + return await Promise.resolve(); } catch (e) { - return Promise.reject(e) + return await Promise.reject(e); } } return Promise.all([ prepareMaxLedgerVersion(), prepareFee(), - prepareSequence() - ]).then(() => formatPrepareResponse(newTxJSON)) + prepareSequence(), + ]).then(() => formatPrepareResponse(newTxJSON)); } function convertStringToHex(string: string): string { - return Buffer.from(string, 'utf8').toString('hex').toUpperCase() + return Buffer.from(string, "utf8").toString("hex").toUpperCase(); } -function convertMemo(memo: Memo): {Memo: ApiMemo} { +function convertMemo(memo: Memo): { Memo: ApiMemo } { return { Memo: removeUndefined({ MemoData: memo.data ? convertStringToHex(memo.data) : undefined, MemoType: memo.type ? convertStringToHex(memo.type) : undefined, - MemoFormat: memo.format ? convertStringToHex(memo.format) : undefined - }) - } + MemoFormat: memo.format ? convertStringToHex(memo.format) : undefined, + }), + }; } export { @@ -412,5 +418,5 @@ export { prepareTransaction, common, setCanonicalFlag, - getClassicAccountAndTag -} + getClassicAccountAndTag, +}; diff --git a/src/tsconfig.json b/src/tsconfig.json deleted file mode 100644 index f9e9ba03..00000000 --- a/src/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../tsconfig-base", - "compilerOptions": { - "outDir": "../dist/npm", - "rootDir": ".", - "composite": true - }, - "include": [ - "**/*.ts" - ] -} diff --git a/src/utils/derive.ts b/src/utils/derive.ts index bfd7cf69..14682414 100644 --- a/src/utils/derive.ts +++ b/src/utils/derive.ts @@ -1,13 +1,13 @@ -import {deriveKeypair, deriveAddress} from 'ripple-keypairs' -import {classicAddressToXAddress} from 'ripple-address-codec' +import { classicAddressToXAddress } from "ripple-address-codec"; +import { deriveKeypair, deriveAddress } from "ripple-keypairs"; function deriveXAddress(options: { - publicKey: string - tag: number | false - test: boolean + publicKey: string; + tag: number | false; + test: boolean; }): string { - const classicAddress = deriveAddress(options.publicKey) - return classicAddressToXAddress(classicAddress, options.tag, options.test) + const classicAddress = deriveAddress(options.publicKey); + return classicAddressToXAddress(classicAddress, options.tag, options.test); } -export {deriveKeypair, deriveAddress, deriveXAddress} +export { deriveKeypair, deriveAddress, deriveXAddress }; diff --git a/src/utils/generateAddress.ts b/src/utils/generateAddress.ts index 215ac769..a9115b5d 100644 --- a/src/utils/generateAddress.ts +++ b/src/utils/generateAddress.ts @@ -1,63 +1,66 @@ -import {classicAddressToXAddress} from 'ripple-address-codec' -import keypairs from 'ripple-keypairs' -import {errors, validate} from '../common' -import ECDSA from '../common/ecdsa' +import { classicAddressToXAddress } from "ripple-address-codec"; +import keypairs from "ripple-keypairs"; -export type GeneratedAddress = { - xAddress: string - classicAddress?: string - address?: string // @deprecated Use `classicAddress` instead. - secret: string +import { errors, validate } from "../common"; +import ECDSA from "../common/ecdsa"; + +export interface GeneratedAddress { + xAddress: string; + classicAddress?: string; + address?: string; // @deprecated Use `classicAddress` instead. + secret: string; } export interface GenerateAddressOptions { // The entropy to use to generate the seed. - entropy?: Uint8Array | number[] + entropy?: Uint8Array | number[]; // The digital signature algorithm to generate an address for. Can be `ecdsa-secp256k1` (default) or `ed25519`. - algorithm?: ECDSA + algorithm?: ECDSA; // Specifies whether the address is intended for use on a test network such as Testnet or Devnet. // If `true`, the address should only be used for testing, and will start with `T`. // If `false` (default), the address should only be used on mainnet, and will start with `X`. - test?: boolean + test?: boolean; // If `true`, return the classic address, in addition to the X-address. - includeClassicAddress?: boolean + includeClassicAddress?: boolean; } // TODO: move this function to be a static function of the Wallet class (Along with its helper data types) -function generateXAddress(options: GenerateAddressOptions = {}): GeneratedAddress { - validate.generateAddress({options}) +function generateXAddress( + options: GenerateAddressOptions = {} +): GeneratedAddress { + validate.generateAddress({ options }); try { const generateSeedOptions: { - entropy?: Uint8Array - algorithm?: ECDSA + entropy?: Uint8Array; + algorithm?: ECDSA; } = { - algorithm: options.algorithm - } + algorithm: options.algorithm, + }; if (options.entropy) { - generateSeedOptions.entropy = Uint8Array.from(options.entropy) + generateSeedOptions.entropy = Uint8Array.from(options.entropy); } - const secret = keypairs.generateSeed(generateSeedOptions) - const keypair = keypairs.deriveKeypair(secret) - const classicAddress = keypairs.deriveAddress(keypair.publicKey) + const secret = keypairs.generateSeed(generateSeedOptions); + const keypair = keypairs.deriveKeypair(secret); + const classicAddress = keypairs.deriveAddress(keypair.publicKey); const returnValue: any = { xAddress: classicAddressToXAddress( classicAddress, false, - options && options.test + options.test ?? false ), - secret - } + secret, + }; if (options.includeClassicAddress) { - returnValue.classicAddress = classicAddress - returnValue.address = classicAddress + returnValue.classicAddress = classicAddress; + returnValue.address = classicAddress; } - return returnValue + return returnValue; } catch (error) { - throw new errors.UnexpectedError(error.message) + throw new errors.UnexpectedError(error.message); } } -export {generateXAddress} +export { generateXAddress }; diff --git a/src/utils/hashes/hashPrefix.ts b/src/utils/hashes/hashPrefix.ts index efdb0324..33fe5618 100644 --- a/src/utils/hashes/hashPrefix.ts +++ b/src/utils/hashes/hashPrefix.ts @@ -34,7 +34,7 @@ enum HashPrefix { TRANSACTION_MULTISIGN = 0x534d5400, // 'SMT' // ledger - LEDGER = 0x4c575200 // 'LWR' + LEDGER = 0x4c575200, // 'LWR' } -export default HashPrefix +export default HashPrefix; diff --git a/src/utils/hashes/index.ts b/src/utils/hashes/index.ts index 06048eea..5f38e97c 100644 --- a/src/utils/hashes/index.ts +++ b/src/utils/hashes/index.ts @@ -1,190 +1,197 @@ -import BigNumber from 'bignumber.js' -import {decodeAccountID} from 'ripple-address-codec' -import sha512Half from './sha512Half' -import HashPrefix from './hashPrefix' -import {SHAMap, NodeType} from './shamap' -import {encode} from 'ripple-binary-codec' -import ledgerSpaces from './ledgerSpaces' +import BigNumber from "bignumber.js"; +import { decodeAccountID } from "ripple-address-codec"; +import { encode } from "ripple-binary-codec"; + +import HashPrefix from "./hashPrefix"; +import ledgerSpaces from "./ledgerSpaces"; +import sha512Half from "./sha512Half"; +import { SHAMap, NodeType } from "./shamap"; const padLeftZero = (string: string, length: number): string => { - return Array(length - string.length + 1).join('0') + string -} + return Array(length - string.length + 1).join("0") + string; +}; const intToHex = (integer: number, byteLength: number): string => { - return padLeftZero(Number(integer).toString(16), byteLength * 2) -} + return padLeftZero(Number(integer).toString(16), byteLength * 2); +}; const bytesToHex = (bytes: number[]): string => { - return Buffer.from(bytes).toString('hex') -} + return Buffer.from(bytes).toString("hex"); +}; const bigintToHex = ( integerString: string | number | BigNumber, byteLength: number ): string => { - const hex = new BigNumber(integerString).toString(16) - return padLeftZero(hex, byteLength * 2) -} + const hex = new BigNumber(integerString).toString(16); + return padLeftZero(hex, byteLength * 2); +}; const ledgerSpaceHex = (name: string): string => { - return intToHex(ledgerSpaces[name].charCodeAt(0), 2) -} + return intToHex(ledgerSpaces[name].charCodeAt(0), 2); +}; const addressToHex = (address: string): string => { - return Buffer.from(decodeAccountID(address)).toString('hex') -} + return Buffer.from(decodeAccountID(address)).toString("hex"); +}; const currencyToHex = (currency: string): string => { if (currency.length === 3) { - const bytes = new Array(20 + 1).join('0').split('').map(parseFloat) - bytes[12] = currency.charCodeAt(0) & 0xff - bytes[13] = currency.charCodeAt(1) & 0xff - bytes[14] = currency.charCodeAt(2) & 0xff - return bytesToHex(bytes) + const bytes = new Array(20 + 1).join("0").split("").map(parseFloat); + bytes[12] = currency.charCodeAt(0) & 0xff; + bytes[13] = currency.charCodeAt(1) & 0xff; + bytes[14] = currency.charCodeAt(2) & 0xff; + return bytesToHex(bytes); } - return currency -} + return currency; +}; const addLengthPrefix = (hex: string): string => { - const length = hex.length / 2 + const length = hex.length / 2; if (length <= 192) { - return bytesToHex([length]) + hex - } else if (length <= 12480) { - const x = length - 193 - return bytesToHex([193 + (x >>> 8), x & 0xff]) + hex - } else if (length <= 918744) { - const x = length - 12481 - return bytesToHex([241 + (x >>> 16), (x >>> 8) & 0xff, x & 0xff]) + hex + return bytesToHex([length]) + hex; } - throw new Error('Variable integer overflow.') -} + if (length <= 12480) { + const x = length - 193; + return bytesToHex([193 + (x >>> 8), x & 0xff]) + hex; + } + if (length <= 918744) { + const x = length - 12481; + return bytesToHex([241 + (x >>> 16), (x >>> 8) & 0xff, x & 0xff]) + hex; + } + throw new Error("Variable integer overflow."); +}; export const computeBinaryTransactionHash = (txBlobHex: string): string => { - const prefix = HashPrefix.TRANSACTION_ID.toString(16).toUpperCase() - return sha512Half(prefix + txBlobHex) -} + const prefix = HashPrefix.TRANSACTION_ID.toString(16).toUpperCase(); + return sha512Half(prefix + txBlobHex); +}; export const computeTransactionHash = (txJSON: any): string => { - return computeBinaryTransactionHash(encode(txJSON)) -} + return computeBinaryTransactionHash(encode(txJSON)); +}; /** * Hash the given binary transaction data with the single-signing prefix. * - * See [Serialization Format](https://xrpl.org/serialization.html) + * See [Serialization Format](https://xrpl.org/serialization.html). * - * @param txBlobHex The binary transaction blob as a hexadecimal string - * @returns {string} The hash to sign + * @param txBlobHex - The binary transaction blob as a hexadecimal string. + * @returns The hash to sign. */ export const computeBinaryTransactionSigningHash = ( txBlobHex: string ): string => { - const prefix = HashPrefix.TRANSACTION_SIGN.toString(16).toUpperCase() - return sha512Half(prefix + txBlobHex) -} + const prefix = HashPrefix.TRANSACTION_SIGN.toString(16).toUpperCase(); + return sha512Half(prefix + txBlobHex); +}; /** - * Compute Account Root Index + * Compute Account Root Index. * * All objects in a ledger's state tree have a unique index. * The Account Root index is derived by hashing the * address with a namespace identifier. This ensures every * index is unique. * - * See [Ledger Object IDs](https://xrpl.org/ledger-object-ids.html) + * See [Ledger Object IDs](https://xrpl.org/ledger-object-ids.html). * - * @param address The classic account address - * @returns {string} The Ledger Object Index for the account + * @param address - The classic account address. + * @returns The Ledger Object Index for the account. */ export const computeAccountRootIndex = (address: string): string => { - return sha512Half(ledgerSpaceHex('account') + addressToHex(address)) -} + return sha512Half(ledgerSpaceHex("account") + addressToHex(address)); +}; /** - * [SignerList ID Format](https://xrpl.org/signerlist.html#signerlist-id-format) + * [SignerList ID Format](https://xrpl.org/signerlist.html#signerlist-id-format). * * The index of a SignerList object is the SHA-512Half of the following values, concatenated in order: * * The RippleState space key (0x0053) * * The AccountID of the owner of the SignerList - * * The SignerListID (currently always 0) + * * The SignerListID (currently always 0). * * This method computes a SignerList index. * - * @param address The classic account address of the SignerList owner (starting with r) - * @return {string} The ID of the account's SignerList object + * @param address - The classic account address of the SignerList owner (starting with r). + * @returns The ID of the account's SignerList object. */ export const computeSignerListIndex = (address: string): string => { return sha512Half( - ledgerSpaceHex('signerList') + addressToHex(address) + '00000000' - ) // uint32(0) signer list index -} + `${ledgerSpaceHex("signerList") + addressToHex(address)}00000000` + ); // uint32(0) signer list index +}; /** - * [Offer ID Format](https://xrpl.org/offer.html#offer-id-format) + * [Offer ID Format](https://xrpl.org/offer.html#offer-id-format). * * The index of a Offer object is the SHA-512Half of the following values, concatenated in order: - * * The Offer space key (0x006F) - * * The AccountID of the account placing the offer - * * The Sequence number of the OfferCreate transaction that created the offer + * * The Offer space key (0x006F) + * * The AccountID of the account placing the offer + * * The Sequence number of the OfferCreate transaction that created the offer. * * This method computes an Offer Index (aka Order Index). * - * @param address The classic account address of the SignerList owner (starting with r) - * @returns {string} The index of the account's Offer object + * @param address - The classic account address of the SignerList owner (starting with r). + * @param sequence + * @returns The index of the account's Offer object. */ -export const computeOfferIndex = (address: string, sequence: number): string => { - const prefix = '00' + intToHex(ledgerSpaces.offer.charCodeAt(0), 1) - return sha512Half(prefix + addressToHex(address) + intToHex(sequence, 4)) -} +export const computeOfferIndex = ( + address: string, + sequence: number +): string => { + const prefix = `00${intToHex(ledgerSpaces.offer.charCodeAt(0), 1)}`; + return sha512Half(prefix + addressToHex(address) + intToHex(sequence, 4)); +}; export const computeTrustlineHash = ( address1: string, address2: string, currency: string ): string => { - const address1Hex = addressToHex(address1) - const address2Hex = addressToHex(address2) + const address1Hex = addressToHex(address1); + const address2Hex = addressToHex(address2); const swap = new BigNumber(address1Hex, 16).isGreaterThan( new BigNumber(address2Hex, 16) - ) - const lowAddressHex = swap ? address2Hex : address1Hex - const highAddressHex = swap ? address1Hex : address2Hex + ); + const lowAddressHex = swap ? address2Hex : address1Hex; + const highAddressHex = swap ? address1Hex : address2Hex; - const prefix = ledgerSpaceHex('rippleState') + const prefix = ledgerSpaceHex("rippleState"); return sha512Half( prefix + lowAddressHex + highAddressHex + currencyToHex(currency) - ) -} + ); +}; export const computeTransactionTreeHash = (transactions: any[]): string => { - const shamap = new SHAMap() + const shamap = new SHAMap(); transactions.forEach((txJSON) => { - const txBlobHex = encode(txJSON) - const metaHex = encode(txJSON.metaData) - const txHash = computeBinaryTransactionHash(txBlobHex) - const data = addLengthPrefix(txBlobHex) + addLengthPrefix(metaHex) - shamap.addItem(txHash, data, NodeType.TRANSACTION_METADATA) - }) + const txBlobHex = encode(txJSON); + const metaHex = encode(txJSON.metaData); + const txHash = computeBinaryTransactionHash(txBlobHex); + const data = addLengthPrefix(txBlobHex) + addLengthPrefix(metaHex); + shamap.addItem(txHash, data, NodeType.TRANSACTION_METADATA); + }); - return shamap.hash -} + return shamap.hash; +}; export const computeStateTreeHash = (entries: any[]): string => { - const shamap = new SHAMap() + const shamap = new SHAMap(); entries.forEach((ledgerEntry) => { - const data = encode(ledgerEntry) - shamap.addItem(ledgerEntry.index, data, NodeType.ACCOUNT_STATE) - }) + const data = encode(ledgerEntry); + shamap.addItem(ledgerEntry.index, data, NodeType.ACCOUNT_STATE); + }); - return shamap.hash -} + return shamap.hash; +}; // see rippled Ledger::updateHash() export const computeLedgerHash = (ledgerHeader): string => { - const prefix = HashPrefix.LEDGER.toString(16).toUpperCase() + const prefix = HashPrefix.LEDGER.toString(16).toUpperCase(); return sha512Half( prefix + intToHex(ledgerHeader.ledger_index, 4) + @@ -196,14 +203,14 @@ export const computeLedgerHash = (ledgerHeader): string => { intToHex(ledgerHeader.close_time, 4) + intToHex(ledgerHeader.close_time_resolution, 1) + intToHex(ledgerHeader.close_flags, 1) - ) -} + ); +}; export const computeEscrowHash = (address, sequence): string => { return sha512Half( - ledgerSpaceHex('escrow') + addressToHex(address) + intToHex(sequence, 4) - ) -} + ledgerSpaceHex("escrow") + addressToHex(address) + intToHex(sequence, 4) + ); +}; export const computePaymentChannelHash = ( address, @@ -211,9 +218,9 @@ export const computePaymentChannelHash = ( sequence ): string => { return sha512Half( - ledgerSpaceHex('paychan') + + ledgerSpaceHex("paychan") + addressToHex(address) + addressToHex(dstAddress) + intToHex(sequence, 4) - ) -} + ); +}; diff --git a/src/utils/hashes/ledgerSpaces.ts b/src/utils/hashes/ledgerSpaces.ts index 8777d213..14de8386 100644 --- a/src/utils/hashes/ledgerSpaces.ts +++ b/src/utils/hashes/ledgerSpaces.ts @@ -6,24 +6,24 @@ * * Each namespace is just a single character prefix. * - * See [LedgerNameSpace enum](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/LedgerFormats.h#L100) + * See [LedgerNameSpace enum](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/LedgerFormats.h#L100). */ export default { - account: 'a', - dirNode: 'd', - generatorMap: 'g', - rippleState: 'r', - offer: 'o', // Entry for an offer. - ownerDir: 'O', // Directory of things owned by an account. - bookDir: 'B', // Directory of order books. - contract: 'c', - skipList: 's', - escrow: 'u', - amendment: 'f', - feeSettings: 'e', - ticket: 'T', - signerList: 'S', - paychan: 'x', - check: 'C', - depositPreauth: 'p' -} + account: "a", + dirNode: "d", + generatorMap: "g", + rippleState: "r", + offer: "o", // Entry for an offer. + ownerDir: "O", // Directory of things owned by an account. + bookDir: "B", // Directory of order books. + contract: "c", + skipList: "s", + escrow: "u", + amendment: "f", + feeSettings: "e", + ticket: "T", + signerList: "S", + paychan: "x", + check: "C", + depositPreauth: "p", +}; diff --git a/src/utils/hashes/sha512Half.ts b/src/utils/hashes/sha512Half.ts index 114ed821..b327a098 100644 --- a/src/utils/hashes/sha512Half.ts +++ b/src/utils/hashes/sha512Half.ts @@ -1,11 +1,11 @@ -import {createHash} from 'crypto' +import { createHash } from "crypto"; const sha512Half = (hex: string): string => { - return createHash('sha512') - .update(Buffer.from(hex, 'hex')) - .digest('hex') + return createHash("sha512") + .update(Buffer.from(hex, "hex")) + .digest("hex") .toUpperCase() - .slice(0, 64) -} + .slice(0, 64); +}; -export default sha512Half +export default sha512Half; diff --git a/src/utils/hashes/shamap.ts b/src/utils/hashes/shamap.ts index 9f8b621e..dbf792b0 100644 --- a/src/utils/hashes/shamap.ts +++ b/src/utils/hashes/shamap.ts @@ -1,181 +1,191 @@ -import hashPrefix from './hashPrefix' -import sha512Half from './sha512Half' +import hashPrefix from "./hashPrefix"; +import sha512Half from "./sha512Half"; + const HEX_ZERO = - '0000000000000000000000000000000000000000000000000000000000000000' + "0000000000000000000000000000000000000000000000000000000000000000"; export enum NodeType { INNER = 1, TRANSACTION_NO_METADATA = 2, TRANSACTION_METADATA = 3, - ACCOUNT_STATE = 4 + ACCOUNT_STATE = 4, } export abstract class Node { /** * Abstract constructor representing a node in a SHAMap tree. * Can be either InnerNode or Leaf. - * @constructor + * + * @class */ public constructor() {} public addItem(_tag: string, _node: Node): void { throw new Error( - 'Called unimplemented virtual method SHAMapTreeNode#addItem.' - ) + "Called unimplemented virtual method SHAMapTreeNode#addItem." + ); } + public get hash(): string | void { - throw new Error('Called unimplemented virtual method SHAMapTreeNode#hash.') + throw new Error("Called unimplemented virtual method SHAMapTreeNode#hash."); } } export class InnerNode extends Node { - public leaves: {[slot: number]: Node} - public type: NodeType - public depth: number - public empty: boolean + public leaves: { [slot: number]: Node }; + public type: NodeType; + public depth: number; + public empty: boolean; /** * Define an Inner (non-leaf) node in a SHAMap tree. - * @param {number} depth i.e. how many parent inner nodes - * @constructor + * + * @param depth - I.e. How many parent inner nodes. + * @class */ - public constructor(depth: number = 0) { - super() - this.leaves = {} - this.type = NodeType.INNER - this.depth = depth - this.empty = true + public constructor(depth = 0) { + super(); + this.leaves = {}; + this.type = NodeType.INNER; + this.depth = depth; + this.empty = true; } /** - * @param {string} tag equates to a ledger entry `index` - * @param {Node} node to add - * @return {void} + * @param {string} tag - Equates to a ledger entry `index`. + * @param {Node} node - To add. + * @returns {void} */ public addItem(tag: string, node: Node): void { - const existingNode = this.getNode(parseInt(tag[this.depth], 16)) + const existingNode = this.getNode(parseInt(tag[this.depth], 16)); if (existingNode) { // A node already exists in this slot if (existingNode instanceof InnerNode) { // There is an inner node, so we need to go deeper - existingNode.addItem(tag, node) + existingNode.addItem(tag, node); } else if (existingNode instanceof Leaf) { if (existingNode.tag === tag) { // Collision throw new Error( - 'Tried to add a node to a SHAMap that was already in there.' - ) + "Tried to add a node to a SHAMap that was already in there." + ); } else { // Turn it into an inner node - const newInnerNode = new InnerNode(this.depth + 1) + const newInnerNode = new InnerNode(this.depth + 1); // Parent new and existing node - newInnerNode.addItem(existingNode.tag, existingNode) - newInnerNode.addItem(tag, node) + newInnerNode.addItem(existingNode.tag, existingNode); + newInnerNode.addItem(tag, node); // And place the newly created inner node in the slot - this.setNode(parseInt(tag[this.depth], 16), newInnerNode) + this.setNode(parseInt(tag[this.depth], 16), newInnerNode); } } } else { // Neat, we have a nice open spot for the new node - this.setNode(parseInt(tag[this.depth], 16), node) + this.setNode(parseInt(tag[this.depth], 16), node); } } /** * Overwrite the node that is currently in a given slot. - * @param {number} slot a number 0-15 - * @param {Node} node to place - * @return {void} + * + * @param slot - A number 0-15. + * @param node - To place. + * @returns */ public setNode(slot: number, node: Node): void { if (slot < 0 || slot > 15) { - throw new Error('Invalid slot: slot must be between 0-15.') + throw new Error("Invalid slot: slot must be between 0-15."); } - this.leaves[slot] = node - this.empty = false + this.leaves[slot] = node; + this.empty = false; } /** * Get the node that is currently in a given slot. - * @param {number} slot a number 0-15 - * @return {Node} + * + * @param slot - A number 0-15. + * @returns */ public getNode(slot: number): Node { if (slot < 0 || slot > 15) { - throw new Error('Invalid slot: slot must be between 0-15.') + throw new Error("Invalid slot: slot must be between 0-15."); } - return this.leaves[slot] + return this.leaves[slot]; } public get hash(): string { - if (this.empty) return HEX_ZERO - let hex = '' - for (let i = 0; i < 16; i++) { - hex += this.leaves[i] ? this.leaves[i].hash : HEX_ZERO + if (this.empty) { + return HEX_ZERO; } - const prefix = hashPrefix.INNER_NODE.toString(16) - return sha512Half(prefix + hex) + let hex = ""; + for (let i = 0; i < 16; i++) { + hex += this.leaves[i] ? this.leaves[i].hash : HEX_ZERO; + } + const prefix = hashPrefix.INNER_NODE.toString(16); + return sha512Half(prefix + hex); } } export class Leaf extends Node { - public tag: string - public type: NodeType - public data: string + public tag: string; + public type: NodeType; + public data: string; /** * Leaf node in a SHAMap tree. - * @param {string} tag equates to a ledger entry `index` - * @param {string} data hex of account state, transaction etc - * @param {number} type one of TYPE_ACCOUNT_STATE, TYPE_TRANSACTION_MD etc - * @constructor + * + * @param tag - Equates to a ledger entry `index`. + * @param data - Hex of account state, transaction etc. + * @param type - One of TYPE_ACCOUNT_STATE, TYPE_TRANSACTION_MD etc. + * @class */ public constructor(tag: string, data: string, type: NodeType) { - super() - this.tag = tag - this.type = type - this.data = data + super(); + this.tag = tag; + this.type = type; + this.data = data; } public get hash(): string | void { switch (this.type) { case NodeType.ACCOUNT_STATE: { - const leafPrefix = hashPrefix.LEAF_NODE.toString(16) - return sha512Half(leafPrefix + this.data + this.tag) + const leafPrefix = hashPrefix.LEAF_NODE.toString(16); + return sha512Half(leafPrefix + this.data + this.tag); } case NodeType.TRANSACTION_NO_METADATA: { - const txIDPrefix = hashPrefix.TRANSACTION_ID.toString(16) - return sha512Half(txIDPrefix + this.data) + const txIDPrefix = hashPrefix.TRANSACTION_ID.toString(16); + return sha512Half(txIDPrefix + this.data); } case NodeType.TRANSACTION_METADATA: { - const txNodePrefix = hashPrefix.TRANSACTION_NODE.toString(16) - return sha512Half(txNodePrefix + this.data + this.tag) + const txNodePrefix = hashPrefix.TRANSACTION_NODE.toString(16); + return sha512Half(txNodePrefix + this.data + this.tag); } default: - throw new Error('Tried to hash a SHAMap node of unknown type.') + throw new Error("Tried to hash a SHAMap node of unknown type."); } } } export class SHAMap { - public root: InnerNode + public root: InnerNode; /** * SHAMap tree. - * @constructor + * + * @class */ public constructor() { - this.root = new InnerNode(0) + this.root = new InnerNode(0); } public addItem(tag: string, data: string, type: NodeType): void { - this.root.addItem(tag, new Leaf(tag, data, type)) + this.root.addItem(tag, new Leaf(tag, data, type)); } public get hash(): string { - return this.root.hash + return this.root.hash; } } diff --git a/src/utils/index.ts b/src/utils/index.ts index 69a23e35..7212d9e8 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,63 +1,64 @@ -import _ from 'lodash' -import BigNumber from 'bignumber.js' -import {RippledAmount} from '../common/types/objects' -import {ValidationError} from '../common/errors' -import {xAddressToClassicAddress} from 'ripple-address-codec' +import BigNumber from "bignumber.js"; +import _ from "lodash"; +import { xAddressToClassicAddress } from "ripple-address-codec"; -import { deriveKeypair, deriveAddress, deriveXAddress } from './derive' -import computeLedgerHeaderHash from './ledgerHash' -import signPaymentChannelClaim from './signPaymentChannelClaim' -import verifyPaymentChannelClaim from './verifyPaymentChannelClaim' +import { ValidationError } from "../common/errors"; +import { RippledAmount } from "../common/types/objects"; + +import { deriveKeypair, deriveAddress, deriveXAddress } from "./derive"; +import { generateXAddress } from "./generateAddress"; import { - computeBinaryTransactionHash, - computeTransactionHash, - computeBinaryTransactionSigningHash, - computeAccountRootIndex, - computeSignerListIndex, - computeOfferIndex, - computeTrustlineHash, - computeTransactionTreeHash, - computeStateTreeHash, - computeLedgerHash, - computeEscrowHash, - computePaymentChannelHash, -} from './hashes' -import { generateXAddress } from './generateAddress' + computeBinaryTransactionHash, + computeTransactionHash, + computeBinaryTransactionSigningHash, + computeAccountRootIndex, + computeSignerListIndex, + computeOfferIndex, + computeTrustlineHash, + computeTransactionTreeHash, + computeStateTreeHash, + computeLedgerHash, + computeEscrowHash, + computePaymentChannelHash, +} from "./hashes"; +import computeLedgerHeaderHash from "./ledgerHash"; +import signPaymentChannelClaim from "./signPaymentChannelClaim"; +import verifyPaymentChannelClaim from "./verifyPaymentChannelClaim"; function isValidSecret(secret: string): boolean { try { - deriveKeypair(secret) - return true + deriveKeypair(secret); + return true; } catch (err) { - return false + return false; } } function dropsToXrp(drops: BigNumber.Value): string { - if (typeof drops === 'string') { + if (typeof drops === "string") { if (!drops.match(/^-?[0-9]*\.?[0-9]*$/)) { throw new ValidationError( `dropsToXrp: invalid value '${drops}',` + ` should be a number matching (^-?[0-9]*\\.?[0-9]*$).` - ) - } else if (drops === '.') { + ); + } else if (drops === ".") { throw new ValidationError( `dropsToXrp: invalid value '${drops}',` + ` should be a BigNumber or string-encoded number.` - ) + ); } } // Converting to BigNumber and then back to string should remove any // decimal point followed by zeros, e.g. '1.00'. // Important: specify base 10 to avoid exponential notation, e.g. '1e-7'. - drops = new BigNumber(drops).toString(10) + drops = new BigNumber(drops).toString(10); // drops are only whole units - if (drops.includes('.')) { + if (drops.includes(".")) { throw new ValidationError( `dropsToXrp: value '${drops}' has` + ` too many decimal places.` - ) + ); } // This should never happen; the value has already been @@ -68,29 +69,29 @@ function dropsToXrp(drops: BigNumber.Value): string { `dropsToXrp: failed sanity check -` + ` value '${drops}',` + ` does not match (^-?[0-9]+$).` - ) + ); } - return new BigNumber(drops).dividedBy(1000000.0).toString(10) + return new BigNumber(drops).dividedBy(1000000.0).toString(10); } function xrpToDrops(xrp: BigNumber.Value): string { - if (typeof xrp === 'string') { + if (typeof xrp === "string") { if (!xrp.match(/^-?[0-9]*\.?[0-9]*$/)) { throw new ValidationError( `xrpToDrops: invalid value '${xrp}',` + ` should be a number matching (^-?[0-9]*\\.?[0-9]*$).` - ) - } else if (xrp === '.') { + ); + } else if (xrp === ".") { throw new ValidationError( `xrpToDrops: invalid value '${xrp}',` + ` should be a BigNumber or string-encoded number.` - ) + ); } } // Important: specify base 10 to avoid exponential notation, e.g. '1e-7'. - xrp = new BigNumber(xrp).toString(10) + xrp = new BigNumber(xrp).toString(10); // This should never happen; the value has already been // validated above. This just ensures BigNumber did not do @@ -100,143 +101,145 @@ function xrpToDrops(xrp: BigNumber.Value): string { `xrpToDrops: failed sanity check -` + ` value '${xrp}',` + ` does not match (^-?[0-9.]+$).` - ) + ); } - const components = xrp.split('.') + const components = xrp.split("."); if (components.length > 2) { throw new ValidationError( `xrpToDrops: failed sanity check -` + ` value '${xrp}' has` + ` too many decimal points.` - ) + ); } - const fraction = components[1] || '0' + const fraction = components[1] || "0"; if (fraction.length > 6) { throw new ValidationError( `xrpToDrops: value '${xrp}' has` + ` too many decimal places.` - ) + ); } return new BigNumber(xrp) .times(1000000.0) .integerValue(BigNumber.ROUND_FLOOR) - .toString(10) + .toString(10); } function toRippledAmount(amount: RippledAmount): RippledAmount { - if (typeof amount === 'string') + if (typeof amount === "string") { return amount; - - if (amount.currency === 'XRP') { - return xrpToDrops(amount.value) - } - if (amount.currency === 'drops') { - return amount.value } - let issuer = amount.counterparty || amount.issuer + if (amount.currency === "XRP") { + return xrpToDrops(amount.value); + } + if (amount.currency === "drops") { + return amount.value; + } + + let issuer = amount.counterparty || amount.issuer; let tag: number | false = false; try { - ({classicAddress: issuer, tag} = xAddressToClassicAddress(issuer)) - } catch (e) { /* not an X-address */ } - + if (issuer) { + ({ classicAddress: issuer, tag } = xAddressToClassicAddress(issuer)); + } + } catch (e) { + /* not an X-address */ + } + if (tag !== false) { - throw new ValidationError("Issuer X-address includes a tag") + throw new ValidationError("Issuer X-address includes a tag"); } return { currency: amount.currency, issuer, - value: amount.value - } + value: amount.value, + }; } function convertKeysFromSnakeCaseToCamelCase(obj: any): any { - if (typeof obj === 'object') { - const accumulator = Array.isArray(obj) ? [] : {} - let newKey - return Object.entries(obj).reduce( - (result, [key, value]) => { - newKey = key - // taking this out of function leads to error in PhantomJS - const FINDSNAKE = /([a-zA-Z]_[a-zA-Z])/g - if (FINDSNAKE.test(key)) { - newKey = key.replace(FINDSNAKE, (r) => r[0] + r[2].toUpperCase()) - } - result[newKey] = convertKeysFromSnakeCaseToCamelCase(value) - return result - }, - accumulator - ) + if (typeof obj === "object") { + const accumulator = Array.isArray(obj) ? [] : {}; + let newKey; + return Object.entries(obj).reduce((result, [key, value]) => { + newKey = key; + // taking this out of function leads to error in PhantomJS + const FINDSNAKE = /([a-zA-Z]_[a-zA-Z])/g; + if (FINDSNAKE.test(key)) { + newKey = key.replace(FINDSNAKE, (r) => r[0] + r[2].toUpperCase()); + } + result[newKey] = convertKeysFromSnakeCaseToCamelCase(value); + return result; + }, accumulator); } - return obj + return obj; } function removeUndefined(obj: T): T { - return _.omitBy(obj, value => value == null) as T + return _.omitBy(obj, (value) => value == null) as T; } /** - * @param {Number} rpepoch (seconds since 1/1/2000 GMT) - * @return {Number} ms since unix epoch + * @param rpepoch - (seconds since 1/1/2000 GMT). + * @returns Milliseconds since unix epoch. */ function rippleToUnixTimestamp(rpepoch: number): number { - return (rpepoch + 0x386d4380) * 1000 + return (rpepoch + 0x386d4380) * 1000; } /** - * @param {Number|Date} timestamp (ms since unix epoch) - * @return {Number} seconds since Ripple Epoch (1/1/2000 GMT) + * @param timestamp - (ms since unix epoch). + * @returns Seconds since Ripple Epoch (1/1/2000 GMT). */ function unixToRippleTimestamp(timestamp: number): number { - return Math.round(timestamp / 1000) - 0x386d4380 + return Math.round(timestamp / 1000) - 0x386d4380; } /** - * @param {number} rippleTime is the number of seconds since Ripple Epoch (1/1/2000 GMT) - * @return {string} iso8601 international standard date format + * @param rippleTime - Is the number of seconds since Ripple Epoch (1/1/2000 GMT). + * @returns Iso8601 international standard date format. */ function rippleTimeToISOTime(rippleTime: number): string { - return new Date(rippleToUnixTimestamp(rippleTime)).toISOString() + return new Date(rippleToUnixTimestamp(rippleTime)).toISOString(); } /** - * @param {string} iso8601 international standard date format - * @return {number} seconds since ripple epoch (1/1/2000 GMT) + * @param iso8601 - International standard date format. + * @returns Seconds since ripple epoch (1/1/2000 GMT). */ function ISOTimeToRippleTime(iso8601: string): number { - return unixToRippleTimestamp(Date.parse(iso8601)) + return unixToRippleTimestamp(Date.parse(iso8601)); } export { - computeLedgerHeaderHash, - dropsToXrp, - xrpToDrops, - toRippledAmount, - convertKeysFromSnakeCaseToCamelCase, - removeUndefined, - rippleTimeToISOTime, - ISOTimeToRippleTime, - isValidSecret, - computeBinaryTransactionHash, - computeTransactionHash, - computeBinaryTransactionSigningHash, - computeAccountRootIndex, - computeSignerListIndex, - computeOfferIndex, - computeTrustlineHash, - computeTransactionTreeHash, - computeStateTreeHash, - computeLedgerHash, - computeEscrowHash, - computePaymentChannelHash, - generateXAddress, - deriveKeypair, - deriveAddress, - deriveXAddress, - signPaymentChannelClaim, - verifyPaymentChannelClaim, -} + computeLedgerHeaderHash, + dropsToXrp, + xrpToDrops, + toRippledAmount, + convertKeysFromSnakeCaseToCamelCase, + removeUndefined, + rippleTimeToISOTime, + ISOTimeToRippleTime, + isValidSecret, + computeBinaryTransactionHash, + computeTransactionHash, + computeBinaryTransactionSigningHash, + computeAccountRootIndex, + computeSignerListIndex, + computeOfferIndex, + computeTrustlineHash, + computeTransactionTreeHash, + computeStateTreeHash, + computeLedgerHash, + computeEscrowHash, + computePaymentChannelHash, + generateXAddress, + deriveKeypair, + deriveAddress, + deriveXAddress, + signPaymentChannelClaim, + verifyPaymentChannelClaim, +}; diff --git a/src/utils/ledgerHash.ts b/src/utils/ledgerHash.ts index cd92535c..c49fd733 100644 --- a/src/utils/ledgerHash.ts +++ b/src/utils/ledgerHash.ts @@ -1,11 +1,14 @@ -import _ from 'lodash' -import { ISOTimeToRippleTime } from '.' -import { ValidationError } from '../common/errors' +import _ from "lodash"; + +import { ValidationError } from "../common/errors"; + import { computeLedgerHash, computeTransactionTreeHash, - computeStateTreeHash -} from '../utils/hashes' + computeStateTreeHash, +} from "./hashes"; + +import { ISOTimeToRippleTime } from "."; function convertLedgerHeader(header): any { return { @@ -19,94 +22,91 @@ function convertLedgerHeader(header): any { parent_hash: header.parentLedgerHash, parent_close_time: ISOTimeToRippleTime(header.parentCloseTime), total_coins: header.totalDrops, - transaction_hash: header.transactionHash - } + transaction_hash: header.transactionHash, + }; } function hashLedgerHeader(ledgerHeader) { - const header = convertLedgerHeader(ledgerHeader) - return computeLedgerHash(header) + const header = convertLedgerHeader(ledgerHeader); + return computeLedgerHash(header); } function computeTransactionHash( ledger, options: ComputeLedgerHeaderHashOptions ) { - let transactions: any[] + let transactions: any[] = []; if (ledger.rawTransactions) { - transactions = JSON.parse(ledger.rawTransactions) + transactions = JSON.parse(ledger.rawTransactions); } else if (ledger.transactions) { try { transactions = ledger.transactions.map((tx) => JSON.parse(tx.rawTransaction) - ) + ); } catch (e) { if ( e.toString() === - 'SyntaxError: Unexpected' + ' token u in JSON at position 0' + "SyntaxError: Unexpected" + " token u in JSON at position 0" ) { // one or more of the `tx.rawTransaction`s is undefined - throw new ValidationError( - 'ledger' + ' is missing raw transactions' - ) + throw new ValidationError("ledger" + " is missing raw transactions"); } } } else { if (options.computeTreeHashes) { throw new ValidationError( - 'transactions' + ' property is missing from the ledger' - ) + "transactions" + " property is missing from the ledger" + ); } - return ledger.transactionHash + return ledger.transactionHash; } const txs = transactions.map((tx) => { - const mergeTx = Object.assign({}, _.omit(tx, 'tx'), tx.tx || {}) + const mergeTx = { ..._.omit(tx, "tx"), ...(tx.tx || {}) }; // rename `meta` back to `metaData` - const renameMeta = Object.assign( - {}, - _.omit(mergeTx, 'meta'), - tx.meta ? {metaData: tx.meta} : {} - ) - return renameMeta - }) - const transactionHash = computeTransactionTreeHash(txs) + const renameMeta = { + ..._.omit(mergeTx, "meta"), + ...(tx.meta ? { metaData: tx.meta } : {}), + }; + return renameMeta; + }); + const transactionHash = computeTransactionTreeHash(txs); if ( ledger.transactionHash != null && ledger.transactionHash !== transactionHash ) { throw new ValidationError( - 'transactionHash in header' + - ' does not match computed hash of transactions', + "transactionHash in header" + + " does not match computed hash of transactions", { transactionHashInHeader: ledger.transactionHash, - computedHashOfTransactions: transactionHash + computedHashOfTransactions: transactionHash, } - ) + ); } - return transactionHash + return transactionHash; } function computeStateHash(ledger, options: ComputeLedgerHeaderHashOptions) { if (ledger.rawState == null) { if (options.computeTreeHashes) { throw new ValidationError( - 'rawState' + ' property is missing from the ledger' - ) + "rawState" + " property is missing from the ledger" + ); } - return ledger.stateHash + return ledger.stateHash; } - const state = JSON.parse(ledger.rawState) - const stateHash = computeStateTreeHash(state) + const state = JSON.parse(ledger.rawState); + const stateHash = computeStateTreeHash(state); if (ledger.stateHash != null && ledger.stateHash !== stateHash) { throw new ValidationError( - 'stateHash in header' + ' does not match computed hash of state' - ) + "stateHash in header" + " does not match computed hash of state" + ); } - return stateHash + return stateHash; } -export type ComputeLedgerHeaderHashOptions = { - computeTreeHashes?: boolean +export interface ComputeLedgerHeaderHashOptions { + computeTreeHashes?: boolean; } function computeLedgerHeaderHash( @@ -115,9 +115,9 @@ function computeLedgerHeaderHash( ): string { const subhashes = { transactionHash: computeTransactionHash(ledger, options), - stateHash: computeStateHash(ledger, options) - } - return hashLedgerHeader(Object.assign({}, ledger, subhashes)) + stateHash: computeStateHash(ledger, options), + }; + return hashLedgerHeader({ ...ledger, ...subhashes }); } -export default computeLedgerHeaderHash +export default computeLedgerHeaderHash; diff --git a/src/utils/signPaymentChannelClaim.ts b/src/utils/signPaymentChannelClaim.ts index 5c604e4f..5cbbe67e 100644 --- a/src/utils/signPaymentChannelClaim.ts +++ b/src/utils/signPaymentChannelClaim.ts @@ -1,19 +1,21 @@ -import keypairs from 'ripple-keypairs' -import binary from 'ripple-binary-codec' -import { validate } from '../common' -import { xrpToDrops } from '.' +import binary from "ripple-binary-codec"; +import keypairs from "ripple-keypairs"; + +import { validate } from "../common"; + +import { xrpToDrops } from "."; function signPaymentChannelClaim( channel: string, amount: string, privateKey: string ): string { - validate.signPaymentChannelClaim({channel, amount, privateKey}) + validate.signPaymentChannelClaim({ channel, amount, privateKey }); const signingData = binary.encodeForSigningClaim({ - channel: channel, - amount: xrpToDrops(amount) - }) - return keypairs.sign(signingData, privateKey) + channel, + amount: xrpToDrops(amount), + }); + return keypairs.sign(signingData, privateKey); } -export default signPaymentChannelClaim +export default signPaymentChannelClaim; diff --git a/src/utils/verifyPaymentChannelClaim.ts b/src/utils/verifyPaymentChannelClaim.ts index b9d9c6f9..e11f91c5 100644 --- a/src/utils/verifyPaymentChannelClaim.ts +++ b/src/utils/verifyPaymentChannelClaim.ts @@ -1,7 +1,9 @@ -import keypairs from 'ripple-keypairs' -import binary from 'ripple-binary-codec' -import {validate} from '../common' -import {xrpToDrops} from '.' +import binary from "ripple-binary-codec"; +import keypairs from "ripple-keypairs"; + +import { validate } from "../common"; + +import { xrpToDrops } from "."; function verifyPaymentChannelClaim( channel: string, @@ -9,13 +11,13 @@ function verifyPaymentChannelClaim( signature: string, publicKey: string ): boolean { - validate.verifyPaymentChannelClaim({channel, amount, signature, publicKey}) + validate.verifyPaymentChannelClaim({ channel, amount, signature, publicKey }); const signingData = binary.encodeForSigningClaim({ - channel: channel, - amount: xrpToDrops(amount) - }) - return keypairs.verify(signingData, signature, publicKey) + channel, + amount: xrpToDrops(amount), + }); + return keypairs.verify(signingData, signature, publicKey); } -export default verifyPaymentChannelClaim +export default verifyPaymentChannelClaim; diff --git a/src/wallet/wallet-generation.ts b/src/wallet/wallet-generation.ts index fbae8083..bf1a5fef 100644 --- a/src/wallet/wallet-generation.ts +++ b/src/wallet/wallet-generation.ts @@ -1,59 +1,61 @@ -import https = require('https') +import https = require("https"); -import {Client} from '..' -import {errors} from '../common' -import {GeneratedAddress} from '../utils/generateAddress' -import {isValidAddress} from '../common/schema-validator' -import {RippledError} from '../common/errors' +import { Client } from ".."; +import { errors } from "../common"; +import { RippledError } from "../common/errors"; +import { isValidAddress } from "../common/schema-validator"; +import { GeneratedAddress } from "../utils/generateAddress"; export interface FaucetWallet { - account: GeneratedAddress - amount: number - balance: number + account: GeneratedAddress; + amount: number; + balance: number; } export enum FaucetNetwork { - Testnet = 'faucet.altnet.rippletest.net', - Devnet = 'faucet.devnet.rippletest.net' + Testnet = "faucet.altnet.rippletest.net", + Devnet = "faucet.devnet.rippletest.net", } -const INTERVAL_SECONDS = 1 // Interval to check an account balance -const MAX_ATTEMPTS = 20 // Maximum attempts to retrieve a balance +const INTERVAL_SECONDS = 1; // Interval to check an account balance +const MAX_ATTEMPTS = 20; // Maximum attempts to retrieve a balance /** * Generates a random wallet with some amount of XRP (usually 1000 XRP). * + * @param this * @param address - An existing XRPL address to fund, if undefined, a new wallet will be created. - * @returns - A Wallet on the Testnet or Devnet that contains some amount of XRP. + * @returns A Wallet on the Testnet or Devnet that contains some amount of XRP. */ async function generateFaucetWallet( this: Client, address?: string ): Promise { - if(!this.isConnected()) - throw new RippledError("Client not connected, cannot call faucet") + if (!this.isConnected()) { + throw new RippledError("Client not connected, cannot call faucet"); + } // Initialize some variables - let body: Uint8Array - let startingBalance = 0 - let faucetUrl = getFaucetUrl(this) + let body: Uint8Array | undefined; + let startingBalance = 0; + const faucetUrl = getFaucetUrl(this); // If the user provides an existing wallet to fund if (address && isValidAddress(address)) { // Create the POST request body body = new TextEncoder().encode( JSON.stringify({ - destination: address + destination: address, }) - ) + ); // Retrieve the existing account balance - const addressToFundBalance = await getAddressXrpBalance(this, address) + const addressToFundBalance = await getAddressXrpBalance(this, address); // Check the address balance is not undefined and is a number - if (addressToFundBalance && !isNaN(+addressToFundBalance)) { - startingBalance = +addressToFundBalance + if (addressToFundBalance && !isNaN(Number(addressToFundBalance))) { + startingBalance = Number(addressToFundBalance); } else { - startingBalance = 0 + startingBalance = 0; } } @@ -61,27 +63,27 @@ async function generateFaucetWallet( const options = { hostname: faucetUrl, port: 443, - path: '/accounts', - method: 'POST', + path: "/accounts", + method: "POST", headers: { - 'Content-Type': 'application/json', - 'Content-Length': body ? body.length : 0 - } - } + "Content-Type": "application/json", + "Content-Length": body ? body.length : 0, + }, + }; return new Promise((resolve, reject) => { const request = https.request(options, (response) => { - const chunks = [] - response.on('data', (d) => { - chunks.push(d) - }) - response.on('end', async () => { - const body = Buffer.concat(chunks).toString() + const chunks: any[] = []; + response.on("data", (d) => { + chunks.push(d); + }); + response.on("end", async () => { + const body = Buffer.concat(chunks).toString(); // "application/json; charset=utf-8" - if (response.headers['content-type'].startsWith('application/json')) { - const wallet: FaucetWallet = JSON.parse(body) - const classicAddress = wallet.account.classicAddress + if (response.headers["content-type"]?.startsWith("application/json")) { + const wallet: FaucetWallet = JSON.parse(body); + const classicAddress = wallet.account.classicAddress; if (classicAddress) { try { @@ -90,10 +92,10 @@ async function generateFaucetWallet( this, classicAddress, startingBalance - ) + ); if (isFunded) { - resolve(wallet) + resolve(wallet); } else { reject( new errors.XRPLFaucetError( @@ -101,42 +103,42 @@ async function generateFaucetWallet( INTERVAL_SECONDS * MAX_ATTEMPTS } seconds` ) - ) + ); } } catch (err) { - reject(new errors.XRPLFaucetError(err)) + reject(new errors.XRPLFaucetError(err)); } } else { reject( new errors.XRPLFaucetError( `The faucet account classic address is undefined` ) - ) + ); } } else { reject({ statusCode: response.statusCode, - contentType: response.headers['content-type'], - body - }) + contentType: response.headers["content-type"], + body, + }); } - }) - }) + }); + }); // POST the body - request.write(body ? body : '') + request.write(body || ""); - request.on('error', (error) => { - reject(error) - }) + request.on("error", (error) => { + reject(error); + }); - request.end() - }) + request.end(); + }); } /** - * Retrieves an XRPL address XRP balance + * Retrieves an XRPL address XRP balance. * - * @param client - Client + * @param client - Client. * @param address - XRPL address. * @returns */ @@ -146,25 +148,25 @@ async function getAddressXrpBalance( ): Promise { // Get all the account balances try { - const balances = await client.getBalances(address) + const balances = await client.getBalances(address); // Retrieve the XRP balance const xrpBalance = balances.filter( - (balance) => balance.currency.toUpperCase() === 'XRP' - ) - return xrpBalance[0].value + (balance) => balance.currency.toUpperCase() === "XRP" + ); + return xrpBalance[0].value; } catch (err) { - return `Unable to retrieve ${address} balance. Error: ${err}` + return `Unable to retrieve ${address} balance. Error: ${err}`; } } /** - * Check at regular interval if the address is enabled on the XRPL and funded + * Check at regular interval if the address is enabled on the XRPL and funded. * - * @param client - Client - * @param address - the account address to check - * @param originalBalance - the initial balance before the funding - * @returns A Promise boolean + * @param client - Client. + * @param address - The account address to check. + * @param originalBalance - The initial balance before the funding. + * @returns A Promise boolean. */ async function hasAddressBalanceIncreased( client: Client, @@ -172,51 +174,52 @@ async function hasAddressBalanceIncreased( originalBalance: number ): Promise { return new Promise((resolve, reject) => { - let attempts = MAX_ATTEMPTS + let attempts = MAX_ATTEMPTS; const interval = setInterval(async () => { if (attempts < 0) { - clearInterval(interval) - resolve(false) + clearInterval(interval); + resolve(false); } else { - attempts-- + attempts--; } try { - const newBalance = +(await getAddressXrpBalance(client, address)) + const newBalance = Number(await getAddressXrpBalance(client, address)); if (newBalance > originalBalance) { - clearInterval(interval) - resolve(true) + clearInterval(interval); + resolve(true); } } catch (err) { - clearInterval(interval) + clearInterval(interval); reject( new errors.XRPLFaucetError( `Unable to check if the address ${address} balance has increased. Error: ${err}` ) - ) + ); } - }, INTERVAL_SECONDS * 1000) - }) + }, INTERVAL_SECONDS * 1000); + }); } /** - * Get the faucet URL based on the Client connection - * @param client - Client - * @returns A {@link FaucetNetwork} + * Get the faucet URL based on the Client connection. + * + * @param client - Client. + * @returns A {@link FaucetNetwork}. */ export function getFaucetUrl(client: Client) { - const connectionUrl = client.connection.getUrl() + const connectionUrl = client.connection.getUrl(); // 'altnet' for Ripple Testnet server and 'testnet' for XRPL Labs Testnet server - if (connectionUrl.includes('altnet') || connectionUrl.includes('testnet')) { - return FaucetNetwork.Testnet + if (connectionUrl.includes("altnet") || connectionUrl.includes("testnet")) { + return FaucetNetwork.Testnet; } - if (connectionUrl.includes('devnet')) { - return FaucetNetwork.Devnet + if (connectionUrl.includes("devnet")) { + return FaucetNetwork.Devnet; } - return undefined + return undefined; } -export default generateFaucetWallet +export default generateFaucetWallet; diff --git a/test/backoff.ts b/test/backoff.ts index c863739c..402f873d 100644 --- a/test/backoff.ts +++ b/test/backoff.ts @@ -1,37 +1,38 @@ -import assert from 'assert-diff' -import {ExponentialBackoff} from '../src/client/backoff' +import assert from "assert-diff"; -describe('ExponentialBackoff', function () { - it('duration() return value starts with the min value', function () { +import { ExponentialBackoff } from "../src/client/backoff"; + +describe("ExponentialBackoff", function () { + it("duration() return value starts with the min value", function () { // default: 100ms - assert(new ExponentialBackoff().duration(), 100) - assert(new ExponentialBackoff({min: 100}).duration(), 100) - assert(new ExponentialBackoff({min: 123}).duration(), 123) - }) + assert(new ExponentialBackoff().duration(), 100); + assert(new ExponentialBackoff({ min: 100 }).duration(), 100); + assert(new ExponentialBackoff({ min: 123 }).duration(), 123); + }); - it('duration() return value increases when called multiple times', function () { - const backoff = new ExponentialBackoff({min: 100, max: 1000}) - assert.strictEqual(backoff.duration(), 100) - assert.strictEqual(backoff.duration(), 200) - assert.strictEqual(backoff.duration(), 400) - assert.strictEqual(backoff.duration(), 800) - }) + it("duration() return value increases when called multiple times", function () { + const backoff = new ExponentialBackoff({ min: 100, max: 1000 }); + assert.strictEqual(backoff.duration(), 100); + assert.strictEqual(backoff.duration(), 200); + assert.strictEqual(backoff.duration(), 400); + assert.strictEqual(backoff.duration(), 800); + }); - it('duration() never returns greater than the max value', function () { - const backoff = new ExponentialBackoff({min: 300, max: 1000}) - assert.strictEqual(backoff.duration(), 300) - assert.strictEqual(backoff.duration(), 600) - assert.strictEqual(backoff.duration(), 1000) - assert.strictEqual(backoff.duration(), 1000) - }) + it("duration() never returns greater than the max value", function () { + const backoff = new ExponentialBackoff({ min: 300, max: 1000 }); + assert.strictEqual(backoff.duration(), 300); + assert.strictEqual(backoff.duration(), 600); + assert.strictEqual(backoff.duration(), 1000); + assert.strictEqual(backoff.duration(), 1000); + }); - it('reset() will reset the duration() value', function () { - const backoff = new ExponentialBackoff({min: 100, max: 1000}) - assert.strictEqual(backoff.duration(), 100) - assert.strictEqual(backoff.duration(), 200) - assert.strictEqual(backoff.duration(), 400) - backoff.reset() - assert.strictEqual(backoff.duration(), 100) - assert.strictEqual(backoff.duration(), 200) - }) -}) + it("reset() will reset the duration() value", function () { + const backoff = new ExponentialBackoff({ min: 100, max: 1000 }); + assert.strictEqual(backoff.duration(), 100); + assert.strictEqual(backoff.duration(), 200); + assert.strictEqual(backoff.duration(), 400); + backoff.reset(); + assert.strictEqual(backoff.duration(), 100); + assert.strictEqual(backoff.duration(), 200); + }); +}); diff --git a/test/broadcastClient.ts b/test/broadcastClient.ts index 86becef0..7b8a8495 100644 --- a/test/broadcastClient.ts +++ b/test/broadcastClient.ts @@ -1,53 +1,52 @@ -import _ from 'lodash' -import assert from 'assert-diff' -import setupClient from './setupClient' -import responses from './fixtures/responses' -import rippled from './fixtures/rippled' -import {ignoreWebSocketDisconnect} from './testUtils' +import assert from "assert-diff"; +import _ from "lodash"; -const TIMEOUT = 20000 +import responses from "./fixtures/responses"; +import rippled from "./fixtures/rippled"; +import setupClient from "./setupClient"; +import { ignoreWebSocketDisconnect } from "./testUtils"; + +const TIMEOUT = 20000; function checkResult(expected, response) { if (expected.txJSON) { - assert(response.txJSON) - assert.deepEqual(JSON.parse(response.txJSON), JSON.parse(expected.txJSON)) + assert(response.txJSON); + assert.deepEqual(JSON.parse(response.txJSON), JSON.parse(expected.txJSON)); } - assert.deepEqual(_.omit(response, 'txJSON'), _.omit(expected, 'txJSON')) - return response + assert.deepEqual(_.omit(response, "txJSON"), _.omit(expected, "txJSON")); + return response; } -describe('BroadcastClient', function () { - this.timeout(TIMEOUT) - beforeEach(setupClient.setupBroadcast) - afterEach(setupClient.teardown) +describe("BroadcastClient", function () { + this.timeout(TIMEOUT); + beforeEach(setupClient.setupBroadcast); + afterEach(setupClient.teardown); - it('base', function () { + it("base", function () { this.mocks.forEach((mock) => { - mock.addResponse({command: 'server_info'}, rippled.server_info.normal) - }) - assert(this.client.isConnected()) - return this.client - .request({command: "server_info"}) - .then(response => { - return checkResult(responses.getServerInfo, response.result.info) - }) - }) + mock.addResponse({ command: "server_info" }, rippled.server_info.normal); + }); + assert(this.client.isConnected()); + return this.client.request({ command: "server_info" }).then((response) => { + return checkResult(responses.getServerInfo, response.result.info); + }); + }); - it('error propagation', function (done) { - const data = {error: 'type', error_message: 'info'} + it("error propagation", function (done) { + const data = { error: "type", error_message: "info" }; this.mocks.forEach((mock) => { - mock.addResponse({command: 'echo'}, data) - }) - this.client.once('error', (type, info) => { - assert.strictEqual(type, 'type') - assert.strictEqual(info, 'info') - done() - }) + mock.addResponse({ command: "echo" }, data); + }); + this.client.once("error", (type, info) => { + assert.strictEqual(type, "type"); + assert.strictEqual(info, "info"); + done(); + }); this.client._clients[1].connection .request({ - command: 'echo', - data + command: "echo", + data, }) - .catch(ignoreWebSocketDisconnect) - }) -}) + .catch(ignoreWebSocketDisconnect); + }); +}); diff --git a/test/browser/browserIntegration.ts b/test/browser/browserIntegration.ts index 35a1bce9..91dcaffe 100644 --- a/test/browser/browserIntegration.ts +++ b/test/browser/browserIntegration.ts @@ -1,30 +1,35 @@ -import assert from 'assert' -import puppeteer from 'puppeteer' +import { expect, assert } from "chai"; +import puppeteer from "puppeteer"; -describe("Browser Tests", () => { - it("Integration Tests", async () => { - const browser = await puppeteer.launch({"headless": true}); - try { - const page = await browser.newPage().catch(); - await page.goto(`file:///${__dirname}/../localIntegrationRunner.html`); +describe("Browser Tests", function () { + it("Integration Tests", async function () { + const browser = await puppeteer.launch({ headless: true }); + try { + const page = await browser.newPage().catch(); + await page.goto(`file:///${__dirname}/../localIntegrationRunner.html`); - await page.waitForFunction('document.querySelector("body").innerText.includes("submit multisigned transaction")'); + await page.waitForFunction( + 'document.querySelector("body").innerText.includes("submit multisigned transaction")' + ); - const fails = await page.evaluate(() => { - return document.querySelector('.failures').textContent - }) - const passes = await page.evaluate(() => { - return document.querySelector('.passes').textContent - }) + const fails = await page.evaluate(() => { + const element = document.querySelector(".failures"); - assert.equal(fails, "failures: 0") - assert.notEqual(passes, "passes: 0") + return element == null ? null : element.textContent; + }); + const passes = await page.evaluate(() => { + const element = document.querySelector(".passes"); - } catch (err) { - console.log(err) - assert(false) - } finally { - await browser.close(); - } - }).timeout(40000) -}) \ No newline at end of file + return element == null ? null : element.textContent; + }); + + expect(fails).to.equal("failures: 0"); + expect(passes).to.not.equal("passes: 0"); + } catch (err) { + console.log(err); + assert(false); + } finally { + await browser.close(); + } + }).timeout(40000); +}); diff --git a/test/client/combine.ts b/test/client/combine.ts index f26f866b..489c1392 100644 --- a/test/client/combine.ts +++ b/test/client/combine.ts @@ -1,10 +1,12 @@ -import assert from 'assert-diff' -import binary from 'ripple-binary-codec' -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import {assertResultMatch, TestSuite} from '../testUtils' -const {combine: REQUEST_FIXTURES} = requests -const {combine: RESPONSE_FIXTURES} = responses +import assert from "assert-diff"; +import binary from "ripple-binary-codec"; + +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import { assertResultMatch, TestSuite } from "../testUtils"; + +const { combine: REQUEST_FIXTURES } = requests; +const { combine: RESPONSE_FIXTURES } = responses; /** * Every test suite exports their tests in the default object. @@ -12,18 +14,18 @@ const {combine: RESPONSE_FIXTURES} = responses * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'combine': async (client, address) => { - const combined = client.combine(REQUEST_FIXTURES.setDomain) - assertResultMatch(combined, RESPONSE_FIXTURES.single, 'sign') + async combine(client, address) { + const combined = client.combine(REQUEST_FIXTURES.setDomain); + assertResultMatch(combined, RESPONSE_FIXTURES.single, "sign"); }, - 'combine - different transactions': async (client, address) => { - const request = [REQUEST_FIXTURES.setDomain[0]] - const tx = binary.decode(REQUEST_FIXTURES.setDomain[0]) - tx.Flags = 0 - request.push(binary.encode(tx)) + "combine - different transactions": async (client, address) => { + const request = [REQUEST_FIXTURES.setDomain[0]]; + const tx = binary.decode(REQUEST_FIXTURES.setDomain[0]); + tx.Flags = 0; + request.push(binary.encode(tx)); assert.throws(() => { - client.combine(request) - }, /txJSON is not the same for all signedTransactions/) - } -} + client.combine(request); + }, /txJSON is not the same for all signedTransactions/); + }, +}; diff --git a/test/client/constructor.ts b/test/client/constructor.ts index 0d99a347..bea8199e 100644 --- a/test/client/constructor.ts +++ b/test/client/constructor.ts @@ -1,6 +1,8 @@ -import assert from 'assert-diff' -import {TestSuite} from '../testUtils' -import {Client} from 'xrpl-local' +import assert from "assert-diff"; + +import { Client } from "xrpl-local"; + +import { TestSuite } from "../testUtils"; /** * Every test suite exports their tests in the default object. @@ -8,22 +10,22 @@ import {Client} from 'xrpl-local' * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'Client - implicit server port': () => { - new Client('wss://s1.ripple.com') + "Client - implicit server port": () => { + new Client("wss://s1.ripple.com"); }, - 'Client invalid options': () => { - // @ts-ignore - This is intentionally invalid - assert.throws(() => new Client({invalid: true})) + "Client invalid options": () => { + // @ts-expect-error - This is intentionally invalid + assert.throws(() => new Client({ invalid: true })); }, - 'Client valid options': () => { - const client = new Client('wss://s:1') - const privateConnectionUrl = (client.connection as any)._url - assert.deepEqual(privateConnectionUrl, 'wss://s:1') + "Client valid options": () => { + const client = new Client("wss://s:1"); + const privateConnectionUrl = (client.connection as any)._url; + assert.deepEqual(privateConnectionUrl, "wss://s:1"); }, - 'Client invalid server uri': () => { - assert.throws(() => new Client('wss//s:1')) - } -} + "Client invalid server uri": () => { + assert.throws(() => new Client("wss//s:1")); + }, +}; diff --git a/test/client/deriveXAddress.ts b/test/client/deriveXAddress.ts index 11bdc3c8..34229905 100644 --- a/test/client/deriveXAddress.ts +++ b/test/client/deriveXAddress.ts @@ -1,6 +1,7 @@ -import assert from 'assert-diff' -import {TestSuite} from '../testUtils' -import {Client} from '../../src' +import assert from "assert-diff"; + +import { Client } from "../../src"; +import { TestSuite } from "../testUtils"; /** * Every test suite exports their tests in the default object. @@ -8,24 +9,24 @@ import {Client} from '../../src' * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'returns address for public key': async (client, address) => { + "returns address for public key": async (client, address) => { assert.equal( Client.deriveXAddress({ publicKey: - '035332FBA71D705BD5D97014A833BE2BBB25BEFCD3506198E14AFEA241B98C2D06', + "035332FBA71D705BD5D97014A833BE2BBB25BEFCD3506198E14AFEA241B98C2D06", tag: false, - test: false + test: false, }), - 'XVZVpQj8YSVpNyiwXYSqvQoQqgBttTxAZwMcuJd4xteQHyt' - ) + "XVZVpQj8YSVpNyiwXYSqvQoQqgBttTxAZwMcuJd4xteQHyt" + ); assert.equal( Client.deriveXAddress({ publicKey: - '035332FBA71D705BD5D97014A833BE2BBB25BEFCD3506198E14AFEA241B98C2D06', + "035332FBA71D705BD5D97014A833BE2BBB25BEFCD3506198E14AFEA241B98C2D06", tag: false, - test: true + test: true, }), - 'TVVrSWtmQQssgVcmoMBcFQZKKf56QscyWLKnUyiuZW8ALU4' - ) - } -} + "TVVrSWtmQQssgVcmoMBcFQZKKf56QscyWLKnUyiuZW8ALU4" + ); + }, +}; diff --git a/test/client/errors.ts b/test/client/errors.ts index e117302f..fd9d262c 100644 --- a/test/client/errors.ts +++ b/test/client/errors.ts @@ -1,5 +1,6 @@ -import assert from 'assert-diff' -import {TestSuite} from '../testUtils' +import assert from "assert-diff"; + +import { TestSuite } from "../testUtils"; /** * Every test suite exports their tests in the default object. @@ -7,13 +8,13 @@ import {TestSuite} from '../testUtils' * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'RippleError with data': async (client, address) => { - const error = new client.errors.RippleError('_message_', '_data_') - assert.strictEqual(error.toString(), "[RippleError(_message_, '_data_')]") + "RippleError with data": async (client, address) => { + const error = new client.errors.RippleError("_message_", "_data_"); + assert.strictEqual(error.toString(), "[RippleError(_message_, '_data_')]"); }, - 'NotFoundError default message': async (client, address) => { - const error = new client.errors.NotFoundError() - assert.strictEqual(error.toString(), '[NotFoundError(Not found)]') - } -} + "NotFoundError default message": async (client, address) => { + const error = new client.errors.NotFoundError(); + assert.strictEqual(error.toString(), "[NotFoundError(Not found)]"); + }, +}; diff --git a/test/client/formatBidsAndAsks.ts b/test/client/formatBidsAndAsks.ts index 74473af2..9c7d6399 100644 --- a/test/client/formatBidsAndAsks.ts +++ b/test/client/formatBidsAndAsks.ts @@ -3,7 +3,7 @@ // import {Client} from 'xrpl-local' // import requests from '../fixtures/requests' // import responses from '../fixtures/responses' -import {TestSuite} from '../testUtils' +import { TestSuite } from "../testUtils"; // function checkSortingOfOrders(orders) { // let previousRate = '0' @@ -56,7 +56,6 @@ export default { // counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' // } // } - // await Promise.all([ // client.request({command: 'book_offers', // taker_gets: orderbookInfo.base, @@ -88,7 +87,6 @@ export default { // assert.deepEqual(orderbook, responses.getOrderbook.normal) // }) // }, - // 'with XRP': async (client, address) => { // const orderbookInfo = { // base: { @@ -99,7 +97,6 @@ export default { // currency: 'XRP' // } // } - // await Promise.all([ // client.request({command: 'book_offers', // taker_gets: orderbookInfo.base, @@ -131,7 +128,6 @@ export default { // assert.deepEqual(orderbook, responses.getOrderbook.withXRP) // }) // }, - // 'sample XRP/JPY book has orders sorted correctly': async (client, address) => { // const orderbookInfo = { // base: { @@ -143,9 +139,7 @@ export default { // issuer: 'rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS' // } // } - // const myAddress = 'rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR' - // await Promise.all([ // client.request({command: 'book_offers', // taker_gets: orderbookInfo.base, @@ -178,7 +172,6 @@ export default { // return checkSortingOfOrders(orderbook.asks) // }) // }, - // 'sample USD/XRP book has orders sorted correctly': async (client, address) => { // const orderbookInfo = { // counter: {currency: 'XRP'}, @@ -187,9 +180,7 @@ export default { // counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' // } // } - // const myAddress = 'rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR' - // await Promise.all([ // client.request({command: 'book_offers', // taker_gets: orderbookInfo.base, @@ -224,7 +215,6 @@ export default { // ) // }) // }, - // 'sorted so that best deals come first': async (client, address) => { // const orderbookInfo = { // base: { @@ -236,7 +226,6 @@ export default { // counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' // } // } - // await Promise.all([ // client.request({command: 'book_offers', // taker_gets: orderbookInfo.base, @@ -265,7 +254,6 @@ export default { // ...directOffers, // ...reverseOffers // ]) - // const bidRates = orderbook.bids.map( // (bid) => bid.properties.makerExchangeRate // ) @@ -279,7 +267,6 @@ export default { // assert.deepEqual(askRates.map((x) => Number(x)).sort(), askRates) // }) // }, - // 'currency & counterparty are correct': async (client, address) => { // const orderbookInfo = { // base: { @@ -291,7 +278,6 @@ export default { // counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' // } // } - // await Promise.all([ // client.request({command: 'book_offers', // taker_gets: orderbookInfo.base, @@ -320,7 +306,6 @@ export default { // ...directOffers, // ...reverseOffers // ]) - // const orders = [...orderbook.bids, ...orderbook.asks] // orders.forEach((order) => { // const quantity = order.specification.quantity @@ -333,7 +318,6 @@ export default { // }) // }) // }, - // 'direction is correct for bids and asks': async (client, address) => { // const orderbookInfo = { // base: { @@ -345,7 +329,6 @@ export default { // counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' // } // } - // await Promise.all([ // client.request({command: 'book_offers', // taker_gets: orderbookInfo.base, @@ -374,7 +357,6 @@ export default { // ...directOffers, // ...reverseOffers // ]) - // assert( // orderbook.bids.every((bid) => bid.specification.direction === 'buy') // ) @@ -383,4 +365,4 @@ export default { // ) // }) // } -} +}; diff --git a/test/client/getBalances.ts b/test/client/getBalances.ts index 2ff2bb9d..2c2d0db8 100644 --- a/test/client/getBalances.ts +++ b/test/client/getBalances.ts @@ -1,7 +1,7 @@ -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import rippledAccountLines from '../fixtures/rippled/accountLines' -import {assertResultMatch, TestSuite} from '../testUtils' +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import rippledAccountLines from "../fixtures/rippled/accountLines"; +import { assertResultMatch, TestSuite } from "../testUtils"; /** * Every test suite exports their tests in the default object. @@ -9,54 +9,82 @@ import {assertResultMatch, TestSuite} from '../testUtils' * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'getBalances': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - mockRippled.addResponse({command: 'account_lines'}, rippledAccountLines.normal) - mockRippled.addResponse({command: 'ledger'}, rippled.ledger.normal) - const result = await client.getBalances(address) - assertResultMatch(result, responses.getBalances, 'getBalances') + async getBalances(client, address, mockRippled) { + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + mockRippled.addResponse( + { command: "account_lines" }, + rippledAccountLines.normal + ); + mockRippled.addResponse({ command: "ledger" }, rippled.ledger.normal); + const result = await client.getBalances(address); + assertResultMatch(result, responses.getBalances, "getBalances"); }, - 'getBalances - limit': async (client, address, mockRippled) => { - const options = {limit: 3, ledgerVersion: 123456} - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - mockRippled.addResponse({command: 'account_lines'}, rippledAccountLines.normal) - mockRippled.addResponse({command: 'ledger'}, rippled.ledger.normal) - const expectedResponse = responses.getBalances.slice(0, 3) - const result = await client.getBalances(address, options) - assertResultMatch(result, expectedResponse, 'getBalances') + "getBalances - limit": async (client, address, mockRippled) => { + const options = { limit: 3, ledgerVersion: 123456 }; + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + mockRippled.addResponse( + { command: "account_lines" }, + rippledAccountLines.normal + ); + mockRippled.addResponse({ command: "ledger" }, rippled.ledger.normal); + const expectedResponse = responses.getBalances.slice(0, 3); + const result = await client.getBalances(address, options); + assertResultMatch(result, expectedResponse, "getBalances"); }, - 'getBalances - limit & currency': async (client, address, mockRippled) => { - const options = {currency: 'USD', limit: 3} - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - mockRippled.addResponse({command: 'account_lines'}, rippledAccountLines.normal) - mockRippled.addResponse({command: 'ledger'}, rippled.ledger.normal) + "getBalances - limit & currency": async (client, address, mockRippled) => { + const options = { currency: "USD", limit: 3 }; + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + mockRippled.addResponse( + { command: "account_lines" }, + rippledAccountLines.normal + ); + mockRippled.addResponse({ command: "ledger" }, rippled.ledger.normal); const expectedResponse = responses.getBalances - .filter((item) => item.currency === 'USD') - .slice(0, 3) - const result = await client.getBalances(address, options) - assertResultMatch(result, expectedResponse, 'getBalances') + .filter((item) => item.currency === "USD") + .slice(0, 3); + const result = await client.getBalances(address, options); + assertResultMatch(result, expectedResponse, "getBalances"); }, - 'getBalances - limit & currency & issuer': async (client, address, mockRippled) => { + "getBalances - limit & currency & issuer": async ( + client, + address, + mockRippled + ) => { const options = { - currency: 'USD', - counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', - limit: 3 - } - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - mockRippled.addResponse({command: 'account_lines'}, rippledAccountLines.normal) - mockRippled.addResponse({command: 'ledger'}, rippled.ledger.normal) - + currency: "USD", + counterparty: "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + limit: 3, + }; + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + mockRippled.addResponse( + { command: "account_lines" }, + rippledAccountLines.normal + ); + mockRippled.addResponse({ command: "ledger" }, rippled.ledger.normal); + const expectedResponse = responses.getBalances .filter( (item) => - item.currency === 'USD' && - item.counterparty === 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' + item.currency === "USD" && + item.counterparty === "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" ) - .slice(0, 3) - const result = await client.getBalances(address, options) - assertResultMatch(result, expectedResponse, 'getBalances') - } -} + .slice(0, 3); + const result = await client.getBalances(address, options); + assertResultMatch(result, expectedResponse, "getBalances"); + }, +}; diff --git a/test/client/getFee.ts b/test/client/getFee.ts index 120b6224..50981819 100644 --- a/test/client/getFee.ts +++ b/test/client/getFee.ts @@ -1,6 +1,7 @@ -import assert from 'assert-diff' -import rippled from '../fixtures/rippled' -import {TestSuite} from '../testUtils' +import assert from "assert-diff"; + +import rippled from "../fixtures/rippled"; +import { TestSuite } from "../testUtils"; /** * Every test suite exports their tests in the default object. @@ -8,54 +9,78 @@ import {TestSuite} from '../testUtils' * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'getFee': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - const fee = await client.getFee() - assert.strictEqual(fee, '0.000012') + async getFee(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + const fee = await client.getFee(); + assert.strictEqual(fee, "0.000012"); }, - 'getFee default': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - client._feeCushion = undefined - const fee = await client.getFee() - assert.strictEqual(fee, '0.000012') + "getFee default": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + client._feeCushion = undefined as unknown as number; + const fee = await client.getFee(); + assert.strictEqual(fee, "0.000012"); }, - 'getFee - high load_factor': async (client, address, mockRippled) => { - - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.highLoadFactor) - const fee = await client.getFee() - assert.strictEqual(fee, '2') + "getFee - high load_factor": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.highLoadFactor + ); + const fee = await client.getFee(); + assert.strictEqual(fee, "2"); }, - 'getFee - high load_factor with custom maxFeeXRP': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.highLoadFactor) + "getFee - high load_factor with custom maxFeeXRP": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.highLoadFactor + ); // Ensure that overriding with high maxFeeXRP of '51540' causes no errors. // (fee will actually be 51539.607552) - client._maxFeeXRP = '51540' - const fee = await client.getFee() - assert.strictEqual(fee, '51539.607552') + client._maxFeeXRP = "51540"; + const fee = await client.getFee(); + assert.strictEqual(fee, "51539.607552"); }, - 'getFee custom cushion': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - client._feeCushion = 1.4 - const fee = await client.getFee() - assert.strictEqual(fee, '0.000014') + "getFee custom cushion": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + client._feeCushion = 1.4; + const fee = await client.getFee(); + assert.strictEqual(fee, "0.000014"); }, // This is not recommended since it may result in attempting to pay // less than the base fee. However, this test verifies the existing behavior. - 'getFee cushion less than 1.0': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - client._feeCushion = 0.9 - const fee = await client.getFee() - assert.strictEqual(fee, '0.000009') + "getFee cushion less than 1.0": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + client._feeCushion = 0.9; + const fee = await client.getFee(); + assert.strictEqual(fee, "0.000009"); }, - 'getFee reporting': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - const fee = await client.getFee() - assert.strictEqual(fee, '0.000012') - } -} + "getFee reporting": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + const fee = await client.getFee(); + assert.strictEqual(fee, "0.000012"); + }, +}; diff --git a/test/client/getOrderbook.ts b/test/client/getOrderbook.ts index e4c37abc..cb434336 100644 --- a/test/client/getOrderbook.ts +++ b/test/client/getOrderbook.ts @@ -1,9 +1,10 @@ -import assert from 'assert-diff' -import responses from '../fixtures/responses' -import requests from '../fixtures/requests' -import rippled from '../fixtures/rippled' -import {TestSuite, assertResultMatch, assertRejects} from '../testUtils' -import { BookOffersRequest } from '../../src' +import assert from "assert-diff"; + +import { BookOffersRequest } from "../../src"; +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { TestSuite, assertResultMatch, assertRejects } from "../testUtils"; // import BigNumber from 'bignumber.js' // function checkSortingOfOrders(orders) { @@ -41,11 +42,17 @@ import { BookOffersRequest } from '../../src' // } function isUSD(currency: string) { - return currency === 'USD' || currency === '0000000000000000000000005553440000000000' + return ( + currency === "USD" || + currency === "0000000000000000000000005553440000000000" + ); } function isBTC(currency: string) { - return currency === 'BTC' || currency === '0000000000000000000000004254430000000000' + return ( + currency === "BTC" || + currency === "0000000000000000000000004254430000000000" + ); } function normalRippledResponse(request: BookOffersRequest): object { @@ -53,23 +60,27 @@ function normalRippledResponse(request: BookOffersRequest): object { isBTC(request.taker_gets.currency) && isUSD(request.taker_pays.currency) ) { - return rippled.book_offers.fabric.requestBookOffersBidsResponse(request) - } else if ( + return rippled.book_offers.fabric.requestBookOffersBidsResponse(request); + } + if ( isUSD(request.taker_gets.currency) && isBTC(request.taker_pays.currency) ) { - return rippled.book_offers.fabric.requestBookOffersAsksResponse(request) + return rippled.book_offers.fabric.requestBookOffersAsksResponse(request); } + + return {}; } function xrpRippledResponse(request: BookOffersRequest): object { - if (request.taker_pays.issuer === 'rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw') { - return rippled.book_offers.xrp_usd - } else if ( - request.taker_gets.issuer === 'rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw' - ) { - return rippled.book_offers.usd_xrp + if (request.taker_pays.issuer === "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw") { + return rippled.book_offers.xrp_usd; } + if (request.taker_gets.issuer === "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw") { + return rippled.book_offers.usd_xrp; + } + + return {}; } /** @@ -78,34 +89,34 @@ function xrpRippledResponse(request: BookOffersRequest): object { * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'normal': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'book_offers'}, normalRippledResponse) + async normal(client, address, mockRippled) { + mockRippled.addResponse({ command: "book_offers" }, normalRippledResponse); const response = await client.getOrderbook( address, requests.getOrderbook.normal, - {limit: 20} - ) - assertResultMatch(response, responses.getOrderbook.normal, 'getOrderbook') + { limit: 20 } + ); + assertResultMatch(response, responses.getOrderbook.normal, "getOrderbook"); }, - 'invalid options': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'book_offers'}, normalRippledResponse) + "invalid options": async (client, address, mockRippled) => { + mockRippled.addResponse({ command: "book_offers" }, normalRippledResponse); assertRejects( client.getOrderbook(address, requests.getOrderbook.normal, { - // @ts-ignore - invalid: 'options' + // @ts-expect-error + invalid: "options", }), client.errors.ValidationError - ) + ); }, - 'with XRP': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'book_offers'}, xrpRippledResponse) + "with XRP": async (client, address, mockRippled) => { + mockRippled.addResponse({ command: "book_offers" }, xrpRippledResponse); const response = await client.getOrderbook( address, requests.getOrderbook.withXRP - ) - assertResultMatch(response, responses.getOrderbook.withXRP, 'getOrderbook') + ); + assertResultMatch(response, responses.getOrderbook.withXRP, "getOrderbook"); }, // 'sample XRP/JPY book has orders sorted correctly': async (client, address, mockRippled) => { @@ -140,55 +151,69 @@ export default { // }, // WARNING: This test fails to catch the sorting bug, issue #766 - 'sorted so that best deals come first [bad test]': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'book_offers'}, normalRippledResponse) + "sorted so that best deals come first [bad test]": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse({ command: "book_offers" }, normalRippledResponse); const response = await client.getOrderbook( address, requests.getOrderbook.normal - ) + ); const bidRates = response.bids.map( (bid) => bid.properties.makerExchangeRate - ) + ); const askRates = response.asks.map( (ask) => ask.properties.makerExchangeRate - ) + ); // makerExchangeRate = quality = takerPays.value/takerGets.value // so the best deal for the taker is the lowest makerExchangeRate // bids and asks should be sorted so that the best deals come first assert.deepEqual( bidRates.sort((x) => Number(x)), bidRates - ) + ); assert.deepEqual( askRates.sort((x) => Number(x)), askRates - ) + ); }, - 'currency & counterparty are correct': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'book_offers'}, normalRippledResponse) + "currency & counterparty are correct": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse({ command: "book_offers" }, normalRippledResponse); const response = await client.getOrderbook( address, requests.getOrderbook.normal - ) - ;[...response.bids, ...response.asks].forEach((order) => { - const quantity = order.specification.quantity - const totalPrice = order.specification.totalPrice - const {base, counter} = requests.getOrderbook.normal - assert.strictEqual(quantity.currency, base.currency) - assert.strictEqual(quantity.counterparty, base.counterparty) - assert.strictEqual(totalPrice.currency, counter.currency) - assert.strictEqual(totalPrice.counterparty, counter.counterparty) - }) + ); + [...response.bids, ...response.asks].forEach((order) => { + const quantity = order.specification.quantity; + const totalPrice = order.specification.totalPrice; + const { base, counter } = requests.getOrderbook.normal; + assert.strictEqual(quantity.currency, base.currency); + assert.strictEqual(quantity.counterparty, base.counterparty); + assert.strictEqual(totalPrice.currency, counter.currency); + assert.strictEqual(totalPrice.counterparty, counter.counterparty); + }); }, - 'direction is correct for bids and asks': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'book_offers'}, normalRippledResponse) + "direction is correct for bids and asks": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse({ command: "book_offers" }, normalRippledResponse); const response = await client.getOrderbook( address, requests.getOrderbook.normal - ) - assert(response.bids.every((bid) => bid.specification.direction === 'buy')) - assert(response.asks.every((ask) => ask.specification.direction === 'sell')) - } -} + ); + assert(response.bids.every((bid) => bid.specification.direction === "buy")); + assert( + response.asks.every((ask) => ask.specification.direction === "sell") + ); + }, +}; diff --git a/test/client/getPaths.ts b/test/client/getPaths.ts index 7c8ef54b..6dc824ae 100644 --- a/test/client/getPaths.ts +++ b/test/client/getPaths.ts @@ -1,10 +1,11 @@ -import assert from 'assert-diff' -import { assertRejects, TestSuite } from '../testUtils' -import requests from '../fixtures/requests' +import assert from "assert-diff"; + +import addresses from "../fixtures/addresses.json"; +import requests from "../fixtures/requests"; +import rippled from "../fixtures/rippled"; +import { assertRejects, TestSuite } from "../testUtils"; // import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import addresses from '../fixtures/addresses.json' -const {getPaths: REQUEST_FIXTURES} = requests +const { getPaths: REQUEST_FIXTURES } = requests; // const {getPaths: RESPONSE_FIXTURES} = responses const rippledResponse = rippled.path_find.generate.generateIOUPaymentPaths( @@ -12,7 +13,7 @@ const rippledResponse = rippled.path_find.generate.generateIOUPaymentPaths( REQUEST_FIXTURES.normal.source.address, REQUEST_FIXTURES.normal.destination.address, REQUEST_FIXTURES.normal.destination.amount -) +); /** * Every test suite exports their tests in the default object. @@ -46,12 +47,12 @@ export default { // const response = await client.getPaths(REQUEST_FIXTURES.XrpToXrp) // assertResultMatch(response, RESPONSE_FIXTURES.XrpToXrp, 'getPaths') // }, - 'source with issuer': async (client, _, mockRippled) => { - mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse) + "source with issuer": async (client, _, mockRippled) => { + mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse); return assertRejects( client.getPaths(REQUEST_FIXTURES.issuer), client.errors.NotFoundError - ) + ); }, // 'XRP 2 XRP - not enough': async (client) => { // return assertRejects( @@ -59,52 +60,52 @@ export default { // client.errors.NotFoundError // ) // }, - 'invalid PathFind': async (client, _, mockRippled) => { - mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse) + "invalid PathFind": async (client, _, mockRippled) => { + mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse); assert.throws(() => { - client.getPaths(REQUEST_FIXTURES.invalid) - }, /Cannot specify both source.amount/) + client.getPaths(REQUEST_FIXTURES.invalid); + }, /Cannot specify both source.amount/); }, - 'does not accept currency': async (client, _, mockRippled) => { - mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse) + "does not accept currency": async (client, _, mockRippled) => { + mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse); return assertRejects( client.getPaths(REQUEST_FIXTURES.NotAcceptCurrency), client.errors.NotFoundError - ) + ); }, - 'no paths': async (client, _, mockRippled) => { - mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse) + "no paths": async (client, _, mockRippled) => { + mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse); return assertRejects( client.getPaths(REQUEST_FIXTURES.NoPaths), client.errors.NotFoundError - ) + ); }, - 'no paths source amount': async (client, _, mockRippled) => { - mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse) + "no paths source amount": async (client, _, mockRippled) => { + mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse); return assertRejects( client.getPaths(REQUEST_FIXTURES.NoPathsSource), client.errors.NotFoundError - ) + ); }, - 'no paths with source currencies': async (client, _, mockRippled) => { - mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse) + "no paths with source currencies": async (client, _, mockRippled) => { + mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse); return assertRejects( client.getPaths(REQUEST_FIXTURES.NoPathsWithCurrencies), client.errors.NotFoundError - ) + ); }, - 'error: srcActNotFound': async (client, _, mockRippled) => { - mockRippled.addResponse({command: 'ripple_path_find'}, rippledResponse) + "error: srcActNotFound": async (client, _, mockRippled) => { + mockRippled.addResponse({ command: "ripple_path_find" }, rippledResponse); return assertRejects( client.getPaths({ ...REQUEST_FIXTURES.normal, - source: {address: addresses.NOTFOUND} + source: { address: addresses.NOTFOUND }, }), client.errors.RippleError - ) + ); }, // 'send all': async (client) => { // const response = await client.getPaths(REQUEST_FIXTURES.sendAll) // assertResultMatch(response, RESPONSE_FIXTURES.sendAll, 'getPaths') // } -} +}; diff --git a/test/client/getTrustlines.ts b/test/client/getTrustlines.ts index 075c664f..35b869c6 100644 --- a/test/client/getTrustlines.ts +++ b/test/client/getTrustlines.ts @@ -1,8 +1,9 @@ -import addresses from '../fixtures/addresses.json' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled/accountLines' -import {assertResultMatch, TestSuite} from '../testUtils' -const {getTrustlines: RESPONSE_FIXTURES} = responses +import addresses from "../fixtures/addresses.json"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled/accountLines"; +import { assertResultMatch, TestSuite } from "../testUtils"; + +const { getTrustlines: RESPONSE_FIXTURES } = responses; /** * Every test suite exports their tests in the default object. @@ -10,46 +11,63 @@ const {getTrustlines: RESPONSE_FIXTURES} = responses * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'getTrustlines - filtered': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'account_lines'}, rippled.normal) - const options = {currency: 'USD'} - const result = await client.getTrustlines(address, options) - assertResultMatch(result, RESPONSE_FIXTURES.filtered, 'getTrustlines') + "getTrustlines - filtered": async (client, address, mockRippled) => { + mockRippled.addResponse({ command: "account_lines" }, rippled.normal); + const options = { currency: "USD" }; + const result = await client.getTrustlines(address, options); + assertResultMatch(result, RESPONSE_FIXTURES.filtered, "getTrustlines"); }, - 'getTrustlines - more than 400 items': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'account_lines'}, rippled.manyItems) - const options = {limit: 401} - const result = await client.getTrustlines(address, options) + "getTrustlines - more than 400 items": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse({ command: "account_lines" }, rippled.manyItems); + const options = { limit: 401 }; + const result = await client.getTrustlines(address, options); assertResultMatch( result, RESPONSE_FIXTURES.moreThan400Items, - 'getTrustlines' - ) + "getTrustlines" + ); }, - 'getTrustlines - no options': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'account_lines'}, rippled.normal) - await client.getTrustlines(address) + "getTrustlines - no options": async (client, address, mockRippled) => { + mockRippled.addResponse({ command: "account_lines" }, rippled.normal); + await client.getTrustlines(address); }, - 'getTrustlines - ripplingDisabled works properly': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'account_lines'}, rippled.ripplingDisabled) - const result = await client.getTrustlines(address) + "getTrustlines - ripplingDisabled works properly": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "account_lines" }, + rippled.ripplingDisabled + ); + const result = await client.getTrustlines(address); assertResultMatch( result, RESPONSE_FIXTURES.ripplingDisabled, - 'getTrustlines' - ) + "getTrustlines" + ); }, - 'getTrustlines - ledger version option': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'account_lines'}, rippled.manyItems) - const result = await client.getTrustlines(addresses.FOURTH_ACCOUNT, {ledgerVersion: 5}) + "getTrustlines - ledger version option": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse({ command: "account_lines" }, rippled.manyItems); + const result = await client.getTrustlines(addresses.FOURTH_ACCOUNT, { + ledgerVersion: 5, + }); assertResultMatch( result, RESPONSE_FIXTURES.moreThan400Items, - 'getTrustlines' - ) + "getTrustlines" + ); }, -} +}; diff --git a/test/client/hasNextPage.ts b/test/client/hasNextPage.ts index b614d077..994bb979 100644 --- a/test/client/hasNextPage.ts +++ b/test/client/hasNextPage.ts @@ -1,6 +1,7 @@ -import assert from 'assert-diff' -import {TestSuite} from '../testUtils' -import rippled from '../fixtures/rippled' +import assert from "assert-diff"; + +import rippled from "../fixtures/rippled"; +import { TestSuite } from "../testUtils"; /** * Every test suite exports their tests in the default object. @@ -8,29 +9,36 @@ import rippled from '../fixtures/rippled' * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'returns true when there is another page': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'ledger_data'}, rippled.ledger_data.first_page) - // @ts-ignore - const response = await client.request({command: 'ledger_data'}) - assert(client.hasNextPage(response)) + "returns true when there is another page": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "ledger_data" }, + rippled.ledger_data.first_page + ); + const response = await client.request({ command: "ledger_data" }); + assert(client.hasNextPage(response)); }, - 'returns false when there are no more pages': async (client, address, mockRippled) => { - const rippledResponse = function(request: Request) : object { - if ('marker' in request) { - return rippled.ledger_data.last_page - } else { - return rippled.ledger_data.first_page + "returns false when there are no more pages": async ( + client, + address, + mockRippled + ) => { + const rippledResponse = function (request: Request): object { + if ("marker" in request) { + return rippled.ledger_data.last_page; } - } - mockRippled.addResponse({command: 'ledger_data'}, rippledResponse) - // @ts-ignore - const response = await client.request({command: 'ledger_data'}) + return rippled.ledger_data.first_page; + }; + mockRippled.addResponse({ command: "ledger_data" }, rippledResponse); + const response = await client.request({ command: "ledger_data" }); const responseNextPage = await client.requestNextPage( - // @ts-ignore - {command: 'ledger_data'}, + { command: "ledger_data" }, response - ) - assert(!client.hasNextPage(responseNextPage)) - } -} + ); + assert(!client.hasNextPage(responseNextPage)); + }, +}; diff --git a/test/client/isConnected.ts b/test/client/isConnected.ts index a95081bc..2e381b41 100644 --- a/test/client/isConnected.ts +++ b/test/client/isConnected.ts @@ -1,5 +1,6 @@ -import assert from 'assert-diff' -import {TestSuite} from '../testUtils' +import assert from "assert-diff"; + +import { TestSuite } from "../testUtils"; /** * Every test suite exports their tests in the default object. @@ -7,9 +8,9 @@ import {TestSuite} from '../testUtils' * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'disconnect & isConnected': async (client, address) => { - assert.strictEqual(client.isConnected(), true) - await client.disconnect() - assert.strictEqual(client.isConnected(), false) - } -} + "disconnect & isConnected": async (client, address) => { + assert.strictEqual(client.isConnected(), true); + await client.disconnect(); + assert.strictEqual(client.isConnected(), false); + }, +}; diff --git a/test/client/isValidAddress.ts b/test/client/isValidAddress.ts index 81a640e1..68992e7c 100644 --- a/test/client/isValidAddress.ts +++ b/test/client/isValidAddress.ts @@ -1,17 +1,18 @@ -import assert from 'assert-diff' -import {TestSuite} from '../testUtils' -import addresses from '../fixtures/addresses.json' +import assert from "assert-diff"; + +import addresses from "../fixtures/addresses.json"; +import { TestSuite } from "../testUtils"; export default { - 'returns true for valid address': async (client, address) => { - assert(client.isValidAddress('rLczgQHxPhWtjkaQqn3Q6UM8AbRbbRvs5K')) - assert(client.isValidAddress(addresses.ACCOUNT_X)) - assert(client.isValidAddress(addresses.ACCOUNT_T)) + "returns true for valid address": async (client, address) => { + assert(client.isValidAddress("rLczgQHxPhWtjkaQqn3Q6UM8AbRbbRvs5K")); + assert(client.isValidAddress(addresses.ACCOUNT_X)); + assert(client.isValidAddress(addresses.ACCOUNT_T)); }, - 'returns false for invalid address': async (client, address) => { - assert(!client.isValidAddress('foobar')) - assert(!client.isValidAddress(addresses.ACCOUNT_X.slice(0, -1))) - assert(!client.isValidAddress(addresses.ACCOUNT_T.slice(1))) - } -} + "returns false for invalid address": async (client, address) => { + assert(!client.isValidAddress("foobar")); + assert(!client.isValidAddress(addresses.ACCOUNT_X.slice(0, -1))); + assert(!client.isValidAddress(addresses.ACCOUNT_T.slice(1))); + }, +}; diff --git a/test/client/isValidSecret.ts b/test/client/isValidSecret.ts index 77e990da..7a9faa09 100644 --- a/test/client/isValidSecret.ts +++ b/test/client/isValidSecret.ts @@ -1,12 +1,13 @@ -import assert from 'assert-diff' -import {TestSuite} from '../testUtils' +import assert from "assert-diff"; + +import { TestSuite } from "../testUtils"; export default { - 'returns true for valid secret': async (client, address) => { - assert(client.isValidSecret('snsakdSrZSLkYpCXxfRkS4Sh96PMK')) + "returns true for valid secret": async (client, address) => { + assert(client.isValidSecret("snsakdSrZSLkYpCXxfRkS4Sh96PMK")); }, - 'returns false for invalid secret': async (client, address) => { - assert(!client.isValidSecret('foobar')) - } -} + "returns false for invalid secret": async (client, address) => { + assert(!client.isValidSecret("foobar")); + }, +}; diff --git a/test/client/prepareCheckCancel.ts b/test/client/prepareCheckCancel.ts index 348041ee..4edb542c 100644 --- a/test/client/prepareCheckCancel.ts +++ b/test/client/prepareCheckCancel.ts @@ -1,8 +1,9 @@ -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; /** * Every test suite exports their tests in the default object. @@ -10,33 +11,51 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'prepareCheckCancel': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async prepareCheckCancel(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareCheckCancel( address, requests.prepareCheckCancel.normal - ) - assertResultMatch(result, responses.prepareCheckCancel.normal, 'prepare') + ); + assertResultMatch(result, responses.prepareCheckCancel.normal, "prepare"); }, - 'with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "with ticket": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - ticketSequence: 23 - } + maxFee: "0.000012", + ticketSequence: 23, + }; const result = await client.prepareCheckCancel( address, requests.prepareCheckCancel.normal, localInstructions - ) - assertResultMatch(result, responses.prepareCheckCancel.ticket, 'prepare') - } -} + ); + assertResultMatch(result, responses.prepareCheckCancel.ticket, "prepare"); + }, +}; diff --git a/test/client/prepareCheckCash.ts b/test/client/prepareCheckCash.ts index 8ce486fd..f757a08e 100644 --- a/test/client/prepareCheckCash.ts +++ b/test/client/prepareCheckCash.ts @@ -1,8 +1,9 @@ -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; /** * Every test suite exports their tests in the default object. @@ -10,45 +11,72 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'prepareCheckCash amount': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "prepareCheckCash amount": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareCheckCash( address, requests.prepareCheckCash.amount - ) - assertResultMatch(result, responses.prepareCheckCash.amount, 'prepare') + ); + assertResultMatch(result, responses.prepareCheckCash.amount, "prepare"); }, - 'prepareCheckCash deliverMin': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "prepareCheckCash deliverMin": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareCheckCash( address, requests.prepareCheckCash.deliverMin - ) - assertResultMatch(result, responses.prepareCheckCash.deliverMin, 'prepare') + ); + assertResultMatch(result, responses.prepareCheckCash.deliverMin, "prepare"); }, - 'with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "with ticket": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - ticketSequence: 23 - } + maxFee: "0.000012", + ticketSequence: 23, + }; const result = await client.prepareCheckCash( address, requests.prepareCheckCash.amount, localInstructions - ) - assertResultMatch(result, responses.prepareCheckCash.ticket, 'prepare') - } -} + ); + assertResultMatch(result, responses.prepareCheckCash.ticket, "prepare"); + }, +}; diff --git a/test/client/prepareCheckCreate.ts b/test/client/prepareCheckCreate.ts index 44a750cd..9c533702 100644 --- a/test/client/prepareCheckCreate.ts +++ b/test/client/prepareCheckCreate.ts @@ -1,8 +1,9 @@ -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; /** * Every test suite exports their tests in the default object. @@ -10,50 +11,77 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'prepareCheckCreate': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async prepareCheckCreate(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const result = await client.prepareCheckCreate( address, requests.prepareCheckCreate.normal, localInstructions - ) - assertResultMatch(result, responses.prepareCheckCreate.normal, 'prepare') + ); + assertResultMatch(result, responses.prepareCheckCreate.normal, "prepare"); }, - 'prepareCheckCreate full': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "prepareCheckCreate full": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareCheckCreate( address, requests.prepareCheckCreate.full - ) - assertResultMatch(result, responses.prepareCheckCreate.full, 'prepare') + ); + assertResultMatch(result, responses.prepareCheckCreate.full, "prepare"); }, - 'prepareCheckCreate with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "prepareCheckCreate with ticket": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - ticketSequence: 23 - } + maxFee: "0.000012", + ticketSequence: 23, + }; const result = await client.prepareCheckCreate( address, requests.prepareCheckCreate.normal, localInstructions - ) - assertResultMatch(result, responses.prepareCheckCreate.ticket, 'prepare') - } -} + ); + assertResultMatch(result, responses.prepareCheckCreate.ticket, "prepare"); + }, +}; diff --git a/test/client/prepareEscrowCancellation.ts b/test/client/prepareEscrowCancellation.ts index 92767534..30862786 100644 --- a/test/client/prepareEscrowCancellation.ts +++ b/test/client/prepareEscrowCancellation.ts @@ -1,8 +1,9 @@ -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; /** * Every test suite exports their tests in the default object. @@ -10,58 +11,89 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'prepareEscrowCancellation': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async prepareEscrowCancellation(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareEscrowCancellation( address, requests.prepareEscrowCancellation.normal, instructionsWithMaxLedgerVersionOffset - ) + ); assertResultMatch( result, responses.prepareEscrowCancellation.normal, - 'prepare' - ) + "prepare" + ); }, - 'prepareEscrowCancellation with memos': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "prepareEscrowCancellation with memos": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareEscrowCancellation( address, requests.prepareEscrowCancellation.memos - ) + ); assertResultMatch( result, responses.prepareEscrowCancellation.memos, - 'prepare' - ) + "prepare" + ); }, - 'with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "with ticket": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - ticketSequence: 23 - } + maxFee: "0.000012", + ticketSequence: 23, + }; const result = await client.prepareEscrowCancellation( address, requests.prepareEscrowCancellation.normal, localInstructions - ) + ); assertResultMatch( result, responses.prepareEscrowCancellation.ticket, - 'prepare' - ) - } -} + "prepare" + ); + }, +}; diff --git a/test/client/prepareEscrowCreation.ts b/test/client/prepareEscrowCreation.ts index 137e6658..0af7f3d3 100644 --- a/test/client/prepareEscrowCreation.ts +++ b/test/client/prepareEscrowCreation.ts @@ -1,15 +1,16 @@ -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {assertRejects, assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertRejects, assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; export const config = { // TODO: The mock server right now returns a hard-coded string, no matter // what "Account" value you pass. We'll need it to support more accurate // responses before we can turn these tests on. - skipXAddress: true -} + skipXAddress: true, +}; /** * Every test suite exports their tests in the default object. @@ -17,64 +18,108 @@ export const config = { * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'prepareEscrowCreation': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async prepareEscrowCreation(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const result = await client.prepareEscrowCreation( address, requests.prepareEscrowCreation.normal, localInstructions - ) - assertResultMatch(result, responses.prepareEscrowCreation.normal, 'prepare') + ); + assertResultMatch( + result, + responses.prepareEscrowCreation.normal, + "prepare" + ); }, - 'prepareEscrowCreation full': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "prepareEscrowCreation full": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareEscrowCreation( address, requests.prepareEscrowCreation.full - ) - assertResultMatch(result, responses.prepareEscrowCreation.full, 'prepare') + ); + assertResultMatch(result, responses.prepareEscrowCreation.full, "prepare"); }, - 'prepareEscrowCreation - invalid': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const escrow = Object.assign({}, requests.prepareEscrowCreation.full) - delete escrow.amount // Make invalid + "prepareEscrowCreation - invalid": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const escrow = { ...requests.prepareEscrowCreation.full }; + delete escrow.amount; // Make invalid await assertRejects( client.prepareEscrowCreation(address, escrow), client.errors.ValidationError, 'instance.escrowCreation requires property "amount"' - ) + ); }, - 'with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "with ticket": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000396', - ticketSequence: 23 - } + maxFee: "0.000396", + ticketSequence: 23, + }; const result = await client.prepareEscrowCreation( address, requests.prepareEscrowCreation.normal, localInstructions - ) - assertResultMatch(result, responses.prepareEscrowCreation.ticket, 'prepare') - } -} + ); + assertResultMatch( + result, + responses.prepareEscrowCreation.ticket, + "prepare" + ); + }, +}; diff --git a/test/client/prepareEscrowExecution.ts b/test/client/prepareEscrowExecution.ts index f8bf49d9..746e2a07 100644 --- a/test/client/prepareEscrowExecution.ts +++ b/test/client/prepareEscrowExecution.ts @@ -1,8 +1,9 @@ -import {TestSuite, assertRejects, assertResultMatch} from '../testUtils' -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { TestSuite, assertRejects, assertResultMatch } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; /** * Every test suite exports their tests in the default object. @@ -10,44 +11,75 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'prepareEscrowExecution': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async prepareEscrowExecution(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareEscrowExecution( address, requests.prepareEscrowExecution.normal, instructionsWithMaxLedgerVersionOffset - ) + ); assertResultMatch( result, responses.prepareEscrowExecution.normal, - 'prepare' - ) + "prepare" + ); }, - 'prepareEscrowExecution - simple': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "prepareEscrowExecution - simple": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareEscrowExecution( address, requests.prepareEscrowExecution.simple - ) + ); assertResultMatch( result, responses.prepareEscrowExecution.simple, - 'prepare' - ) + "prepare" + ); }, - 'prepareEscrowExecution - no condition': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "prepareEscrowExecution - no condition": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); await assertRejects( client.prepareEscrowExecution( address, @@ -56,14 +88,27 @@ export default { ), client.errors.ValidationError, '"condition" and "fulfillment" fields on EscrowFinish must only be specified together.' - ) + ); }, - 'prepareEscrowExecution - no fulfillment': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "prepareEscrowExecution - no fulfillment": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); await assertRejects( client.prepareEscrowExecution( address, @@ -72,28 +117,37 @@ export default { ), client.errors.ValidationError, '"condition" and "fulfillment" fields on EscrowFinish must only be specified together.' - ) + ); }, - 'with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "with ticket": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000396', - ticketSequence: 23 - } + maxFee: "0.000396", + ticketSequence: 23, + }; const result = await client.prepareEscrowExecution( address, requests.prepareEscrowExecution.normal, localInstructions - ) + ); assertResultMatch( result, responses.prepareEscrowExecution.ticket, - 'prepare' - ) - } -} + "prepare" + ); + }, +}; diff --git a/test/client/prepareOrder.ts b/test/client/prepareOrder.ts index bc1dd7d2..ccc353ff 100644 --- a/test/client/prepareOrder.ts +++ b/test/client/prepareOrder.ts @@ -1,8 +1,9 @@ -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {assertRejects, assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertRejects, assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; /** * Every test suite exports their tests in the default object. @@ -10,52 +11,88 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'buy order': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const request = requests.prepareOrder.buy - const result = await client.prepareOrder(address, request) - assertResultMatch(result, responses.prepareOrder.buy, 'prepare') + "buy order": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const request = requests.prepareOrder.buy; + const result = await client.prepareOrder(address, request); + assertResultMatch(result, responses.prepareOrder.buy, "prepare"); }, - 'buy order with expiration': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const request = requests.prepareOrder.expiration - const response = responses.prepareOrder.expiration + "buy order with expiration": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const request = requests.prepareOrder.expiration; + const response = responses.prepareOrder.expiration; const result = await client.prepareOrder( address, request, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(result, response, 'prepare') + ); + assertResultMatch(result, response, "prepare"); }, - 'sell order': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const request = requests.prepareOrder.sell + "sell order": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const request = requests.prepareOrder.sell; const result = await client.prepareOrder( address, request, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(result, responses.prepareOrder.sell, 'prepare') + ); + assertResultMatch(result, responses.prepareOrder.sell, "prepare"); }, - 'invalid': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const request = Object.assign({}, requests.prepareOrder.sell) - delete request.direction // Make invalid + async invalid(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const request = { ...requests.prepareOrder.sell }; + delete request.direction; // Make invalid await assertRejects( client.prepareOrder( address, @@ -64,21 +101,34 @@ export default { ), client.errors.ValidationError, 'instance.order requires property "direction"' - ) + ); }, - 'with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const request = requests.prepareOrder.sell + "with ticket": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const request = requests.prepareOrder.sell; const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - ticketSequence: 23 - } - const result = await client.prepareOrder(address, request, localInstructions) - assertResultMatch(result, responses.prepareOrder.ticket, 'prepare') - } -} + maxFee: "0.000012", + ticketSequence: 23, + }; + const result = await client.prepareOrder( + address, + request, + localInstructions + ); + assertResultMatch(result, responses.prepareOrder.ticket, "prepare"); + }, +}; diff --git a/test/client/prepareOrderCancellation.ts b/test/client/prepareOrderCancellation.ts index 5ae7cb74..3c8ec854 100644 --- a/test/client/prepareOrderCancellation.ts +++ b/test/client/prepareOrderCancellation.ts @@ -1,8 +1,9 @@ -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {assertRejects, assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertRejects, assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; /** * Every test suite exports their tests in the default object. @@ -10,90 +11,134 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'prepareOrderCancellation': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const request = requests.prepareOrderCancellation.simple + async prepareOrderCancellation(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const request = requests.prepareOrderCancellation.simple; const result = await client.prepareOrderCancellation( address, request, instructionsWithMaxLedgerVersionOffset - ) + ); assertResultMatch( result, responses.prepareOrderCancellation.normal, - 'prepare' - ) + "prepare" + ); }, - 'no instructions': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const request = requests.prepareOrderCancellation.simple - const result = await client.prepareOrderCancellation(address, request) + "no instructions": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const request = requests.prepareOrderCancellation.simple; + const result = await client.prepareOrderCancellation(address, request); assertResultMatch( result, responses.prepareOrderCancellation.noInstructions, - 'prepare' - ) + "prepare" + ); }, - 'with memos': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const request = requests.prepareOrderCancellation.withMemos - const result = await client.prepareOrderCancellation(address, request) + "with memos": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const request = requests.prepareOrderCancellation.withMemos; + const result = await client.prepareOrderCancellation(address, request); assertResultMatch( result, responses.prepareOrderCancellation.withMemos, - 'prepare' - ) + "prepare" + ); }, - 'invalid': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const request = Object.assign( - {}, - requests.prepareOrderCancellation.withMemos - ) - delete request.orderSequence // Make invalid + async invalid(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const request = { + ...requests.prepareOrderCancellation.withMemos, + }; + delete request.orderSequence; // Make invalid await assertRejects( client.prepareOrderCancellation(address, request), client.errors.ValidationError, 'instance.orderCancellation requires property "orderSequence"' - ) + ); }, - 'with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const request = requests.prepareOrderCancellation.simple + "with ticket": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const request = requests.prepareOrderCancellation.simple; const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - ticketSequence: 23 - } + maxFee: "0.000012", + ticketSequence: 23, + }; const result = await client.prepareOrderCancellation( address, request, localInstructions - ) + ); assertResultMatch( result, responses.prepareOrderCancellation.ticket, - 'prepare' - ) - } -} + "prepare" + ); + }, +}; diff --git a/test/client/preparePayment.ts b/test/client/preparePayment.ts index 12194ae8..e950ae8c 100644 --- a/test/client/preparePayment.ts +++ b/test/client/preparePayment.ts @@ -1,16 +1,13 @@ -import {assertResultMatch, TestSuite, assertRejects} from '../testUtils' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import requests from '../fixtures/requests' -import {ValidationError} from 'xrpl-local/common/errors' -import binary from 'ripple-binary-codec' -import assert from 'assert-diff' -import * as schemaValidator from 'xrpl-local/common/schema-validator' +import { ValidationError } from "../../src/common/errors"; +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertRejects, assertResultMatch, TestSuite } from "../testUtils"; -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} -const {preparePayment: REQUEST_FIXTURES} = requests -const {preparePayment: RESPONSE_FIXTURES} = responses -const RECIPIENT_ADDRESS = 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; +const { preparePayment: REQUEST_FIXTURES } = requests; +const { preparePayment: RESPONSE_FIXTURES } = responses; +const RECIPIENT_ADDRESS = "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo"; /** * Every test suite exports their tests in the default object. @@ -18,311 +15,445 @@ const RECIPIENT_ADDRESS = 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'normal': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async normal(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const response = await client.preparePayment( address, REQUEST_FIXTURES.normal, localInstructions - ) - assertResultMatch(response, RESPONSE_FIXTURES.normal, 'prepare') + ); + assertResultMatch(response, RESPONSE_FIXTURES.normal, "prepare"); }, - 'min amount xrp': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "min amount xrp": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const response = await client.preparePayment( address, REQUEST_FIXTURES.minAmountXRP, localInstructions - ) - assertResultMatch(response, RESPONSE_FIXTURES.minAmountXRP, 'prepare') + ); + assertResultMatch(response, RESPONSE_FIXTURES.minAmountXRP, "prepare"); }, - 'min amount xrp2xrp': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "min amount xrp2xrp": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const response = await client.preparePayment( address, REQUEST_FIXTURES.minAmount, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, RESPONSE_FIXTURES.minAmountXRPXRP, 'prepare') + ); + assertResultMatch(response, RESPONSE_FIXTURES.minAmountXRPXRP, "prepare"); }, - 'XRP to XRP': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "XRP to XRP": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const payment = { source: { - address: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', - maxAmount: {value: '1', currency: 'XRP'} + address: "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + maxAmount: { value: "1", currency: "XRP" }, }, destination: { - address: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - amount: {value: '1', currency: 'XRP'} - } - } + address: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + amount: { value: "1", currency: "XRP" }, + }, + }; const expected = { txJSON: '{"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":"1000000","Flags":2147483648,"LastLedgerSequence":8820051,"Sequence":23,"Fee":"12"}', instructions: { - fee: '0.000012', + fee: "0.000012", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; const response = await client.preparePayment( address, payment, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, expected, 'prepare') + ); + assertResultMatch(response, expected, "prepare"); }, - 'XRP drops to XRP drops': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "XRP drops to XRP drops": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const payment = { source: { - address: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', - maxAmount: {value: '1000000', currency: 'drops'} + address: "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + maxAmount: { value: "1000000", currency: "drops" }, }, destination: { - address: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - amount: {value: '1000000', currency: 'drops'} - } - } + address: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + amount: { value: "1000000", currency: "drops" }, + }, + }; const expected = { txJSON: '{"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":"1000000","Flags":2147483648,"LastLedgerSequence":8820051,"Sequence":23,"Fee":"12"}', instructions: { - fee: '0.000012', + fee: "0.000012", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; const response = await client.preparePayment( address, payment, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, expected, 'prepare') + ); + assertResultMatch(response, expected, "prepare"); }, - 'XRP drops to XRP': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "XRP drops to XRP": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const payment = { source: { - address: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', - maxAmount: {value: '1000000', currency: 'drops'} + address: "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + maxAmount: { value: "1000000", currency: "drops" }, }, destination: { - address: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - amount: {value: '1', currency: 'XRP'} - } - } + address: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + amount: { value: "1", currency: "XRP" }, + }, + }; const expected = { txJSON: '{"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":"1000000","Flags":2147483648,"LastLedgerSequence":8820051,"Sequence":23,"Fee":"12"}', instructions: { - fee: '0.000012', + fee: "0.000012", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; const response = await client.preparePayment( address, payment, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, expected, 'prepare') + ); + assertResultMatch(response, expected, "prepare"); }, - 'XRP to XRP drops': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "XRP to XRP drops": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const payment = { source: { - address: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', - maxAmount: {value: '1', currency: 'XRP'} + address: "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + maxAmount: { value: "1", currency: "XRP" }, }, destination: { - address: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - amount: {value: '1000000', currency: 'drops'} - } - } + address: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + amount: { value: "1000000", currency: "drops" }, + }, + }; const expected = { txJSON: '{"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":"1000000","Flags":2147483648,"LastLedgerSequence":8820051,"Sequence":23,"Fee":"12"}', instructions: { - fee: '0.000012', + fee: "0.000012", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; const response = await client.preparePayment( address, payment, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, expected, 'prepare') + ); + assertResultMatch(response, expected, "prepare"); }, // Errors - 'rejects promise and does not throw when payment object is invalid': async ( + "rejects promise and does not throw when payment object is invalid": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const payment = { source: { - address: address, + address, // instead of `maxAmount` - amount: {value: '1000', currency: 'drops'} + amount: { value: "1000", currency: "drops" }, }, destination: { address: RECIPIENT_ADDRESS, - amount: {value: '1000', currency: 'drops'} - } - } + amount: { value: "1000", currency: "drops" }, + }, + }; return assertRejects( client.preparePayment(address, payment), ValidationError, - 'payment must specify either (source.maxAmount and destination.amount) or (source.amount and destination.minAmount)' - ) + "payment must specify either (source.maxAmount and destination.amount) or (source.amount and destination.minAmount)" + ); }, - 'rejects promise and does not throw when field is missing': async ( + "rejects promise and does not throw when field is missing": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); // Marking as "any" to get around the fact that TS won't allow this. const payment: any = { - source: {address: address}, + source: { address }, destination: { address: RECIPIENT_ADDRESS, - amount: {value: '1000', currency: 'drops'} - } - } + amount: { value: "1000", currency: "drops" }, + }, + }; return assertRejects( client.preparePayment(address, payment), ValidationError, - 'instance.payment.source is not exactly one from ,' - ) + "instance.payment.source is not exactly one from ," + ); }, - 'rejects promise and does not throw when fee exceeds maxFeeXRP': async ( + "rejects promise and does not throw when fee exceeds maxFeeXRP": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const payment = { source: { - address: address, - maxAmount: {value: '1000', currency: 'drops'} + address, + maxAmount: { value: "1000", currency: "drops" }, }, destination: { address: RECIPIENT_ADDRESS, - amount: {value: '1000', currency: 'drops'} - } - } + amount: { value: "1000", currency: "drops" }, + }, + }; return assertRejects( - client.preparePayment(address, payment, {fee: '3'}), + client.preparePayment(address, payment, { fee: "3" }), ValidationError, - 'Fee of 3 XRP exceeds max of 2 XRP. To use this fee, increase `maxFeeXRP` in the Client constructor.' - ) + "Fee of 3 XRP exceeds max of 2 XRP. To use this fee, increase `maxFeeXRP` in the Client constructor." + ); }, - 'XRP to XRP no partial': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "XRP to XRP no partial": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); return assertRejects( client.preparePayment(address, REQUEST_FIXTURES.wrongPartial), ValidationError, - 'XRP to XRP payments cannot be partial payments' - ) + "XRP to XRP payments cannot be partial payments" + ); }, - 'address must match payment.source.address': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "address must match payment.source.address": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); return assertRejects( client.preparePayment(address, REQUEST_FIXTURES.wrongAddress), ValidationError, - 'address must match payment.source.address' - ) + "address must match payment.source.address" + ); }, - 'wrong amount': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "wrong amount": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); return assertRejects( client.preparePayment(address, REQUEST_FIXTURES.wrongAmount), ValidationError, - 'payment must specify either (source.maxAmount and destination.amount) or (source.amount and destination.minAmount)' - ) + "payment must specify either (source.maxAmount and destination.amount) or (source.amount and destination.minAmount)" + ); }, - 'throws when fee exceeds 2 XRP': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "throws when fee exceeds 2 XRP": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - fee: '2.1' - } + fee: "2.1", + }; return assertRejects( - client.preparePayment(address, REQUEST_FIXTURES.normal, localInstructions), + client.preparePayment( + address, + REQUEST_FIXTURES.normal, + localInstructions + ), ValidationError, - 'Fee of 2.1 XRP exceeds max of 2 XRP. To use this fee, increase `maxFeeXRP` in the Client constructor.' - ) + "Fee of 2.1 XRP exceeds max of 2 XRP. To use this fee, increase `maxFeeXRP` in the Client constructor." + ); }, // 'preparePayment with all options specified': async (client, address) => { @@ -340,228 +471,291 @@ export default { // assertResultMatch(response, RESPONSE_FIXTURES.allOptions, 'prepare') // }, - 'preparePayment without counterparty set': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "preparePayment without counterparty set": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - sequence: 23 - } + sequence: 23, + }; const response = await client.preparePayment( address, REQUEST_FIXTURES.noCounterparty, localInstructions - ) - assertResultMatch(response, RESPONSE_FIXTURES.noCounterparty, 'prepare') + ); + assertResultMatch(response, RESPONSE_FIXTURES.noCounterparty, "prepare"); }, - 'preparePayment with source.amount/destination.minAmount can be signed': async ( - client, - address, - mockRippled - ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - // See also: 'sign succeeds with source.amount/destination.minAmount' + // 'preparePayment with source.amount/destination.minAmount can be signed': + // async (client, address, mockRippled) => { + // mockRippled.addResponse( + // {command: 'server_info'}, + // rippled.server_info.normal + // ) + // mockRippled.addResponse({command: 'fee'}, rippled.fee) + // mockRippled.addResponse( + // {command: 'ledger_current'}, + // rippled.ledger_current + // ) + // mockRippled.addResponse( + // {command: 'account_info'}, + // rippled.account_info.normal + // ) + // // See also: 'sign succeeds with source.amount/destination.minAmount' - const localInstructions = { - ...instructionsWithMaxLedgerVersionOffset, - sequence: 23 - } - const response = await client.preparePayment( - address, - { - source: { - address, - amount: { - currency: 'GBP', - value: '0.1', - counterparty: 'rpat5TmYjDsnFSStmgTumFgXCM9eqsWPro' - } - }, - destination: { - address: 'rEX4LtGJubaUcMWCJULcy4NVxGT9ZEMVRq', - minAmount: { - currency: 'USD', - value: '0.1248548562296331', - counterparty: 'rMaa8VLBTjwTJWA2kSme4Sqgphhr6Lr6FH' - } - } - }, - localInstructions - ) + // const localInstructions = { + // ...instructionsWithMaxLedgerVersionOffset, + // sequence: 23 + // } - // Important: check that the prepared transaction can actually be signed - // https://github.com/ripple/ripple-lib/issues/1237#issuecomment-631670946 + // const response = await client.preparePayment(address, { + // source: { + // address, + // amount: { + // currency: 'GBP', + // value: '0.1', + // counterparty: 'rpat5TmYjDsnFSStmgTumFgXCM9eqsWPro' + // } + // }, + // localInstructions + // }) - const secret = 'shotKgaEotpcYsshSE39vmSnBDRim' - const result = client.sign(response.txJSON, secret) - const expectedResult = { - signedTransaction: - '12000022800200002400000017201B0086955361EC6386F26FC0FFFF0000000000000000000000005553440000000000DC596C88BCDE4E818D416FCDEEBF2C8656BADC9A68400000000000000C69D4438D7EA4C6800000000000000000000000000047425000000000000C155FFE99C8C91F67083CEFFDB69EBFE76348CA6AD4446F8C5D8A5E0B0000000000000000000000005553440000000000DC596C88BCDE4E818D416FCDEEBF2C8656BADC9A7321022B05847086686F9D0499B13136B94AD4323EE1B67D4C429ECC987AB35ACFA34574473045022100D9634523D8E232D4A7807A71856023D82AC928FA29848571B820867898413B5F022041AC00EC1F81A26A6504EBF844A38CC3204694EF2CC1A97A87632721631F93DA81145E7B112523F68D2F5E879DB4EAC51C6698A6930483149F500E50C2F016CA01945E5A1E5846B61EF2D376', - id: '1C558AA9B926C24FB6BBD6950B2DB1350A83F9F12E4385208867907019761A2D' - } - const decoded = binary.decode(result.signedTransaction) - assert( - decoded.Flags === 2147614720, - `Flags = ${decoded.Flags}, should be 2147614720` - ) - assert.deepEqual(result, expectedResult) - schemaValidator.schemaValidate('sign', result) - }, + // // Important: check that the prepared transaction can actually be signed + // // https://github.com/ripple/ripple-lib/issues/1237#issuecomment-631670946 - 'destination.minAmount': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + // const secret = 'shotKgaEotpcYsshSE39vmSnBDRim' + // const result = client.sign(response.txJSON, secret) + // const expectedResult = { + // signedTransaction: + // '12000022800200002400000017201B0086955361EC6386F26FC0FFFF0000000000000000000000005553440000000000DC596C88BCDE4E818D416FCDEEBF2C8656BADC9A68400000000000000C69D4438D7EA4C6800000000000000000000000000047425000000000000C155FFE99C8C91F67083CEFFDB69EBFE76348CA6AD4446F8C5D8A5E0B0000000000000000000000005553440000000000DC596C88BCDE4E818D416FCDEEBF2C8656BADC9A7321022B05847086686F9D0499B13136B94AD4323EE1B67D4C429ECC987AB35ACFA34574473045022100D9634523D8E232D4A7807A71856023D82AC928FA29848571B820867898413B5F022041AC00EC1F81A26A6504EBF844A38CC3204694EF2CC1A97A87632721631F93DA81145E7B112523F68D2F5E879DB4EAC51C6698A6930483149F500E50C2F016CA01945E5A1E5846B61EF2D376', + // id: '1C558AA9B926C24FB6BBD6950B2DB1350A83F9F12E4385208867907019761A2D' + // } + // const decoded = decode(result.signedTransaction) + // assert( + // decoded.Flags === 2147614720, + // `Flags = ${decoded.Flags}, should be 2147614720` + // ) + // assert.deepEqual(result, expectedResult) + // schemaValidator.schemaValidate('sign', result) + // }, + + "destination.minAmount": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const response = await client.preparePayment( address, responses.getPaths.sendAll[0], instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, RESPONSE_FIXTURES.minAmount, 'prepare') + ); + assertResultMatch(response, RESPONSE_FIXTURES.minAmount, "prepare"); }, - 'caps fee at 2 XRP by default': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - client._feeCushion = 1000000 + "caps fee at 2 XRP by default": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + client._feeCushion = 1000000; const expectedResponse = { txJSON: '{"Flags":2147483648,"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"SendMax":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"LastLedgerSequence":8820051,"Fee":"2000000","Sequence":23}', instructions: { - fee: '2', + fee: "2", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; const response = await client.preparePayment( address, REQUEST_FIXTURES.normal, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, expectedResponse, 'prepare') + ); + assertResultMatch(response, expectedResponse, "prepare"); }, - 'allows fee exceeding 2 XRP when maxFeeXRP is higher': async ( + "allows fee exceeding 2 XRP when maxFeeXRP is higher": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - client._maxFeeXRP = '2.2' + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + client._maxFeeXRP = "2.2"; const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - fee: '2.1' - } + fee: "2.1", + }; const expectedResponse = { txJSON: '{"Flags":2147483648,"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"SendMax":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"LastLedgerSequence":8820051,"Fee":"2100000","Sequence":23}', instructions: { - fee: '2.1', + fee: "2.1", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; const response = await client.preparePayment( address, REQUEST_FIXTURES.normal, localInstructions - ) - assertResultMatch(response, expectedResponse, 'prepare') + ); + assertResultMatch(response, expectedResponse, "prepare"); }, - 'fee - default maxFee of 2 XRP': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - client._feeCushion = 1000000 + "fee - default maxFee of 2 XRP": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + client._feeCushion = 1000000; const expectedResponse = { txJSON: '{"Flags":2147483648,"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"SendMax":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"LastLedgerSequence":8820051,"Fee":"2000000","Sequence":23}', instructions: { - fee: '2', + fee: "2", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; const response = await client.preparePayment( address, requests.preparePayment.normal, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, expectedResponse, 'prepare') + ); + assertResultMatch(response, expectedResponse, "prepare"); }, - 'fee - capped to maxFeeXRP when maxFee exceeds maxFeeXRP': async ( + "fee - capped to maxFeeXRP when maxFee exceeds maxFeeXRP": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - client._feeCushion = 1000000 - client._maxFeeXRP = '3' + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + client._feeCushion = 1000000; + client._maxFeeXRP = "3"; const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '4' - } + maxFee: "4", + }; const expectedResponse = { txJSON: '{"Flags":2147483648,"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"SendMax":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"LastLedgerSequence":8820051,"Fee":"3000000","Sequence":23}', instructions: { - fee: '3', + fee: "3", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; const response = await client.preparePayment( address, requests.preparePayment.normal, localInstructions - ) - assertResultMatch(response, expectedResponse, 'prepare') + ); + assertResultMatch(response, expectedResponse, "prepare"); }, - 'fee - capped to maxFee': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - client._feeCushion = 1000000 - client._maxFeeXRP = '5' + "fee - capped to maxFee": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + client._feeCushion = 1000000; + client._maxFeeXRP = "5"; const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '4' - } + maxFee: "4", + }; const expectedResponse = { txJSON: '{"Flags":2147483648,"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"SendMax":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"LastLedgerSequence":8820051,"Fee":"4000000","Sequence":23}', instructions: { - fee: '4', + fee: "4", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; const response = await client.preparePayment( address, requests.preparePayment.normal, localInstructions - ) - assertResultMatch(response, expectedResponse, 'prepare') + ); + assertResultMatch(response, expectedResponse, "prepare"); }, // 'fee - calculated fee does not use more than 6 decimal places': async ( @@ -592,7 +786,7 @@ export default { // Tickets // 'preparePayment with ticketSequence': async (client, address) => { // const ledgerResponse = await client.request({ - // command: 'ledger', + // command: 'ledger', // ledger_index: 'validated' // }) // const version = ledgerResponse.result.ledger_index @@ -614,7 +808,7 @@ export default { // address // ) => { // const ledgerResponse = await client.request({ - // command: 'ledger', + // command: 'ledger', // ledger_index: 'validated' // }) // const version = ledgerResponse.result.ledger_index @@ -634,4 +828,4 @@ export default { // 'instance.instructions is of prohibited type [object Object]' // ) // } -} +}; diff --git a/test/client/preparePaymentChannelClaim.ts b/test/client/preparePaymentChannelClaim.ts index 7391be76..d53bc1ad 100644 --- a/test/client/preparePaymentChannelClaim.ts +++ b/test/client/preparePaymentChannelClaim.ts @@ -1,11 +1,13 @@ -import assert from 'assert-diff' -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} -const {preparePaymentChannelClaim: REQUEST_FIXTURES} = requests -const {preparePaymentChannelClaim: RESPONSE_FIXTURES} = responses +import assert from "assert-diff"; + +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; +const { preparePaymentChannelClaim: REQUEST_FIXTURES } = requests; +const { preparePaymentChannelClaim: RESPONSE_FIXTURES } = responses; /** * Every test suite exports their tests in the default object. @@ -13,126 +15,182 @@ const {preparePaymentChannelClaim: RESPONSE_FIXTURES} = responses * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'default': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async default(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const response = await client.preparePaymentChannelClaim( address, REQUEST_FIXTURES.normal, localInstructions - ) - assertResultMatch(response, RESPONSE_FIXTURES.normal, 'prepare') + ); + assertResultMatch(response, RESPONSE_FIXTURES.normal, "prepare"); }, - 'with renew': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "with renew": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const response = await client.preparePaymentChannelClaim( address, REQUEST_FIXTURES.renew, localInstructions - ) - assertResultMatch(response, RESPONSE_FIXTURES.renew, 'prepare') + ); + assertResultMatch(response, RESPONSE_FIXTURES.renew, "prepare"); }, - 'with close': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "with close": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const response = await client.preparePaymentChannelClaim( address, REQUEST_FIXTURES.close, localInstructions - ) - assertResultMatch(response, RESPONSE_FIXTURES.close, 'prepare') + ); + assertResultMatch(response, RESPONSE_FIXTURES.close, "prepare"); }, - 'with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "with ticket": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - ticketSequence: 23 - } + maxFee: "0.000012", + ticketSequence: 23, + }; const response = await client.preparePaymentChannelClaim( address, REQUEST_FIXTURES.normal, localInstructions - ) - assertResultMatch(response, RESPONSE_FIXTURES.ticket, 'prepare') + ); + assertResultMatch(response, RESPONSE_FIXTURES.ticket, "prepare"); }, - 'rejects Promise on preparePaymentChannelClaim with renew and close': async ( + "rejects Promise on preparePaymentChannelClaim with renew and close": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); try { const prepared = await client.preparePaymentChannelClaim( address, REQUEST_FIXTURES.full - ) + ); throw new Error( - 'Expected method to reject. Prepared transaction: ' + - JSON.stringify(prepared) - ) + `Expected method to reject. Prepared transaction: ${JSON.stringify( + prepared + )}` + ); } catch (err) { - assert.strictEqual(err.name, 'ValidationError') + assert.strictEqual(err.name, "ValidationError"); assert.strictEqual( err.message, '"renew" and "close" flags on PaymentChannelClaim are mutually exclusive' - ) + ); } }, - 'rejects Promise on preparePaymentChannelClaim with no signature': async ( + "rejects Promise on preparePaymentChannelClaim with no signature": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); try { const prepared = await client.preparePaymentChannelClaim( address, REQUEST_FIXTURES.noSignature - ) + ); throw new Error( - 'Expected method to reject. Prepared transaction: ' + - JSON.stringify(prepared) - ) + `Expected method to reject. Prepared transaction: ${JSON.stringify( + prepared + )}` + ); } catch (err) { - assert.strictEqual(err.name, 'ValidationError') + assert.strictEqual(err.name, "ValidationError"); assert.strictEqual( err.message, '"signature" and "publicKey" fields on PaymentChannelClaim must only be specified together.' - ) + ); } - } -} + }, +}; diff --git a/test/client/preparePaymentChannelCreate.ts b/test/client/preparePaymentChannelCreate.ts index f892894a..e5d7b99a 100644 --- a/test/client/preparePaymentChannelCreate.ts +++ b/test/client/preparePaymentChannelCreate.ts @@ -1,15 +1,16 @@ -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; export const config = { // TODO: The mock server right now returns a hard-coded string, no matter // what "Account" value you pass. We'll need it to support more accurate // responses before we can turn these tests on. - skipXAddress: true -} + skipXAddress: true, +}; /** * Every test suite exports their tests in the default object. @@ -17,62 +18,93 @@ export const config = { * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'preparePaymentChannelCreate': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async preparePaymentChannelCreate(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const result = await client.preparePaymentChannelCreate( address, requests.preparePaymentChannelCreate.normal, localInstructions - ) + ); assertResultMatch( result, responses.preparePaymentChannelCreate.normal, - 'prepare' - ) + "prepare" + ); }, - 'preparePaymentChannelCreate full': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "preparePaymentChannelCreate full": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.preparePaymentChannelCreate( address, requests.preparePaymentChannelCreate.full - ) + ); assertResultMatch( result, responses.preparePaymentChannelCreate.full, - 'prepare' - ) + "prepare" + ); }, - 'preparePaymentChannelCreate with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "preparePaymentChannelCreate with ticket": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - ticketSequence: 23 - } + maxFee: "0.000012", + ticketSequence: 23, + }; const result = await client.preparePaymentChannelCreate( address, requests.preparePaymentChannelCreate.normal, localInstructions - ) + ); assertResultMatch( result, responses.preparePaymentChannelCreate.ticket, - 'prepare' - ) - } -} + "prepare" + ); + }, +}; diff --git a/test/client/preparePaymentChannelFund.ts b/test/client/preparePaymentChannelFund.ts index f6172d3e..8bedb5f3 100644 --- a/test/client/preparePaymentChannelFund.ts +++ b/test/client/preparePaymentChannelFund.ts @@ -1,8 +1,9 @@ -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; /** * Every test suite exports their tests in the default object. @@ -10,62 +11,89 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'preparePaymentChannelFund': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async preparePaymentChannelFund(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const result = await client.preparePaymentChannelFund( address, requests.preparePaymentChannelFund.normal, localInstructions - ) + ); assertResultMatch( result, responses.preparePaymentChannelFund.normal, - 'prepare' - ) + "prepare" + ); }, - 'preparePaymentChannelFund full': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "preparePaymentChannelFund full": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.preparePaymentChannelFund( address, requests.preparePaymentChannelFund.full - ) + ); assertResultMatch( result, responses.preparePaymentChannelFund.full, - 'prepare' - ) + "prepare" + ); }, - 'with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "with ticket": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - ticketSequence: 23 - } + maxFee: "0.000012", + ticketSequence: 23, + }; const result = await client.preparePaymentChannelFund( address, requests.preparePaymentChannelFund.normal, localInstructions - ) + ); assertResultMatch( result, responses.preparePaymentChannelFund.ticket, - 'prepare' - ) - } -} + "prepare" + ); + }, +}; diff --git a/test/client/prepareSettings.ts b/test/client/prepareSettings.ts index c69f8f3a..797de077 100644 --- a/test/client/prepareSettings.ts +++ b/test/client/prepareSettings.ts @@ -1,9 +1,12 @@ -import assert from 'assert-diff' -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import assert from "assert-diff"; + +import { FormattedSettings } from "../../src/common/types/objects"; +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; /** * Every test suite exports their tests in the default object. @@ -11,334 +14,513 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'simple test': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "simple test": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const response = await client.prepareSettings( address, requests.prepareSettings.domain, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, responses.prepareSettings.flags, 'prepare') + ); + assertResultMatch(response, responses.prepareSettings.flags, "prepare"); }, - 'no maxLedgerVersion': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "no maxLedgerVersion": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const response = await client.prepareSettings( address, requests.prepareSettings.domain, { - maxLedgerVersion: null + maxLedgerVersion: null as unknown as undefined, } - ) + ); assertResultMatch( response, responses.prepareSettings.noMaxLedgerVersion, - 'prepare' - ) + "prepare" + ); }, - 'no instructions': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "no instructions": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const response = await client.prepareSettings( address, requests.prepareSettings.domain - ) + ); assertResultMatch( response, responses.prepareSettings.noInstructions, - 'prepare' - ) + "prepare" + ); }, - 'regularKey': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const regularKey = {regularKey: 'rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD'} + async regularKey(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const regularKey = { regularKey: "rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD" }; const response = await client.prepareSettings( address, regularKey, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, responses.prepareSettings.regularKey, 'prepare') + ); + assertResultMatch( + response, + responses.prepareSettings.regularKey, + "prepare" + ); }, - 'remove regularKey': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const regularKey = {regularKey: null} + "remove regularKey": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const regularKey = { regularKey: null }; const response = await client.prepareSettings( address, - regularKey, + regularKey as unknown as FormattedSettings, instructionsWithMaxLedgerVersionOffset - ) + ); assertResultMatch( response, responses.prepareSettings.removeRegularKey, - 'prepare' - ) + "prepare" + ); }, - 'flag set': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const settings = {requireDestinationTag: true} + "flag set": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const settings = { requireDestinationTag: true }; const response = await client.prepareSettings( address, settings, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, responses.prepareSettings.flagSet, 'prepare') + ); + assertResultMatch(response, responses.prepareSettings.flagSet, "prepare"); }, - 'flag clear': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const settings = {requireDestinationTag: false} + "flag clear": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const settings = { requireDestinationTag: false }; const response = await client.prepareSettings( address, settings, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, responses.prepareSettings.flagClear, 'prepare') + ); + assertResultMatch(response, responses.prepareSettings.flagClear, "prepare"); }, - 'set depositAuth flag': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const settings = {depositAuth: true} + "set depositAuth flag": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const settings = { depositAuth: true }; const response = await client.prepareSettings( address, settings, instructionsWithMaxLedgerVersionOffset - ) + ); assertResultMatch( response, responses.prepareSettings.flagSetDepositAuth, - 'prepare' - ) + "prepare" + ); }, - 'clear depositAuth flag': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const settings = {depositAuth: false} + "clear depositAuth flag": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const settings = { depositAuth: false }; const response = await client.prepareSettings( address, settings, instructionsWithMaxLedgerVersionOffset - ) + ); assertResultMatch( response, responses.prepareSettings.flagClearDepositAuth, - 'prepare' - ) + "prepare" + ); }, - 'integer field clear': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const settings = {transferRate: null} + "integer field clear": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const settings = { transferRate: null }; const response = await client.prepareSettings( address, settings, instructionsWithMaxLedgerVersionOffset - ) - assert(response) - assert.strictEqual(JSON.parse(response.txJSON).TransferRate, 0) + ); + assert(response); + assert.strictEqual(JSON.parse(response.txJSON).TransferRate, 0); }, - 'set transferRate': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const settings = {transferRate: 1} + "set transferRate": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const settings = { transferRate: 1 }; const response = await client.prepareSettings( address, settings, instructionsWithMaxLedgerVersionOffset - ) + ); assertResultMatch( response, responses.prepareSettings.setTransferRate, - 'prepare' - ) + "prepare" + ); }, - 'set signers': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const settings = requests.prepareSettings.signers.normal + "set signers": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const settings = requests.prepareSettings.signers.normal; const response = await client.prepareSettings( address, settings, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(response, responses.prepareSettings.signers, 'prepare') + ); + assertResultMatch(response, responses.prepareSettings.signers, "prepare"); }, - 'signers no threshold': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const settings = requests.prepareSettings.signers.noThreshold + "signers no threshold": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const settings = requests.prepareSettings.signers.noThreshold; try { const response = await client.prepareSettings( address, settings, instructionsWithMaxLedgerVersionOffset - ) + ); throw new Error( - 'Expected method to reject. Prepared transaction: ' + - JSON.stringify(response) - ) + `Expected method to reject. Prepared transaction: ${JSON.stringify( + response + )}` + ); } catch (err) { assert.strictEqual( err.message, 'instance.settings.signers requires property "threshold"' - ) - assert.strictEqual(err.name, 'ValidationError') + ); + assert.strictEqual(err.name, "ValidationError"); } }, - 'signers no weights': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const settings = requests.prepareSettings.signers.noWeights + "signers no weights": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const settings = requests.prepareSettings.signers.noWeights; const localInstructions = { signersCount: 1, - ...instructionsWithMaxLedgerVersionOffset - } + ...instructionsWithMaxLedgerVersionOffset, + }; const response = await client.prepareSettings( address, settings, localInstructions - ) - assertResultMatch(response, responses.prepareSettings.noWeights, 'prepare') + ); + assertResultMatch(response, responses.prepareSettings.noWeights, "prepare"); }, - 'fee for multisign': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "fee for multisign": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { signersCount: 4, - ...instructionsWithMaxLedgerVersionOffset - } + ...instructionsWithMaxLedgerVersionOffset, + }; const response = await client.prepareSettings( address, requests.prepareSettings.domain, localInstructions - ) + ); assertResultMatch( response, responses.prepareSettings.flagsMultisign, - 'prepare' - ) + "prepare" + ); }, - 'no signer list': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const settings = requests.prepareSettings.noSignerEntries + "no signer list": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const settings = requests.prepareSettings.noSignerEntries; const localInstructions = { signersCount: 1, - ...instructionsWithMaxLedgerVersionOffset - } + ...instructionsWithMaxLedgerVersionOffset, + }; const response = await client.prepareSettings( address, settings, localInstructions - ) + ); assertResultMatch( response, responses.prepareSettings.noSignerList, - 'prepare' - ) + "prepare" + ); }, - 'invalid': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async invalid(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); // domain must be a string - const settings = Object.assign({}, requests.prepareSettings.domain, { - domain: 123 - }) + const settings = { ...requests.prepareSettings.domain, domain: 123 }; const localInstructions = { signersCount: 4, - ...instructionsWithMaxLedgerVersionOffset - } + ...instructionsWithMaxLedgerVersionOffset, + }; try { const response = await client.prepareSettings( address, settings, localInstructions - ) + ); throw new Error( - 'Expected method to reject. Prepared transaction: ' + - JSON.stringify(response) - ) + `Expected method to reject. Prepared transaction: ${JSON.stringify( + response + )}` + ); } catch (err) { assert.strictEqual( err.message, - 'instance.settings.domain is not of a type(s) string' - ) - assert.strictEqual(err.name, 'ValidationError') + "instance.settings.domain is not of a type(s) string" + ); + assert.strictEqual(err.name, "ValidationError"); } }, - 'offline': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' + async offline(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV"; - const settings = requests.prepareSettings.domain + const settings = requests.prepareSettings.domain; const instructions = { sequence: 23, maxLedgerVersion: 8820051, - fee: '0.000012' - } - const result = await client.prepareSettings(address, settings, instructions) - assertResultMatch(result, responses.prepareSettings.flags, 'prepare') + fee: "0.000012", + }; + const result = await client.prepareSettings( + address, + settings, + instructions + ); + assertResultMatch(result, responses.prepareSettings.flags, "prepare"); assert.deepEqual( client.sign(result.txJSON, secret), responses.prepareSettings.signed - ) + ); }, - 'prepare settings with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "prepare settings with ticket": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const instructions = { ticketSequence: 23, maxLedgerVersion: 8820051, - fee: '0.000012' - } + fee: "0.000012", + }; const response = await client.prepareSettings( address, requests.prepareSettings.domain, instructions - ) - assertResultMatch(response, responses.prepareSettings.ticket, 'prepare') - } -} + ); + assertResultMatch(response, responses.prepareSettings.ticket, "prepare"); + }, +}; diff --git a/test/client/prepareTicket.ts b/test/client/prepareTicket.ts index 58a4843e..0f619adc 100644 --- a/test/client/prepareTicket.ts +++ b/test/client/prepareTicket.ts @@ -1,6 +1,6 @@ -import {assertResultMatch, TestSuite} from '../testUtils' +import rippled from "../fixtures/rippled"; +import { assertResultMatch, TestSuite } from "../testUtils"; // import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' // import requests from '../fixtures/requests' // import {ValidationError} from 'xrpl-local/common/errors' // import binary from 'ripple-binary-codec' @@ -19,48 +19,70 @@ import rippled from '../fixtures/rippled' * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'creates a ticket successfully with a sequence number': async ( + "creates a ticket successfully with a sequence number": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const expected = { txJSON: '{"TransactionType":"TicketCreate", "TicketCount": 2, "Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Flags":2147483648,"LastLedgerSequence":8819954,"Sequence":23,"Fee":"12"}', instructions: { maxLedgerVersion: 8819954, sequence: 23, - fee: '0.000012' - } - } - const response = await client.prepareTicketCreate(address, 2) - assertResultMatch(response, expected, 'prepare') + fee: "0.000012", + }, + }; + const response = await client.prepareTicketCreate(address, 2); + assertResultMatch(response, expected, "prepare"); }, - 'creates a ticket successfully with another ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "creates a ticket successfully with another ticket": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const expected = { txJSON: '{"TransactionType":"TicketCreate", "TicketCount": 1, "Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Flags":2147483648,"LastLedgerSequence":8819954,"Sequence": 0,"TicketSequence":23,"Fee":"12"}', instructions: { maxLedgerVersion: 8819954, ticketSequence: 23, - fee: '0.000012' - } - } + fee: "0.000012", + }, + }; const instructions = { maxLedgerVersion: 8819954, ticketSequence: 23, - fee: '0.000012' - } - const response = await client.prepareTicketCreate(address, 1, instructions) - assertResultMatch(response, expected, 'prepare') - } -} + fee: "0.000012", + }; + const response = await client.prepareTicketCreate(address, 1, instructions); + assertResultMatch(response, expected, "prepare"); + }, +}; diff --git a/test/client/prepareTransaction.ts b/test/client/prepareTransaction.ts index 49f6d338..acf6102d 100644 --- a/test/client/prepareTransaction.ts +++ b/test/client/prepareTransaction.ts @@ -1,17 +1,19 @@ -import {ValidationError} from 'xrpl-local/common/errors' +import { ValidationError } from "xrpl-local/common/errors"; + // import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import {xrpToDrops, ISOTimeToRippleTime} from '../../src/utils' -import rippled from '../fixtures/rippled' -import {assertRejects, assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import { xrpToDrops, ISOTimeToRippleTime } from "../../src/utils"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertRejects, assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; export const config = { // TODO: The mock server right now returns a hard-coded string, no matter // what "Account" value you pass. We'll need it to support more accurate // responses before we can turn these tests on. - skipXAddress: true -} + skipXAddress: true, +}; /** * Every test suite exports their tests in the default object. @@ -19,679 +21,913 @@ export const config = { * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'auto-fillable fields - does not overwrite Fee in txJSON': async ( + "auto-fillable fields - does not overwrite Fee in txJSON": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = instructionsWithMaxLedgerVersionOffset + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = instructionsWithMaxLedgerVersionOffset; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Fee: '10' - } - const response = await client.prepareTransaction(txJSON, localInstructions) + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Fee: "10", + }; + const response = await client.prepareTransaction(txJSON, localInstructions); const expected = { txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"10","Sequence":23}`, instructions: { - fee: '0.00001', // Notice there are not always 6 digits after the decimal point as trailing zeros are omitted + fee: "0.00001", // Notice there are not always 6 digits after the decimal point as trailing zeros are omitted sequence: 23, - maxLedgerVersion: 8820051 - } - } - return assertResultMatch(response, expected, 'prepare') + maxLedgerVersion: 8820051, + }, + }; + return assertResultMatch(response, expected, "prepare"); }, - 'does not overwrite Fee in Instructions': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "does not overwrite Fee in Instructions": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - fee: '0.000014' // CAUTION: This `fee` is specified in XRP, not drops. - } + fee: "0.000014", // CAUTION: This `fee` is specified in XRP, not drops. + }; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } - const response = await client.prepareTransaction(txJSON, localInstructions) + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; + const response = await client.prepareTransaction(txJSON, localInstructions); const expected = { txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"14","Sequence":23}`, instructions: { - fee: '0.000014', + fee: "0.000014", sequence: 23, - maxLedgerVersion: 8820051 - } - } - return assertResultMatch(response, expected, 'prepare') + maxLedgerVersion: 8820051, + }, + }; + return assertResultMatch(response, expected, "prepare"); }, - 'rejects Promise if both are set, even when txJSON.Fee matches instructions.fee': async ( + "rejects Promise if both are set, even when txJSON.Fee matches instructions.fee": + async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = { + ...instructionsWithMaxLedgerVersionOffset, + fee: "0.000016", + }; + const txJSON = { + TransactionType: "DepositPreauth", + Account: address, + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Fee: "16", + }; + await assertRejects( + client.prepareTransaction(txJSON, localInstructions), + ValidationError, + "`Fee` in txJSON and `fee` in `instructions` cannot both be set" + ); + }, + + "rejects Promise if both are set, when txJSON.Fee does not match instructions.fee": + async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = { + ...instructionsWithMaxLedgerVersionOffset, + fee: "0.000018", + }; + const txJSON = { + TransactionType: "DepositPreauth", + Account: address, + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Fee: "20", + }; + await assertRejects( + client.prepareTransaction(txJSON, localInstructions), + ValidationError, + "`Fee` in txJSON and `fee` in `instructions` cannot both be set" + ); + }, + + "rejects Promise when the Fee is capitalized in Instructions": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - fee: '0.000016' - } + Fee: "0.000022", // Intentionally capitalized in this test, but the correct field would be `fee` + }; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Fee: '16' - } - await assertRejects( - client.prepareTransaction(txJSON, localInstructions), - ValidationError, - '`Fee` in txJSON and `fee` in `instructions` cannot both be set' - ) - }, - - 'rejects Promise if both are set, when txJSON.Fee does not match instructions.fee': async ( - client, - address, - mockRippled - ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = { - ...instructionsWithMaxLedgerVersionOffset, - fee: '0.000018' - } - const txJSON = { - TransactionType: 'DepositPreauth', - Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Fee: '20' - } - await assertRejects( - client.prepareTransaction(txJSON, localInstructions), - ValidationError, - '`Fee` in txJSON and `fee` in `instructions` cannot both be set' - ) - }, - - 'rejects Promise when the Fee is capitalized in Instructions': async ( - client, - address, - mockRippled - ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = { - ...instructionsWithMaxLedgerVersionOffset, - Fee: '0.000022' // Intentionally capitalized in this test, but the correct field would be `fee` - } - const txJSON = { - TransactionType: 'DepositPreauth', - Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, 'instance additionalProperty "Fee" exists in instance when not allowed' - ) + ); }, - 'rejects Promise when the fee is specified in txJSON': async ( + "rejects Promise when the fee is specified in txJSON": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = instructionsWithMaxLedgerVersionOffset + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = instructionsWithMaxLedgerVersionOffset; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - fee: '10' - } + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + fee: "10", + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, 'txJSON additionalProperty "fee" exists in instance when not allowed' - ) + ); }, - 'does not overwrite Sequence in txJSON': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = { - ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } - const txJSON = { - TransactionType: 'DepositPreauth', - Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Sequence: 100 - } - const response = await client.prepareTransaction(txJSON, localInstructions) - const expected = { - txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":100}`, - instructions: { - fee: '0.000012', - sequence: 100, - maxLedgerVersion: 8820051 - } - } - return assertResultMatch(response, expected, 'prepare') - }, - - 'does not overwrite Sequence in Instructions': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = { - ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - sequence: 100 - } - const txJSON = { - TransactionType: 'DepositPreauth', - Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } - const response = await client.prepareTransaction(txJSON, localInstructions) - const expected = { - txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":100}`, - instructions: { - fee: '0.000012', - sequence: 100, - maxLedgerVersion: 8820051 - } - } - return assertResultMatch(response, expected, 'prepare') - }, - - 'does not overwrite Sequence when same sequence is provided in both txJSON and Instructions': async ( + "does not overwrite Sequence in txJSON": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - sequence: 100 - } + maxFee: "0.000012", + }; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Sequence: 100 - } - const response = await client.prepareTransaction(txJSON, localInstructions) + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Sequence: 100, + }; + const response = await client.prepareTransaction(txJSON, localInstructions); const expected = { txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":100}`, instructions: { - fee: '0.000012', + fee: "0.000012", sequence: 100, - maxLedgerVersion: 8820051 - } - } - return assertResultMatch(response, expected, 'prepare') + maxLedgerVersion: 8820051, + }, + }; + return assertResultMatch(response, expected, "prepare"); }, - 'rejects Promise when Sequence in txJSON does not match sequence in Instructions': async ( + "does not overwrite Sequence in Instructions": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - sequence: 100 - } + maxFee: "0.000012", + sequence: 100, + }; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Sequence: 101 - } - await assertRejects( - client.prepareTransaction(txJSON, localInstructions), - ValidationError, - '`Sequence` in txJSON must match `sequence` in `instructions`' - ) + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; + const response = await client.prepareTransaction(txJSON, localInstructions); + const expected = { + txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":100}`, + instructions: { + fee: "0.000012", + sequence: 100, + maxLedgerVersion: 8820051, + }, + }; + return assertResultMatch(response, expected, "prepare"); }, - 'rejects Promise when the Sequence is capitalized in Instructions': async ( + "does not overwrite Sequence when same sequence is provided in both txJSON and Instructions": + async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = { + ...instructionsWithMaxLedgerVersionOffset, + maxFee: "0.000012", + sequence: 100, + }; + const txJSON = { + TransactionType: "DepositPreauth", + Account: address, + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; + const response = await client.prepareTransaction( + txJSON, + localInstructions + ); + const expected = { + txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":100}`, + instructions: { + fee: "0.000012", + sequence: 100, + maxLedgerVersion: 8820051, + }, + }; + return assertResultMatch(response, expected, "prepare"); + }, + + "rejects Promise when Sequence in txJSON does not match sequence in Instructions": + async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = { + ...instructionsWithMaxLedgerVersionOffset, + maxFee: "0.000012", + sequence: 100, + }; + const txJSON = { + TransactionType: "DepositPreauth", + Account: address, + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Sequence: 101, + }; + await assertRejects( + client.prepareTransaction(txJSON, localInstructions), + ValidationError, + "`Sequence` in txJSON must match `sequence` in `instructions`" + ); + }, + + "rejects Promise when the Sequence is capitalized in Instructions": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - Sequence: 100 // Intentionally capitalized in this test, but the correct field would be `sequence` - } + maxFee: "0.000012", + Sequence: 100, // Intentionally capitalized in this test, but the correct field would be `sequence` + }; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, 'instance additionalProperty "Sequence" exists in instance when not allowed' - ) + ); }, // LastLedgerSequence aka maxLedgerVersion/maxLedgerVersionOffset: - 'does not overwrite LastLedgerSequence in txJSON': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = {} + "does not overwrite LastLedgerSequence in txJSON": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = {}; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Fee: '10', - LastLedgerSequence: 8880000 - } - const response = await client.prepareTransaction(txJSON, localInstructions) + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Fee: "10", + LastLedgerSequence: 8880000, + }; + const response = await client.prepareTransaction(txJSON, localInstructions); const expected = { txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8880000,"Fee":"10","Sequence":23}`, instructions: { - fee: '0.00001', // Notice there are not always 6 digits after the decimal point as trailing zeros are omitted + fee: "0.00001", // Notice there are not always 6 digits after the decimal point as trailing zeros are omitted sequence: 23, - maxLedgerVersion: 8880000 - } - } - return assertResultMatch(response, expected, 'prepare') + maxLedgerVersion: 8880000, + }, + }; + return assertResultMatch(response, expected, "prepare"); }, - 'does not overwrite maxLedgerVersion in Instructions': async ( + "does not overwrite maxLedgerVersion in Instructions": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { - maxLedgerVersion: 8890000 - } + maxLedgerVersion: 8890000, + }; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } - const response = await client.prepareTransaction(txJSON, localInstructions) + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; + const response = await client.prepareTransaction(txJSON, localInstructions); const expected = { txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8890000,"Fee":"12","Sequence":23}`, instructions: { - fee: '0.000012', + fee: "0.000012", sequence: 23, - maxLedgerVersion: 8890000 - } - } - return assertResultMatch(response, expected, 'prepare') + maxLedgerVersion: 8890000, + }, + }; + return assertResultMatch(response, expected, "prepare"); }, - 'does not overwrite maxLedgerVersionOffset in Instructions': async ( + "does not overwrite maxLedgerVersionOffset in Instructions": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxLedgerVersionOffset: 124 - } + maxLedgerVersionOffset: 124, + }; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } - const response = await client.prepareTransaction(txJSON, localInstructions) + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; + const response = await client.prepareTransaction(txJSON, localInstructions); const expected = { txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820075,"Fee":"12","Sequence":23}`, instructions: { - fee: '0.000012', + fee: "0.000012", sequence: 23, - maxLedgerVersion: 8820075 - } - } - return assertResultMatch(response, expected, 'prepare') + maxLedgerVersion: 8820075, + }, + }; + return assertResultMatch(response, expected, "prepare"); }, - 'rejects Promise if txJSON.LastLedgerSequence and instructions.maxLedgerVersion both are set': async ( + "rejects Promise if txJSON.LastLedgerSequence and instructions.maxLedgerVersion both are set": + async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = { + maxLedgerVersion: 8900000, + }; + const txJSON = { + TransactionType: "DepositPreauth", + Account: address, + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Fee: "16", + LastLedgerSequence: 8900000, + }; + await assertRejects( + client.prepareTransaction(txJSON, localInstructions), + ValidationError, + "`LastLedgerSequence` in txJSON and `maxLedgerVersion` in `instructions` cannot both be set" + ); + }, + + "rejects Promise if txJSON.LastLedgerSequence and instructions.maxLedgerVersionOffset both are set": + async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = { + ...instructionsWithMaxLedgerVersionOffset, + maxLedgerVersionOffset: 123, + }; + const txJSON = { + TransactionType: "DepositPreauth", + Account: address, + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Fee: "16", + LastLedgerSequence: 8900000, + }; + await assertRejects( + client.prepareTransaction(txJSON, localInstructions), + ValidationError, + "`LastLedgerSequence` in txJSON and `maxLedgerVersionOffset` in `instructions` cannot both be set" + ); + }, + + "rejects Promise if instructions.maxLedgerVersion and instructions.maxLedgerVersionOffset both are set": + async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = { + ...instructionsWithMaxLedgerVersionOffset, + maxLedgerVersion: 8900000, + maxLedgerVersionOffset: 123, + }; + const txJSON = { + TransactionType: "DepositPreauth", + Account: address, + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Fee: "16", + }; + await assertRejects( + client.prepareTransaction(txJSON, localInstructions), + ValidationError, + "instance is of prohibited type [object Object]" + ); + }, + + "rejects Promise if txJSON.LastLedgerSequence and instructions.maxLedgerVersion and instructions.maxLedgerVersionOffset all are set": + async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = { + ...instructionsWithMaxLedgerVersionOffset, + maxLedgerVersion: 8900000, + maxLedgerVersionOffset: 123, + }; + const txJSON = { + TransactionType: "DepositPreauth", + Account: address, + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Fee: "16", + LastLedgerSequence: 8900000, + }; + await assertRejects( + client.prepareTransaction(txJSON, localInstructions), + ValidationError, + "instance is of prohibited type [object Object]" + ); + }, + + "rejects Promise when the maxLedgerVersion is capitalized in Instructions": + async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = { + ...instructionsWithMaxLedgerVersionOffset, + MaxLedgerVersion: 8900000, // Intentionally capitalized in this test, but the correct field would be `maxLedgerVersion` + }; + const txJSON = { + TransactionType: "DepositPreauth", + Account: address, + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; + await assertRejects( + client.prepareTransaction(txJSON, localInstructions), + ValidationError, + 'instance additionalProperty "MaxLedgerVersion" exists in instance when not allowed' + ); + }, + + "rejects Promise when the maxLedgerVersion is specified in txJSON": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = { - maxLedgerVersion: 8900000 - } + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = instructionsWithMaxLedgerVersionOffset; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Fee: '16', - LastLedgerSequence: 8900000 - } - await assertRejects( - client.prepareTransaction(txJSON, localInstructions), - ValidationError, - '`LastLedgerSequence` in txJSON and `maxLedgerVersion` in `instructions` cannot both be set' - ) - }, - - 'rejects Promise if txJSON.LastLedgerSequence and instructions.maxLedgerVersionOffset both are set': async ( - client, - address, - mockRippled - ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = { - ...instructionsWithMaxLedgerVersionOffset, - maxLedgerVersionOffset: 123 - } - const txJSON = { - TransactionType: 'DepositPreauth', - Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Fee: '16', - LastLedgerSequence: 8900000 - } - await assertRejects( - client.prepareTransaction(txJSON, localInstructions), - ValidationError, - '`LastLedgerSequence` in txJSON and `maxLedgerVersionOffset` in `instructions` cannot both be set' - ) - }, - - 'rejects Promise if instructions.maxLedgerVersion and instructions.maxLedgerVersionOffset both are set': async ( - client, - address, - mockRippled - ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = { - ...instructionsWithMaxLedgerVersionOffset, + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", maxLedgerVersion: 8900000, - maxLedgerVersionOffset: 123 - } - const txJSON = { - TransactionType: 'DepositPreauth', - Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Fee: '16' - } - await assertRejects( - client.prepareTransaction(txJSON, localInstructions), - ValidationError, - 'instance is of prohibited type [object Object]' - ) - }, - - 'rejects Promise if txJSON.LastLedgerSequence and instructions.maxLedgerVersion and instructions.maxLedgerVersionOffset all are set': async ( - client, - address, - mockRippled - ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = { - ...instructionsWithMaxLedgerVersionOffset, - maxLedgerVersion: 8900000, - maxLedgerVersionOffset: 123 - } - const txJSON = { - TransactionType: 'DepositPreauth', - Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Fee: '16', - LastLedgerSequence: 8900000 - } - await assertRejects( - client.prepareTransaction(txJSON, localInstructions), - ValidationError, - 'instance is of prohibited type [object Object]' - ) - }, - - 'rejects Promise when the maxLedgerVersion is capitalized in Instructions': async ( - client, - address, - mockRippled - ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = { - ...instructionsWithMaxLedgerVersionOffset, - MaxLedgerVersion: 8900000 // Intentionally capitalized in this test, but the correct field would be `maxLedgerVersion` - } - const txJSON = { - TransactionType: 'DepositPreauth', - Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } - await assertRejects( - client.prepareTransaction(txJSON, localInstructions), - ValidationError, - 'instance additionalProperty "MaxLedgerVersion" exists in instance when not allowed' - ) - }, - - 'rejects Promise when the maxLedgerVersion is specified in txJSON': async ( - client, - address, - mockRippled - ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = instructionsWithMaxLedgerVersionOffset - const txJSON = { - TransactionType: 'DepositPreauth', - Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - maxLedgerVersion: 8900000 - } + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, 'txJSON additionalProperty "maxLedgerVersion" exists in instance when not allowed' - ) + ); }, - 'rejects Promise when the maxLedgerVersionOffset is specified in txJSON': async ( + "rejects Promise when the maxLedgerVersionOffset is specified in txJSON": + async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = instructionsWithMaxLedgerVersionOffset; + const txJSON = { + TransactionType: "DepositPreauth", + Account: address, + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + maxLedgerVersionOffset: 8900000, + }; + await assertRejects( + client.prepareTransaction(txJSON, localInstructions), + ValidationError, + 'txJSON additionalProperty "maxLedgerVersionOffset" exists in instance when not allowed' + ); + }, + + "rejects Promise when the sequence is specified in txJSON": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = instructionsWithMaxLedgerVersionOffset + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = instructionsWithMaxLedgerVersionOffset; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - maxLedgerVersionOffset: 8900000 - } - await assertRejects( - client.prepareTransaction(txJSON, localInstructions), - ValidationError, - 'txJSON additionalProperty "maxLedgerVersionOffset" exists in instance when not allowed' - ) - }, - - 'rejects Promise when the sequence is specified in txJSON': async ( - client, - address, - mockRippled - ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = instructionsWithMaxLedgerVersionOffset - const txJSON = { - TransactionType: 'DepositPreauth', - Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - sequence: 8900000 - } + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + sequence: 8900000, + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, 'txJSON additionalProperty "sequence" exists in instance when not allowed' - ) + ); }, // Paths: is not auto-filled by ripple-lib. // Other errors: - 'rejects Promise when an unrecognized field is in Instructions': async ( + "rejects Promise when an unrecognized field is in Instructions": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - foo: 'bar' - } + maxFee: "0.000012", + foo: "bar", + }; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, 'instance additionalProperty "foo" exists in instance when not allowed' - ) + ); }, - 'rejects Promise when Account is missing': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "rejects Promise when Account is missing": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; // Marking as "any" to get around the fact that TS won't allow this. const txJSON: any = { - TransactionType: 'DepositPreauth', - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } + TransactionType: "DepositPreauth", + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, 'instance requires property "Account"' - ) + ); }, - 'rejects Promise when Account is not a string': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "rejects Promise when Account is not a string": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; // Marking as "any" to get around the fact that TS won't allow this. const txJSON: any = { Account: 1234, - TransactionType: 'DepositPreauth', - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } + TransactionType: "DepositPreauth", + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, - 'instance.Account is not of a type(s) string,instance.Account is not exactly one from ,' - ) + "instance.Account is not of a type(s) string,instance.Account is not exactly one from ," + ); }, - 'rejects Promise when Account is invalid': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "rejects Promise when Account is invalid": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const txJSON = { - Account: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xkXXXX', // Invalid checksum - TransactionType: 'DepositPreauth', - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } + Account: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xkXXXX", // Invalid checksum + TransactionType: "DepositPreauth", + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, - 'instance.Account is not exactly one from ,' - ) + "instance.Account is not exactly one from ," + ); }, // 'rejects Promise when Account is valid but non-existent on the ledger': async ( @@ -713,25 +949,38 @@ export default { // ) // }, - 'rejects Promise when TransactionType is missing': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "rejects Promise when TransactionType is missing": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; // Marking as "any" to get around the fact that TS won't allow this. const txJSON: any = { Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, 'instance requires property "TransactionType"' - ) + ); }, // Note: This transaction will fail at the `sign` step: @@ -739,56 +988,78 @@ export default { // Error: DepositPreXXXX is not a valid name or ordinal for TransactionType // // at Function.from (ripple-binary-codec/distrib/npm/enums/index.js:43:15) - 'prepares tx when TransactionType is invalid': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = { - ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } - const txJSON = { - Account: address, - TransactionType: 'DepositPreXXXX', - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } - const response = await client.prepareTransaction(txJSON, localInstructions) - const expected = { - txJSON: `{"TransactionType":"DepositPreXXXX","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":23}`, - instructions: { - fee: '0.000012', - sequence: 23, - maxLedgerVersion: 8820051 - } - } - return assertResultMatch(response, expected, 'prepare') - }, - - 'rejects Promise when TransactionType is not a string': async ( + "prepares tx when TransactionType is invalid": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; + const txJSON = { + Account: address, + TransactionType: "DepositPreXXXX", + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; + const response = await client.prepareTransaction(txJSON, localInstructions); + const expected = { + txJSON: `{"TransactionType":"DepositPreXXXX","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":23}`, + instructions: { + fee: "0.000012", + sequence: 23, + maxLedgerVersion: 8820051, + }, + }; + return assertResultMatch(response, expected, "prepare"); + }, + + "rejects Promise when TransactionType is not a string": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = { + ...instructionsWithMaxLedgerVersionOffset, + maxFee: "0.000012", + }; // Marking as "any" to get around the fact that TS won't allow this. const txJSON: any = { Account: address, TransactionType: 1234, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, - 'instance.TransactionType is not of a type(s) string' - ) + "instance.TransactionType is not of a type(s) string" + ); }, // Note: This transaction will fail at the `submit` step: @@ -811,218 +1082,276 @@ export default { // '304402201F0EF6A2DE7F96966F7082294D14F3EC1EF59C21E29443E5858A0120079357A302203CDB7FEBDEAAD93FF39CB589B55778CB80DC3979F96F27E828D5E659BEB26B7A', // hash: // 'C181D470684311658852713DA81F8201062535C8DE2FF853F7DD9981BB85312F' } })] - 'prepares tx when a required field is missing': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "prepares tx when a required field is missing": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const txJSON = { Account: address, - TransactionType: 'DepositPreauth' + TransactionType: "DepositPreauth", // Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' // Normally required, intentionally removed - } - const response = await client.prepareTransaction(txJSON, localInstructions) + }; + const response = await client.prepareTransaction(txJSON, localInstructions); const expected = { txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":23}`, instructions: { - fee: '0.000012', + fee: "0.000012", sequence: 23, - maxLedgerVersion: 8820051 - } - } - return assertResultMatch(response, expected, 'prepare') + maxLedgerVersion: 8820051, + }, + }; + return assertResultMatch(response, expected, "prepare"); }, - 'DepositPreauth - Authorize': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "DepositPreauth - Authorize": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; const expected = { - txJSON: - '{"TransactionType":"DepositPreauth","Account":"' + - address + - '","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":23}', + txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Authorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":23}`, instructions: { - fee: '0.000012', + fee: "0.000012", sequence: 23, - maxLedgerVersion: 8820051 - } - } - const response = await client.prepareTransaction(txJSON, localInstructions) - return assertResultMatch(response, expected, 'prepare') + maxLedgerVersion: 8820051, + }, + }; + const response = await client.prepareTransaction(txJSON, localInstructions); + return assertResultMatch(response, expected, "prepare"); }, - 'DepositPreauth - Unauthorize': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "DepositPreauth - Unauthorize": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Unauthorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo' - } + Unauthorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + }; - const response = await client.prepareTransaction(txJSON, localInstructions) + const response = await client.prepareTransaction(txJSON, localInstructions); const expected = { - txJSON: - '{"TransactionType":"DepositPreauth","Account":"' + - address + - '","Unauthorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":23}', + txJSON: `{"TransactionType":"DepositPreauth","Account":"${address}","Unauthorize":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":23}`, instructions: { - fee: '0.000012', + fee: "0.000012", sequence: 23, - maxLedgerVersion: 8820051 - } - } - return assertResultMatch(response, expected, 'prepare') + maxLedgerVersion: 8820051, + }, + }; + return assertResultMatch(response, expected, "prepare"); }, - 'AccountDelete': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async AccountDelete(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '5.0' // 5 XRP fee for AccountDelete - } + maxFee: "5.0", // 5 XRP fee for AccountDelete + }; const txJSON = { - TransactionType: 'AccountDelete', + TransactionType: "AccountDelete", Account: address, - Destination: 'rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe' - } + Destination: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", + }; - const response = await client.prepareTransaction(txJSON, localInstructions) + const response = await client.prepareTransaction(txJSON, localInstructions); const expected = { - txJSON: - '{"TransactionType":"AccountDelete","Account":"' + - address + - '","Destination":"rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":23}', + txJSON: `{"TransactionType":"AccountDelete","Account":"${address}","Destination":"rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe","Flags":2147483648,"LastLedgerSequence":8820051,"Fee":"12","Sequence":23}`, instructions: { - fee: '0.000012', + fee: "0.000012", sequence: 23, - maxLedgerVersion: 8820051 - } - } - return assertResultMatch(response, expected, 'prepare') + maxLedgerVersion: 8820051, + }, + }; + return assertResultMatch(response, expected, "prepare"); }, // prepareTransaction - Payment - 'Payment - normal': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "Payment - normal": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const txJSON = { - TransactionType: 'Payment', + TransactionType: "Payment", Account: address, - Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', + Destination: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", Amount: { - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM', - value: '0.01' + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", + value: "0.01", }, SendMax: { - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM', - value: '0.01' + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", + value: "0.01", }, - Flags: 0 - } + Flags: 0, + }; - const response = await client.prepareTransaction(txJSON, localInstructions) - assertResultMatch(response, responses.preparePayment.normal, 'prepare') + const response = await client.prepareTransaction(txJSON, localInstructions); + assertResultMatch(response, responses.preparePayment.normal, "prepare"); }, - 'min amount xrp': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "min amount xrp": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const txJSON = { - TransactionType: 'Payment', + TransactionType: "Payment", Account: address, - Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', + Destination: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", // Max amount to send. Use 100 billion XRP to // ensure that we send the full SendMax amount. - Amount: '100000000000000000', + Amount: "100000000000000000", SendMax: { - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM', - value: '0.01' + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", + value: "0.01", }, - DeliverMin: '10000', - Flags: client.txFlags.Payment.PartialPayment - } + DeliverMin: "10000", + Flags: client.txFlags.Payment.PartialPayment, + }; - const response = await client.prepareTransaction(txJSON, localInstructions) + const response = await client.prepareTransaction(txJSON, localInstructions); assertResultMatch( response, responses.preparePayment.minAmountXRP, - 'prepare' - ) + "prepare" + ); }, - 'min amount xrp2xrp': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "min amount xrp2xrp": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const txJSON = { - TransactionType: 'Payment', + TransactionType: "Payment", Account: address, - Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Amount: '10000', - Flags: 0 - } + Destination: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Amount: "10000", + Flags: 0, + }; const response = await client.prepareTransaction( txJSON, instructionsWithMaxLedgerVersionOffset - ) + ); assertResultMatch( response, responses.preparePayment.minAmountXRPXRP, - 'prepare' - ) + "prepare" + ); }, // 'with all options specified': async (client, address) => { // const ledgerResponse = await client.request({ - // command: 'ledger', + // command: 'ledger', // ledger_index: 'validated' // }) // const version = ledgerResponse.result.ledger_index @@ -1057,184 +1386,220 @@ export default { // assertResultMatch(response, responses.preparePayment.allOptions, 'prepare') // }, - 'fee is capped at default maxFee of 2 XRP (using txJSON.LastLedgerSequence)': async ( - client, - address, - mockRippled - ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - client._feeCushion = 1000000 + "fee is capped at default maxFee of 2 XRP (using txJSON.LastLedgerSequence)": + async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + client._feeCushion = 1000000; - const txJSON = { - Flags: 2147483648, - TransactionType: 'Payment', - Account: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', - Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Amount: { - value: '0.01', - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM' - }, - SendMax: { - value: '0.01', - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM' - }, - LastLedgerSequence: 8820051 - } - const localInstructions = {} - const expectedResponse = { - txJSON: - '{"Flags":2147483648,"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"SendMax":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"LastLedgerSequence":8820051,"Fee":"2000000","Sequence":23}', - instructions: { - fee: '2', - sequence: 23, - maxLedgerVersion: 8820051 - } - } - const response = await client.prepareTransaction(txJSON, localInstructions) - assertResultMatch(response, expectedResponse, 'prepare') - }, + const txJSON = { + Flags: 2147483648, + TransactionType: "Payment", + Account: "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + Destination: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Amount: { + value: "0.01", + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", + }, + SendMax: { + value: "0.01", + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", + }, + LastLedgerSequence: 8820051, + }; + const localInstructions = {}; + const expectedResponse = { + txJSON: + '{"Flags":2147483648,"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"SendMax":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"LastLedgerSequence":8820051,"Fee":"2000000","Sequence":23}', + instructions: { + fee: "2", + sequence: 23, + maxLedgerVersion: 8820051, + }, + }; + const response = await client.prepareTransaction( + txJSON, + localInstructions + ); + assertResultMatch(response, expectedResponse, "prepare"); + }, - 'fee is capped at default maxFee of 2 XRP (using instructions.maxLedgerVersion)': async ( - client, - address, - mockRippled - ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - client._feeCushion = 1000000 + "fee is capped at default maxFee of 2 XRP (using instructions.maxLedgerVersion)": + async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + client._feeCushion = 1000000; - const txJSON = { - Flags: 2147483648, - TransactionType: 'Payment', - Account: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', - Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Amount: { - value: '0.01', - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM' - }, - SendMax: { - value: '0.01', - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM' - } - } + const txJSON = { + Flags: 2147483648, + TransactionType: "Payment", + Account: "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + Destination: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Amount: { + value: "0.01", + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", + }, + SendMax: { + value: "0.01", + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", + }, + }; - const localInstructions = { - maxLedgerVersion: 8820051 - } + const localInstructions = { + maxLedgerVersion: 8820051, + }; - const expectedResponse = { - txJSON: - '{"Flags":2147483648,"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"SendMax":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"LastLedgerSequence":8820051,"Fee":"2000000","Sequence":23}', - instructions: { - fee: '2', - sequence: 23, - maxLedgerVersion: 8820051 - } - } + const expectedResponse = { + txJSON: + '{"Flags":2147483648,"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"SendMax":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"LastLedgerSequence":8820051,"Fee":"2000000","Sequence":23}', + instructions: { + fee: "2", + sequence: 23, + maxLedgerVersion: 8820051, + }, + }; - const response = await client.prepareTransaction(txJSON, localInstructions) - assertResultMatch(response, expectedResponse, 'prepare') - }, + const response = await client.prepareTransaction( + txJSON, + localInstructions + ); + assertResultMatch(response, expectedResponse, "prepare"); + }, // prepareTransaction - Payment - 'fee is capped to custom maxFeeXRP when maxFee exceeds maxFeeXRP': async ( + "fee is capped to custom maxFeeXRP when maxFee exceeds maxFeeXRP": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - client._feeCushion = 1000000 - client._maxFeeXRP = '3' + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + client._feeCushion = 1000000; + client._maxFeeXRP = "3"; const localInstructions = { - maxFee: '4' // We are testing that this does not matter; fee is still capped to maxFeeXRP - } + maxFee: "4", // We are testing that this does not matter; fee is still capped to maxFeeXRP + }; const txJSON = { Flags: 2147483648, - TransactionType: 'Payment', - Account: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', - Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', + TransactionType: "Payment", + Account: "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + Destination: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", Amount: { - value: '0.01', - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM' + value: "0.01", + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", }, SendMax: { - value: '0.01', - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM' + value: "0.01", + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", }, - LastLedgerSequence: 8820051 - } + LastLedgerSequence: 8820051, + }; const expectedResponse = { txJSON: '{"Flags":2147483648,"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"SendMax":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"LastLedgerSequence":8820051,"Fee":"3000000","Sequence":23}', instructions: { - fee: '3', + fee: "3", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; - const response = await client.prepareTransaction(txJSON, localInstructions) - assertResultMatch(response, expectedResponse, 'prepare') + const response = await client.prepareTransaction(txJSON, localInstructions); + assertResultMatch(response, expectedResponse, "prepare"); }, // prepareTransaction - Payment - 'fee is capped to maxFee': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - client._feeCushion = 1000000 - client._maxFeeXRP = '5' + "fee is capped to maxFee": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + client._feeCushion = 1000000; + client._maxFeeXRP = "5"; const localInstructions = { - maxFee: '4' // maxFeeXRP does not matter if maxFee is lower than maxFeeXRP - } + maxFee: "4", // maxFeeXRP does not matter if maxFee is lower than maxFeeXRP + }; const txJSON = { Flags: 2147483648, - TransactionType: 'Payment', - Account: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', - Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', + TransactionType: "Payment", + Account: "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + Destination: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", Amount: { - value: '0.01', - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM' + value: "0.01", + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", }, SendMax: { - value: '0.01', - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM' + value: "0.01", + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", }, - LastLedgerSequence: 8820051 - } + LastLedgerSequence: 8820051, + }; const expectedResponse = { txJSON: '{"Flags":2147483648,"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo","Amount":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"SendMax":{"value":"0.01","currency":"USD","issuer":"rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM"},"LastLedgerSequence":8820051,"Fee":"4000000","Sequence":23}', instructions: { - fee: '4', + fee: "4", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; - const response = await client.prepareTransaction(txJSON, localInstructions) - assertResultMatch(response, expectedResponse, 'prepare') + const response = await client.prepareTransaction(txJSON, localInstructions); + assertResultMatch(response, expectedResponse, "prepare"); }, // 'fee - calculated fee does not use more than 6 decimal places': async ( @@ -1264,56 +1629,73 @@ export default { // assertResultMatch(response, expectedResponse, 'prepare') // }, - - 'xaddress-issuer': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "xaddress-issuer": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const txJSON = { - TransactionType: 'Payment', + TransactionType: "Payment", Account: address, - Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', + Destination: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", Amount: { - currency: 'USD', - issuer: 'XVbehP2sFMQAd5orFAy8Lt6vLHGiDhA7VMAnsv9H6WpuB1s', - value: '0.01' + currency: "USD", + issuer: "XVbehP2sFMQAd5orFAy8Lt6vLHGiDhA7VMAnsv9H6WpuB1s", + value: "0.01", }, SendMax: { - currency: 'USD', - issuer: 'XVbehP2sFMQAd5orFAy8Lt6vLHGiDhA7VMAnsv9H6WpuB1s', - value: '0.01' + currency: "USD", + issuer: "XVbehP2sFMQAd5orFAy8Lt6vLHGiDhA7VMAnsv9H6WpuB1s", + value: "0.01", }, - Flags: 0 - } + Flags: 0, + }; - const response = await client.prepareTransaction(txJSON, localInstructions) - assertResultMatch(response, responses.preparePayment.normal, 'prepare') + const response = await client.prepareTransaction(txJSON, localInstructions); + assertResultMatch(response, responses.preparePayment.normal, "prepare"); }, - 'PaymentChannelCreate': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async PaymentChannelCreate(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const response = await client.prepareTransaction( { Account: address, - TransactionType: 'PaymentChannelCreate', - Amount: '1000000', // 1 XRP in drops. Use a string-encoded integer. - Destination: 'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW', + TransactionType: "PaymentChannelCreate", + Amount: "1000000", // 1 XRP in drops. Use a string-encoded integer. + Destination: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", SettleDelay: 86400, PublicKey: - '32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A' + "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A", // If cancelAfter is used, you must use RippleTime. // You can use `ISOTimeToRippleTime()` to convert to RippleTime. @@ -1321,272 +1703,358 @@ export default { // including `sourceTag` and `destinationTag`. }, localInstructions - ) + ); assertResultMatch( response, responses.preparePaymentChannelCreate.normal, - 'prepare' - ) + "prepare" + ); }, - 'PaymentChannelCreate full': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "PaymentChannelCreate full": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const txJSON = { Account: address, - TransactionType: 'PaymentChannelCreate', - Amount: xrpToDrops('1'), // or '1000000' - Destination: 'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW', + TransactionType: "PaymentChannelCreate", + Amount: xrpToDrops("1"), // or '1000000' + Destination: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", SettleDelay: 86400, // Ensure this is in upper case if it is not already - PublicKey: '32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A'.toUpperCase(), - CancelAfter: ISOTimeToRippleTime('2017-02-17T15:04:57Z'), + PublicKey: + "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A".toUpperCase(), + CancelAfter: ISOTimeToRippleTime("2017-02-17T15:04:57Z"), SourceTag: 11747, - DestinationTag: 23480 - } + DestinationTag: 23480, + }; - const response = await client.prepareTransaction(txJSON) + const response = await client.prepareTransaction(txJSON); assertResultMatch( response, responses.preparePaymentChannelCreate.full, - 'prepare' - ) + "prepare" + ); }, - 'PaymentChannelFund': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async PaymentChannelFund(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const txJSON = { Account: address, - TransactionType: 'PaymentChannelFund', + TransactionType: "PaymentChannelFund", Channel: - 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198', - Amount: xrpToDrops('1') // or '1000000' - } - const response = await client.prepareTransaction(txJSON, localInstructions) + "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + Amount: xrpToDrops("1"), // or '1000000' + }; + const response = await client.prepareTransaction(txJSON, localInstructions); assertResultMatch( response, responses.preparePaymentChannelFund.normal, - 'prepare' - ) + "prepare" + ); }, - 'PaymentChannelFund full': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "PaymentChannelFund full": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const txJSON = { Account: address, - TransactionType: 'PaymentChannelFund', + TransactionType: "PaymentChannelFund", Channel: - 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198', - Amount: xrpToDrops('1'), // or '1000000' - Expiration: ISOTimeToRippleTime('2017-02-17T15:04:57Z') - } + "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + Amount: xrpToDrops("1"), // or '1000000' + Expiration: ISOTimeToRippleTime("2017-02-17T15:04:57Z"), + }; - const response = await client.prepareTransaction(txJSON) + const response = await client.prepareTransaction(txJSON); assertResultMatch( response, responses.preparePaymentChannelFund.full, - 'prepare' - ) + "prepare" + ); }, - 'PaymentChannelClaim': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async PaymentChannelClaim(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const txJSON = { Account: address, - TransactionType: 'PaymentChannelClaim', + TransactionType: "PaymentChannelClaim", Channel: - 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198', - Flags: 0 - } + "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + Flags: 0, + }; - const response = await client.prepareTransaction(txJSON, localInstructions) + const response = await client.prepareTransaction(txJSON, localInstructions); assertResultMatch( response, responses.preparePaymentChannelClaim.normal, - 'prepare' - ) + "prepare" + ); }, - 'PaymentChannelClaim with renew': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "PaymentChannelClaim with renew": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const txJSON = { Account: address, - TransactionType: 'PaymentChannelClaim', + TransactionType: "PaymentChannelClaim", Channel: - 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198', - Balance: xrpToDrops('1'), // or '1000000' - Amount: xrpToDrops('1'), // or '1000000' + "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + Balance: xrpToDrops("1"), // or '1000000' + Amount: xrpToDrops("1"), // or '1000000' Signature: - '30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B', + "30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B", PublicKey: - '32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A', - Flags: 0 - } - txJSON.Flags |= client.txFlags.PaymentChannelClaim.Renew + "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A", + Flags: 0, + }; + txJSON.Flags |= client.txFlags.PaymentChannelClaim.Renew; - const response = await client.prepareTransaction(txJSON, localInstructions) + const response = await client.prepareTransaction(txJSON, localInstructions); assertResultMatch( response, responses.preparePaymentChannelClaim.renew, - 'prepare' - ) + "prepare" + ); }, - 'PaymentChannelClaim with close': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "PaymentChannelClaim with close": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012' - } + maxFee: "0.000012", + }; const txJSON = { Account: address, - TransactionType: 'PaymentChannelClaim', + TransactionType: "PaymentChannelClaim", Channel: - 'C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198', - Balance: xrpToDrops('1'), // or 1000000 - Amount: xrpToDrops('1'), // or 1000000 + "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + Balance: xrpToDrops("1"), // or 1000000 + Amount: xrpToDrops("1"), // or 1000000 Signature: - '30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B', + "30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B", PublicKey: - '32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A', - Flags: 0 - } - txJSON.Flags |= client.txFlags.PaymentChannelClaim.Close + "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A", + Flags: 0, + }; + txJSON.Flags |= client.txFlags.PaymentChannelClaim.Close; - const response = await client.prepareTransaction(txJSON, localInstructions) + const response = await client.prepareTransaction(txJSON, localInstructions); assertResultMatch( response, responses.preparePaymentChannelClaim.close, - 'prepare' - ) + "prepare" + ); }, - 'rejects Promise if both sequence and ticketSecuence are set': async ( + "rejects Promise if both sequence and ticketSecuence are set": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ticketSequence: 23, - sequence: 23 - } + sequence: 23, + }; const txJSON = { - TransactionType: 'DepositPreauth', + TransactionType: "DepositPreauth", Account: address, - Authorize: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Fee: '16' - } + Authorize: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Fee: "16", + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, - 'instance is of prohibited type [object Object]' - ) + "instance is of prohibited type [object Object]" + ); }, - 'sets sequence to 0 if a ticketSequence is passed': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const localInstructions = { - ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - ticketSequence: 23 - } - - const txJSON = { - TransactionType: 'Payment', - Account: address, - Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', - Amount: { - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM', - value: '0.01' - }, - SendMax: { - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM', - value: '0.01' - }, - Flags: 0 - } - - const response = await client.prepareTransaction(txJSON, localInstructions) - assertResultMatch(response, responses.preparePayment.ticket, 'prepare') - }, - - 'rejects Promise if a sequence with value 0 is passed': async ( + "sets sequence to 0 if a ticketSequence is passed": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - sequence: 0 - } + maxFee: "0.000012", + ticketSequence: 23, + }; const txJSON = { - TransactionType: 'Payment', + TransactionType: "Payment", Account: address, - Destination: 'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo', + Destination: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", Amount: { - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM', - value: '0.01' + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", + value: "0.01", }, SendMax: { - currency: 'USD', - issuer: 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM', - value: '0.01' + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", + value: "0.01", }, - Flags: 0 - } + Flags: 0, + }; + + const response = await client.prepareTransaction(txJSON, localInstructions); + assertResultMatch(response, responses.preparePayment.ticket, "prepare"); + }, + + "rejects Promise if a sequence with value 0 is passed": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const localInstructions = { + ...instructionsWithMaxLedgerVersionOffset, + maxFee: "0.000012", + sequence: 0, + }; + + const txJSON = { + TransactionType: "Payment", + Account: address, + Destination: "rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo", + Amount: { + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", + value: "0.01", + }, + SendMax: { + currency: "USD", + issuer: "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM", + value: "0.01", + }, + Flags: 0, + }; await assertRejects( client.prepareTransaction(txJSON, localInstructions), ValidationError, - '`sequence` cannot be 0' - ) - } -} + "`sequence` cannot be 0" + ); + }, +}; diff --git a/test/client/prepareTrustline.ts b/test/client/prepareTrustline.ts index ac791eb5..69ce5d09 100644 --- a/test/client/prepareTrustline.ts +++ b/test/client/prepareTrustline.ts @@ -1,8 +1,9 @@ -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {assertRejects, assertResultMatch, TestSuite} from '../testUtils' -const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { assertRejects, assertResultMatch, TestSuite } from "../testUtils"; + +const instructionsWithMaxLedgerVersionOffset = { maxLedgerVersionOffset: 100 }; /** * Every test suite exports their tests in the default object. @@ -10,51 +11,87 @@ const instructionsWithMaxLedgerVersionOffset = {maxLedgerVersionOffset: 100} * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'simple': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async simple(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareTrustline( address, requests.prepareTrustline.simple, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(result, responses.prepareTrustline.simple, 'prepare') + ); + assertResultMatch(result, responses.prepareTrustline.simple, "prepare"); }, - 'frozen': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async frozen(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareTrustline( address, requests.prepareTrustline.frozen - ) - assertResultMatch(result, responses.prepareTrustline.frozen, 'prepare') + ); + assertResultMatch(result, responses.prepareTrustline.frozen, "prepare"); }, - 'complex': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + async complex(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareTrustline( address, requests.prepareTrustline.complex, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(result, responses.prepareTrustline.complex, 'prepare') + ); + assertResultMatch(result, responses.prepareTrustline.complex, "prepare"); }, - 'invalid': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const trustline = Object.assign({}, requests.prepareTrustline.complex) - delete trustline.limit // Make invalid + async invalid(client, address, mockRippled) { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const trustline = { ...requests.prepareTrustline.complex }; + delete trustline.limit; // Make invalid await assertRejects( client.prepareTrustline( @@ -64,37 +101,59 @@ export default { ), client.errors.ValidationError, 'instance.trustline requires property "limit"' - ) + ); }, - 'xaddress-issuer': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "xaddress-issuer": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const result = await client.prepareTrustline( address, requests.prepareTrustline.issuedXAddress, instructionsWithMaxLedgerVersionOffset - ) - assertResultMatch(result, responses.prepareTrustline.issuedXAddress, 'prepare') + ); + assertResultMatch( + result, + responses.prepareTrustline.issuedXAddress, + "prepare" + ); }, - 'with ticket': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "with ticket": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const localInstructions = { ...instructionsWithMaxLedgerVersionOffset, - maxFee: '0.000012', - ticketSequence: 23 - } + maxFee: "0.000012", + ticketSequence: 23, + }; const result = await client.prepareTrustline( address, requests.prepareTrustline.simple, localInstructions - ) - assertResultMatch(result, responses.prepareTrustline.ticket, 'prepare') - } -} + ); + assertResultMatch(result, responses.prepareTrustline.ticket, "prepare"); + }, +}; diff --git a/test/client/request.ts b/test/client/request.ts index 61135139..82514c1e 100644 --- a/test/client/request.ts +++ b/test/client/request.ts @@ -1,6 +1,6 @@ -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {TestSuite, assertResultMatch} from '../testUtils' +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { TestSuite, assertResultMatch } from "../testUtils"; /** * Every test suite exports their tests in the default object. @@ -8,31 +8,41 @@ import {TestSuite, assertResultMatch} from '../testUtils' * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'request account_objects': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'account_objects', account: address}, rippled.account_objects.normal) - const result = await client.request({command: 'account_objects', - account: address - }) + "request account_objects": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "account_objects", account: address }, + rippled.account_objects.normal + ); + const result = await client.request({ + command: "account_objects", + account: address, + }); assertResultMatch( result.result, responses.getAccountObjects, - 'AccountObjectsResponse' - ) + "AccountObjectsResponse" + ); }, - 'request account_objects - invalid options': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'account_objects', account: address}, rippled.account_objects.normal) - // @ts-ignore Intentionally no local validation of these options - const result = await client.request({command: 'account_objects', + "request account_objects - invalid options": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse( + { command: "account_objects", account: address }, + rippled.account_objects.normal + ); + const result = await client.request({ + command: "account_objects", account: address, - invalid: 'options' - }) + }); assertResultMatch( result.result, responses.getAccountObjects, - 'AccountObjectsResponse' - ) - } -} + "AccountObjectsResponse" + ); + }, +}; diff --git a/test/client/requestNextPage.ts b/test/client/requestNextPage.ts index af82a054..e9b99b6f 100644 --- a/test/client/requestNextPage.ts +++ b/test/client/requestNextPage.ts @@ -1,14 +1,14 @@ -import assert from 'assert-diff' -import {assertRejects, TestSuite} from '../testUtils' -import rippled from '../fixtures/rippled' +import assert from "assert-diff"; -const rippledResponse = function(request: Request) : object { - if ('marker' in request) { - return rippled.ledger_data.last_page - } else { - return rippled.ledger_data.first_page +import rippled from "../fixtures/rippled"; +import { assertRejects, TestSuite } from "../testUtils"; + +const rippledResponse = function (request: Request): object { + if ("marker" in request) { + return rippled.ledger_data.last_page; } -} + return rippled.ledger_data.first_page; +}; /** * Every test suite exports their tests in the default object. @@ -16,37 +16,35 @@ const rippledResponse = function(request: Request) : object { * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'requests the next page': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'ledger_data'}, rippledResponse) - // @ts-ignore - const response = await client.request({command: 'ledger_data'}) + "requests the next page": async (client, address, mockRippled) => { + mockRippled.addResponse({ command: "ledger_data" }, rippledResponse); + const response = await client.request({ command: "ledger_data" }); const responseNextPage = await client.requestNextPage( - // @ts-ignore - {command: 'ledger_data'}, + { command: "ledger_data" }, response - ) + ); assert.equal( - // @ts-ignore responseNextPage.result.state[0].index, - '000B714B790C3C79FEE00D17C4DEB436B375466F29679447BA64F265FD63D731' - ) + "000B714B790C3C79FEE00D17C4DEB436B375466F29679447BA64F265FD63D731" + ); }, - 'rejects when there are no more pages': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'ledger_data'}, rippledResponse) - // @ts-ignore - const response = await client.request({command: 'ledger_data'}) + "rejects when there are no more pages": async ( + client, + address, + mockRippled + ) => { + mockRippled.addResponse({ command: "ledger_data" }, rippledResponse); + const response = await client.request({ command: "ledger_data" }); const responseNextPage = await client.requestNextPage( - // @ts-ignore - {command: 'ledger_data'}, + { command: "ledger_data" }, response - ) - assert(!client.hasNextPage(responseNextPage)) + ); + assert(!client.hasNextPage(responseNextPage)); await assertRejects( - // @ts-ignore - client.requestNextPage({command: 'ledger_data'}, responseNextPage), + client.requestNextPage({ command: "ledger_data" }, responseNextPage), Error, - 'response does not have a next page' - ) - } -} + "response does not have a next page" + ); + }, +}; diff --git a/test/client/sign.ts b/test/client/sign.ts index ee8f6cef..8fb73ba6 100644 --- a/test/client/sign.ts +++ b/test/client/sign.ts @@ -1,13 +1,15 @@ -import assert from 'assert-diff' -import binary from 'ripple-binary-codec' -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import rippled from '../fixtures/rippled' -import {TestSuite} from '../testUtils' -import * as schemaValidator from 'xrpl-local/common/schema-validator' +import assert from "assert-diff"; +import binary from "ripple-binary-codec"; -const {sign: REQUEST_FIXTURES} = requests -const {sign: RESPONSE_FIXTURES} = responses +import * as schemaValidator from "xrpl-local/common/schema-validator"; + +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import rippled from "../fixtures/rippled"; +import { TestSuite } from "../testUtils"; + +const { sign: REQUEST_FIXTURES } = requests; +const { sign: RESPONSE_FIXTURES } = responses; /** * Every test suite exports their tests in the default object. @@ -15,413 +17,453 @@ const {sign: RESPONSE_FIXTURES} = responses * - Check out "test/client/index.ts" for more information about the test runner. */ export default { - 'sign': async (client, address) => { - const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' - const result = client.sign(REQUEST_FIXTURES.normal.txJSON, secret) - assert.deepEqual(result, RESPONSE_FIXTURES.normal) - schemaValidator.schemaValidate('sign', result) + async sign(client, address) { + const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV"; + const result = client.sign(REQUEST_FIXTURES.normal.txJSON, secret); + assert.deepEqual(result, RESPONSE_FIXTURES.normal); + schemaValidator.schemaValidate("sign", result); }, - 'sign with lowercase hex data in memo (hex should be case insensitive)': async (client, address) => { - const secret = 'shd2nxpFD6iBRKWsRss2P4tKMWyy9'; - const lowercaseMemoTxJson = { - "TransactionType" : "Payment", - "Flags" : 2147483648, - "Account" : "rwiZ3q3D3QuG4Ga2HyGdq3kPKJRGctVG8a", - "Amount" : "10000000", - "LastLedgerSequence": 14000999, - "Destination" : "rUeEBYXHo8vF86Rqir3zWGRQ84W9efdAQd", - "Fee" : "12", - "Sequence" : 12, - "SourceTag" : 8888, - "DestinationTag" : 9999, - "Memos" : [ - { - "Memo": { - "MemoType" :"687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963", - "MemoData" :"72656e74" - } - } - ] - } + "sign with lowercase hex data in memo (hex should be case insensitive)": + async (client, address) => { + const secret = "shd2nxpFD6iBRKWsRss2P4tKMWyy9"; + const lowercaseMemoTxJson = { + TransactionType: "Payment", + Flags: 2147483648, + Account: "rwiZ3q3D3QuG4Ga2HyGdq3kPKJRGctVG8a", + Amount: "10000000", + LastLedgerSequence: 14000999, + Destination: "rUeEBYXHo8vF86Rqir3zWGRQ84W9efdAQd", + Fee: "12", + Sequence: 12, + SourceTag: 8888, + DestinationTag: 9999, + Memos: [ + { + Memo: { + MemoType: + "687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963", + MemoData: "72656e74", + }, + }, + ], + }; - const txParams = JSON.stringify(lowercaseMemoTxJson); - const result = client.sign(txParams, secret); - assert.deepEqual(result, { - signedTransaction: '120000228000000023000022B8240000000C2E0000270F201B00D5A36761400000000098968068400000000000000C73210305E09ED602D40AB1AF65646A4007C2DAC17CB6CDACDE301E74FB2D728EA057CF744730450221009C00E8439E017CA622A5A1EE7643E26B4DE9C808DE2ABE45D33479D49A4CEC66022062175BE8733442FA2A4D9A35F85A57D58252AE7B19A66401FE238B36FA28E5A081146C1856D0E36019EA75C56D7E8CBA6E35F9B3F71583147FB49CD110A1C46838788CD12764E3B0F837E0DDF9EA7C1F687474703A2F2F6578616D706C652E636F6D2F6D656D6F2F67656E657269637D0472656E74E1F1', - id: '41B9CB78D8E18A796CDD4B0BC6FB0EA19F64C4F25FDE23049197852CAB71D10D' - }) - }, + const txParams = JSON.stringify(lowercaseMemoTxJson); + const result = client.sign(txParams, secret); + assert.deepEqual(result, { + signedTransaction: + "120000228000000023000022B8240000000C2E0000270F201B00D5A36761400000000098968068400000000000000C73210305E09ED602D40AB1AF65646A4007C2DAC17CB6CDACDE301E74FB2D728EA057CF744730450221009C00E8439E017CA622A5A1EE7643E26B4DE9C808DE2ABE45D33479D49A4CEC66022062175BE8733442FA2A4D9A35F85A57D58252AE7B19A66401FE238B36FA28E5A081146C1856D0E36019EA75C56D7E8CBA6E35F9B3F71583147FB49CD110A1C46838788CD12764E3B0F837E0DDF9EA7C1F687474703A2F2F6578616D706C652E636F6D2F6D656D6F2F67656E657269637D0472656E74E1F1", + id: "41B9CB78D8E18A796CDD4B0BC6FB0EA19F64C4F25FDE23049197852CAB71D10D", + }); + }, - 'sign with paths': async ( - client, - address, - mockRippled - ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) - const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' + "sign with paths": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); + const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV"; const payment = { source: { - address: address, + address, amount: { - currency: 'drops', - value: '100' - } + currency: "drops", + value: "100", + }, }, destination: { - address: 'rKT4JX4cCof6LcDYRz8o3rGRu7qxzZ2Zwj', + address: "rKT4JX4cCof6LcDYRz8o3rGRu7qxzZ2Zwj", minAmount: { - currency: 'USD', - value: '0.00004579644712312366', - counterparty: 'rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc' - } + currency: "USD", + value: "0.00004579644712312366", + counterparty: "rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc", + }, }, // eslint-disable-next-line no-useless-escape - paths: '[[{\"currency\":\"USD\",\"issuer\":\"rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc\"}]]' - } - const ret = await client.preparePayment(address, payment, {sequence: 1, maxLedgerVersion: 15696358}) - const result = client.sign(ret.txJSON, secret) + paths: + '[[{"currency":"USD","issuer":"rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc"}]]', + }; + const ret = await client.preparePayment(address, payment, { + sequence: 1, + maxLedgerVersion: 15696358, + }); + const result = client.sign(ret.txJSON, secret); assert.deepEqual(result, { - signedTransaction: '12000022800200002400000001201B00EF81E661EC6386F26FC0FFFF0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461968400000000000000C6940000000000000646AD3504529A0465E2E0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D1664619732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D87446304402200A693FB5CA6B21250EBDFD8CFF526EE0DF7C9E4E31EB0660692E75E6A93BF5F802203CC39463DDA21386898CA31E18AD1A6828647D65741DD637BAD71BC83E29DB9481145E7B112523F68D2F5E879DB4EAC51C6698A693048314CA6EDC7A28252DAEA6F2045B24F4D7C333E146170112300000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461900', - id: '78874FE5F5299FEE3EA85D3CF6C1FB1F1D46BB08F716662A3E3D1F0ADE4EF796' - }) - schemaValidator.schemaValidate('sign', result) + signedTransaction: + "12000022800200002400000001201B00EF81E661EC6386F26FC0FFFF0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461968400000000000000C6940000000000000646AD3504529A0465E2E0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D1664619732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D87446304402200A693FB5CA6B21250EBDFD8CFF526EE0DF7C9E4E31EB0660692E75E6A93BF5F802203CC39463DDA21386898CA31E18AD1A6828647D65741DD637BAD71BC83E29DB9481145E7B112523F68D2F5E879DB4EAC51C6698A693048314CA6EDC7A28252DAEA6F2045B24F4D7C333E146170112300000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461900", + id: "78874FE5F5299FEE3EA85D3CF6C1FB1F1D46BB08F716662A3E3D1F0ADE4EF796", + }); + schemaValidator.schemaValidate("sign", result); }, - 'already signed': async (client, address) => { - const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' - const result = client.sign(REQUEST_FIXTURES.normal.txJSON, secret) + "already signed": async (client, address) => { + const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV"; + const result = client.sign(REQUEST_FIXTURES.normal.txJSON, secret); assert.throws(() => { - const tx = JSON.stringify(binary.decode(result.signedTransaction)) - client.sign(tx, secret) - }, /txJSON must not contain "TxnSignature" or "Signers" properties/) + const tx = JSON.stringify(binary.decode(result.signedTransaction)); + client.sign(tx, secret); + }, /txJSON must not contain "TxnSignature" or "Signers" properties/); }, - 'EscrowExecution': async (client, address) => { - const secret = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb' - const result = client.sign(REQUEST_FIXTURES.escrow.txJSON, secret) - assert.deepEqual(result, RESPONSE_FIXTURES.escrow) - schemaValidator.schemaValidate('sign', result) + async EscrowExecution(client, address) { + const secret = "snoPBrXtMeMyMHUVTgbuqAfg1SUTb"; + const result = client.sign(REQUEST_FIXTURES.escrow.txJSON, secret); + assert.deepEqual(result, RESPONSE_FIXTURES.escrow); + schemaValidator.schemaValidate("sign", result); }, - 'signAs': async (client, address) => { - const txJSON = REQUEST_FIXTURES.signAs - const secret = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb' + async signAs(client, address) { + const txJSON = REQUEST_FIXTURES.signAs; + const secret = "snoPBrXtMeMyMHUVTgbuqAfg1SUTb"; const signature = client.sign(JSON.stringify(txJSON), secret, { - signAs: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh' - }) - assert.deepEqual(signature, RESPONSE_FIXTURES.signAs) + signAs: "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + }); + assert.deepEqual(signature, RESPONSE_FIXTURES.signAs); }, - 'withKeypair': async (client, address) => { + async withKeypair(client, address) { const keypair = { privateKey: - '00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A', + "00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A", publicKey: - '02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8' - } - const result = client.sign(REQUEST_FIXTURES.normal.txJSON, keypair) - assert.deepEqual(result, RESPONSE_FIXTURES.normal) - schemaValidator.schemaValidate('sign', result) + "02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8", + }; + const result = client.sign(REQUEST_FIXTURES.normal.txJSON, keypair); + assert.deepEqual(result, RESPONSE_FIXTURES.normal); + schemaValidator.schemaValidate("sign", result); }, - 'withKeypair already signed': async (client, address) => { + "withKeypair already signed": async (client, address) => { const keypair = { privateKey: - '00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A', + "00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A", publicKey: - '02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8' - } - const result = client.sign(REQUEST_FIXTURES.normal.txJSON, keypair) + "02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8", + }; + const result = client.sign(REQUEST_FIXTURES.normal.txJSON, keypair); assert.throws(() => { - const tx = JSON.stringify(binary.decode(result.signedTransaction)) - client.sign(tx, keypair) - }, /txJSON must not contain "TxnSignature" or "Signers" properties/) + const tx = JSON.stringify(binary.decode(result.signedTransaction)); + client.sign(tx, keypair); + }, /txJSON must not contain "TxnSignature" or "Signers" properties/); }, - 'withKeypair EscrowExecution': async (client, address) => { + "withKeypair EscrowExecution": async (client, address) => { const keypair = { privateKey: - '001ACAAEDECE405B2A958212629E16F2EB46B153EEE94CDD350FDEFF52795525B7', + "001ACAAEDECE405B2A958212629E16F2EB46B153EEE94CDD350FDEFF52795525B7", publicKey: - '0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020' - } - const result = client.sign(REQUEST_FIXTURES.escrow.txJSON, keypair) - assert.deepEqual(result, RESPONSE_FIXTURES.escrow) - schemaValidator.schemaValidate('sign', result) + "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020", + }; + const result = client.sign(REQUEST_FIXTURES.escrow.txJSON, keypair); + assert.deepEqual(result, RESPONSE_FIXTURES.escrow); + schemaValidator.schemaValidate("sign", result); }, - 'withKeypair signAs': async (client, address) => { - const txJSON = REQUEST_FIXTURES.signAs + "withKeypair signAs": async (client, address) => { + const txJSON = REQUEST_FIXTURES.signAs; const keypair = { privateKey: - '001ACAAEDECE405B2A958212629E16F2EB46B153EEE94CDD350FDEFF52795525B7', + "001ACAAEDECE405B2A958212629E16F2EB46B153EEE94CDD350FDEFF52795525B7", publicKey: - '0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020' - } + "0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020", + }; const signature = client.sign(JSON.stringify(txJSON), keypair, { - signAs: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh' - }) - assert.deepEqual(signature, RESPONSE_FIXTURES.signAs) + signAs: "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + }); + assert.deepEqual(signature, RESPONSE_FIXTURES.signAs); }, - 'succeeds - prepared payment': async (client, address, mockRippled) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + "succeeds - prepared payment": async (client, address, mockRippled) => { + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const payment = await client.preparePayment(address, { source: { - address: address, + address, maxAmount: { - value: '1', - currency: 'drops' - } + value: "1", + currency: "drops", + }, }, destination: { - address: 'rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r', + address: "rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r", amount: { - value: '1', - currency: 'drops' - } - } - }) - const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' - const result = client.sign(payment.txJSON, secret) + value: "1", + currency: "drops", + }, + }, + }); + const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV"; + const result = client.sign(payment.txJSON, secret); const expectedResult = { signedTransaction: - '12000022800000002400000017201B008694F261400000000000000168400000000000000C732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D874473045022100A9C91D4CFAE45686146EE0B56D4C53A2E7C2D672FB834D43E0BE2D2E9106519A022075DDA2F92DE552B0C45D83D4E6D35889B3FBF51BFBBD9B25EBF70DE3C96D0D6681145E7B112523F68D2F5E879DB4EAC51C6698A693048314FDB08D07AAA0EB711793A3027304D688E10C3648', - id: '88D6B913C66279EA31ADC25C5806C48B2D4E5680261666790A736E1961217700' - } - assert.deepEqual(result, expectedResult) - schemaValidator.schemaValidate('sign', result) + "12000022800000002400000017201B008694F261400000000000000168400000000000000C732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D874473045022100A9C91D4CFAE45686146EE0B56D4C53A2E7C2D672FB834D43E0BE2D2E9106519A022075DDA2F92DE552B0C45D83D4E6D35889B3FBF51BFBBD9B25EBF70DE3C96D0D6681145E7B112523F68D2F5E879DB4EAC51C6698A693048314FDB08D07AAA0EB711793A3027304D688E10C3648", + id: "88D6B913C66279EA31ADC25C5806C48B2D4E5680261666790A736E1961217700", + }; + assert.deepEqual(result, expectedResult); + schemaValidator.schemaValidate("sign", result); }, - 'succeeds - no flags': async (client, address) => { + "succeeds - no flags": async (client, address) => { const txJSON = - '{"TransactionType":"Payment","Account":"r45Rev1EXGxy2hAUmJPCne97KUE7qyrD3j","Destination":"rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r","Amount":"20000000","Sequence":1,"Fee":"12"}' - const secret = 'shotKgaEotpcYsshSE39vmSnBDRim' - const result = client.sign(txJSON, secret) + '{"TransactionType":"Payment","Account":"r45Rev1EXGxy2hAUmJPCne97KUE7qyrD3j","Destination":"rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r","Amount":"20000000","Sequence":1,"Fee":"12"}'; + const secret = "shotKgaEotpcYsshSE39vmSnBDRim"; + const result = client.sign(txJSON, secret); const expectedResult = { signedTransaction: - '1200002400000001614000000001312D0068400000000000000C7321022B05847086686F9D0499B13136B94AD4323EE1B67D4C429ECC987AB35ACFA34574473045022100C104B7B97C31FACA4597E7D6FCF13BD85BD11375963A62A0AC45B0061236E39802207784F157F6A98DFC85B051CDDF61CC3084C4F5750B82674801C8E9950280D1998114EE3046A5DDF8422C40DDB93F1D522BB4FE6419158314FDB08D07AAA0EB711793A3027304D688E10C3648', - id: '0596925967F541BF332FF6756645B2576A9858414B5B363DC3D34915BE8A70D6' - } - const decoded = binary.decode(result.signedTransaction) + "1200002400000001614000000001312D0068400000000000000C7321022B05847086686F9D0499B13136B94AD4323EE1B67D4C429ECC987AB35ACFA34574473045022100C104B7B97C31FACA4597E7D6FCF13BD85BD11375963A62A0AC45B0061236E39802207784F157F6A98DFC85B051CDDF61CC3084C4F5750B82674801C8E9950280D1998114EE3046A5DDF8422C40DDB93F1D522BB4FE6419158314FDB08D07AAA0EB711793A3027304D688E10C3648", + id: "0596925967F541BF332FF6756645B2576A9858414B5B363DC3D34915BE8A70D6", + }; + const decoded = binary.decode(result.signedTransaction); assert( decoded.Flags == null, `Flags = ${decoded.Flags}, should be undefined` - ) - assert.deepEqual(result, expectedResult) - schemaValidator.schemaValidate('sign', result) + ); + assert.deepEqual(result, expectedResult); + schemaValidator.schemaValidate("sign", result); }, - 'sign succeeds with source.amount/destination.minAmount': async ( + "sign succeeds with source.amount/destination.minAmount": async ( client, address ) => { // See also: 'preparePayment with source.amount/destination.minAmount' const txJSON = - '{"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rEX4LtGJubaUcMWCJULcy4NVxGT9ZEMVRq","Amount":{"currency":"USD","issuer":"rMaa8VLBTjwTJWA2kSme4Sqgphhr6Lr6FH","value":"999999999999999900000000000000000000000000000000000000000000000000000000000000000000000000000000"},"Flags":2147614720,"SendMax":{"currency":"GBP","issuer":"rpat5TmYjDsnFSStmgTumFgXCM9eqsWPro","value":"0.1"},"DeliverMin":{"currency":"USD","issuer":"rMaa8VLBTjwTJWA2kSme4Sqgphhr6Lr6FH","value":"0.1248548562296331"},"Sequence":23,"LastLedgerSequence":8820051,"Fee":"12"}' - const secret = 'shotKgaEotpcYsshSE39vmSnBDRim' - const result = client.sign(txJSON, secret) + '{"TransactionType":"Payment","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Destination":"rEX4LtGJubaUcMWCJULcy4NVxGT9ZEMVRq","Amount":{"currency":"USD","issuer":"rMaa8VLBTjwTJWA2kSme4Sqgphhr6Lr6FH","value":"999999999999999900000000000000000000000000000000000000000000000000000000000000000000000000000000"},"Flags":2147614720,"SendMax":{"currency":"GBP","issuer":"rpat5TmYjDsnFSStmgTumFgXCM9eqsWPro","value":"0.1"},"DeliverMin":{"currency":"USD","issuer":"rMaa8VLBTjwTJWA2kSme4Sqgphhr6Lr6FH","value":"0.1248548562296331"},"Sequence":23,"LastLedgerSequence":8820051,"Fee":"12"}'; + const secret = "shotKgaEotpcYsshSE39vmSnBDRim"; + const result = client.sign(txJSON, secret); const expectedResult = { signedTransaction: - '12000022800200002400000017201B0086955361EC6386F26FC0FFFF0000000000000000000000005553440000000000DC596C88BCDE4E818D416FCDEEBF2C8656BADC9A68400000000000000C69D4438D7EA4C6800000000000000000000000000047425000000000000C155FFE99C8C91F67083CEFFDB69EBFE76348CA6AD4446F8C5D8A5E0B0000000000000000000000005553440000000000DC596C88BCDE4E818D416FCDEEBF2C8656BADC9A7321022B05847086686F9D0499B13136B94AD4323EE1B67D4C429ECC987AB35ACFA34574473045022100D9634523D8E232D4A7807A71856023D82AC928FA29848571B820867898413B5F022041AC00EC1F81A26A6504EBF844A38CC3204694EF2CC1A97A87632721631F93DA81145E7B112523F68D2F5E879DB4EAC51C6698A6930483149F500E50C2F016CA01945E5A1E5846B61EF2D376', - id: '1C558AA9B926C24FB6BBD6950B2DB1350A83F9F12E4385208867907019761A2D' - } - const decoded = binary.decode(result.signedTransaction) + "12000022800200002400000017201B0086955361EC6386F26FC0FFFF0000000000000000000000005553440000000000DC596C88BCDE4E818D416FCDEEBF2C8656BADC9A68400000000000000C69D4438D7EA4C6800000000000000000000000000047425000000000000C155FFE99C8C91F67083CEFFDB69EBFE76348CA6AD4446F8C5D8A5E0B0000000000000000000000005553440000000000DC596C88BCDE4E818D416FCDEEBF2C8656BADC9A7321022B05847086686F9D0499B13136B94AD4323EE1B67D4C429ECC987AB35ACFA34574473045022100D9634523D8E232D4A7807A71856023D82AC928FA29848571B820867898413B5F022041AC00EC1F81A26A6504EBF844A38CC3204694EF2CC1A97A87632721631F93DA81145E7B112523F68D2F5E879DB4EAC51C6698A6930483149F500E50C2F016CA01945E5A1E5846B61EF2D376", + id: "1C558AA9B926C24FB6BBD6950B2DB1350A83F9F12E4385208867907019761A2D", + }; + const decoded = binary.decode(result.signedTransaction); assert( decoded.Flags === 2147614720, `Flags = ${decoded.Flags}, should be 2147614720` - ) - assert.deepEqual(result, expectedResult) - schemaValidator.schemaValidate('sign', result) + ); + assert.deepEqual(result, expectedResult); + schemaValidator.schemaValidate("sign", result); }, - 'throws when encoded tx does not match decoded tx - prepared payment': async ( + "throws when encoded tx does not match decoded tx - prepared payment": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const payment = await client.preparePayment(address, { source: { - address: address, + address, maxAmount: { - value: '1.1234567', - currency: 'drops' - } + value: "1.1234567", + currency: "drops", + }, }, destination: { - address: 'rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r', + address: "rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r", amount: { - value: '1.1234567', - currency: 'drops' - } - } - }) - const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' + value: "1.1234567", + currency: "drops", + }, + }, + }); + const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV"; assert.throws(() => { - client.sign(payment.txJSON, secret) - }, /^Error: 1\.1234567 is an illegal amount/) + client.sign(payment.txJSON, secret); + }, /^Error: 1\.1234567 is an illegal amount/); }, - 'throws when encoded tx does not match decoded tx - prepared order': async ( + "throws when encoded tx does not match decoded tx - prepared order": async ( client, address, mockRippled ) => { - mockRippled.addResponse({command: 'server_info'}, rippled.server_info.normal) - mockRippled.addResponse({command: 'fee'}, rippled.fee) - mockRippled.addResponse({command: 'ledger_current'}, rippled.ledger_current) - mockRippled.addResponse({command: 'account_info'}, rippled.account_info.normal) + mockRippled.addResponse( + { command: "server_info" }, + rippled.server_info.normal + ); + mockRippled.addResponse({ command: "fee" }, rippled.fee); + mockRippled.addResponse( + { command: "ledger_current" }, + rippled.ledger_current + ); + mockRippled.addResponse( + { command: "account_info" }, + rippled.account_info.normal + ); const order = { - direction: 'sell', + direction: "sell", quantity: { - currency: 'USD', - counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', - value: '3.140000' + currency: "USD", + counterparty: "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + value: "3.140000", }, totalPrice: { - currency: 'XRP', - value: '31415' - } - } - const prepared = await client.prepareOrder(address, order, {sequence: 123}) - const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' + currency: "XRP", + value: "31415", + }, + }; + const prepared = await client.prepareOrder(address, order, { + sequence: 123, + }); + const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV"; try { - client.sign(prepared.txJSON, secret) - return Promise.reject(new Error('client.sign should have thrown')) + client.sign(prepared.txJSON, secret); + return await Promise.reject(new Error("client.sign should have thrown")); } catch (error) { - assert.equal(error.name, 'ValidationError') + assert.equal(error.name, "ValidationError"); assert.equal( error.message, - 'Serialized transaction does not match original txJSON. See `error.data`' - ) + "Serialized transaction does not match original txJSON. See `error.data`" + ); assert.deepEqual(error.data.diff, { TakerGets: { - value: '3.14' - } - }) + value: "3.14", + }, + }); } }, - 'throws when encoded tx does not match decoded tx - AccountSet': async ( + "throws when encoded tx does not match decoded tx - AccountSet": async ( client, address ) => { - const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' + const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV"; const request = { // TODO: This fails when address is X-address txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Domain":"6578616D706C652E636F6D","LastLedgerSequence":8820051,"Fee":"1.2","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`, instructions: { - fee: '0.0000012', + fee: "0.0000012", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; assert.throws(() => { - client.sign(request.txJSON, secret) - }, /Error: 1\.2 is an illegal amount/) + client.sign(request.txJSON, secret); + }, /Error: 1\.2 is an illegal amount/); }, - 'throws when encoded tx does not match decoded tx - higher fee': async ( + "throws when encoded tx does not match decoded tx - higher fee": async ( client, address ) => { - const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' + const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV"; const request = { // TODO: This fails when address is X-address txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Domain":"6578616D706C652E636F6D","LastLedgerSequence":8820051,"Fee":"1123456.7","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`, instructions: { - fee: '1.1234567', + fee: "1.1234567", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; assert.throws(() => { - client.sign(request.txJSON, secret) - }, /Error: 1123456\.7 is an illegal amount/) + client.sign(request.txJSON, secret); + }, /Error: 1123456\.7 is an illegal amount/); }, - 'throws when Fee exceeds maxFeeXRP (in drops)': async (client, address) => { - const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' + "throws when Fee exceeds maxFeeXRP (in drops)": async (client, address) => { + const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV"; const request = { txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"${address}","Domain":"6578616D706C652E636F6D","LastLedgerSequence":8820051,"Fee":"2010000","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`, instructions: { - fee: '2.01', + fee: "2.01", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; assert.throws(() => { - client.sign(request.txJSON, secret) - }, /Fee" should not exceed "2000000"\. To use a higher fee, set `maxFeeXRP` in the Client constructor\./) + client.sign(request.txJSON, secret); + }, /Fee" should not exceed "2000000"\. To use a higher fee, set `maxFeeXRP` in the Client constructor\./); }, - 'throws when Fee exceeds maxFeeXRP (in drops) - custom maxFeeXRP': async ( + "throws when Fee exceeds maxFeeXRP (in drops) - custom maxFeeXRP": async ( client, address ) => { - client._maxFeeXRP = '1.9' - const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' + client._maxFeeXRP = "1.9"; + const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV"; const request = { txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"${address}","Domain":"6578616D706C652E636F6D","LastLedgerSequence":8820051,"Fee":"2010000","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`, instructions: { - fee: '2.01', + fee: "2.01", sequence: 23, - maxLedgerVersion: 8820051 - } - } + maxLedgerVersion: 8820051, + }, + }; assert.throws(() => { - client.sign(request.txJSON, secret) - }, /Fee" should not exceed "1900000"\. To use a higher fee, set `maxFeeXRP` in the Client constructor\./) + client.sign(request.txJSON, secret); + }, /Fee" should not exceed "1900000"\. To use a higher fee, set `maxFeeXRP` in the Client constructor\./); }, - 'permits fee exceeding 2000000 drops when maxFeeXRP is higher than 2 XRP': async ( - client, - address - ) => { - client._maxFeeXRP = '2.1' - const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV' - const request = { - // TODO: This fails when address is X-address - txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","LastLedgerSequence":8820051,"Fee":"2010000","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`, - instructions: { - fee: '2.01', - sequence: 23, - maxLedgerVersion: 8820051 - } - } + "permits fee exceeding 2000000 drops when maxFeeXRP is higher than 2 XRP": + async (client, address) => { + client._maxFeeXRP = "2.1"; + const secret = "shsWGZcmZz6YsWWmcnpfr6fLTdtFV"; + const request = { + // TODO: This fails when address is X-address + txJSON: `{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","LastLedgerSequence":8820051,"Fee":"2010000","Sequence":23,"SigningPubKey":"02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"}`, + instructions: { + fee: "2.01", + sequence: 23, + maxLedgerVersion: 8820051, + }, + }; - const result = client.sign(request.txJSON, secret) + const result = client.sign(request.txJSON, secret); - const expectedResponse = { - signedTransaction: - '12000322800000002400000017201B008695536840000000001EAB90732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D87446304402200203F219F5371D2C6506888B1B02B27E74998F7A42D412C32FE319AC1A5B8DEF02205959A1B02253ACCCE542759E9886466C56D16B04676FA492AD34AA0E877E91F381145E7B112523F68D2F5E879DB4EAC51C6698A69304', - id: '061D5593E0A117F389826419CAC049A73C7CFCA65A20B788781D41240143D864' - } + const expectedResponse = { + signedTransaction: + "12000322800000002400000017201B008695536840000000001EAB90732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D87446304402200203F219F5371D2C6506888B1B02B27E74998F7A42D412C32FE319AC1A5B8DEF02205959A1B02253ACCCE542759E9886466C56D16B04676FA492AD34AA0E877E91F381145E7B112523F68D2F5E879DB4EAC51C6698A69304", + id: "061D5593E0A117F389826419CAC049A73C7CFCA65A20B788781D41240143D864", + }; - assert.deepEqual(result, expectedResponse) - schemaValidator.schemaValidate('sign', result) + assert.deepEqual(result, expectedResponse); + schemaValidator.schemaValidate("sign", result); + }, + + "sign with ticket": async (client, address) => { + const secret = "sn7n5R1cR5Y3fRFkuWXA94Ts1frVJ"; + const result = client.sign(REQUEST_FIXTURES.ticket.txJSON, secret); + assert.deepEqual(result, RESPONSE_FIXTURES.ticket); + schemaValidator.schemaValidate("sign", result); }, - - 'sign with ticket': async (client, address) => { - const secret = 'sn7n5R1cR5Y3fRFkuWXA94Ts1frVJ' - const result = client.sign(REQUEST_FIXTURES.ticket.txJSON, secret) - assert.deepEqual(result, RESPONSE_FIXTURES.ticket) - schemaValidator.schemaValidate('sign', result) - } -} +}; diff --git a/test/connection.ts b/test/connection.ts index 0ee5e8d4..60aff067 100644 --- a/test/connection.ts +++ b/test/connection.ts @@ -1,541 +1,529 @@ -import _ from 'lodash' -import net from 'net' -import assert from 'assert-diff' -import setupClient from './setupClient' -import {Client} from 'xrpl-local' -import {ignoreWebSocketDisconnect} from './testUtils' -import {Connection} from 'xrpl-local/client' -import rippled from './fixtures/rippled' +import net from "net"; -const TIMEOUT = 200000 // how long before each test case times out -const isBrowser = (process as any).browser +import assert from "assert-diff"; +import _ from "lodash"; + +import { Client } from "xrpl-local"; +import { Connection } from "xrpl-local/client"; + +import rippled from "./fixtures/rippled"; +import setupClient from "./setupClient"; +import { ignoreWebSocketDisconnect } from "./testUtils"; + +const TIMEOUT = 200000; // how long before each test case times out +const isBrowser = (process as any).browser; function createServer() { return new Promise((resolve, reject) => { - const server = net.createServer() - server.on('listening', function () { - resolve(server) - }) - server.on('error', function (error) { - reject(error) - }) - server.listen(0, '0.0.0.0') - }) + const server = net.createServer(); + server.on("listening", function () { + resolve(server); + }); + server.on("error", function (error) { + reject(error); + }); + server.listen(0, "0.0.0.0"); + }); } -describe('Connection', function () { - this.timeout(TIMEOUT) - beforeEach(setupClient.setup) - afterEach(setupClient.teardown) +describe("Connection", function () { + this.timeout(TIMEOUT); + beforeEach(setupClient.setup); + afterEach(setupClient.teardown); - it('default options', function () { - const connection: any = new Connection('url') - assert.strictEqual(connection._url, 'url') - assert(connection._config.proxy == null) - assert(connection._config.authorization == null) - }) + it("default options", function () { + const connection: any = new Connection("url"); + assert.strictEqual(connection._url, "url"); + assert(connection._config.proxy == null); + assert(connection._config.authorization == null); + }); - describe('trace', () => { - const mockedRequestData = {mocked: 'request'} - const mockedResponse = JSON.stringify({mocked: 'response', id: 0}) + describe("trace", function () { + const mockedRequestData = { mocked: "request" }; + const mockedResponse = JSON.stringify({ mocked: "response", id: 0 }); const expectedMessages = [ // We add the ID here, since it's not a part of the user-provided request. - ['send', JSON.stringify({...mockedRequestData, id: 0})], - ['receive', mockedResponse] - ] - const originalConsoleLog = console.log + ["send", JSON.stringify({ ...mockedRequestData, id: 0 })], + ["receive", mockedResponse], + ]; + const originalConsoleLog = console.log; - afterEach(() => { - console.log = originalConsoleLog - }) + afterEach(function () { + console.log = originalConsoleLog; + }); - it('as false', function () { - const messages = [] - console.log = (id, message) => messages.push([id, message]) - const connection: any = new Connection('url', {trace: false}) - connection._ws = {send: function () {}} - connection.request(mockedRequestData) - connection._onMessage(mockedResponse) - assert.deepEqual(messages, []) - }) + it("as false", function () { + const messages: any[] = []; + console.log = (id, message) => messages.push([id, message]); + const connection: any = new Connection("url", { trace: false }); + connection._ws = { send() {} }; + connection.request(mockedRequestData); + connection._onMessage(mockedResponse); + assert.deepEqual(messages, []); + }); - it('as true', function () { - const messages = [] - console.log = (id, message) => messages.push([id, message]) - const connection: any = new Connection('url', {trace: true}) - connection._ws = {send: function () {}} - connection.request(mockedRequestData) - connection._onMessage(mockedResponse) - assert.deepEqual(messages, expectedMessages) - }) + it("as true", function () { + const messages: any[] = []; + console.log = (id, message) => messages.push([id, message]); + const connection: any = new Connection("url", { trace: true }); + connection._ws = { send() {} }; + connection.request(mockedRequestData); + connection._onMessage(mockedResponse); + assert.deepEqual(messages, expectedMessages); + }); - it('as a function', function () { - const messages = [] - const connection: any = new Connection('url', { - trace: (id, message) => messages.push([id, message]) - }) - connection._ws = {send: function () {}} - connection.request(mockedRequestData) - connection._onMessage(mockedResponse) - assert.deepEqual(messages, expectedMessages) - }) - }) + it("as a function", function () { + const messages: any[] = []; + const connection: any = new Connection("url", { + trace: (id, message) => messages.push([id, message]), + }); + connection._ws = { send() {} }; + connection.request(mockedRequestData); + connection._onMessage(mockedResponse); + assert.deepEqual(messages, expectedMessages); + }); + }); - it('with proxy', function (done) { + it("with proxy", function (done) { if (isBrowser) { - done() - return + done(); + return; } createServer().then((server: any) => { - const port = server.address().port - const expect = 'CONNECT localhost' - server.on('connection', (socket) => { - socket.on('data', (data) => { - const got = data.toString('ascii', 0, expect.length) - assert.strictEqual(got, expect) - server.close() - connection.disconnect() - done() - }) - }) + const port = server.address().port; + const expect = "CONNECT localhost"; + server.on("connection", (socket) => { + socket.on("data", (data) => { + const got = data.toString("ascii", 0, expect.length); + assert.strictEqual(got, expect); + server.close(); + connection.disconnect(); + done(); + }); + }); const options = { - proxy: 'ws://localhost:' + port, - authorization: 'authorization', - trustedCertificates: ['path/to/pem'] - } - const connection = new Connection( - this.client.connection._url, - options - ) + proxy: `ws://localhost:${port}`, + authorization: "authorization", + trustedCertificates: ["path/to/pem"], + }; + const connection = new Connection(this.client.connection._url, options); connection.connect().catch((err) => { - assert(err instanceof this.client.errors.NotConnectedError) - }) - }, done) - }) + assert(err instanceof this.client.errors.NotConnectedError); + }); + }, done); + }); - it('Multiply disconnect calls', function () { - this.client.disconnect() - return this.client.disconnect() - }) + it("Multiply disconnect calls", function () { + this.client.disconnect(); + return this.client.disconnect(); + }); - it('reconnect', function () { - return this.client.connection.reconnect() - }) + it("reconnect", function () { + return this.client.connection.reconnect(); + }); - it('NotConnectedError', function () { - const connection = new Connection('url') - return connection.request({ - command: 'ledger', - ledger_index: 'validated' + it("NotConnectedError", function () { + const connection = new Connection("url"); + return connection + .request({ + command: "ledger", + ledger_index: "validated", }) .then(() => { - assert(false, 'Should throw NotConnectedError') + assert(false, "Should throw NotConnectedError"); }) .catch((error) => { - assert(error instanceof this.client.errors.NotConnectedError) - }) - }) + assert(error instanceof this.client.errors.NotConnectedError); + }); + }); - it('should throw NotConnectedError if server not responding ', function (done) { + it("should throw NotConnectedError if server not responding ", function (done) { if (isBrowser) { - const phantomTest = /PhantomJS/ - if (phantomTest.test(navigator.userAgent)) { + if (navigator.userAgent.includes("PhantomJS")) { // inside PhantomJS this one just hangs, so skip as not very relevant - done() - return + done(); + return; } } // Address where no one listens - const connection = new Connection( - 'ws://testripple.circleci.com:129' - ) - connection.on('error', done) + const connection = new Connection("ws://testripple.circleci.com:129"); + connection.on("error", done); connection.connect().catch((error) => { - assert(error instanceof this.client.errors.NotConnectedError) - done() - }) - }) + assert(error instanceof this.client.errors.NotConnectedError); + done(); + }); + }); - it('DisconnectedError', async function () { - this.mockRippled.suppressOutput = true + it("DisconnectedError", async function () { + this.mockRippled.suppressOutput = true; this.mockRippled.on(`request_server_info`, function (request, conn) { - assert.strictEqual(request.command, 'server_info') - conn.close() - }) + assert.strictEqual(request.command, "server_info"); + conn.close(); + }); return this.client - .request({command: "server_info"}) + .request({ command: "server_info" }) .then(() => { - assert(false, 'Should throw DisconnectedError') + assert(false, "Should throw DisconnectedError"); }) .catch((error) => { - assert(error instanceof this.client.errors.DisconnectedError) - }) - }) + assert(error instanceof this.client.errors.DisconnectedError); + }); + }); - it('TimeoutError', function () { - this.client.connection._ws.send = function (message, options, callback) { - callback(null) - } - const request = {command: 'server_info'} + it("TimeoutError", function () { + this.client.connection._ws.send = function (message, callback) { + callback(null); + }; + const request = { command: "server_info" }; return this.client.connection .request(request, 10) .then(() => { - assert(false, 'Should throw TimeoutError') + assert(false, "Should throw TimeoutError"); }) .catch((error) => { - assert(error instanceof this.client.errors.TimeoutError) - }) - }) + assert(error instanceof this.client.errors.TimeoutError); + }); + }); - it('DisconnectedError on send', function () { - this.client.connection._ws.send = function (message, options, callback) { - callback({message: 'not connected'}) - } + it("DisconnectedError on send", function () { + this.client.connection._ws.send = function (message, callback) { + callback({ message: "not connected" }); + }; return this.client - .request({command: "server_info"}) + .request({ command: "server_info" }) .then(() => { - assert(false, 'Should throw DisconnectedError') + assert(false, "Should throw DisconnectedError"); }) .catch((error) => { - assert(error instanceof this.client.errors.DisconnectedError) - assert.strictEqual(error.message, 'not connected') - }) - }) + console.log(error); + assert(error instanceof this.client.errors.DisconnectedError); + assert.strictEqual(error.message, "not connected"); + }); + }); - it('DisconnectedError on initial _onOpen send', async function () { + it("DisconnectedError on initial _onOpen send", async function () { // _onOpen previously could throw PromiseRejectionHandledWarning: Promise rejection was handled asynchronously // do not rely on the client.setup hook to test this as it bypasses the case, disconnect client connection first - await this.client.disconnect() + await this.client.disconnect(); // stub _onOpen to only run logic relevant to test case this.client.connection._onOpen = () => { // overload websocket send on open when _ws exists this.client.connection._ws.send = function (data, options, cb) { // recent ws throws this error instead of calling back - throw new Error('WebSocket is not open: readyState 0 (CONNECTING)') - } - const request = {command: 'subscribe', streams: ['ledger']} - return this.client.connection.request(request) - } + throw new Error("WebSocket is not open: readyState 0 (CONNECTING)"); + }; + const request = { command: "subscribe", streams: ["ledger"] }; + return this.client.connection.request(request); + }; try { - await this.client.connect() + await this.client.connect(); } catch (error) { - assert(error instanceof this.client.errors.DisconnectedError) + assert(error instanceof this.client.errors.DisconnectedError); assert.strictEqual( error.message, - 'WebSocket is not open: readyState 0 (CONNECTING)' - ) + "WebSocket is not open: readyState 0 (CONNECTING)" + ); } - }) + }); - it('ResponseFormatError', function () { + it("ResponseFormatError", function () { return this.client - .request({command: 'test_command', data: {unrecognizedResponse: true}}) + .request({ + command: "test_command", + data: { unrecognizedResponse: true }, + }) .then(() => { - assert(false, 'Should throw ResponseFormatError') + assert(false, "Should throw ResponseFormatError"); }) .catch((error) => { - assert(error instanceof this.client.errors.ResponseFormatError) - }) - }) + assert(error instanceof this.client.errors.ResponseFormatError); + }); + }); - it('reconnect on unexpected close', function (done) { - this.client.connection.on('connected', () => { - done() - }) + it("reconnect on unexpected close", function (done) { + this.client.connection.on("connected", () => { + done(); + }); setTimeout(() => { - this.client.connection._ws.close() - }, 1) - }) + this.client.connection._ws.close(); + }, 1); + }); - describe('reconnection test', function () { - it('reconnect on several unexpected close', function (done) { + describe("reconnection test", function () { + it("reconnect on several unexpected close", function (done) { if (isBrowser) { - const phantomTest = /PhantomJS/ - if (phantomTest.test(navigator.userAgent)) { + if (navigator.userAgent.includes("PhantomJS")) { // inside PhantomJS this one just hangs, so skip as not very relevant - done() - return + done(); + return; } } - this.timeout(70001) - const self = this + this.timeout(70001); + const self = this; function breakConnection() { self.client.connection .request({ - command: 'test_command', - data: {disconnectIn: 10} + command: "test_command", + data: { disconnectIn: 10 }, }) - .catch(ignoreWebSocketDisconnect) + .catch(ignoreWebSocketDisconnect); } - let connectsCount = 0 - let disconnectsCount = 0 - let reconnectsCount = 0 - let code = 0 - this.client.connection.on('reconnecting', () => { - reconnectsCount += 1 - }) - this.client.connection.on('disconnected', (_code) => { - code = _code - disconnectsCount += 1 - }) - const num = 3 - this.client.connection.on('connected', () => { - connectsCount += 1 + let connectsCount = 0; + let disconnectsCount = 0; + let reconnectsCount = 0; + let code = 0; + this.client.connection.on("reconnecting", () => { + reconnectsCount += 1; + }); + this.client.connection.on("disconnected", (_code) => { + code = _code; + disconnectsCount += 1; + }); + const num = 3; + this.client.connection.on("connected", () => { + connectsCount += 1; if (connectsCount < num) { - breakConnection() + breakConnection(); } if (connectsCount === num) { if (disconnectsCount !== num) { done( new Error( - 'disconnectsCount must be equal to ' + - num + - '(got ' + - disconnectsCount + - ' instead)' + `disconnectsCount must be equal to ${num}(got ${disconnectsCount} instead)` ) - ) + ); } else if (reconnectsCount !== num) { done( new Error( - 'reconnectsCount must be equal to ' + - num + - ' (got ' + - reconnectsCount + - ' instead)' + `reconnectsCount must be equal to ${num} (got ${reconnectsCount} instead)` ) - ) + ); } else if (code !== 1006) { done( - new Error( - 'disconnect must send code 1006 (got ' + code + ' instead)' - ) - ) + new Error(`disconnect must send code 1006 (got ${code} instead)`) + ); } else { - done() + done(); } } - }) + }); - breakConnection() - }) - }) + breakConnection(); + }); + }); - it('reconnect event on heartbeat failure', function (done) { + it("reconnect event on heartbeat failure", function (done) { if (isBrowser) { - const phantomTest = /PhantomJS/ - if (phantomTest.test(navigator.userAgent)) { + if (navigator.userAgent.includes("PhantomJS")) { // inside PhantomJS this one just hangs, so skip as not very relevant - done() - return + done(); + return; } } // Set the heartbeat to less than the 1 second ping response - this.client.connection._config.timeout = 500 + this.client.connection._config.timeout = 500; // Drop the test runner timeout, since this should be a quick test - this.timeout(5000) + this.timeout(5000); // Hook up a listener for the reconnect event - this.client.connection.on('reconnect', () => done()) + this.client.connection.on("reconnect", () => done()); // Trigger a heartbeat this.client.connection._heartbeat().catch((error) => { /* ignore - test expects heartbeat failure */ - }) - }) + }); + }); - it('heartbeat failure and reconnect failure', function (done) { + it("heartbeat failure and reconnect failure", function (done) { if (isBrowser) { - const phantomTest = /PhantomJS/ - if (phantomTest.test(navigator.userAgent)) { + if (navigator.userAgent.includes("PhantomJS")) { // inside PhantomJS this one just hangs, so skip as not very relevant - done() - return + done(); + return; } } // Set the heartbeat to less than the 1 second ping response - this.client.connection._config.timeout = 500 + this.client.connection._config.timeout = 500; // Drop the test runner timeout, since this should be a quick test - this.timeout(5000) + this.timeout(5000); // fail on reconnect/connection this.client.connection.reconnect = async () => { - throw new Error('error on reconnect') - } + throw new Error("error on reconnect"); + }; // Hook up a listener for the reconnect error event - this.client.on('error', (error, message) => { - if (error === 'reconnect' && message === 'error on reconnect') { - return done() + this.client.on("error", (error, message) => { + if (error === "reconnect" && message === "error on reconnect") { + return done(); } - return done(new Error('Expected error on reconnect')) - }) + return done(new Error("Expected error on reconnect")); + }); // Trigger a heartbeat - this.client.connection._heartbeat() - }) + this.client.connection._heartbeat(); + }); - it('should emit disconnected event with code 1000 (CLOSE_NORMAL)', function (done) { - this.client.once('disconnected', (code) => { - assert.strictEqual(code, 1000) - done() - }) - this.client.disconnect() - }) + it("should emit disconnected event with code 1000 (CLOSE_NORMAL)", function (done) { + this.client.once("disconnected", (code) => { + assert.strictEqual(code, 1000); + done(); + }); + this.client.disconnect(); + }); - it('should emit disconnected event with code 1006 (CLOSE_ABNORMAL)', function (done) { - this.client.connection.once('error', (error) => { - done(new Error('should not throw error, got ' + String(error))) - }) - this.client.connection.once('disconnected', (code) => { - assert.strictEqual(code, 1006) - done() - }) + it("should emit disconnected event with code 1006 (CLOSE_ABNORMAL)", function (done) { + this.client.connection.once("error", (error) => { + done(new Error(`should not throw error, got ${String(error)}`)); + }); + this.client.connection.once("disconnected", (code) => { + assert.strictEqual(code, 1006); + done(); + }); this.client.connection .request({ - command: 'test_command', - data: {disconnectIn: 10} + command: "test_command", + data: { disconnectIn: 10 }, }) - .catch(ignoreWebSocketDisconnect) - }) + .catch(ignoreWebSocketDisconnect); + }); - it('should emit connected event on after reconnect', function (done) { - this.client.once('connected', done) - this.client.connection._ws.close() - }) + it("should emit connected event on after reconnect", function (done) { + this.client.once("connected", done); + this.client.connection._ws.close(); + }); - it('Multiply connect calls', function () { + it("Multiply connect calls", function () { return this.client.connect().then(() => { - return this.client.connect() - }) - }) + return this.client.connect(); + }); + }); - it('Cannot connect because no server', function () { - const connection = new Connection(undefined as string) + it("Cannot connect because no server", function () { + const connection = new Connection(undefined as unknown as string); return connection .connect() .then(() => { - assert(false, 'Should throw ConnectionError') + assert(false, "Should throw ConnectionError"); }) .catch((error) => { assert( error instanceof this.client.errors.ConnectionError, - 'Should throw ConnectionError' - ) - }) - }) + "Should throw ConnectionError" + ); + }); + }); - it('connect multiserver error', function () { + it("connect multiserver error", function () { assert.throws(function () { new Client({ - servers: ['wss://server1.com', 'wss://server2.com'] - } as any) - }, this.client.errors.RippleError) - }) + servers: ["wss://server1.com", "wss://server2.com"], + } as any); + }, this.client.errors.RippleError); + }); - it('connect throws error', function (done) { - this.client.once('error', (type, info) => { - assert.strictEqual(type, 'type') - assert.strictEqual(info, 'info') - done() - }) - this.client.connection.emit('error', 'type', 'info') - }) + it("connect throws error", function (done) { + this.client.once("error", (type, info) => { + assert.strictEqual(type, "type"); + assert.strictEqual(info, "info"); + done(); + }); + this.client.connection.emit("error", "type", "info"); + }); - it('emit stream messages', function (done) { - let transactionCount = 0 - let pathFindCount = 0 - this.client.connection.on('transaction', () => { - transactionCount++ - }) - this.client.connection.on('path_find', () => { - pathFindCount++ - }) - this.client.connection.on('response', (message) => { - assert.strictEqual(message.id, 1) - assert.strictEqual(transactionCount, 1) - assert.strictEqual(pathFindCount, 1) - done() - }) + it("emit stream messages", function (done) { + let transactionCount = 0; + let pathFindCount = 0; + this.client.connection.on("transaction", () => { + transactionCount++; + }); + this.client.connection.on("path_find", () => { + pathFindCount++; + }); + this.client.connection.on("response", (message) => { + assert.strictEqual(message.id, 1); + assert.strictEqual(transactionCount, 1); + assert.strictEqual(pathFindCount, 1); + done(); + }); this.client.connection._onMessage( JSON.stringify({ - type: 'transaction' + type: "transaction", }) - ) + ); this.client.connection._onMessage( JSON.stringify({ - type: 'path_find' + type: "path_find", }) - ) + ); this.client.connection._onMessage( JSON.stringify({ - type: 'response', - id: 1 + type: "response", + id: 1, }) - ) - }) + ); + }); - it('invalid message id', function (done) { - this.client.on('error', (errorCode, errorMessage, message) => { - assert.strictEqual(errorCode, 'badMessage') - assert.strictEqual(errorMessage, 'valid id not found in response') - assert.strictEqual(message, '{"type":"response","id":"must be integer"}') - done() - }) + it("invalid message id", function (done) { + this.client.on("error", (errorCode, errorMessage, message) => { + assert.strictEqual(errorCode, "badMessage"); + assert.strictEqual(errorMessage, "valid id not found in response"); + assert.strictEqual(message, '{"type":"response","id":"must be integer"}'); + done(); + }); this.client.connection._onMessage( JSON.stringify({ - type: 'response', - id: 'must be integer' + type: "response", + id: "must be integer", }) - ) - }) + ); + }); - it('propagates error message', function (done) { - this.client.on('error', (errorCode, errorMessage, data) => { - assert.strictEqual(errorCode, 'slowDown') - assert.strictEqual(errorMessage, 'slow down') - assert.deepEqual(data, {error: 'slowDown', error_message: 'slow down'}) - done() - }) + it("propagates error message", function (done) { + this.client.on("error", (errorCode, errorMessage, data) => { + assert.strictEqual(errorCode, "slowDown"); + assert.strictEqual(errorMessage, "slow down"); + assert.deepEqual(data, { error: "slowDown", error_message: "slow down" }); + done(); + }); this.client.connection._onMessage( JSON.stringify({ - error: 'slowDown', - error_message: 'slow down' + error: "slowDown", + error_message: "slow down", }) - ) - }) + ); + }); + + it("propagates RippledError data", function (done) { + const request = { command: "subscribe", streams: "validations" }; + this.mockRippled.addResponse(request, rippled.subscribe.error); - it('propagates RippledError data', function (done) { - const request = {command: 'subscribe', streams: 'validations'} - this.mockRippled.addResponse(request, rippled.subscribe.error) this.client.request(request).catch((error) => { - assert.strictEqual(error.name, 'RippledError') - assert.strictEqual(error.data.error, 'invalidParams') - assert.strictEqual(error.message, 'Invalid parameters.') - assert.strictEqual(error.data.error_code, 31) - assert.strictEqual(error.data.error_message, 'Invalid parameters.') + assert.strictEqual(error.name, "RippledError"); + assert.strictEqual(error.data.error, "invalidParams"); + assert.strictEqual(error.message, "Invalid parameters."); + assert.strictEqual(error.data.error_code, 31); + assert.strictEqual(error.data.error_message, "Invalid parameters."); assert.deepEqual(error.data.request, { - command: 'subscribe', + command: "subscribe", id: 0, - streams: 'validations' - }) - assert.strictEqual(error.data.status, 'error') - assert.strictEqual(error.data.type, 'response') - done() - }) - }) + streams: "validations", + }); + done(); + }); + }); - it('unrecognized message type', function (done) { + it("unrecognized message type", function (done) { // This enables us to automatically support any // new messages added by rippled in the future. - this.client.connection.on('unknown', (event) => { - assert.deepEqual(event, {type: 'unknown'}) - done() - }) + this.client.connection.on("unknown", (event) => { + assert.deepEqual(event, { type: "unknown" }); + done(); + }); - this.client.connection._onMessage(JSON.stringify({type: 'unknown'})) - }) + this.client.connection._onMessage(JSON.stringify({ type: "unknown" })); + }); // it('should clean up websocket connection if error after websocket is opened', async function () { // await this.client.disconnect() @@ -555,34 +543,35 @@ describe('Connection', function () { // } // }) - it('should try to reconnect on empty subscribe response on reconnect', function (done) { - this.timeout(23000) - this.client.on('error', (error) => { - done(error || new Error('Should not emit error.')) - }) - let disconnectedCount = 0 - this.client.on('connected', () => { + it("should try to reconnect on empty subscribe response on reconnect", function (done) { + this.timeout(23000); + this.client.on("error", (error) => { + done(error || new Error("Should not emit error.")); + }); + let disconnectedCount = 0; + this.client.on("connected", () => { done( disconnectedCount !== 1 - ? new Error('Wrong number of disconnects') + ? new Error("Wrong number of disconnects") : undefined - ) - }) - this.client.on('disconnected', () => { - disconnectedCount++ - }) + ); + }); + this.client.on("disconnected", () => { + disconnectedCount++; + }); this.client.connection.request({ - command: 'test_command', - data: {disconnectIn: 5} - }) - }) + command: "test_command", + data: { disconnectIn: 5 }, + }); + }); - it('should not crash on error', async function (done) { - this.mockRippled.suppressOutput = true - this.client.connection.request({ - command: 'test_garbage' - }) - .then(() => new Error('Should not have succeeded')) - .catch(done()) - }) -}) + it("should not crash on error", async function (done) { + this.mockRippled.suppressOutput = true; + this.client.connection + .request({ + command: "test_garbage", + }) + .then(() => new Error("Should not have succeeded")) + .catch(done()); + }); +}); diff --git a/test/integration/integration.ts b/test/integration/integration.ts index ab5659ff..241433f4 100644 --- a/test/integration/integration.ts +++ b/test/integration/integration.ts @@ -1,49 +1,54 @@ -import _ from 'lodash' -import assert from 'assert' -import wallet from './wallet' -import requests from '../fixtures/requests' -import {Client} from 'xrpl-local' -import {payTo, ledgerAccept} from './utils' -import {errors} from 'xrpl-local/common' -import {isValidSecret} from 'xrpl-local/utils' -import { generateXAddress } from '../../src/utils/generateAddress' -import { isValidXAddress } from 'ripple-address-codec' +import assert from "assert"; + +import _ from "lodash"; +import { isValidXAddress } from "ripple-address-codec"; + +import { Client } from "xrpl-local"; +import { errors } from "xrpl-local/common"; +import { isValidSecret } from "xrpl-local/utils"; + +import { generateXAddress } from "../../src/utils/generateAddress"; +import requests from "../fixtures/requests"; + +import { payTo, ledgerAccept } from "./utils"; +import wallet from "./wallet"; // how long before each test case times out -const TIMEOUT = 20000 -const INTERVAL = 1000 // how long to wait between checks for validated ledger +const TIMEOUT = 20000; +const INTERVAL = 1000; // how long to wait between checks for validated ledger -const HOST = process.env.HOST ?? "0.0.0.0" -const PORT = process.env.PORT ?? "6006" -const serverUrl = `ws://${HOST}:${PORT}` +const HOST = process.env.HOST ?? "0.0.0.0"; +const PORT = process.env.PORT ?? "6006"; +const serverUrl = `ws://${HOST}:${PORT}`; -console.log(serverUrl) +console.log(serverUrl); function acceptLedger(client) { - return client.connection.request({command: 'ledger_accept'}) + return client.connection.request({ command: "ledger_accept" }); } function verifyTransaction(testcase, hash, type, options, txData, account) { - console.log('VERIFY...') + console.log("VERIFY..."); return testcase.client .request({ - command: 'tx', + command: "tx", transaction: hash, min_ledger: options.minLedgerVersion, - max_ledger: options.maxLedgerVersion - }).then((data) => { - assert(data && data.result) - assert.strictEqual(data.result.TransactionType, type) - assert.strictEqual(data.result.Account, account) - assert.strictEqual(data.result.meta.TransactionResult, 'tesSUCCESS') + max_ledger: options.maxLedgerVersion, + }) + .then((data) => { + assert(data && data.result); + assert.strictEqual(data.result.TransactionType, type); + assert.strictEqual(data.result.Account, account); + assert.strictEqual(data.result.meta.TransactionResult, "tesSUCCESS"); if (testcase.transactions != null) { - testcase.transactions.push(hash) + testcase.transactions.push(hash); } - return {txJSON: JSON.stringify(txData), id: hash, tx: data} + return { txJSON: JSON.stringify(txData), id: hash, tx: data }; }) .catch((error) => { if (error instanceof errors.PendingLedgerVersionError) { - console.log('NOT VALIDATED YET...') + console.log("NOT VALIDATED YET..."); return new Promise((resolve, reject) => { setTimeout( () => @@ -56,12 +61,12 @@ function verifyTransaction(testcase, hash, type, options, txData, account) { account ).then(resolve, reject), INTERVAL - ) - }) + ); + }); } - console.log(error.stack) - assert(false, 'Transaction not successful: ' + error.message) - }) + console.log(error.stack); + assert(false, `Transaction not successful: ${error.message}`); + }); } function testTransaction( @@ -72,27 +77,27 @@ function testTransaction( address = wallet.getAddress(), secret = wallet.getSecret() ) { - const txJSON = prepared.txJSON - assert(txJSON, 'missing txJSON') - const txData = JSON.parse(txJSON) - assert.strictEqual(txData.Account, address) - const signedData = testcase.client.sign(txJSON, secret) - console.log('PREPARED...') + const txJSON = prepared.txJSON; + assert(txJSON, "missing txJSON"); + const txData = JSON.parse(txJSON); + assert.strictEqual(txData.Account, address); + const signedData = testcase.client.sign(txJSON, secret); + console.log("PREPARED..."); return testcase.client - .request({command: 'submit', tx_blob: signedData.signedTransaction}) + .request({ command: "submit", tx_blob: signedData.signedTransaction }) .then((response) => - testcase.test.title.indexOf('multisign') !== -1 + testcase.test.title.indexOf("multisign") !== -1 ? acceptLedger(testcase.client).then(() => response) : response ) .then((response) => { - console.log('SUBMITTED...') - assert.strictEqual(response.result.engine_result, 'tesSUCCESS') + console.log("SUBMITTED..."); + assert.strictEqual(response.result.engine_result, "tesSUCCESS"); const options = { minLedgerVersion: lastClosedLedgerVersion, - maxLedgerVersion: txData.LastLedgerSequence - } - ledgerAccept(testcase.client) + maxLedgerVersion: txData.LastLedgerSequence, + }; + ledgerAccept(testcase.client); return new Promise((resolve, reject) => { setTimeout( () => @@ -105,71 +110,81 @@ function testTransaction( address ).then(resolve, reject), INTERVAL - ) - }) - }) + ); + }); + }); } function setup(this: any, server = serverUrl) { - this.client = new Client(server) - console.log('CONNECTING...') + this.client = new Client(server); + console.log("CONNECTING..."); return this.client.connect().then( () => { - console.log('CONNECTED...') + console.log("CONNECTED..."); }, (error) => { - console.log('ERROR:', error) - throw error + console.log("ERROR:", error); + throw error; } - ) + ); } -const masterAccount = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh' -const masterSecret = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb' +const masterAccount = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; +const masterSecret = "snoPBrXtMeMyMHUVTgbuqAfg1SUTb"; function makeTrustLine(testcase, address, secret) { - const client = testcase.client + const client = testcase.client; const specification = { - currency: 'USD', + currency: "USD", counterparty: masterAccount, - limit: '1341.1', - ripplingDisabled: true - } + limit: "1341.1", + ripplingDisabled: true, + }; const trust = client .prepareTrustline(address, specification, {}) .then((data) => { - const signed = client.sign(data.txJSON, secret) + const signed = client.sign(data.txJSON, secret); if (address === wallet.getAddress()) { - testcase.transactions.push(signed.id) + testcase.transactions.push(signed.id); } - return client.request({command: 'submit', tx_blob: signed.signedTransaction}) + return client.request({ + command: "submit", + tx_blob: signed.signedTransaction, + }); }) - .then(() => ledgerAccept(client)) - return trust + .then(() => ledgerAccept(client)); + return trust; } function makeOrder(client, address, specification, secret) { return client .prepareOrder(address, specification) .then((data) => client.sign(data.txJSON, secret)) - .then((signed) => client.request({command: 'submit', tx_blob: signed.signedTransaction})) - .then(() => ledgerAccept(client)) + .then((signed) => + client.request({ command: "submit", tx_blob: signed.signedTransaction }) + ) + .then(() => ledgerAccept(client)); } function setupAccounts(testcase) { - const client = testcase.client + const client = testcase.client; - const promise = payTo(client, 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM') + const promise = payTo(client, "rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM") .then(() => payTo(client, wallet.getAddress())) .then(() => payTo(client, testcase.newWallet.xAddress)) - .then(() => payTo(client, 'rKmBGxocj9Abgy25J51Mk1iqFzW9aVF9Tc')) - .then(() => payTo(client, 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q')) + .then(() => payTo(client, "rKmBGxocj9Abgy25J51Mk1iqFzW9aVF9Tc")) + .then(() => payTo(client, "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q")) .then(() => { return client - .prepareSettings(masterAccount, {defaultRipple: true}) + .prepareSettings(masterAccount, { defaultRipple: true }) .then((data) => client.sign(data.txJSON, masterSecret)) - .then((signed) => client.request({command: 'submit', tx_blob: signed.signedTransaction})) - .then(() => ledgerAccept(client)) + .then((signed) => + client.request({ + command: "submit", + tx_blob: signed.signedTransaction, + }) + ) + .then(() => ledgerAccept(client)); }) .then(() => makeTrustLine(testcase, wallet.getAddress(), wallet.getSecret()) @@ -181,57 +196,57 @@ function setupAccounts(testcase) { testcase.newWallet.secret ) ) - .then(() => payTo(client, wallet.getAddress(), '123', 'USD', masterAccount)) - .then(() => payTo(client, 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q')) + .then(() => payTo(client, wallet.getAddress(), "123", "USD", masterAccount)) + .then(() => payTo(client, "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q")) .then(() => { const orderSpecification = { - direction: 'buy', + direction: "buy", quantity: { - currency: 'USD', - value: '432', - counterparty: masterAccount + currency: "USD", + value: "432", + counterparty: masterAccount, }, totalPrice: { - currency: 'XRP', - value: '432' - } - } + currency: "XRP", + value: "432", + }, + }; return makeOrder( testcase.client, testcase.newWallet.xAddress, orderSpecification, testcase.newWallet.secret - ) + ); }) .then(() => { const orderSpecification = { - direction: 'buy', + direction: "buy", quantity: { - currency: 'XRP', - value: '1741' + currency: "XRP", + value: "1741", }, totalPrice: { - currency: 'USD', - value: '171', - counterparty: masterAccount - } - } + currency: "USD", + value: "171", + counterparty: masterAccount, + }, + }; return makeOrder( testcase.client, masterAccount, orderSpecification, masterSecret - ) - }) - return promise + ); + }); + return promise; } function teardown(this: any) { - return this.client.disconnect() + return this.client.disconnect(); } function suiteSetup(this: any) { - this.transactions = [] + this.transactions = []; return ( setup @@ -241,208 +256,209 @@ function suiteSetup(this: any) { // two times to give time to server to send `ledgerClosed` event // so getLedgerVersion will return right value .then(() => ledgerAccept(this.client)) - .then(() => this.client.request({ - command: 'ledger', - ledger_index: 'validated' - }) - .then(response => response.result.ledger_index)) + .then(() => + this.client + .request({ + command: "ledger", + ledger_index: "validated", + }) + .then((response) => response.result.ledger_index) + ) .then((ledgerVersion) => { - this.startLedgerVersion = ledgerVersion + this.startLedgerVersion = ledgerVersion; }) .then(() => setupAccounts(this)) .then(() => teardown.bind(this)()) - ) + ); } -describe('integration tests', function () { - const address = wallet.getAddress() - const instructions = {maxLedgerVersionOffset: 10} - this.timeout(TIMEOUT) +describe("integration tests", function () { + const address = wallet.getAddress(); + const instructions = { maxLedgerVersionOffset: 10 }; + this.timeout(TIMEOUT); - before(suiteSetup) - beforeEach(_.partial(setup, serverUrl)) - afterEach(teardown) + before(suiteSetup); + beforeEach(_.partial(setup, serverUrl)); + afterEach(teardown); - it('trustline', function () { - return this.client.request({ - command: 'ledger', - ledger_index: 'validated' - }) - .then(response => response.result.ledger_index) - .then((ledgerVersion) => { - return this.client - .prepareTrustline( - address, - requests.prepareTrustline.simple, - instructions - ) - .then((prepared) => - testTransaction(this, 'TrustSet', ledgerVersion, prepared) - ) - }) - }) + it("trustline", function () { + return this.client + .request({ + command: "ledger", + ledger_index: "validated", + }) + .then((response) => response.result.ledger_index) + .then((ledgerVersion) => { + return this.client + .prepareTrustline( + address, + requests.prepareTrustline.simple, + instructions + ) + .then((prepared) => + testTransaction(this, "TrustSet", ledgerVersion, prepared) + ); + }); + }); - it('payment', function () { - const amount = {currency: 'XRP', value: '0.000001'} + it("payment", function () { + const amount = { currency: "XRP", value: "0.000001" }; const paymentSpecification = { source: { - address: address, - maxAmount: amount + address, + maxAmount: amount, }, destination: { - address: 'rKmBGxocj9Abgy25J51Mk1iqFzW9aVF9Tc', - amount: amount - } - } - return this.client.request({ - command: 'ledger', - ledger_index: 'validated' - }) - .then(response => response.result.ledger_index) - .then((ledgerVersion) => { - return this.client - .preparePayment(address, paymentSpecification, instructions) - .then((prepared) => - testTransaction(this, 'Payment', ledgerVersion, prepared) - ) - }) - }) + address: "rKmBGxocj9Abgy25J51Mk1iqFzW9aVF9Tc", + amount, + }, + }; + return this.client + .request({ + command: "ledger", + ledger_index: "validated", + }) + .then((response) => response.result.ledger_index) + .then((ledgerVersion) => { + return this.client + .preparePayment(address, paymentSpecification, instructions) + .then((prepared) => + testTransaction(this, "Payment", ledgerVersion, prepared) + ); + }); + }); - it('order', function () { + it("order", function () { const orderSpecification = { - direction: 'buy', + direction: "buy", quantity: { - currency: 'USD', - value: '237', - counterparty: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q' + currency: "USD", + value: "237", + counterparty: "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q", }, totalPrice: { - currency: 'XRP', - value: '0.0002' - } - } + currency: "XRP", + value: "0.0002", + }, + }; const expectedOrder = { flags: 0, quality: "1.185", - taker_gets: '200', + taker_gets: "200", taker_pays: { - currency: 'USD', - value: '237', - issuer: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q' - } - } - return this.client.request({ - command: 'ledger', - ledger_index: 'validated' - }) - .then(response => response.result.ledger_index) - .then((ledgerVersion) => { - return this.client - .prepareOrder(address, orderSpecification, instructions) - .then((prepared) => - testTransaction(this, 'OfferCreate', ledgerVersion, prepared) - ) - .then((result) => { - const txData = JSON.parse(result.txJSON) - return this.client.request({ - command: 'account_offers', - account: address - }).then(response => response.result.offers) - .then((orders) => { - assert(orders && orders.length > 0) - const createdOrder = ( - orders.filter((order) => { - return order.seq === txData.Sequence + currency: "USD", + value: "237", + issuer: "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q", + }, + }; + return this.client + .request({ + command: "ledger", + ledger_index: "validated", + }) + .then((response) => response.result.ledger_index) + .then((ledgerVersion) => { + return this.client + .prepareOrder(address, orderSpecification, instructions) + .then((prepared) => + testTransaction(this, "OfferCreate", ledgerVersion, prepared) + ) + .then((result) => { + const txData = JSON.parse(result.txJSON); + return this.client + .request({ + command: "account_offers", + account: address, }) - )[0] - assert(createdOrder) - delete createdOrder.seq - assert.deepEqual(createdOrder, expectedOrder) - return txData + .then((response) => response.result.offers) + .then((orders) => { + assert(orders && orders.length > 0); + const createdOrder = orders.filter((order) => { + return order.seq === txData.Sequence; + })[0]; + assert(createdOrder); + delete createdOrder.seq; + assert.deepEqual(createdOrder, expectedOrder); + return txData; + }); }) - }) - .then((txData) => - this.client - .prepareOrderCancellation( - address, - {orderSequence: txData.Sequence}, - instructions - ) - .then((prepared) => - testTransaction( - this, - 'OfferCancel', - ledgerVersion, - prepared + .then((txData) => + this.client + .prepareOrderCancellation( + address, + { orderSequence: txData.Sequence }, + instructions ) - ) - ) - }) - }) + .then((prepared) => + testTransaction(this, "OfferCancel", ledgerVersion, prepared) + ) + ); + }); + }); - it('isConnected', function () { - assert(this.client.isConnected()) - }) + it("isConnected", function () { + assert(this.client.isConnected()); + }); - it('getFee', function () { + it("getFee", function () { return this.client.getFee().then((fee) => { - assert.strictEqual(typeof fee, 'string') - assert(!isNaN(Number(fee))) - assert(parseFloat(fee) === Number(fee)) - }) - }) + assert.strictEqual(typeof fee, "string"); + assert(!isNaN(Number(fee))); + assert(parseFloat(fee) === Number(fee)); + }); + }); - it('getTrustlines', function () { - const fixture = requests.prepareTrustline.simple - const { currency, counterparty } = fixture - const options = { currency, counterparty } + it("getTrustlines", function () { + const fixture = requests.prepareTrustline.simple; + const { currency, counterparty } = fixture; + const options = { currency, counterparty }; return this.client.getTrustlines(address, options).then((data) => { - assert(data && data.length > 0 && data[0] && data[0].specification) - const specification = data[0].specification - assert.strictEqual(Number(specification.limit), Number(fixture.limit)) - assert.strictEqual(specification.currency, fixture.currency) - assert.strictEqual(specification.counterparty, fixture.counterparty) - }) - }) + assert(data && data.length > 0 && data[0] && data[0].specification); + const specification = data[0].specification; + assert.strictEqual(Number(specification.limit), Number(fixture.limit)); + assert.strictEqual(specification.currency, fixture.currency); + assert.strictEqual(specification.counterparty, fixture.counterparty); + }); + }); - it('getBalances', function () { - const fixture = requests.prepareTrustline.simple - const { currency, counterparty } = fixture - const options = { currency, counterparty } + it("getBalances", function () { + const fixture = requests.prepareTrustline.simple; + const { currency, counterparty } = fixture; + const options = { currency, counterparty }; return this.client.getBalances(address, options).then((data) => { - assert(data && data.length > 0 && data[0]) - assert.strictEqual(data[0].currency, fixture.currency) - assert.strictEqual(data[0].counterparty, fixture.counterparty) - }) - }) + assert(data && data.length > 0 && data[0]); + assert.strictEqual(data[0].currency, fixture.currency); + assert.strictEqual(data[0].counterparty, fixture.counterparty); + }); + }); - it('getOrderbook', function () { + it("getOrderbook", function () { const orderbook = { base: { - currency: 'XRP' + currency: "XRP", }, counter: { - currency: 'USD', - counterparty: masterAccount - } - } + currency: "USD", + counterparty: masterAccount, + }, + }; return this.client.getOrderbook(address, orderbook).then((book) => { - assert(book && book.bids && book.bids.length > 0) - assert(book.asks && book.asks.length > 0) - const bid = book.bids[0] - assert(bid && bid.specification && bid.specification.quantity) - assert(bid.specification.totalPrice) - assert.strictEqual(bid.specification.direction, 'buy') - assert.strictEqual(bid.specification.quantity.currency, 'XRP') - assert.strictEqual(bid.specification.totalPrice.currency, 'USD') - const ask = book.asks[0] - assert(ask && ask.specification && ask.specification.quantity) - assert(ask.specification.totalPrice) - assert.strictEqual(ask.specification.direction, 'sell') - assert.strictEqual(ask.specification.quantity.currency, 'XRP') - assert.strictEqual(ask.specification.totalPrice.currency, 'USD') - }) - }) + assert(book && book.bids && book.bids.length > 0); + assert(book.asks && book.asks.length > 0); + const bid = book.bids[0]; + assert(bid && bid.specification && bid.specification.quantity); + assert(bid.specification.totalPrice); + assert.strictEqual(bid.specification.direction, "buy"); + assert.strictEqual(bid.specification.quantity.currency, "XRP"); + assert.strictEqual(bid.specification.totalPrice.currency, "USD"); + const ask = book.asks[0]; + assert(ask && ask.specification && ask.specification.quantity); + assert(ask.specification.totalPrice); + assert.strictEqual(ask.specification.direction, "sell"); + assert.strictEqual(ask.specification.quantity.currency, "XRP"); + assert.strictEqual(ask.specification.totalPrice.currency, "USD"); + }); + }); // it('getPaths', function () { // const pathfind = { @@ -501,100 +517,104 @@ describe('integration tests', function () { // }) // }) - it('generateWallet', function () { - const newWallet = generateXAddress() - assert(newWallet && newWallet.xAddress && newWallet.secret) - assert(isValidXAddress(newWallet.xAddress)) - assert(isValidSecret(newWallet.secret)) - }) -}) + it("generateWallet", function () { + const newWallet = generateXAddress(); + assert(newWallet && newWallet.xAddress && newWallet.secret); + assert(isValidXAddress(newWallet.xAddress)); + assert(isValidSecret(newWallet.secret)); + }); +}); -describe('integration tests - standalone rippled', function () { - const instructions = {maxLedgerVersionOffset: 10} - this.timeout(TIMEOUT) +describe("integration tests - standalone rippled", function () { + const instructions = { maxLedgerVersionOffset: 10 }; + this.timeout(TIMEOUT); - beforeEach(_.partial(setup, serverUrl)) - afterEach(teardown) - const address = 'r5nx8ZkwEbFztnc8Qyi22DE9JYjRzNmvs' - const secret = 'ss6F8381Br6wwpy9p582H8sBt19J3' - const signer1address = 'rQDhz2ZNXmhxzCYwxU6qAbdxsHA4HV45Y2' - const signer1secret = 'shK6YXzwYfnFVn3YZSaMh5zuAddKx' - const signer2address = 'r3RtUvGw9nMoJ5FuHxuoVJvcENhKtuF9ud' - const signer2secret = 'shUHQnL4EH27V4EiBrj6EfhWvZngF' + beforeEach(_.partial(setup, serverUrl)); + afterEach(teardown); + const address = "r5nx8ZkwEbFztnc8Qyi22DE9JYjRzNmvs"; + const secret = "ss6F8381Br6wwpy9p582H8sBt19J3"; + const signer1address = "rQDhz2ZNXmhxzCYwxU6qAbdxsHA4HV45Y2"; + const signer1secret = "shK6YXzwYfnFVn3YZSaMh5zuAddKx"; + const signer2address = "r3RtUvGw9nMoJ5FuHxuoVJvcENhKtuF9ud"; + const signer2secret = "shUHQnL4EH27V4EiBrj6EfhWvZngF"; - it('submit multisigned transaction', function () { + it("submit multisigned transaction", function () { const signers = { threshold: 2, weights: [ - {address: signer1address, weight: 1}, - {address: signer2address, weight: 1} - ] - } - let minLedgerVersion = null + { address: signer1address, weight: 1 }, + { address: signer2address, weight: 1 }, + ], + }; + let minLedgerVersion = null; return payTo(this.client, address) .then(() => { - return this.client.request({ - command: 'ledger', - ledger_index: 'validated' - }) - .then(response => response.result.ledger_index) - .then((ledgerVersion) => { - minLedgerVersion = ledgerVersion - return this.client - .prepareSettings(address, {signers}, instructions) - .then((prepared) => { - return testTransaction( - this, - 'SignerListSet', - ledgerVersion, - prepared, - address, - secret - ) - }) - }) + return this.client + .request({ + command: "ledger", + ledger_index: "validated", + }) + .then((response) => response.result.ledger_index) + .then((ledgerVersion) => { + minLedgerVersion = ledgerVersion; + return this.client + .prepareSettings(address, { signers }, instructions) + .then((prepared) => { + return testTransaction( + this, + "SignerListSet", + ledgerVersion, + prepared, + address, + secret + ); + }); + }); }) .then(() => { - const multisignInstructions = Object.assign({}, instructions, { - signersCount: 2 - }) + const multisignInstructions = { ...instructions, signersCount: 2 }; return this.client .prepareSettings( address, - {domain: 'example.com'}, + { domain: "example.com" }, multisignInstructions ) .then((prepared) => { const signed1 = this.client.sign(prepared.txJSON, signer1secret, { - signAs: signer1address - }) + signAs: signer1address, + }); const signed2 = this.client.sign(prepared.txJSON, signer2secret, { - signAs: signer2address - }) + signAs: signer2address, + }); const combined = this.client.combine([ signed1.signedTransaction, - signed2.signedTransaction - ]) + signed2.signedTransaction, + ]); return this.client - .request({command: 'submit', tx_blob: combined.signedTransaction}) - .then((response) => acceptLedger(this.client).then(() => response)) + .request({ + command: "submit", + tx_blob: combined.signedTransaction, + }) + .then((response) => + acceptLedger(this.client).then(() => response) + ) .then((response) => { - assert.strictEqual(response.result.engine_result, 'tesSUCCESS') - const options = {minLedgerVersion} + assert.strictEqual(response.result.engine_result, "tesSUCCESS"); + const options = { minLedgerVersion }; return verifyTransaction( this, combined.id, - 'AccountSet', + "AccountSet", options, {}, address - ) + ); }) .catch((error) => { - console.log(error.message) - throw error - }) - }) - }) - }) -}) \ No newline at end of file + console.log(error.message); + throw error; + }); + }); + }); + }); +}); diff --git a/test/mockRippled.ts b/test/mockRippled.ts index 414a82fa..a2cafa52 100644 --- a/test/mockRippled.ts +++ b/test/mockRippled.ts @@ -1,17 +1,18 @@ -import _ from 'lodash' -import {Server as WebSocketServer} from 'ws' -import {EventEmitter2} from 'eventemitter2' -import {getFreePort} from './testUtils' -import { Request } from '../src' +import { EventEmitter2 } from "eventemitter2"; +import _ from "lodash"; +import { Server as WebSocketServer } from "ws"; +import type { Request } from "../src"; + +import { getFreePort } from "./testUtils"; function createResponse(request, response, overrides = {}) { - const result = Object.assign({}, response.result, overrides) + const result = { ...response.result, ...overrides }; const change = response.result && !_.isEmpty(overrides) - ? {id: request.id, result: result} - : {id: request.id} - return JSON.stringify(Object.assign({}, response, change)) + ? { id: request.id, result } + : { id: request.id }; + return JSON.stringify({ ...response, ...change }); } function ping(conn, request) { @@ -19,105 +20,111 @@ function ping(conn, request) { conn.send( createResponse(request, { result: {}, - status: 'success', - type: 'response' + status: "success", + type: "response", }) - ) - }, 1000 * 2) + ); + }, 1000 * 2); } // We mock out WebSocketServer in these tests and add a lot of custom // properties not defined on the normal WebSocketServer object. -type MockedWebSocketServer = any +type MockedWebSocketServer = any; export function createMockRippled(port) { - const mock = new WebSocketServer({port: port}) as MockedWebSocketServer - Object.assign(mock, EventEmitter2.prototype) + const mock = new WebSocketServer({ port }) as MockedWebSocketServer; + Object.assign(mock, EventEmitter2.prototype); - mock.responses = {} - mock.suppressOutput = false + mock.responses = {}; + mock.suppressOutput = false; - mock.on('connection', function (this: MockedWebSocketServer, conn: any) { - this.socket = conn - conn.on('message', function (requestJSON) { + mock.on("connection", function (this: MockedWebSocketServer, conn: any) { + this.socket = conn; + conn.on("message", function (requestJSON) { try { - const request = JSON.parse(requestJSON) - if (request.command === 'ping') { - ping(conn, request) - } else if (request.command === 'test_command') { - mock.testCommand(conn, request) - }else if (request.command in mock.responses) { - conn.send(createResponse(request, mock.getResponse(request))) + const request = JSON.parse(requestJSON); + if (request.command === "ping") { + ping(conn, request); + } else if (request.command === "test_command") { + mock.testCommand(conn, request); + } else if (request.command in mock.responses) { + conn.send(createResponse(request, mock.getResponse(request))); } else { - throw new Error(`No event handler registered in mock rippled for ${request.command}`) + throw new Error( + `No event handler registered in mock rippled for ${request.command}` + ); } } catch (err) { - if (!mock.suppressOutput) - console.error('Error: ' + err.message) - conn.close(4000, err.message) + if (!mock.suppressOutput) { + console.error(`Error: ${err.message}`); + } + conn.close(4000, err.message); } - }) - }) + }); + }); // Adds a mocked response // If an object is passed in for `response`, then the response is static for the command // If a function is passed in for `response`, then the response can be determined by the exact request shape - mock.addResponse = (request: Request, response: object | ((r: Request) => object)) => { - const command = request.command - mock.responses[command] = response - } + mock.addResponse = ( + request: Request, + response: object | ((r: Request) => object) + ) => { + const command = request.command; + mock.responses[command] = response; + }; - mock.getResponse = (request: Request) : object => { + mock.getResponse = (request: Request): object => { if (!(request.command in mock.responses)) { - throw new Error(`No handler for ${request.command}`) + throw new Error(`No handler for ${request.command}`); } - const functionOrObject = mock.responses[request.command] - if (typeof functionOrObject === 'function') { - return functionOrObject(request) + const functionOrObject = mock.responses[request.command]; + if (typeof functionOrObject === "function") { + return functionOrObject(request); } - return functionOrObject - } + return functionOrObject; + }; mock.testCommand = function testCommand(conn, request) { if (request.data.disconnectIn) { - setTimeout(conn.terminate.bind(conn), request.data.disconnectIn) + setTimeout(conn.terminate.bind(conn), request.data.disconnectIn); conn.send( createResponse(request, { - status: 'success', - type: 'response', - result: {} + status: "success", + type: "response", + result: {}, }) - ) + ); } else if (request.data.openOnOtherPort) { getFreePort().then((newPort) => { - createMockRippled(newPort) + createMockRippled(newPort); conn.send( createResponse(request, { - status: 'success', - type: 'response', - result: {port: newPort} + status: "success", + type: "response", + result: { port: newPort }, }) - ) - }) + ); + }); } else if (request.data.closeServerAndReopen) { setTimeout(() => { - conn.terminate() + conn.terminate(); mock.close.call(mock, () => { setTimeout(() => { - createMockRippled(port) - }, request.data.closeServerAndReopen) - }) - }, 10) + createMockRippled(port); + }, request.data.closeServerAndReopen); + }); + }, 10); } else if (request.data.unrecognizedResponse) { conn.send( createResponse(request, { - status: 'unrecognized', - type: 'response', - result: {} + status: "unrecognized", + type: "response", + result: {}, }) - ) + ); } - } + }; - return mock + return mock; } diff --git a/test/mockedServer.ts b/test/mockedServer.ts index cee9183f..b0ea85ea 100644 --- a/test/mockedServer.ts +++ b/test/mockedServer.ts @@ -1,15 +1,17 @@ -const port = 34371 -import {createMockRippled} from './mockRippled' +import { createMockRippled } from "./mockRippled"; + +const port = 34371; function main() { + // @ts-expect-error -- mocha. if (global.describe) { // we are running inside mocha, exiting - return + return; } - console.log('starting server on port ' + port) - createMockRippled(port) - console.log('starting server on port ' + String(port + 1)) - createMockRippled(port + 1) + console.log(`starting server on port ${port}`); + createMockRippled(port); + console.log(`starting server on port ${String(port + 1)}`); + createMockRippled(port + 1); } -main() +main(); diff --git a/test/models/accountDelete.ts b/test/models/accountDelete.ts index caf87a52..a7e0d813 100644 --- a/test/models/accountDelete.ts +++ b/test/models/accountDelete.ts @@ -1,78 +1,77 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyAccountDelete } from './../../src/models/transactions/accountDelete' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyAccountDelete } from "../../src/models/transactions/accountDelete"; /** - * AccountDelete Transaction Verification Testing + * AccountDelete Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('AccountDelete Transaction Verification', function () { - - it (`verifies valid AccountDelete`, () => { - const validAccountDelete = { - TransactionType: "AccountDelete", - Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", - Destination: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", - DestinationTag: 13, - Fee: "5000000", - Sequence: 2470665, - Flags: 2147483648 - } as any - - assert.doesNotThrow(() => verifyAccountDelete(validAccountDelete)) - }) +describe("AccountDelete Transaction Verification", function () { + it(`verifies valid AccountDelete`, function () { + const validAccountDelete = { + TransactionType: "AccountDelete", + Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + Destination: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", + DestinationTag: 13, + Fee: "5000000", + Sequence: 2470665, + Flags: 2147483648, + } as any; + assert.doesNotThrow(() => verifyAccountDelete(validAccountDelete)); + }); - it (`throws w/ missing Destination`, () => { - const invalidDestination = { - TransactionType: "AccountDelete", - Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", - Fee: "5000000", - Sequence: 2470665, - Flags: 2147483648 - } as any + it(`throws w/ missing Destination`, function () { + const invalidDestination = { + TransactionType: "AccountDelete", + Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + Fee: "5000000", + Sequence: 2470665, + Flags: 2147483648, + } as any; - assert.throws( - () => verifyAccountDelete(invalidDestination), - ValidationError, - "AccountDelete: missing field Destination" - ) - }) + assert.throws( + () => verifyAccountDelete(invalidDestination), + ValidationError, + "AccountDelete: missing field Destination" + ); + }); - it (`throws w/ invalid Destination`, () => { - const invalidDestination = { - TransactionType: "AccountDelete", - Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", - Destination: 65478965, - Fee: "5000000", - Sequence: 2470665, - Flags: 2147483648 - } as any + it(`throws w/ invalid Destination`, function () { + const invalidDestination = { + TransactionType: "AccountDelete", + Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + Destination: 65478965, + Fee: "5000000", + Sequence: 2470665, + Flags: 2147483648, + } as any; - assert.throws( - () => verifyAccountDelete(invalidDestination), - ValidationError, - "AccountDelete: invalid Destination" - ) - }) + assert.throws( + () => verifyAccountDelete(invalidDestination), + ValidationError, + "AccountDelete: invalid Destination" + ); + }); - it (`throws w/ invalid DestinationTag`, () => { - const invalidDestinationTag = { - TransactionType: "AccountDelete", - Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", - Destination: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", - DestinationTag: "gvftyujnbv", - Fee: "5000000", - Sequence: 2470665, - Flags: 2147483648 - } as any + it(`throws w/ invalid DestinationTag`, function () { + const invalidDestinationTag = { + TransactionType: "AccountDelete", + Account: "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + Destination: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", + DestinationTag: "gvftyujnbv", + Fee: "5000000", + Sequence: 2470665, + Flags: 2147483648, + } as any; - assert.throws( - () => verifyAccountDelete(invalidDestinationTag), - ValidationError, - "AccountDelete: invalid DestinationTag" - ) - }) - -}) \ No newline at end of file + assert.throws( + () => verifyAccountDelete(invalidDestinationTag), + ValidationError, + "AccountDelete: invalid DestinationTag" + ); + }); +}); diff --git a/test/models/accountSet.ts b/test/models/accountSet.ts index c3829092..1526c55e 100644 --- a/test/models/accountSet.ts +++ b/test/models/accountSet.ts @@ -1,110 +1,111 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyAccountSet } from './../../src/models/transactions/accountSet' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyAccountSet } from "../../src/models/transactions/accountSet"; /** - * AccountSet Transaction Verification Testing + * AccountSet Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('AccountSet Transaction Verification', function () { +describe("AccountSet Transaction Verification", function () { + let account; - let account + beforeEach(function () { + account = { + TransactionType: "AccountSet", + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + Fee: "12", + Sequence: 5, + Domain: "6578616D706C652E636F6D", + SetFlag: 5, + MessageKey: + "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB", + } as any; + }); - beforeEach(() => { - account = { - TransactionType : "AccountSet", - Account : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - Fee : "12", - Sequence : 5, - Domain : "6578616D706C652E636F6D", - SetFlag : 5, - MessageKey : "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB" - } as any - }) + it(`verifies valid AccountSet`, function () { + assert.doesNotThrow(() => verifyAccountSet(account)); + }); - it (`verifies valid AccountSet`, () => { - assert.doesNotThrow(() => verifyAccountSet(account)) - }) + it(`throws w/ invalid SetFlag (out of range)`, function () { + account.SetFlag = 12; - it (`throws w/ invalid SetFlag (out of range)`, () => { - account.SetFlag = 12 + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid SetFlag" + ); + }); - assert.throws( - () => verifyAccountSet(account), - ValidationError, - "AccountSet: invalid SetFlag" - ) - }) + it(`throws w/ invalid SetFlag (incorrect type)`, function () { + account.SetFlag = "abc"; - it (`throws w/ invalid SetFlag (incorrect type)`, () => { - account.SetFlag = 'abc' - - assert.throws( - () => verifyAccountSet(account), - ValidationError, - "AccountSet: invalid SetFlag" - ) - }) + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid SetFlag" + ); + }); - it (`throws w/ invalid ClearFlag`, () => { - account.ClearFlag = 12 + it(`throws w/ invalid ClearFlag`, function () { + account.ClearFlag = 12; - assert.throws( - () => verifyAccountSet(account), - ValidationError, - "AccountSet: invalid ClearFlag" - ) - }) + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid ClearFlag" + ); + }); - it (`throws w/ invalid Domain`, () => { - account.Domain = 6578616 + it(`throws w/ invalid Domain`, function () { + account.Domain = 6578616; - assert.throws( - () => verifyAccountSet(account), - ValidationError, - "AccountSet: invalid Domain" - ) - }) + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid Domain" + ); + }); - it (`throws w/ invalid EmailHash`, () => { - account.EmailHash = 657861645678909876543456789876543 + it(`throws w/ invalid EmailHash`, function () { + account.EmailHash = 657861645678909876543456789876543; - assert.throws( - () => verifyAccountSet(account), - ValidationError, - "AccountSet: invalid EmailHash" - ) - }) + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid EmailHash" + ); + }); - it (`throws w/ invalid MessageKey`, () => { - account.MessageKey = 65786165678908765456789567890678 + it(`throws w/ invalid MessageKey`, function () { + account.MessageKey = 65786165678908765456789567890678; - assert.throws( - () => verifyAccountSet(account), - ValidationError, - "AccountSet: invalid MessageKey" - ) - }) + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid MessageKey" + ); + }); - it (`throws w/ invalid TransferRate`, () => { - account.TransferRate = "1000000001" + it(`throws w/ invalid TransferRate`, function () { + account.TransferRate = "1000000001"; - assert.throws( - () => verifyAccountSet(account), - ValidationError, - "AccountSet: invalid TransferRate" - ) - }) + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid TransferRate" + ); + }); - it (`throws w/ invalid TickSize`, () => { - account.TickSize = 20 + it(`throws w/ invalid TickSize`, function () { + account.TickSize = 20; - assert.throws( - () => verifyAccountSet(account), - ValidationError, - "AccountSet: invalid TickSize" - ) - }) - -}) \ No newline at end of file + assert.throws( + () => verifyAccountSet(account), + ValidationError, + "AccountSet: invalid TickSize" + ); + }); +}); diff --git a/test/models/baseTransaction.ts b/test/models/baseTransaction.ts index 6e4ef991..a40fce7e 100644 --- a/test/models/baseTransaction.ts +++ b/test/models/baseTransaction.ts @@ -1,225 +1,232 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyBaseTransaction } from './../../src/models/transactions/common' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyBaseTransaction } from "../../src/models/transactions/common"; /** - * Transaction Verification Testing + * Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('Transaction Verification', function () { - it(`Verifies all optional BaseTransaction`, () => { - const txJson = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - Fee: "12", - Sequence: 100, - AccountTxnID: "DEADBEEF", - Flags: 15, - LastLedgerSequence: 1383, - Memos: [ - { - Memo: { - MemoType: "687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963", - MemoData: "72656e74" - } - }, - { - Memo: { - MemoFormat: "687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963", - MemoData: "72656e74" - } - }, - { - Memo: { - MemoType: "72656e74" - } - } - ], - Signers: [ - { - Account: "r....", - TxnSignature: "DEADBEEF", - SigningPubKey: "hex-string" - } - ], - SourceTag: 31, - SigningPublicKey: "03680DD274EE55594F7244F489CD38CF3A5A1A4657122FB8143E185B2BA043DF36", - TicketSequence: 10, - TxnSignature: "3045022100C6708538AE5A697895937C758E99A595B57A16393F370F11B8D4C032E80B532002207776A8E85BB9FAF460A92113B9C60F170CD964196B1F084E0DAB65BAEC368B66" - } +describe("Transaction Verification", function () { + it(`Verifies all optional BaseTransaction`, function () { + const txJson = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + Fee: "12", + Sequence: 100, + AccountTxnID: "DEADBEEF", + Flags: 15, + LastLedgerSequence: 1383, + Memos: [ + { + Memo: { + MemoType: + "687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963", + MemoData: "72656e74", + }, + }, + { + Memo: { + MemoFormat: + "687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963", + MemoData: "72656e74", + }, + }, + { + Memo: { + MemoType: "72656e74", + }, + }, + ], + Signers: [ + { + Account: "r....", + TxnSignature: "DEADBEEF", + SigningPubKey: "hex-string", + }, + ], + SourceTag: 31, + SigningPublicKey: + "03680DD274EE55594F7244F489CD38CF3A5A1A4657122FB8143E185B2BA043DF36", + TicketSequence: 10, + TxnSignature: + "3045022100C6708538AE5A697895937C758E99A595B57A16393F370F11B8D4C032E80B532002207776A8E85BB9FAF460A92113B9C60F170CD964196B1F084E0DAB65BAEC368B66", + }; - assert.doesNotThrow(() => verifyBaseTransaction(txJson)) - }) + assert.doesNotThrow(() => verifyBaseTransaction(txJson)); + }); - it(`Verifies only required BaseTransaction`, () => { - const txJson = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - } - - assert.doesNotThrow(() => verifyBaseTransaction(txJson)) - }) + it(`Verifies only required BaseTransaction`, function () { + const txJson = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + }; - it (`Handles invalid Fee`, () => { - const invalidFee = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - Fee: 1000 - } as any + assert.doesNotThrow(() => verifyBaseTransaction(txJson)); + }); - assert.throws( - () => verifyBaseTransaction(invalidFee), - ValidationError, - "BaseTransaction: invalid Fee" - ) - }) + it(`Handles invalid Fee`, function () { + const invalidFee = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + Fee: 1000, + } as any; - it (`Handles invalid Sequence`, () => { - const invalidSeq = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - Sequence: "145" - } as any + assert.throws( + () => verifyBaseTransaction(invalidFee), + ValidationError, + "BaseTransaction: invalid Fee" + ); + }); - assert.throws( - () => verifyBaseTransaction(invalidSeq), - ValidationError, - "BaseTransaction: invalid Sequence" - ) - }) + it(`Handles invalid Sequence`, function () { + const invalidSeq = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + Sequence: "145", + } as any; - it (`Handles invalid AccountTxnID`, () => { - const invalidID = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - AccountTxnID: ["WRONG"] - } as any + assert.throws( + () => verifyBaseTransaction(invalidSeq), + ValidationError, + "BaseTransaction: invalid Sequence" + ); + }); - assert.throws( - () => verifyBaseTransaction(invalidID), - ValidationError, - "BaseTransaction: invalid AccountTxnID" - ) - }) + it(`Handles invalid AccountTxnID`, function () { + const invalidID = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + AccountTxnID: ["WRONG"], + } as any; - it (`Handles invalid LastLedgerSequence`, () => { - const invalidLastLedgerSequence = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - LastLedgerSequence: "1000" - } as any + assert.throws( + () => verifyBaseTransaction(invalidID), + ValidationError, + "BaseTransaction: invalid AccountTxnID" + ); + }); - assert.throws( - () => verifyBaseTransaction(invalidLastLedgerSequence), - ValidationError, - "BaseTransaction: invalid LastLedgerSequence" - ) - }) + it(`Handles invalid LastLedgerSequence`, function () { + const invalidLastLedgerSequence = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + LastLedgerSequence: "1000", + } as any; - it (`Handles invalid SourceTag`, () => { - const invalidSourceTag = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - SourceTag: ["ARRAY"] - } as any + assert.throws( + () => verifyBaseTransaction(invalidLastLedgerSequence), + ValidationError, + "BaseTransaction: invalid LastLedgerSequence" + ); + }); - - assert.throws( - () => verifyBaseTransaction(invalidSourceTag), - ValidationError, - "BaseTransaction: invalid SourceTag" - ) - }) + it(`Handles invalid SourceTag`, function () { + const invalidSourceTag = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + SourceTag: ["ARRAY"], + } as any; - it (`Handles invalid SigningPubKey`, () => { - const invalidSigningPubKey = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - SigningPubKey: 1000 - } as any + assert.throws( + () => verifyBaseTransaction(invalidSourceTag), + ValidationError, + "BaseTransaction: invalid SourceTag" + ); + }); - assert.throws( - () => verifyBaseTransaction(invalidSigningPubKey), - ValidationError, - "BaseTransaction: invalid SigningPubKey" - ) - }) + it(`Handles invalid SigningPubKey`, function () { + const invalidSigningPubKey = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + SigningPubKey: 1000, + } as any; - it (`Handles invalid TicketSequence`, () => { - const invalidTicketSequence = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - TicketSequence: "1000" - } as any + assert.throws( + () => verifyBaseTransaction(invalidSigningPubKey), + ValidationError, + "BaseTransaction: invalid SigningPubKey" + ); + }); - assert.throws( - () => verifyBaseTransaction(invalidTicketSequence), - ValidationError, - "BaseTransaction: invalid TicketSequence" - ) - }) + it(`Handles invalid TicketSequence`, function () { + const invalidTicketSequence = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + TicketSequence: "1000", + } as any; - it (`Handles invalid TxnSignature`, () => { - const invalidTxnSignature = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - TxnSignature: 1000 - } as any - - assert.throws( - () => verifyBaseTransaction(invalidTxnSignature), - ValidationError, - "BaseTransaction: invalid TxnSignature" - ) - }) + assert.throws( + () => verifyBaseTransaction(invalidTicketSequence), + ValidationError, + "BaseTransaction: invalid TicketSequence" + ); + }); - it (`Handles invalid Signers`, () => { - const invalidSigners = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - Signers: [] - } as any + it(`Handles invalid TxnSignature`, function () { + const invalidTxnSignature = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + TxnSignature: 1000, + } as any; - assert.throws( - () => verifyBaseTransaction(invalidSigners), - ValidationError, - "BaseTransaction: invalid Signers" - ) + assert.throws( + () => verifyBaseTransaction(invalidTxnSignature), + ValidationError, + "BaseTransaction: invalid TxnSignature" + ); + }); - const invalidSigners2 = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - Signers: [ - { - "Account": "r...." - } - ] - } as any + it(`Handles invalid Signers`, function () { + const invalidSigners = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + Signers: [], + } as any; - assert.throws( - () => verifyBaseTransaction(invalidSigners2), - ValidationError, - "BaseTransaction: invalid Signers" - ) - }) + assert.throws( + () => verifyBaseTransaction(invalidSigners), + ValidationError, + "BaseTransaction: invalid Signers" + ); - it (`Handles invalid Memo`, () => { - const invalidMemo = { - Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", - TransactionType: "Payment", - Memos: [{ - Memo: { - MemoData: "HI", - Address: "WRONG" - } - }] - } as any + const invalidSigners2 = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + Signers: [ + { + Account: "r....", + }, + ], + } as any; - assert.throws( - () => verifyBaseTransaction(invalidMemo), - ValidationError, - "BaseTransaction: invalid Memos" - ) - }) -}) \ No newline at end of file + assert.throws( + () => verifyBaseTransaction(invalidSigners2), + ValidationError, + "BaseTransaction: invalid Signers" + ); + }); + + it(`Handles invalid Memo`, function () { + const invalidMemo = { + Account: "r97KeayHuEsDwyU1yPBVtMLLoQr79QcRFe", + TransactionType: "Payment", + Memos: [ + { + Memo: { + MemoData: "HI", + Address: "WRONG", + }, + }, + ], + } as any; + + assert.throws( + () => verifyBaseTransaction(invalidMemo), + ValidationError, + "BaseTransaction: invalid Memos" + ); + }); +}); diff --git a/test/models/checkCancel.ts b/test/models/checkCancel.ts index 2fc0dee9..e20c5ee1 100644 --- a/test/models/checkCancel.ts +++ b/test/models/checkCancel.ts @@ -1,35 +1,37 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyCheckCancel} from './../../src/models/transactions/checkCancel' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyCheckCancel } from "../../src/models/transactions/checkCancel"; /** - * CheckCancel Transaction Verification Testing + * CheckCancel Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('CheckCancel Transaction Verification', function () { +describe("CheckCancel Transaction Verification", function () { + it(`verifies valid CheckCancel`, function () { + const validCheckCancel = { + Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + TransactionType: "CheckCancel", + CheckID: + "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0", + } as any; - it (`verifies valid CheckCancel`, () => { - const validCheckCancel = { - Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", - TransactionType : "CheckCancel", - CheckID : "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0" - } as any + assert.doesNotThrow(() => verifyCheckCancel(validCheckCancel)); + }); - assert.doesNotThrow(() => verifyCheckCancel(validCheckCancel)) - }) + it(`throws w/ invalid CheckCancel`, function () { + const invalidCheckID = { + Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + TransactionType: "CheckCancel", + CheckID: 496473456789876545678909876545678, + } as any; - it (`throws w/ invalid CheckCancel`, () => { - const invalidCheckID = { - Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", - TransactionType : "CheckCancel", - CheckID : 496473456789876545678909876545678 - } as any - - assert.throws( - () => verifyCheckCancel(invalidCheckID), - ValidationError, - "CheckCancel: invalid CheckID" - ) - }) -}) \ No newline at end of file + assert.throws( + () => verifyCheckCancel(invalidCheckID), + ValidationError, + "CheckCancel: invalid CheckID" + ); + }); +}); diff --git a/test/models/checkCash.ts b/test/models/checkCash.ts index a51dcb1d..79459aa2 100644 --- a/test/models/checkCash.ts +++ b/test/models/checkCash.ts @@ -1,84 +1,89 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyCheckCash } from './../../src/models/transactions/checkCash' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyCheckCash } from "../../src/models/transactions/checkCash"; /** - * CheckCash Transaction Verification Testing + * CheckCash Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('CheckCash Transaction Verification', function () { - - it (`verifies valid CheckCash`, () => { - const validCheckCash = { - Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", - TransactionType : "CheckCash", - Amount : "100000000", - CheckID : "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334", - Fee : "12" - } as any - - assert.doesNotThrow(() => verifyCheckCash(validCheckCash)) - }) +describe("CheckCash Transaction Verification", function () { + it(`verifies valid CheckCash`, function () { + const validCheckCash = { + Account: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + TransactionType: "CheckCash", + Amount: "100000000", + CheckID: + "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334", + Fee: "12", + } as any; - it (`throws w/ invalid CheckID`, () => { - const invalidCheckID = { - Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", - TransactionType : "CheckCash", - Amount : "100000000", - CheckID : 83876645678909854567890 - } as any + assert.doesNotThrow(() => verifyCheckCash(validCheckCash)); + }); - assert.throws( - () => verifyCheckCash(invalidCheckID), - ValidationError, - "CheckCash: invalid CheckID" - ) - }) + it(`throws w/ invalid CheckID`, function () { + const invalidCheckID = { + Account: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + TransactionType: "CheckCash", + Amount: "100000000", + CheckID: 83876645678909854567890, + } as any; - it (`throws w/ invalid Amount`, () => { - const invalidAmount = { - Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", - TransactionType : "CheckCash", - Amount : 100000000, - CheckID : "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334" - } as any + assert.throws( + () => verifyCheckCash(invalidCheckID), + ValidationError, + "CheckCash: invalid CheckID" + ); + }); - assert.throws( - () => verifyCheckCash(invalidAmount), - ValidationError, - "CheckCash: invalid Amount" - ) - }) + it(`throws w/ invalid Amount`, function () { + const invalidAmount = { + Account: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + TransactionType: "CheckCash", + Amount: 100000000, + CheckID: + "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334", + } as any; - it (`throws w/ having both Amount and DeliverMin`, () => { - const invalidDeliverMin = { - Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", - TransactionType : "CheckCash", - Amount : "100000000", - DeliverMin: 852156963, - CheckID : "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334" - } as any + assert.throws( + () => verifyCheckCash(invalidAmount), + ValidationError, + "CheckCash: invalid Amount" + ); + }); - assert.throws( - () => verifyCheckCash(invalidDeliverMin), - ValidationError, - "CheckCash: cannot have both Amount and DeliverMin" - ) - }) + it(`throws w/ having both Amount and DeliverMin`, function () { + const invalidDeliverMin = { + Account: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + TransactionType: "CheckCash", + Amount: "100000000", + DeliverMin: 852156963, + CheckID: + "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334", + } as any; - it (`throws w/ invalid DeliverMin`, () => { - const invalidDeliverMin = { - Account : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", - TransactionType : "CheckCash", - DeliverMin: 852156963, - CheckID : "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334" - } as any + assert.throws( + () => verifyCheckCash(invalidDeliverMin), + ValidationError, + "CheckCash: cannot have both Amount and DeliverMin" + ); + }); - assert.throws( - () => verifyCheckCash(invalidDeliverMin), - ValidationError, - "CheckCash: invalid DeliverMin" - ) - }) -}) \ No newline at end of file + it(`throws w/ invalid DeliverMin`, function () { + const invalidDeliverMin = { + Account: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + TransactionType: "CheckCash", + DeliverMin: 852156963, + CheckID: + "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334", + } as any; + + assert.throws( + () => verifyCheckCash(invalidDeliverMin), + ValidationError, + "CheckCash: invalid DeliverMin" + ); + }); +}); diff --git a/test/models/checkCreate.ts b/test/models/checkCreate.ts index d0e04fae..400dfdaa 100644 --- a/test/models/checkCreate.ts +++ b/test/models/checkCreate.ts @@ -1,123 +1,127 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyCheckCreate } from './../../src/models/transactions/checkCreate' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyCheckCreate } from "../../src/models/transactions/checkCreate"; /** - * CheckCreate Transaction Verification Testing + * CheckCreate Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('CheckCreate Transaction Verification', function () { - - it (`verifies valid CheckCreate`, () => { - const validCheck = { - TransactionType : "CheckCreate", - Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", - Destination : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", - SendMax : "100000000", - Expiration : 570113521, - InvoiceID : "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B", - DestinationTag : 1, - Fee : "12" - } as any - - assert.doesNotThrow(() => verifyCheckCreate(validCheck)) - }) +describe("CheckCreate Transaction Verification", function () { + it(`verifies valid CheckCreate`, function () { + const validCheck = { + TransactionType: "CheckCreate", + Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + Destination: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + SendMax: "100000000", + Expiration: 570113521, + InvoiceID: + "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B", + DestinationTag: 1, + Fee: "12", + } as any; + assert.doesNotThrow(() => verifyCheckCreate(validCheck)); + }); - it (`throws w/ invalid Destination`, () => { - const invalidDestination = { - TransactionType : "CheckCreate", - Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", - Destination : 7896214563214789632154, - SendMax : "100000000", - Expiration : 570113521, - InvoiceID : "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B", - DestinationTag : 1, - Fee : "12" - } as any + it(`throws w/ invalid Destination`, function () { + const invalidDestination = { + TransactionType: "CheckCreate", + Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + Destination: 7896214563214789632154, + SendMax: "100000000", + Expiration: 570113521, + InvoiceID: + "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B", + DestinationTag: 1, + Fee: "12", + } as any; - assert.throws( - () => verifyCheckCreate(invalidDestination), - ValidationError, - "CheckCreate: invalid Destination" - ) - }) + assert.throws( + () => verifyCheckCreate(invalidDestination), + ValidationError, + "CheckCreate: invalid Destination" + ); + }); - it (`throws w/ invalid SendMax`, () => { - const invalidSendMax = { - TransactionType : "CheckCreate", - Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", - Destination : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", - SendMax : 100000000, - Expiration : 570113521, - InvoiceID : "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B", - DestinationTag : 1, - Fee : "12" - } as any + it(`throws w/ invalid SendMax`, function () { + const invalidSendMax = { + TransactionType: "CheckCreate", + Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + Destination: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + SendMax: 100000000, + Expiration: 570113521, + InvoiceID: + "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B", + DestinationTag: 1, + Fee: "12", + } as any; - assert.throws( - () => verifyCheckCreate(invalidSendMax), - ValidationError, - "CheckCreate: invalid SendMax" - ) - }) + assert.throws( + () => verifyCheckCreate(invalidSendMax), + ValidationError, + "CheckCreate: invalid SendMax" + ); + }); - it (`throws w/ invalid DestinationTag`, () => { - const invalidDestinationTag = { - TransactionType : "CheckCreate", - Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", - Destination : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", - SendMax : "100000000", - Expiration : 570113521, - InvoiceID : "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B", - DestinationTag : "1", - Fee : "12" - } as any + it(`throws w/ invalid DestinationTag`, function () { + const invalidDestinationTag = { + TransactionType: "CheckCreate", + Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + Destination: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + SendMax: "100000000", + Expiration: 570113521, + InvoiceID: + "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B", + DestinationTag: "1", + Fee: "12", + } as any; - assert.throws( - () => verifyCheckCreate(invalidDestinationTag), - ValidationError, - "CheckCreate: invalid DestinationTag" - ) - }) + assert.throws( + () => verifyCheckCreate(invalidDestinationTag), + ValidationError, + "CheckCreate: invalid DestinationTag" + ); + }); - it (`throws w/ invalid Expiration`, () => { - const invalidExpiration = { - TransactionType : "CheckCreate", - Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", - Destination : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", - SendMax : "100000000", - Expiration : "570113521", - InvoiceID : "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B", - DestinationTag : 1, - Fee : "12" - } as any + it(`throws w/ invalid Expiration`, function () { + const invalidExpiration = { + TransactionType: "CheckCreate", + Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + Destination: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + SendMax: "100000000", + Expiration: "570113521", + InvoiceID: + "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B", + DestinationTag: 1, + Fee: "12", + } as any; - assert.throws( - () => verifyCheckCreate(invalidExpiration), - ValidationError, - "CheckCreate: invalid Expiration" - ) - }) + assert.throws( + () => verifyCheckCreate(invalidExpiration), + ValidationError, + "CheckCreate: invalid Expiration" + ); + }); - it (`throws w/ invalid InvoiceID`, () => { - const invalidInvoiceID = { - TransactionType : "CheckCreate", - Account : "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", - Destination : "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", - SendMax : "100000000", - Expiration : 570113521, - InvoiceID : 7896545655285446963258531, - DestinationTag : 1, - Fee : "12" - } as any + it(`throws w/ invalid InvoiceID`, function () { + const invalidInvoiceID = { + TransactionType: "CheckCreate", + Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + Destination: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + SendMax: "100000000", + Expiration: 570113521, + InvoiceID: 7896545655285446963258531, + DestinationTag: 1, + Fee: "12", + } as any; - assert.throws( - () => verifyCheckCreate(invalidInvoiceID), - ValidationError, - "CheckCreate: invalid InvoiceID" - ) - }) - -}) \ No newline at end of file + assert.throws( + () => verifyCheckCreate(invalidInvoiceID), + ValidationError, + "CheckCreate: invalid InvoiceID" + ); + }); +}); diff --git a/test/models/depositPreauth.ts b/test/models/depositPreauth.ts index 689cb8a6..388cd892 100644 --- a/test/models/depositPreauth.ts +++ b/test/models/depositPreauth.ts @@ -1,83 +1,85 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyDepositPreauth } from './../../src/models/transactions/depositPreauth' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyDepositPreauth } from "../../src/models/transactions/depositPreauth"; /** - * DepositPreauth Transaction Verification Testing + * DepositPreauth Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('DepositPreauth Transaction Verification', () => { - let depositPreauth +describe("DepositPreauth Transaction Verification", function () { + let depositPreauth; - beforeEach(() => { - depositPreauth = { - TransactionType: 'DepositPreauth', - Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo', - } as any - }) + beforeEach(function () { + depositPreauth = { + TransactionType: "DepositPreauth", + Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + } as any; + }); - it ('verifies valid DepositPreauth when only Authorize is provided', () => { - depositPreauth.Authorize = 'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW' - assert.doesNotThrow(() => verifyDepositPreauth(depositPreauth)) - }) + it("verifies valid DepositPreauth when only Authorize is provided", function () { + depositPreauth.Authorize = "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW"; + assert.doesNotThrow(() => verifyDepositPreauth(depositPreauth)); + }); - it ('verifies valid DepositPreauth when only Unauthorize is provided', () => { - depositPreauth.Unauthorize = 'raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n' - assert.doesNotThrow(() => verifyDepositPreauth(depositPreauth)) - }) + it("verifies valid DepositPreauth when only Unauthorize is provided", function () { + depositPreauth.Unauthorize = "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n"; + assert.doesNotThrow(() => verifyDepositPreauth(depositPreauth)); + }); - it ('throws when both Authorize and Unauthorize are provided', () => { - depositPreauth.Authorize = 'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW' - depositPreauth.Unauthorize = 'raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n' - assert.throws( - () => verifyDepositPreauth(depositPreauth), - ValidationError, - "DepositPreauth: can't provide both Authorize and Unauthorize fields" - ) - }) + it("throws when both Authorize and Unauthorize are provided", function () { + depositPreauth.Authorize = "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW"; + depositPreauth.Unauthorize = "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n"; + assert.throws( + () => verifyDepositPreauth(depositPreauth), + ValidationError, + "DepositPreauth: can't provide both Authorize and Unauthorize fields" + ); + }); - it ('throws when neither Authorize nor Unauthorize are provided', () => { - assert.throws( - () => verifyDepositPreauth(depositPreauth), - ValidationError, - 'DepositPreauth: must provide either Authorize or Unauthorize field' - ) - }) + it("throws when neither Authorize nor Unauthorize are provided", function () { + assert.throws( + () => verifyDepositPreauth(depositPreauth), + ValidationError, + "DepositPreauth: must provide either Authorize or Unauthorize field" + ); + }); - it ('throws when Authorize is not a string', () => { - depositPreauth.Authorize = 1234 - assert.throws( - () => verifyDepositPreauth(depositPreauth), - ValidationError, - 'DepositPreauth: Authorize must be a string' - ) - }) + it("throws when Authorize is not a string", function () { + depositPreauth.Authorize = 1234; + assert.throws( + () => verifyDepositPreauth(depositPreauth), + ValidationError, + "DepositPreauth: Authorize must be a string" + ); + }); - it ('throws when an Account attempts to preauthorize its own address', () => { - depositPreauth.Authorize = depositPreauth.Account - assert.throws( - () => verifyDepositPreauth(depositPreauth), - ValidationError, - "DepositPreauth: Account can't preauthorize its own address" - ) - }) + it("throws when an Account attempts to preauthorize its own address", function () { + depositPreauth.Authorize = depositPreauth.Account; + assert.throws( + () => verifyDepositPreauth(depositPreauth), + ValidationError, + "DepositPreauth: Account can't preauthorize its own address" + ); + }); - it ('throws when Unauthorize is not a string', () => { - depositPreauth.Unauthorize = 1234 - assert.throws( - () => verifyDepositPreauth(depositPreauth), - ValidationError, - 'DepositPreauth: Unauthorize must be a string' - ) - }) + it("throws when Unauthorize is not a string", function () { + depositPreauth.Unauthorize = 1234; + assert.throws( + () => verifyDepositPreauth(depositPreauth), + ValidationError, + "DepositPreauth: Unauthorize must be a string" + ); + }); - it ('throws when an Account attempts to unauthorize its own address', () => { - depositPreauth.Unauthorize = depositPreauth.Account - assert.throws( - () => verifyDepositPreauth(depositPreauth), - ValidationError, - "DepositPreauth: Account can't unauthorize its own address" - ) - }) -}) + it("throws when an Account attempts to unauthorize its own address", function () { + depositPreauth.Unauthorize = depositPreauth.Account; + assert.throws( + () => verifyDepositPreauth(depositPreauth), + ValidationError, + "DepositPreauth: Account can't unauthorize its own address" + ); + }); +}); diff --git a/test/models/escrowCancel.ts b/test/models/escrowCancel.ts index e6bc3474..0f8d9130 100644 --- a/test/models/escrowCancel.ts +++ b/test/models/escrowCancel.ts @@ -1,65 +1,66 @@ -import { verifyEscrowCancel } from './../../src/models/transactions/escrowCancel' -import { assert } from 'chai' -import { ValidationError } from '../../src/common/errors' +import { assert } from "chai"; + +import { ValidationError } from "../../src/common/errors"; +import { verifyEscrowCancel } from "../../src/models/transactions/escrowCancel"; /** - * Transaction Verification Testing + * Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('Transaction Verification', function () { - let cancel +describe("Transaction Verification", function () { + let cancel; - beforeEach(() => { - cancel = { - TransactionType: "EscrowCancel", - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - Owner: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - OfferSequence: 7, - } - }) + beforeEach(function () { + cancel = { + TransactionType: "EscrowCancel", + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + Owner: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + OfferSequence: 7, + }; + }); - it (`Valid EscrowCancel`, () => { - assert.doesNotThrow(() => verifyEscrowCancel(cancel)) - }) + it(`Valid EscrowCancel`, function () { + assert.doesNotThrow(() => verifyEscrowCancel(cancel)); + }); - it (`Invalid EscrowCancel missing owner`, () => { - delete cancel.Owner + it(`Invalid EscrowCancel missing owner`, function () { + delete cancel.Owner; - assert.throws( - () => verifyEscrowCancel(cancel), - ValidationError, - 'EscrowCancel: missing Owner' - ) - }) - - it (`Invalid EscrowCancel missing offerSequence`, () => { - delete cancel.OfferSequence + assert.throws( + () => verifyEscrowCancel(cancel), + ValidationError, + "EscrowCancel: missing Owner" + ); + }); - assert.throws( - () => verifyEscrowCancel(cancel), - ValidationError, - 'EscrowCancel: missing OfferSequence' - ) - }) + it(`Invalid EscrowCancel missing offerSequence`, function () { + delete cancel.OfferSequence; - it (`Invalid OfferSequence`, () => { - cancel.Owner = 10 + assert.throws( + () => verifyEscrowCancel(cancel), + ValidationError, + "EscrowCancel: missing OfferSequence" + ); + }); - assert.throws( - () => verifyEscrowCancel(cancel), - ValidationError, - 'EscrowCancel: Owner must be a string' - ) - }) + it(`Invalid OfferSequence`, function () { + cancel.Owner = 10; - it (`Invalid owner`, () => { - cancel.OfferSequence = "10" + assert.throws( + () => verifyEscrowCancel(cancel), + ValidationError, + "EscrowCancel: Owner must be a string" + ); + }); - assert.throws( - () => verifyEscrowCancel(cancel), - ValidationError, - 'EscrowCancel: OfferSequence must be a number' - ) - }) -}) \ No newline at end of file + it(`Invalid owner`, function () { + cancel.OfferSequence = "10"; + + assert.throws( + () => verifyEscrowCancel(cancel), + ValidationError, + "EscrowCancel: OfferSequence must be a number" + ); + }); +}); diff --git a/test/models/escrowCreate.ts b/test/models/escrowCreate.ts index 3ad4d3d5..1dbb506e 100644 --- a/test/models/escrowCreate.ts +++ b/test/models/escrowCreate.ts @@ -1,132 +1,135 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyEscrowCreate } from './../../src/models/transactions/escrowCreate' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyEscrowCreate } from "../../src/models/transactions/escrowCreate"; /** - * EscrowCreate Transaction Verification Testing + * EscrowCreate Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('EscrowCreate Transaction Verification', function () { - let escrow +describe("EscrowCreate Transaction Verification", function () { + let escrow; - beforeEach(() => { - escrow = { - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - TransactionType: "EscrowCreate", - Amount: "10000", - Destination: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", - CancelAfter: 533257958, - FinishAfter: 533171558, - Condition: "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100", - DestinationTag: 23480, - SourceTag: 11747 - } - }) - - it (`verifies valid EscrowCreate`, () => { - assert.doesNotThrow(() => verifyEscrowCreate(escrow)) - }) + beforeEach(function () { + escrow = { + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + TransactionType: "EscrowCreate", + Amount: "10000", + Destination: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + CancelAfter: 533257958, + FinishAfter: 533171558, + Condition: + "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100", + DestinationTag: 23480, + SourceTag: 11747, + }; + }); - it (`Missing amount`, () => { - delete escrow.Amount - - assert.throws( - () => verifyEscrowCreate(escrow), - ValidationError, - "EscrowCreate: missing field Amount" - ) - }) + it(`verifies valid EscrowCreate`, function () { + assert.doesNotThrow(() => verifyEscrowCreate(escrow)); + }); - it (`Missing destination`, () => { - delete escrow.Destination - - assert.throws( - () => verifyEscrowCreate(escrow), - ValidationError, - "EscrowCreate: missing field Destination" - ) - }) + it(`Missing amount`, function () { + delete escrow.Amount; - it (`throws w/ invalid Destination`, () => { - escrow.Destination = 10 + assert.throws( + () => verifyEscrowCreate(escrow), + ValidationError, + "EscrowCreate: missing field Amount" + ); + }); - assert.throws( - () => verifyEscrowCreate(escrow), - ValidationError, - "EscrowCreate: Destination must be a string" - ) - }) + it(`Missing destination`, function () { + delete escrow.Destination; - it (`throws w/ invalid Amount`, () => { - escrow.Amount = 1000 + assert.throws( + () => verifyEscrowCreate(escrow), + ValidationError, + "EscrowCreate: missing field Destination" + ); + }); - assert.throws( - () => verifyEscrowCreate(escrow), - ValidationError, - "EscrowCreate: Amount must be a string" - ) - }) + it(`throws w/ invalid Destination`, function () { + escrow.Destination = 10; - it (`invalid CancelAfter`, () => { - escrow.CancelAfter = "100" - - assert.throws( - () => verifyEscrowCreate(escrow), - ValidationError, - "EscrowCreate: CancelAfter must be a number" - ) - }) + assert.throws( + () => verifyEscrowCreate(escrow), + ValidationError, + "EscrowCreate: Destination must be a string" + ); + }); - it (`invalid FinishAfter`, () => { - escrow.FinishAfter = "1000" + it(`throws w/ invalid Amount`, function () { + escrow.Amount = 1000; - assert.throws( - () => verifyEscrowCreate(escrow), - ValidationError, - "EscrowCreate: FinishAfter must be a number" - ) - }) + assert.throws( + () => verifyEscrowCreate(escrow), + ValidationError, + "EscrowCreate: Amount must be a string" + ); + }); - it (`invalid Condition`, () => { - escrow.Condition = 0x141243 - - assert.throws( - () => verifyEscrowCreate(escrow), - ValidationError, - "EscrowCreate: Condition must be a string" - ) - }) + it(`invalid CancelAfter`, function () { + escrow.CancelAfter = "100"; - it (`invalid DestinationTag`, () => { - escrow.DestinationTag = "100" - - assert.throws( - () => verifyEscrowCreate(escrow), - ValidationError, - "EscrowCreate: DestinationTag must be a number" - ) - }) + assert.throws( + () => verifyEscrowCreate(escrow), + ValidationError, + "EscrowCreate: CancelAfter must be a number" + ); + }); - it (`Missing both CancelAfter and FinishAfter`, () => { - delete escrow.CancelAfter - delete escrow.FinishAfter - - assert.throws( - () => verifyEscrowCreate(escrow), - ValidationError, - "EscrowCreate: Either CancelAfter or FinishAfter must be specified" - ) - }) + it(`invalid FinishAfter`, function () { + escrow.FinishAfter = "1000"; - it (`Missing both Condition and FinishAfter`, () => { - delete escrow.Condition - delete escrow.FinishAfter - - assert.throws( - () => verifyEscrowCreate(escrow), - ValidationError, - "EscrowCreate: Either Condition or FinishAfter must be specified" - ) - }) -}) \ No newline at end of file + assert.throws( + () => verifyEscrowCreate(escrow), + ValidationError, + "EscrowCreate: FinishAfter must be a number" + ); + }); + + it(`invalid Condition`, function () { + escrow.Condition = 0x141243; + + assert.throws( + () => verifyEscrowCreate(escrow), + ValidationError, + "EscrowCreate: Condition must be a string" + ); + }); + + it(`invalid DestinationTag`, function () { + escrow.DestinationTag = "100"; + + assert.throws( + () => verifyEscrowCreate(escrow), + ValidationError, + "EscrowCreate: DestinationTag must be a number" + ); + }); + + it(`Missing both CancelAfter and FinishAfter`, function () { + delete escrow.CancelAfter; + delete escrow.FinishAfter; + + assert.throws( + () => verifyEscrowCreate(escrow), + ValidationError, + "EscrowCreate: Either CancelAfter or FinishAfter must be specified" + ); + }); + + it(`Missing both Condition and FinishAfter`, function () { + delete escrow.Condition; + delete escrow.FinishAfter; + + assert.throws( + () => verifyEscrowCreate(escrow), + ValidationError, + "EscrowCreate: Either Condition or FinishAfter must be specified" + ); + }); +}); diff --git a/test/models/escrowFinish.ts b/test/models/escrowFinish.ts index c16faf5e..94e0d470 100644 --- a/test/models/escrowFinish.ts +++ b/test/models/escrowFinish.ts @@ -1,75 +1,76 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyEscrowFinish } from './../../src/models/transactions/escrowFinish' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyEscrowFinish } from "../../src/models/transactions/escrowFinish"; /** - * EscrowFinish Transaction Verification Testing + * EscrowFinish Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('EscrowFinish Transaction Verification', function () { - let escrow +describe("EscrowFinish Transaction Verification", function () { + let escrow; - beforeEach(() => { - escrow = { - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - TransactionType: "EscrowFinish", - Owner: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - OfferSequence: 7, - Condition: "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100", - Fulfillment: "A0028000" - } - }) - it (`verifies valid EscrowFinish`, () => { - assert.doesNotThrow(() => verifyEscrowFinish(escrow)) - }) + beforeEach(function () { + escrow = { + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + TransactionType: "EscrowFinish", + Owner: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + OfferSequence: 7, + Condition: + "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100", + Fulfillment: "A0028000", + }; + }); + it(`verifies valid EscrowFinish`, function () { + assert.doesNotThrow(() => verifyEscrowFinish(escrow)); + }); - it (`verifies valid EscrowFinish w/o optional`, () => { - delete escrow.Condition - delete escrow.Fulfillment - - assert.doesNotThrow(() => verifyEscrowFinish(escrow)) - }) + it(`verifies valid EscrowFinish w/o optional`, function () { + delete escrow.Condition; + delete escrow.Fulfillment; + assert.doesNotThrow(() => verifyEscrowFinish(escrow)); + }); - it (`throws w/ invalid Owner`, () => { - escrow.Owner = 0x15415253 - + it(`throws w/ invalid Owner`, function () { + escrow.Owner = 0x15415253; - assert.throws( - () => verifyEscrowFinish(escrow), - ValidationError, - "EscrowFinish: Owner must be a string" - ) - }) + assert.throws( + () => verifyEscrowFinish(escrow), + ValidationError, + "EscrowFinish: Owner must be a string" + ); + }); - it (`throws w/ invalid OfferSequence`, () => { - escrow.OfferSequence = "10" + it(`throws w/ invalid OfferSequence`, function () { + escrow.OfferSequence = "10"; - assert.throws( - () => verifyEscrowFinish(escrow), - ValidationError, - "EscrowFinish: OfferSequence must be a number" - ) - }) + assert.throws( + () => verifyEscrowFinish(escrow), + ValidationError, + "EscrowFinish: OfferSequence must be a number" + ); + }); - it (`throws w/ invalid Condition`, () => { - escrow.Condition = 10 + it(`throws w/ invalid Condition`, function () { + escrow.Condition = 10; - assert.throws( - () => verifyEscrowFinish(escrow), - ValidationError, - "EscrowFinish: Condition must be a string" - ) - }) + assert.throws( + () => verifyEscrowFinish(escrow), + ValidationError, + "EscrowFinish: Condition must be a string" + ); + }); - it (`throws w/ invalid Fulfillment`, () => { - escrow.Fulfillment = 0x142341 + it(`throws w/ invalid Fulfillment`, function () { + escrow.Fulfillment = 0x142341; - assert.throws( - () => verifyEscrowFinish(escrow), - ValidationError, - "EscrowFinish: Fulfillment must be a string" - ) - }) -}) \ No newline at end of file + assert.throws( + () => verifyEscrowFinish(escrow), + ValidationError, + "EscrowFinish: Fulfillment must be a string" + ); + }); +}); diff --git a/test/models/offerCancel.ts b/test/models/offerCancel.ts index 7568581b..69aa2507 100644 --- a/test/models/offerCancel.ts +++ b/test/models/offerCancel.ts @@ -1,53 +1,57 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyOfferCancel } from './../../src/models/transactions/offerCancel' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyOfferCancel } from "../../src/models/transactions/offerCancel"; /** - * OfferCancel Transaction Verification Testing + * OfferCancel Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('OfferCancel Transaction Verification', function () { - let offer - - beforeEach(() => { - offer = { - Account: "rnKiczmiQkZFiDES8THYyLA2pQohC5C6EF", - Fee: "10", - LastLedgerSequence: 65477334, - OfferSequence: 60797528, - Sequence: 60797535, - SigningPubKey: "0361BFD43D1EEA54B77CC152887312949EBF052997FBFFCDAF6F2653164B55B21...", - TransactionType: "OfferCancel", - TxnSignature: "30450221008C43BDCFC68B4793857CA47DF454C07E5B45D3F80E8E6785CAB9292...", - date: "2021-08-06T21:04:11Z" - } as any - }) +describe("OfferCancel Transaction Verification", function () { + let offer; - it (`verifies valid OfferCancel`, () => { - assert.doesNotThrow(() => verifyOfferCancel(offer)) - }) + beforeEach(function () { + offer = { + Account: "rnKiczmiQkZFiDES8THYyLA2pQohC5C6EF", + Fee: "10", + LastLedgerSequence: 65477334, + OfferSequence: 60797528, + Sequence: 60797535, + SigningPubKey: + "0361BFD43D1EEA54B77CC152887312949EBF052997FBFFCDAF6F2653164B55B21...", + TransactionType: "OfferCancel", + TxnSignature: + "30450221008C43BDCFC68B4793857CA47DF454C07E5B45D3F80E8E6785CAB9292...", + date: "2021-08-06T21:04:11Z", + } as any; + }); - it (`verifies valid OfferCancel with flags`, () => { - offer.Flags = 2147483648 - assert.doesNotThrow(() => verifyOfferCancel(offer)) - }) + it(`verifies valid OfferCancel`, function () { + assert.doesNotThrow(() => verifyOfferCancel(offer)); + }); - it (`throws w/ OfferSequence must be a number`, () => { - offer.OfferSequence = '99' - assert.throws( - () => verifyOfferCancel(offer), - ValidationError, - "OfferCancel: OfferSequence must be a number" - ) - }) + it(`verifies valid OfferCancel with flags`, function () { + offer.Flags = 2147483648; + assert.doesNotThrow(() => verifyOfferCancel(offer)); + }); - it (`throws w/ missing OfferSequence`, () => { - delete offer.OfferSequence - assert.throws( - () => verifyOfferCancel(offer), - ValidationError, - "OfferCancel: missing field OfferSequence" - ) - }) -}) \ No newline at end of file + it(`throws w/ OfferSequence must be a number`, function () { + offer.OfferSequence = "99"; + assert.throws( + () => verifyOfferCancel(offer), + ValidationError, + "OfferCancel: OfferSequence must be a number" + ); + }); + + it(`throws w/ missing OfferSequence`, function () { + delete offer.OfferSequence; + assert.throws( + () => verifyOfferCancel(offer), + ValidationError, + "OfferCancel: missing field OfferSequence" + ); + }); +}); diff --git a/test/models/offerCreate.ts b/test/models/offerCreate.ts index c082f37e..c1bfc4a1 100644 --- a/test/models/offerCreate.ts +++ b/test/models/offerCreate.ts @@ -1,177 +1,191 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyOfferCreate } from './../../src/models/transactions/offerCreate' -import { assert } from 'chai' +import { assert } from "chai"; +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyOfferCreate } from "../../src/models/transactions/offerCreate"; /** - * OfferCreate Transaction Verification Testing + * OfferCreate Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('OfferCreate Transaction Verification', function () { - it (`verifies valid OfferCreate`, () => { - const offer = { - Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", - Fee: "10", - Flags: 0, - LastLedgerSequence: 65453019, - Sequence: 40949322, - SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", - Expiration: 10, - OfferSequence: 12, - TakerGets: { - currency: "DSH", - issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", - value: "43.11584856965009" - }, - TakerPays: "12928290425", - TransactionType: "OfferCreate", - TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", - } as any - - assert.doesNotThrow(() => verifyOfferCreate(offer)) +describe("OfferCreate Transaction Verification", function () { + it(`verifies valid OfferCreate`, function () { + const offer = { + Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", + Fee: "10", + Flags: 0, + LastLedgerSequence: 65453019, + Sequence: 40949322, + SigningPubKey: + "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", + Expiration: 10, + OfferSequence: 12, + TakerGets: { + currency: "DSH", + issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", + value: "43.11584856965009", + }, + TakerPays: "12928290425", + TransactionType: "OfferCreate", + TxnSignature: + "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", + } as any; - const offer2 = { - Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", - Fee: "10", - Flags: 0, - LastLedgerSequence: 65453019, - Sequence: 40949322, - SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", - TakerGets: "12928290425", - TakerPays: { - currency: "DSH", - issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", - value: "43.11584856965009" - }, - TransactionType: "OfferCreate", - TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", - } as any + assert.doesNotThrow(() => verifyOfferCreate(offer)); - assert.doesNotThrow(() => verifyOfferCreate(offer2)) + const offer2 = { + Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", + Fee: "10", + Flags: 0, + LastLedgerSequence: 65453019, + Sequence: 40949322, + SigningPubKey: + "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", + TakerGets: "12928290425", + TakerPays: { + currency: "DSH", + issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", + value: "43.11584856965009", + }, + TransactionType: "OfferCreate", + TxnSignature: + "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", + } as any; + assert.doesNotThrow(() => verifyOfferCreate(offer2)); - const offer3 = { - Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", - Fee: "10", - Flags: 0, - LastLedgerSequence: 65453019, - Sequence: 40949322, - SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", - TakerGets: { - currency: "DSH", - issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", - value: "43.11584856965009" - }, - TakerPays: { - currency: "DSH", - issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", - value: "43.11584856965009" - }, - TransactionType: "OfferCreate", - TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", - } as any + const offer3 = { + Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", + Fee: "10", + Flags: 0, + LastLedgerSequence: 65453019, + Sequence: 40949322, + SigningPubKey: + "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", + TakerGets: { + currency: "DSH", + issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", + value: "43.11584856965009", + }, + TakerPays: { + currency: "DSH", + issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", + value: "43.11584856965009", + }, + TransactionType: "OfferCreate", + TxnSignature: + "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", + } as any; - assert.doesNotThrow(() => verifyOfferCreate(offer3)) - }) + assert.doesNotThrow(() => verifyOfferCreate(offer3)); + }); - it (`throws w/ invalid Expiration`, () => { - const offer = { - Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", - Fee: "10", - Flags: 0, - LastLedgerSequence: 65453019, - Sequence: 40949322, - SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", - Expiration: "11", - TakerGets: "12928290425", - TakerPays: { - currency: "DSH", - issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", - value: "43.11584856965009" - }, - TransactionType: "OfferCreate", - TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", - } as any + it(`throws w/ invalid Expiration`, function () { + const offer = { + Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", + Fee: "10", + Flags: 0, + LastLedgerSequence: 65453019, + Sequence: 40949322, + SigningPubKey: + "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", + Expiration: "11", + TakerGets: "12928290425", + TakerPays: { + currency: "DSH", + issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", + value: "43.11584856965009", + }, + TransactionType: "OfferCreate", + TxnSignature: + "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", + } as any; - assert.throws( - () => verifyOfferCreate(offer), - ValidationError, - "OfferCreate: invalid Expiration" - ) - }) + assert.throws( + () => verifyOfferCreate(offer), + ValidationError, + "OfferCreate: invalid Expiration" + ); + }); - it (`throws w/ invalid OfferSequence`, () => { - const offer = { - Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", - Fee: "10", - Flags: 0, - LastLedgerSequence: 65453019, - Sequence: 40949322, - SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", - OfferSequence: "11", - TakerGets: "12928290425", - TakerPays: { - currency: "DSH", - issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", - value: "43.11584856965009" - }, - TransactionType: "OfferCreate", - TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", - } as any + it(`throws w/ invalid OfferSequence`, function () { + const offer = { + Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", + Fee: "10", + Flags: 0, + LastLedgerSequence: 65453019, + Sequence: 40949322, + SigningPubKey: + "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", + OfferSequence: "11", + TakerGets: "12928290425", + TakerPays: { + currency: "DSH", + issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", + value: "43.11584856965009", + }, + TransactionType: "OfferCreate", + TxnSignature: + "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", + } as any; - assert.throws( - () => verifyOfferCreate(offer), - ValidationError, - "OfferCreate: invalid OfferSequence" - ) - }) + assert.throws( + () => verifyOfferCreate(offer), + ValidationError, + "OfferCreate: invalid OfferSequence" + ); + }); - it (`throws w/ invalid TakerPays`, () => { - const offer = { - Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", - Fee: "10", - Flags: 0, - LastLedgerSequence: 65453019, - Sequence: 40949322, - SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", - OfferSequence: "11", - TakerGets: "12928290425", - TakerPays: 10, - TransactionType: "OfferCreate", - TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", - } as any + it(`throws w/ invalid TakerPays`, function () { + const offer = { + Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", + Fee: "10", + Flags: 0, + LastLedgerSequence: 65453019, + Sequence: 40949322, + SigningPubKey: + "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", + OfferSequence: "11", + TakerGets: "12928290425", + TakerPays: 10, + TransactionType: "OfferCreate", + TxnSignature: + "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", + } as any; - assert.throws( - () => verifyOfferCreate(offer), - ValidationError, - "OfferCreate: invalid TakerPays" - ) - }) + assert.throws( + () => verifyOfferCreate(offer), + ValidationError, + "OfferCreate: invalid TakerPays" + ); + }); - it (`throws w/ invalid TakerGets`, () => { - const offer = { - Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", - Fee: "10", - Flags: 0, - LastLedgerSequence: 65453019, - Sequence: 40949322, - SigningPubKey: "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", - OfferSequence: "11", - TakerGets: 11, - TakerPays: { - currency: "DSH", - issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", - value: "43.11584856965009" - }, - TransactionType: "OfferCreate", - TxnSignature: "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", - } as any + it(`throws w/ invalid TakerGets`, function () { + const offer = { + Account: "r3rhWeE31Jt5sWmi4QiGLMZnY3ENgqw96W", + Fee: "10", + Flags: 0, + LastLedgerSequence: 65453019, + Sequence: 40949322, + SigningPubKey: + "03C48299E57F5AE7C2BE1391B581D313F1967EA2301628C07AC412092FDC15BA22", + OfferSequence: "11", + TakerGets: 11, + TakerPays: { + currency: "DSH", + issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", + value: "43.11584856965009", + }, + TransactionType: "OfferCreate", + TxnSignature: + "3045022100D874CDDD6BB24ED66E83B1D3574D3ECAC753A78F26DB7EBA89EAB8E7D72B95F802207C8CCD6CEA64E4AE2014E59EE9654E02CA8F03FE7FCE0539E958EAE182234D91", + } as any; - assert.throws( - () => verifyOfferCreate(offer), - ValidationError, - "OfferCreate: invalid TakerGets" - ) - }) -}) \ No newline at end of file + assert.throws( + () => verifyOfferCreate(offer), + ValidationError, + "OfferCreate: invalid TakerGets" + ); + }); +}); diff --git a/test/models/paymentChannelClaim.ts b/test/models/paymentChannelClaim.ts index e3d4e252..ae0949e9 100644 --- a/test/models/paymentChannelClaim.ts +++ b/test/models/paymentChannelClaim.ts @@ -1,98 +1,102 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyPaymentChannelClaim } from './../../src/models/transactions/paymentChannelClaim' -import { assert } from 'chai' +import { assert } from "chai"; +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyPaymentChannelClaim } from "../../src/models/transactions/paymentChannelClaim"; /** - * PaymentChannelClaim Transaction Verification Testing + * PaymentChannelClaim Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('PaymentChannelClaim Transaction Verification', function () { - let channel +describe("PaymentChannelClaim Transaction Verification", function () { + let channel; - beforeEach(() => { - channel = { - "Account": "r...", - "TransactionType": "PaymentChannelClaim", - "Channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", - "Balance": "1000000", - "Amount": "1000000", - "Signature": "30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B", - "PublicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A" - } - }) + beforeEach(function () { + channel = { + Account: "r...", + TransactionType: "PaymentChannelClaim", + Channel: + "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + Balance: "1000000", + Amount: "1000000", + Signature: + "30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B", + PublicKey: + "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A", + }; + }); - it (`verifies valid PaymentChannelClaim`, () => { - assert.doesNotThrow(() => verifyPaymentChannelClaim(channel)) - }) + it(`verifies valid PaymentChannelClaim`, function () { + assert.doesNotThrow(() => verifyPaymentChannelClaim(channel)); + }); - it (`verifies valid PaymentChannelClaim w/o optional`, () => { - delete channel.Balance - delete channel.Amount - delete channel.Signature - delete channel.PublicKey - - assert.doesNotThrow(() => verifyPaymentChannelClaim(channel)) - }) + it(`verifies valid PaymentChannelClaim w/o optional`, function () { + delete channel.Balance; + delete channel.Amount; + delete channel.Signature; + delete channel.PublicKey; - it (`throws w/ missing Channel`, () => { - delete channel.Channel - - assert.throws( - () => verifyPaymentChannelClaim(channel), - ValidationError, - "PaymentChannelClaim: missing Channel" - ) - }) + assert.doesNotThrow(() => verifyPaymentChannelClaim(channel)); + }); - it (`throws w/ invalid Channel`, () => { - channel.Channel = 100 - - assert.throws( - () => verifyPaymentChannelClaim(channel), - ValidationError, - "PaymentChannelClaim: Channel must be a string" - ) - }) + it(`throws w/ missing Channel`, function () { + delete channel.Channel; - it (`throws w/ invalid Balance`, () => { - channel.Balance = 100 - - assert.throws( - () => verifyPaymentChannelClaim(channel), - ValidationError, - "PaymentChannelClaim: Balance must be a string" - ) - }) + assert.throws( + () => verifyPaymentChannelClaim(channel), + ValidationError, + "PaymentChannelClaim: missing Channel" + ); + }); - it (`throws w/ invalid Amount`, () => { - channel.Amount = 1000 - - assert.throws( - () => verifyPaymentChannelClaim(channel), - ValidationError, - "PaymentChannelClaim: Amount must be a string" - ) - }) + it(`throws w/ invalid Channel`, function () { + channel.Channel = 100; - it (`throws w/ invalid Signature`, () => { - channel.Signature = 1000 - - assert.throws( - () => verifyPaymentChannelClaim(channel), - ValidationError, - "PaymentChannelClaim: Signature must be a string" - ) - }) + assert.throws( + () => verifyPaymentChannelClaim(channel), + ValidationError, + "PaymentChannelClaim: Channel must be a string" + ); + }); - it (`throws w/ invalid PublicKey`, () => { - channel.PublicKey = ["100000"] - - assert.throws( - () => verifyPaymentChannelClaim(channel), - ValidationError, - "PaymentChannelClaim: PublicKey must be a string" - ) - }) -}) \ No newline at end of file + it(`throws w/ invalid Balance`, function () { + channel.Balance = 100; + + assert.throws( + () => verifyPaymentChannelClaim(channel), + ValidationError, + "PaymentChannelClaim: Balance must be a string" + ); + }); + + it(`throws w/ invalid Amount`, function () { + channel.Amount = 1000; + + assert.throws( + () => verifyPaymentChannelClaim(channel), + ValidationError, + "PaymentChannelClaim: Amount must be a string" + ); + }); + + it(`throws w/ invalid Signature`, function () { + channel.Signature = 1000; + + assert.throws( + () => verifyPaymentChannelClaim(channel), + ValidationError, + "PaymentChannelClaim: Signature must be a string" + ); + }); + + it(`throws w/ invalid PublicKey`, function () { + channel.PublicKey = ["100000"]; + + assert.throws( + () => verifyPaymentChannelClaim(channel), + ValidationError, + "PaymentChannelClaim: PublicKey must be a string" + ); + }); +}); diff --git a/test/models/paymentChannelCreate.ts b/test/models/paymentChannelCreate.ts index 4f0e507e..8ec43a6e 100644 --- a/test/models/paymentChannelCreate.ts +++ b/test/models/paymentChannelCreate.ts @@ -1,140 +1,141 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyPaymentChannelCreate } from './../../src/models/transactions/paymentChannelCreate' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyPaymentChannelCreate } from "../../src/models/transactions/paymentChannelCreate"; /** - * PaymentChannelCreate Transaction Verification Testing + * PaymentChannelCreate Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('PaymentChannelCreate Transaction Verification', function () { - let channel +describe("PaymentChannelCreate Transaction Verification", function () { + let channel; - beforeEach(() => { - channel = { - "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "TransactionType": "PaymentChannelCreate", - "Amount": "10000", - "Destination": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", - "SettleDelay": 86400, - "PublicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A", - "CancelAfter": 533171558, - "DestinationTag": 23480, - "SourceTag": 11747 - } - }) - - it (`verifies valid PaymentChannelCreate`, () => { - assert.doesNotThrow(() => verifyPaymentChannelCreate(channel)) - }) + beforeEach(function () { + channel = { + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + TransactionType: "PaymentChannelCreate", + Amount: "10000", + Destination: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + SettleDelay: 86400, + PublicKey: + "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A", + CancelAfter: 533171558, + DestinationTag: 23480, + SourceTag: 11747, + }; + }); - it (`verifies valid PaymentChannelCreate w/o optional`, () => { - delete channel.CancelAfter - delete channel.DestinationTag - delete channel.SourceTag + it(`verifies valid PaymentChannelCreate`, function () { + assert.doesNotThrow(() => verifyPaymentChannelCreate(channel)); + }); - assert.doesNotThrow(() => verifyPaymentChannelCreate(channel)) - }) + it(`verifies valid PaymentChannelCreate w/o optional`, function () { + delete channel.CancelAfter; + delete channel.DestinationTag; + delete channel.SourceTag; - it (`missing Amount`, () => { - delete channel.Amount - - assert.throws( - () => verifyPaymentChannelCreate(channel), - ValidationError, - "PaymentChannelCreate: missing Amount" - ) - }) + assert.doesNotThrow(() => verifyPaymentChannelCreate(channel)); + }); + it(`missing Amount`, function () { + delete channel.Amount; - it (`missing Destination`, () => { - delete channel.Destination - - assert.throws( - () => verifyPaymentChannelCreate(channel), - ValidationError, - "PaymentChannelCreate: missing Destination" - ) - }) + assert.throws( + () => verifyPaymentChannelCreate(channel), + ValidationError, + "PaymentChannelCreate: missing Amount" + ); + }); - it (`missing SettleDelay`, () => { - delete channel.SettleDelay - - assert.throws( - () => verifyPaymentChannelCreate(channel), - ValidationError, - "PaymentChannelCreate: missing SettleDelay" - ) - }) + it(`missing Destination`, function () { + delete channel.Destination; - it (`missing PublicKey`, () => { - delete channel.PublicKey - - assert.throws( - () => verifyPaymentChannelCreate(channel), - ValidationError, - "PaymentChannelCreate: missing PublicKey" - ) - }) + assert.throws( + () => verifyPaymentChannelCreate(channel), + ValidationError, + "PaymentChannelCreate: missing Destination" + ); + }); - it (`invalid Amount`, () => { - channel.Amount = 1000 - - assert.throws( - () => verifyPaymentChannelCreate(channel), - ValidationError, - "PaymentChannelCreate: Amount must be a string" - ) - }) + it(`missing SettleDelay`, function () { + delete channel.SettleDelay; + assert.throws( + () => verifyPaymentChannelCreate(channel), + ValidationError, + "PaymentChannelCreate: missing SettleDelay" + ); + }); - it (`invalid Destination`, () => { - channel.Destination = 10; - - assert.throws( - () => verifyPaymentChannelCreate(channel), - ValidationError, - "PaymentChannelCreate: Destination must be a string" - ) - }) + it(`missing PublicKey`, function () { + delete channel.PublicKey; - it (`invalid SettleDelay`, () => { - channel.SettleDelay = "10" - - assert.throws( - () => verifyPaymentChannelCreate(channel), - ValidationError, - "PaymentChannelCreate: SettleDelay must be a number" - ) - }) + assert.throws( + () => verifyPaymentChannelCreate(channel), + ValidationError, + "PaymentChannelCreate: missing PublicKey" + ); + }); - it (`invalid PublicKey`, () => { - channel.PublicKey = 10 - - assert.throws( - () => verifyPaymentChannelCreate(channel), - ValidationError, - "PaymentChannelCreate: PublicKey must be a string" - ) - }) + it(`invalid Amount`, function () { + channel.Amount = 1000; - it (`invalid DestinationTag`, () => { - channel.DestinationTag = "10" + assert.throws( + () => verifyPaymentChannelCreate(channel), + ValidationError, + "PaymentChannelCreate: Amount must be a string" + ); + }); - assert.throws( - () => verifyPaymentChannelCreate(channel), - ValidationError, - "PaymentChannelCreate: DestinationTag must be a number" - ) - }) + it(`invalid Destination`, function () { + channel.Destination = 10; - it (`invalid CancelAfter`, () => { - channel.CancelAfter = "100" - - assert.throws( - () => verifyPaymentChannelCreate(channel), - ValidationError, - "PaymentChannelCreate: CancelAfter must be a number" - ) - }) -}) \ No newline at end of file + assert.throws( + () => verifyPaymentChannelCreate(channel), + ValidationError, + "PaymentChannelCreate: Destination must be a string" + ); + }); + + it(`invalid SettleDelay`, function () { + channel.SettleDelay = "10"; + + assert.throws( + () => verifyPaymentChannelCreate(channel), + ValidationError, + "PaymentChannelCreate: SettleDelay must be a number" + ); + }); + + it(`invalid PublicKey`, function () { + channel.PublicKey = 10; + + assert.throws( + () => verifyPaymentChannelCreate(channel), + ValidationError, + "PaymentChannelCreate: PublicKey must be a string" + ); + }); + + it(`invalid DestinationTag`, function () { + channel.DestinationTag = "10"; + + assert.throws( + () => verifyPaymentChannelCreate(channel), + ValidationError, + "PaymentChannelCreate: DestinationTag must be a number" + ); + }); + + it(`invalid CancelAfter`, function () { + channel.CancelAfter = "100"; + + assert.throws( + () => verifyPaymentChannelCreate(channel), + ValidationError, + "PaymentChannelCreate: CancelAfter must be a number" + ); + }); +}); diff --git a/test/models/paymentChannelFund.ts b/test/models/paymentChannelFund.ts index edc78907..ba491ae7 100644 --- a/test/models/paymentChannelFund.ts +++ b/test/models/paymentChannelFund.ts @@ -1,83 +1,85 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyPaymentChannelFund } from './../../src/models/transactions/paymentChannelFund' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyPaymentChannelFund } from "../../src/models/transactions/paymentChannelFund"; /** - * PaymentChannelFund Transaction Verification Testing + * PaymentChannelFund Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('PaymentChannelFund Transaction Verification', function () { - let channel +describe("PaymentChannelFund Transaction Verification", function () { + let channel; - beforeEach(() => { - channel = { - "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "TransactionType": "PaymentChannelFund", - "Channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", - "Amount": "200000", - "Expiration": 543171558 - } - }) - - it (`verifies valid PaymentChannelFund`, () => { - assert.doesNotThrow(() => verifyPaymentChannelFund(channel)) - }) + beforeEach(function () { + channel = { + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + TransactionType: "PaymentChannelFund", + Channel: + "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + Amount: "200000", + Expiration: 543171558, + }; + }); - it (`verifies valid PaymentChannelFund w/o optional`, () => { - delete channel.Expiration - - assert.doesNotThrow(() => verifyPaymentChannelFund(channel)) - }) + it(`verifies valid PaymentChannelFund`, function () { + assert.doesNotThrow(() => verifyPaymentChannelFund(channel)); + }); - it (`throws w/ missing Amount`, () => { - delete channel.Amount + it(`verifies valid PaymentChannelFund w/o optional`, function () { + delete channel.Expiration; - assert.throws( - () => verifyPaymentChannelFund(channel), - ValidationError, - "PaymentChannelFund: missing Amount" - ) - }) + assert.doesNotThrow(() => verifyPaymentChannelFund(channel)); + }); - it (`throws w/ missing Channel`, () => { - delete channel.Channel + it(`throws w/ missing Amount`, function () { + delete channel.Amount; - assert.throws( - () => verifyPaymentChannelFund(channel), - ValidationError, - "PaymentChannelFund: missing Channel" - ) - }) + assert.throws( + () => verifyPaymentChannelFund(channel), + ValidationError, + "PaymentChannelFund: missing Amount" + ); + }); - it (`throws w/ invalid Amount`, () => { - channel.Amount = 100 + it(`throws w/ missing Channel`, function () { + delete channel.Channel; - assert.throws( - () => verifyPaymentChannelFund(channel), - ValidationError, - "PaymentChannelFund: Amount must be a string" - ) - }) + assert.throws( + () => verifyPaymentChannelFund(channel), + ValidationError, + "PaymentChannelFund: missing Channel" + ); + }); - it (`throws w/ invalid Channel`, () => { - channel.Channel = 1000 + it(`throws w/ invalid Amount`, function () { + channel.Amount = 100; - assert.throws( - () => verifyPaymentChannelFund(channel), - ValidationError, - "PaymentChannelFund: Channel must be a string" - ) - }) + assert.throws( + () => verifyPaymentChannelFund(channel), + ValidationError, + "PaymentChannelFund: Amount must be a string" + ); + }); - it (`throws w/ invalid Expiration`, () => { - channel.Expiration = "1000" - - assert.throws( - () => verifyPaymentChannelFund(channel), - ValidationError, - "PaymentChannelFund: Expiration must be a number" - ) - }) + it(`throws w/ invalid Channel`, function () { + channel.Channel = 1000; -}) \ No newline at end of file + assert.throws( + () => verifyPaymentChannelFund(channel), + ValidationError, + "PaymentChannelFund: Channel must be a string" + ); + }); + + it(`throws w/ invalid Expiration`, function () { + channel.Expiration = "1000"; + + assert.throws( + () => verifyPaymentChannelFund(channel), + ValidationError, + "PaymentChannelFund: Expiration must be a number" + ); + }); +}); diff --git a/test/models/paymentTransaction.ts b/test/models/paymentTransaction.ts index 59f47a25..c28d0e75 100644 --- a/test/models/paymentTransaction.ts +++ b/test/models/paymentTransaction.ts @@ -1,132 +1,140 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { PaymentTransactionFlagsEnum, verifyPaymentTransaction } from './../../src/models/transactions/paymentTransaction' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { + PaymentTransactionFlagsEnum, + verifyPaymentTransaction, +} from "../../src/models/transactions/paymentTransaction"; /** - * PaymentTransaction Verification Testing + * PaymentTransaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('Payment Transaction Verification', () => { - let paymentTransaction +describe("Payment Transaction Verification", function () { + let paymentTransaction; - beforeEach(() => { - paymentTransaction = { - TransactionType: 'Payment', - Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo', - Amount: '1234', - Destination: 'rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy', - DestinationTag: 1, - InvoiceID: '6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B', - Paths: [[{ account: 'aw0efji', currency: 'XRP', issuer: 'apsoeijf90wp34fh'}]], - SendMax: '100000000', - } as any - }) + beforeEach(function () { + paymentTransaction = { + TransactionType: "Payment", + Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + Amount: "1234", + Destination: "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + DestinationTag: 1, + InvoiceID: + "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B", + Paths: [ + [{ account: "aw0efji", currency: "XRP", issuer: "apsoeijf90wp34fh" }], + ], + SendMax: "100000000", + } as any; + }); - it (`verifies valid PaymentTransaction`, () => { - assert.doesNotThrow(() => verifyPaymentTransaction(paymentTransaction)) - }) + it(`verifies valid PaymentTransaction`, function () { + assert.doesNotThrow(() => verifyPaymentTransaction(paymentTransaction)); + }); - it (`throws when Amount is missing`, () => { - delete paymentTransaction.Amount - assert.throws( - () => verifyPaymentTransaction(paymentTransaction), - ValidationError, - 'PaymentTransaction: missing field Amount' - ) - }) + it(`throws when Amount is missing`, function () { + delete paymentTransaction.Amount; + assert.throws( + () => verifyPaymentTransaction(paymentTransaction), + ValidationError, + "PaymentTransaction: missing field Amount" + ); + }); - it (`throws when Amount is invalid`, () => { - paymentTransaction.Amount = 1234 - assert.throws( - () => verifyPaymentTransaction(paymentTransaction), - ValidationError, - 'PaymentTransaction: invalid Amount' - ) - }) + it(`throws when Amount is invalid`, function () { + paymentTransaction.Amount = 1234; + assert.throws( + () => verifyPaymentTransaction(paymentTransaction), + ValidationError, + "PaymentTransaction: invalid Amount" + ); + }); - it (`throws when Destination is missing`, () => { - delete paymentTransaction.Destination - assert.throws( - () => verifyPaymentTransaction(paymentTransaction), - ValidationError, - 'PaymentTransaction: missing field Destination' - ) - }) + it(`throws when Destination is missing`, function () { + delete paymentTransaction.Destination; + assert.throws( + () => verifyPaymentTransaction(paymentTransaction), + ValidationError, + "PaymentTransaction: missing field Destination" + ); + }); - it (`throws when Destination is invalid`, () => { - paymentTransaction.Destination = 7896214 - assert.throws( - () => verifyPaymentTransaction(paymentTransaction), - ValidationError, - 'PaymentTransaction: invalid Destination' - ) - }) + it(`throws when Destination is invalid`, function () { + paymentTransaction.Destination = 7896214; + assert.throws( + () => verifyPaymentTransaction(paymentTransaction), + ValidationError, + "PaymentTransaction: invalid Destination" + ); + }); - it (`throws when DestinationTag is not a number`, () => { - paymentTransaction.DestinationTag = '1' - assert.throws( - () => verifyPaymentTransaction(paymentTransaction), - ValidationError, - 'PaymentTransaction: DestinationTag must be a number' - ) - }) + it(`throws when DestinationTag is not a number`, function () { + paymentTransaction.DestinationTag = "1"; + assert.throws( + () => verifyPaymentTransaction(paymentTransaction), + ValidationError, + "PaymentTransaction: DestinationTag must be a number" + ); + }); - it (`throws when InvoiceID is not a string`, () => { - paymentTransaction.InvoiceID = 19832 - assert.throws( - () => verifyPaymentTransaction(paymentTransaction), - ValidationError, - 'PaymentTransaction: InvoiceID must be a string' - ) - }) + it(`throws when InvoiceID is not a string`, function () { + paymentTransaction.InvoiceID = 19832; + assert.throws( + () => verifyPaymentTransaction(paymentTransaction), + ValidationError, + "PaymentTransaction: InvoiceID must be a string" + ); + }); - it (`throws when Paths is invalid`, () => { - paymentTransaction.Paths = [[{ account: 123 }]] - assert.throws( - () => verifyPaymentTransaction(paymentTransaction), - ValidationError, - 'PaymentTransaction: invalid Paths' - ) - }) + it(`throws when Paths is invalid`, function () { + paymentTransaction.Paths = [[{ account: 123 }]]; + assert.throws( + () => verifyPaymentTransaction(paymentTransaction), + ValidationError, + "PaymentTransaction: invalid Paths" + ); + }); - it (`throws when SendMax is invalid`, () => { - paymentTransaction.SendMax = 100000000 - assert.throws( - () => verifyPaymentTransaction(paymentTransaction), - ValidationError, - 'PaymentTransaction: invalid SendMax' - ) - }) + it(`throws when SendMax is invalid`, function () { + paymentTransaction.SendMax = 100000000; + assert.throws( + () => verifyPaymentTransaction(paymentTransaction), + ValidationError, + "PaymentTransaction: invalid SendMax" + ); + }); - it (`verifies valid DeliverMin with tfPartialPayment flag set as a number`, () => { - paymentTransaction.DeliverMin = '10000' - paymentTransaction.Flags = PaymentTransactionFlagsEnum.tfPartialPayment, - assert.doesNotThrow(() => verifyPaymentTransaction(paymentTransaction)) - }) + it(`verifies valid DeliverMin with tfPartialPayment flag set as a number`, function () { + paymentTransaction.DeliverMin = "10000"; + (paymentTransaction.Flags = PaymentTransactionFlagsEnum.tfPartialPayment), + assert.doesNotThrow(() => verifyPaymentTransaction(paymentTransaction)); + }); - it (`verifies valid DeliverMin with tfPartialPayment flag set as a boolean`, () => { - paymentTransaction.DeliverMin = '10000' - paymentTransaction.Flags = { tfPartialPayment: true } - assert.doesNotThrow(() => verifyPaymentTransaction(paymentTransaction)) - }) + it(`verifies valid DeliverMin with tfPartialPayment flag set as a boolean`, function () { + paymentTransaction.DeliverMin = "10000"; + paymentTransaction.Flags = { tfPartialPayment: true }; + assert.doesNotThrow(() => verifyPaymentTransaction(paymentTransaction)); + }); - it (`throws when DeliverMin is invalid`, () => { - paymentTransaction.DeliverMin = 10000 - paymentTransaction.Flags = { tfPartialPayment: true } - assert.throws( - () => verifyPaymentTransaction(paymentTransaction), - ValidationError, - 'PaymentTransaction: invalid DeliverMin' - ) - }) + it(`throws when DeliverMin is invalid`, function () { + paymentTransaction.DeliverMin = 10000; + paymentTransaction.Flags = { tfPartialPayment: true }; + assert.throws( + () => verifyPaymentTransaction(paymentTransaction), + ValidationError, + "PaymentTransaction: invalid DeliverMin" + ); + }); - it (`throws when tfPartialPayment flag is missing with valid DeliverMin`, () => { - paymentTransaction.DeliverMin = '10000' - assert.throws( - () => verifyPaymentTransaction(paymentTransaction), - ValidationError, - 'PaymentTransaction: tfPartialPayment flag required with DeliverMin' - ) - }) -}) + it(`throws when tfPartialPayment flag is missing with valid DeliverMin`, function () { + paymentTransaction.DeliverMin = "10000"; + assert.throws( + () => verifyPaymentTransaction(paymentTransaction), + ValidationError, + "PaymentTransaction: tfPartialPayment flag required with DeliverMin" + ); + }); +}); diff --git a/test/models/setRegularKey.ts b/test/models/setRegularKey.ts index e8a8fc87..0d945d1b 100644 --- a/test/models/setRegularKey.ts +++ b/test/models/setRegularKey.ts @@ -1,42 +1,43 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifySetRegularKey } from './../../src/models/transactions/setRegularKey' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifySetRegularKey } from "../../src/models/transactions/setRegularKey"; /** - * SetRegularKey Transaction Verification Testing + * SetRegularKey Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('SetRegularKey Transaction Verification', function () { - let account +describe("SetRegularKey Transaction Verification", function () { + let account; - beforeEach(() => { - account = { - TransactionType : "SetRegularKey", - Account : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - Fee : "12", - Flags : 0, - RegularKey : "rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD" - } as any - }) + beforeEach(function () { + account = { + TransactionType: "SetRegularKey", + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + Fee: "12", + Flags: 0, + RegularKey: "rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD", + } as any; + }); - it (`verifies valid SetRegularKey`, () => { - assert.doesNotThrow(() => verifySetRegularKey(account)) - }) + it(`verifies valid SetRegularKey`, function () { + assert.doesNotThrow(() => verifySetRegularKey(account)); + }); - it (`verifies w/o SetRegularKey`, () => { - account.RegularKey = undefined - assert.doesNotThrow(() => verifySetRegularKey(account)) - }) + it(`verifies w/o SetRegularKey`, function () { + account.RegularKey = undefined; + assert.doesNotThrow(() => verifySetRegularKey(account)); + }); - it (`throws w/ invalid RegularKey`, () => { - account.RegularKey = 12369846963 + it(`throws w/ invalid RegularKey`, function () { + account.RegularKey = 12369846963; - assert.throws( - () => verifySetRegularKey(account), - ValidationError, - "SetRegularKey: RegularKey must be a string" - ) - }) - -}) \ No newline at end of file + assert.throws( + () => verifySetRegularKey(account), + ValidationError, + "SetRegularKey: RegularKey must be a string" + ); + }); +}); diff --git a/test/models/signerListSet.ts b/test/models/signerListSet.ts index a810c6ec..6d76a752 100644 --- a/test/models/signerListSet.ts +++ b/test/models/signerListSet.ts @@ -1,77 +1,78 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifySignerListSet } from './../../src/models/transactions/signerListSet' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifySignerListSet } from "../../src/models/transactions/signerListSet"; /** - * SignerListSet Transaction Verification Testing + * SignerListSet Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('SignerListSet Transaction Verification', function () { - let SignerListSetTx +describe("SignerListSet Transaction Verification", function () { + let SignerListSetTx; - beforeEach(() => { - SignerListSetTx = { - Flags: 0, - TransactionType: "SignerListSet", - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - Fee: "12", - SignerQuorum: 3, - SignerEntries: [ - { - SignerEntry: { - Account: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", - SignerWeight: 2 - } - }, - { - SignerEntry: { - Account: "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v", - SignerWeight: 1 - } - }, - { - SignerEntry: { - Account: "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n", - SignerWeight: 1 - } - } - ] - } as any - }) - - it (`verifies valid SignerListSet`, () => { - assert.doesNotThrow(() => verifySignerListSet(SignerListSetTx)) - }) + beforeEach(function () { + SignerListSetTx = { + Flags: 0, + TransactionType: "SignerListSet", + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + Fee: "12", + SignerQuorum: 3, + SignerEntries: [ + { + SignerEntry: { + Account: "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + SignerWeight: 2, + }, + }, + { + SignerEntry: { + Account: "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v", + SignerWeight: 1, + }, + }, + { + SignerEntry: { + Account: "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n", + SignerWeight: 1, + }, + }, + ], + } as any; + }); + it(`verifies valid SignerListSet`, function () { + assert.doesNotThrow(() => verifySignerListSet(SignerListSetTx)); + }); - it (`throws w/ missing SignerQuorum`, () => { - SignerListSetTx.SignerQuorum = undefined + it(`throws w/ missing SignerQuorum`, function () { + SignerListSetTx.SignerQuorum = undefined; - assert.throws( - () => verifySignerListSet(SignerListSetTx), - ValidationError, - "SignerListSet: missing field SignerQuorum" - ) - }) + assert.throws( + () => verifySignerListSet(SignerListSetTx), + ValidationError, + "SignerListSet: missing field SignerQuorum" + ); + }); - it (`throws w/ empty SignerEntries`, () => { - SignerListSetTx.SignerEntries = [] + it(`throws w/ empty SignerEntries`, function () { + SignerListSetTx.SignerEntries = []; - assert.throws( - () => verifySignerListSet(SignerListSetTx), - ValidationError, - "SignerListSet: need atleast 1 member in SignerEntries" - ) - }) + assert.throws( + () => verifySignerListSet(SignerListSetTx), + ValidationError, + "SignerListSet: need atleast 1 member in SignerEntries" + ); + }); - it (`throws w/ invalid SignerEntries`, () => { - SignerListSetTx.SignerEntries = "khgfgyhujk" - - assert.throws( - () => verifySignerListSet(SignerListSetTx), - ValidationError, - "SignerListSet: invalid SignerEntries" - ) - }) -}) \ No newline at end of file + it(`throws w/ invalid SignerEntries`, function () { + SignerListSetTx.SignerEntries = "khgfgyhujk"; + + assert.throws( + () => verifySignerListSet(SignerListSetTx), + ValidationError, + "SignerListSet: invalid SignerEntries" + ); + }); +}); diff --git a/test/models/ticketCreate.ts b/test/models/ticketCreate.ts index 74a2f8df..0bdd4a23 100644 --- a/test/models/ticketCreate.ts +++ b/test/models/ticketCreate.ts @@ -1,69 +1,71 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyTicketCreate } from './../../src/models/transactions/ticketCreate' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyTicketCreate } from "../../src/models/transactions/ticketCreate"; /** - * TicketCreate Transaction Verification Testing + * TicketCreate Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('TicketCreate Transaction Verification', () => { - let ticketCreate +describe("TicketCreate Transaction Verification", function () { + let ticketCreate; - beforeEach(() => { - ticketCreate = { - TransactionType: 'TicketCreate', - Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo', - TicketCount: 150, - } as any - }) + beforeEach(function () { + ticketCreate = { + TransactionType: "TicketCreate", + Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + TicketCount: 150, + } as any; + }); - it ('verifies valid TicketCreate', () => { - assert.doesNotThrow(() => verifyTicketCreate(ticketCreate)) - }) + it("verifies valid TicketCreate", function () { + assert.doesNotThrow(() => verifyTicketCreate(ticketCreate)); + }); - it ('throws when TicketCount is missing', () => { - delete ticketCreate.TicketCount - assert.throws( - () => verifyTicketCreate(ticketCreate), - ValidationError, - 'TicketCreate: missing field TicketCount' - ) - }) + it("throws when TicketCount is missing", function () { + delete ticketCreate.TicketCount; + assert.throws( + () => verifyTicketCreate(ticketCreate), + ValidationError, + "TicketCreate: missing field TicketCount" + ); + }); - it ('throws when TicketCount is not a number', () => { - ticketCreate.TicketCount = '150' - assert.throws( - () => verifyTicketCreate(ticketCreate), - ValidationError, - 'TicketCreate: TicketCount must be a number' - ) - }) + it("throws when TicketCount is not a number", function () { + ticketCreate.TicketCount = "150"; + assert.throws( + () => verifyTicketCreate(ticketCreate), + ValidationError, + "TicketCreate: TicketCount must be a number" + ); + }); - it ('throws when TicketCount is not an integer', () => { - ticketCreate.TicketCount = 12.5 - assert.throws( - () => verifyTicketCreate(ticketCreate), - ValidationError, - 'TicketCreate: TicketCount must be an integer from 1 to 250' - ) - }) + it("throws when TicketCount is not an integer", function () { + ticketCreate.TicketCount = 12.5; + assert.throws( + () => verifyTicketCreate(ticketCreate), + ValidationError, + "TicketCreate: TicketCount must be an integer from 1 to 250" + ); + }); - it ('throws when TicketCount is < 1', () => { - ticketCreate.TicketCount = 0 - assert.throws( - () => verifyTicketCreate(ticketCreate), - ValidationError, - 'TicketCreate: TicketCount must be an integer from 1 to 250' - ) - }) + it("throws when TicketCount is < 1", function () { + ticketCreate.TicketCount = 0; + assert.throws( + () => verifyTicketCreate(ticketCreate), + ValidationError, + "TicketCreate: TicketCount must be an integer from 1 to 250" + ); + }); - it ('throws when TicketCount is > 250', () => { - ticketCreate.TicketCount = 251 - assert.throws( - () => verifyTicketCreate(ticketCreate), - ValidationError, - 'TicketCreate: TicketCount must be an integer from 1 to 250' - ) - }) -}) + it("throws when TicketCount is > 250", function () { + ticketCreate.TicketCount = 251; + assert.throws( + () => verifyTicketCreate(ticketCreate), + ValidationError, + "TicketCreate: TicketCount must be an integer from 1 to 250" + ); + }); +}); diff --git a/test/models/trustSet.ts b/test/models/trustSet.ts index 16165a8d..15806bd2 100644 --- a/test/models/trustSet.ts +++ b/test/models/trustSet.ts @@ -1,66 +1,68 @@ -import { ValidationError } from 'xrpl-local/common/errors' -import { verifyTrustSet } from './../../src/models/transactions/trustSet' -import { assert } from 'chai' +import { assert } from "chai"; + +import { ValidationError } from "xrpl-local/common/errors"; + +import { verifyTrustSet } from "../../src/models/transactions/trustSet"; /** - * TrustSet Transaction Verification Testing + * TrustSet Transaction Verification Testing. * - * Providing runtime verification testing for each specific transaction type + * Providing runtime verification testing for each specific transaction type. */ -describe('TrustSet Transaction Verification', () => { - let trustSet +describe("TrustSet Transaction Verification", function () { + let trustSet; - beforeEach(() => { - trustSet = { - TransactionType: 'TrustSet', - Account: 'rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo', - LimitAmount: { - currency: 'XRP', - issuer: 'rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX', - value: '4329.23' - }, - QualityIn: 1234, - QualityOut: 4321, - } as any - }) + beforeEach(function () { + trustSet = { + TransactionType: "TrustSet", + Account: "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + LimitAmount: { + currency: "XRP", + issuer: "rcXY84C4g14iFp6taFXjjQGVeHqSCh9RX", + value: "4329.23", + }, + QualityIn: 1234, + QualityOut: 4321, + } as any; + }); - it ('verifies valid TrustSet', () => { - assert.doesNotThrow(() => verifyTrustSet(trustSet)) - }) + it("verifies valid TrustSet", function () { + assert.doesNotThrow(() => verifyTrustSet(trustSet)); + }); - it ('throws when LimitAmount is missing', () => { - delete trustSet.LimitAmount - assert.throws( - () => verifyTrustSet(trustSet), - ValidationError, - 'TrustSet: missing field LimitAmount' - ) - }) + it("throws when LimitAmount is missing", function () { + delete trustSet.LimitAmount; + assert.throws( + () => verifyTrustSet(trustSet), + ValidationError, + "TrustSet: missing field LimitAmount" + ); + }); - it ('throws when LimitAmount is invalid', () => { - trustSet.LimitAmount = 1234 - assert.throws( - () => verifyTrustSet(trustSet), - ValidationError, - 'TrustSet: invalid LimitAmount' - ) - }) + it("throws when LimitAmount is invalid", function () { + trustSet.LimitAmount = 1234; + assert.throws( + () => verifyTrustSet(trustSet), + ValidationError, + "TrustSet: invalid LimitAmount" + ); + }); - it ('throws when QualityIn is not a number', () => { - trustSet.QualityIn = '1234' - assert.throws( - () => verifyTrustSet(trustSet), - ValidationError, - 'TrustSet: QualityIn must be a number' - ) - }) + it("throws when QualityIn is not a number", function () { + trustSet.QualityIn = "1234"; + assert.throws( + () => verifyTrustSet(trustSet), + ValidationError, + "TrustSet: QualityIn must be a number" + ); + }); - it ('throws when QualityOut is not a number', () => { - trustSet.QualityOut = '4321' - assert.throws( - () => verifyTrustSet(trustSet), - ValidationError, - 'TrustSet: QualityOut must be a number' - ) - }) -}) + it("throws when QualityOut is not a number", function () { + trustSet.QualityOut = "4321"; + assert.throws( + () => verifyTrustSet(trustSet), + ValidationError, + "TrustSet: QualityOut must be a number" + ); + }); +}); diff --git a/test/models/utils.ts b/test/models/utils.ts index 07de6d25..c3c33476 100644 --- a/test/models/utils.ts +++ b/test/models/utils.ts @@ -1,29 +1,30 @@ -import { isFlagEnabled } from '../../src/models/utils' -import { assert } from 'chai' +import { assert } from "chai"; + +import { isFlagEnabled } from "../../src/models/utils"; /** - * Utils Testing + * Utils Testing. * - * Provides tests for utils used in models + * Provides tests for utils used in models. */ -describe('Models Utils', () => { - describe('isFlagEnabled', () => { - let flags - const flag1 = 0x00010000 - const flag2 = 0x00020000 +describe("Models Utils", function () { + describe("isFlagEnabled", function () { + let flags; + const flag1 = 0x00010000; + const flag2 = 0x00020000; - beforeEach(() => { - flags = 0x00000000 - }) + beforeEach(function () { + flags = 0x00000000; + }); - it('verifies a flag is enabled', () => { - flags += flag1 + flag2 - assert.isTrue(isFlagEnabled(flags, flag1)) - }) + it("verifies a flag is enabled", function () { + flags += flag1 + flag2; + assert.isTrue(isFlagEnabled(flags, flag1)); + }); - it('verifies a flag is not enabled', () => { - flags += flag2 - assert.isFalse(isFlagEnabled(flags, flag1)) - }) - }) -}) + it("verifies a flag is not enabled", function () { + flags += flag2; + assert.isFalse(isFlagEnabled(flags, flag1)); + }); + }); +}); diff --git a/test/rangeset.ts b/test/rangeset.ts index fae13571..4312c41c 100644 --- a/test/rangeset.ts +++ b/test/rangeset.ts @@ -1,79 +1,80 @@ -import assert from 'assert' -import RangeSet from 'xrpl-local/client/rangeSet' +import assert from "assert"; -describe('RangeSet', function () { - it('addRange()/addValue()', function () { - const r = new RangeSet() +import RangeSet from "xrpl-local/client/rangeSet"; - r.addRange(4, 5) - r.addRange(7, 10) - r.addRange(1, 2) - r.addValue(3) +describe("RangeSet", function () { + it("addRange()/addValue()", function () { + const r = new RangeSet(); - assert.deepEqual(r.serialize(), '1-5,7-10') - }) + r.addRange(4, 5); + r.addRange(7, 10); + r.addRange(1, 2); + r.addValue(3); - it('addValue()/addRange() -- malformed', function () { - const r = new RangeSet() + assert.deepEqual(r.serialize(), "1-5,7-10"); + }); + + it("addValue()/addRange() -- malformed", function () { + const r = new RangeSet(); assert.throws(function () { - r.addRange(2, 1) - }) - }) + r.addRange(2, 1); + }); + }); - it('parseAndAddRanges()', function () { - const r = new RangeSet() - r.parseAndAddRanges('4-5,7-10,1-2,3-3') - assert.deepEqual(r.serialize(), '1-5,7-10') - }) - it('parseAndAddRanges() -- single ledger', function () { - const r = new RangeSet() + it("parseAndAddRanges()", function () { + const r = new RangeSet(); + r.parseAndAddRanges("4-5,7-10,1-2,3-3"); + assert.deepEqual(r.serialize(), "1-5,7-10"); + }); + it("parseAndAddRanges() -- single ledger", function () { + const r = new RangeSet(); - r.parseAndAddRanges('3') - assert.strictEqual(r.serialize(), '3-3') - assert(r.containsValue(3)) - assert(!r.containsValue(0)) - assert(!r.containsValue(2)) - assert(!r.containsValue(4)) - assert(r.containsRange(3, 3)) - assert(!r.containsRange(2, 3)) - assert(!r.containsRange(3, 4)) + r.parseAndAddRanges("3"); + assert.strictEqual(r.serialize(), "3-3"); + assert(r.containsValue(3)); + assert(!r.containsValue(0)); + assert(!r.containsValue(2)); + assert(!r.containsValue(4)); + assert(r.containsRange(3, 3)); + assert(!r.containsRange(2, 3)); + assert(!r.containsRange(3, 4)); - r.parseAndAddRanges('1-5') - assert.strictEqual(r.serialize(), '1-5') - assert(r.containsValue(3)) - assert(r.containsValue(1)) - assert(r.containsValue(5)) - assert(!r.containsValue(6)) - assert(!r.containsValue(0)) - assert(r.containsRange(1, 5)) - assert(r.containsRange(2, 4)) - assert(!r.containsRange(1, 6)) - assert(!r.containsRange(0, 3)) - }) + r.parseAndAddRanges("1-5"); + assert.strictEqual(r.serialize(), "1-5"); + assert(r.containsValue(3)); + assert(r.containsValue(1)); + assert(r.containsValue(5)); + assert(!r.containsValue(6)); + assert(!r.containsValue(0)); + assert(r.containsRange(1, 5)); + assert(r.containsRange(2, 4)); + assert(!r.containsRange(1, 6)); + assert(!r.containsRange(0, 3)); + }); - it('containsValue()', function () { - const r = new RangeSet() + it("containsValue()", function () { + const r = new RangeSet(); - r.addRange(32570, 11005146) - r.addValue(11005147) + r.addRange(32570, 11005146); + r.addValue(11005147); - assert.strictEqual(r.containsValue(1), false) - assert.strictEqual(r.containsValue(32569), false) - assert.strictEqual(r.containsValue(32570), true) - assert.strictEqual(r.containsValue(50000), true) - assert.strictEqual(r.containsValue(11005146), true) - assert.strictEqual(r.containsValue(11005147), true) - assert.strictEqual(r.containsValue(11005148), false) - assert.strictEqual(r.containsValue(12000000), false) - }) + assert.strictEqual(r.containsValue(1), false); + assert.strictEqual(r.containsValue(32569), false); + assert.strictEqual(r.containsValue(32570), true); + assert.strictEqual(r.containsValue(50000), true); + assert.strictEqual(r.containsValue(11005146), true); + assert.strictEqual(r.containsValue(11005147), true); + assert.strictEqual(r.containsValue(11005148), false); + assert.strictEqual(r.containsValue(12000000), false); + }); - it('reset()', function () { - const r = new RangeSet() + it("reset()", function () { + const r = new RangeSet(); - r.addRange(4, 5) - r.addRange(7, 10) - r.reset() + r.addRange(4, 5); + r.addRange(7, 10); + r.reset(); - assert.deepEqual(r.serialize(), '') - }) -}) + assert.deepEqual(r.serialize(), ""); + }); +}); diff --git a/test/rippleClient.ts b/test/rippleClient.ts index d3453769..63c9f3bf 100644 --- a/test/rippleClient.ts +++ b/test/rippleClient.ts @@ -1,10 +1,11 @@ -import setupClient from './setupClient' -import {Client} from 'xrpl-local' -import addresses from './fixtures/addresses.json' -import {getAllPublicMethods, loadTestSuites} from './testUtils' +import { Client } from "xrpl-local"; + +import addresses from "./fixtures/addresses.json"; +import setupClient from "./setupClient"; +import { getAllPublicMethods, loadTestSuites } from "./testUtils"; /** - * Client Test Runner + * Client Test Runner. * * Background: "test/api-test.ts" had hit 4000+ lines of test code and 300+ * individual tests. Additionally, a new address format was added which @@ -21,62 +22,62 @@ import {getAllPublicMethods, loadTestSuites} from './testUtils' * - Type the Client object under test and catch typing issues (currently untyped). * - Sets the stage for more cleanup, like moving test-specific fixtures closer to their tests. */ -describe('Client [Test Runner]', function () { - beforeEach(setupClient.setup) - afterEach(setupClient.teardown) +describe("Client [Test Runner]", function () { + beforeEach(setupClient.setup); + afterEach(setupClient.teardown); // Collect all the tests: - const allPublicMethods = getAllPublicMethods(new Client("wss://")) + const allPublicMethods = getAllPublicMethods(new Client("wss://")); // doesn't need the client, just needs to instantiate to get public methods - const allTestSuites = loadTestSuites() + const allTestSuites = loadTestSuites(); // Run all the tests: - for (const {name: methodName, tests, config} of allTestSuites) { - describe(`${methodName}`, () => { + for (const { name: methodName, tests, config } of allTestSuites) { + describe(`${methodName}`, function () { // Run each test that does not use an address. for (const [testName, fn] of tests) { if (fn.length === 1) { it(testName, function () { - return fn(this.client, addresses.ACCOUNT, this.mockRippled) - }) + return fn(this.client, addresses.ACCOUNT, this.mockRippled); + }); } } // Run each test with a classic address. - describe(`[Classic Address]`, () => { + describe(`[Classic Address]`, function () { for (const [testName, fn] of tests) { if (fn.length >= 2) { it(testName, function () { - return fn(this.client, addresses.ACCOUNT, this.mockRippled) - }) + return fn(this.client, addresses.ACCOUNT, this.mockRippled); + }); } } - }) + }); // Run each test with an X-address. if (!config.skipXAddress) { - describe(`[X-address]`, () => { + describe(`[X-address]`, function () { for (const [testName, fn] of tests) { if (fn.length >= 2) { it(testName, function () { - return fn(this.client, addresses.ACCOUNT_X, this.mockRippled) - }) + return fn(this.client, addresses.ACCOUNT_X, this.mockRippled); + }); } } - }) + }); } - }) + }); } // Report any missing tests. - const allTestedMethods = new Set(allTestSuites.map((s) => s.name)) + const allTestedMethods = new Set(allTestSuites.map((s) => s.name)); for (const methodName of allPublicMethods) { if (!allTestedMethods.has(methodName)) { // TODO: Once migration is complete, remove `.skip()` so that missing tests are reported as failures. - it.skip(`${methodName} - no test suite found`, () => { + it.skip(`${methodName} - no test suite found`, function () { throw new Error( `Test file not found! Create file "test/client/${methodName}/index.ts".` - ) - }) + ); + }); } } -}) +}); diff --git a/test/rippleClientPrivate.ts b/test/rippleClientPrivate.ts index e6a3e959..584ccbec 100644 --- a/test/rippleClientPrivate.ts +++ b/test/rippleClientPrivate.ts @@ -1,181 +1,181 @@ -import assert from 'assert-diff' -import _ from 'lodash' -import {Client} from 'xrpl-local' -import {RecursiveData} from 'xrpl-local/ledger/utils' -import {assertRejects} from './testUtils' -import addresses from './fixtures/addresses.json' -import setupClient from './setupClient' -import {toRippledAmount} from '../src' -import * as schemaValidator from 'xrpl-local/common/schema-validator' -import {validate} from 'xrpl-local/common' +import assert from "assert-diff"; +import _ from "lodash"; + +import { Client } from "xrpl-local"; +import { validate } from "xrpl-local/common"; +import * as schemaValidator from "xrpl-local/common/schema-validator"; import { + RecursiveData, renameCounterpartyToIssuerInOrder, compareTransactions, - getRecursive -} from 'xrpl-local/ledger/utils' + getRecursive, +} from "xrpl-local/ledger/utils"; -const address = addresses.ACCOUNT -assert.options.strict = true +import { toRippledAmount } from "../src"; + +import addresses from "./fixtures/addresses.json"; +import setupClient from "./setupClient"; +import { assertRejects } from "./testUtils"; + +const address = addresses.ACCOUNT; +assert.options.strict = true; // how long before each test case times out -const TIMEOUT = 20000 +const TIMEOUT = 20000; -describe('Client', function () { - this.timeout(TIMEOUT) - beforeEach(setupClient.setup) - afterEach(setupClient.teardown) +describe("Client", function () { + this.timeout(TIMEOUT); + beforeEach(setupClient.setup); + afterEach(setupClient.teardown); - it('Client - implicit server port', function () { - new Client('wss://s1.ripple.com') - }) + it("Client - implicit server port", function () { + new Client("wss://s1.ripple.com"); + }); - it('Client invalid options', function () { - // @ts-ignore - This is intentionally invalid - assert.throws(() => new Client({invalid: true})) - }) + it("Client invalid options", function () { + // @ts-expect-error - This is intentionally invalid + assert.throws(() => new Client({ invalid: true })); + }); - it('Client valid options', function () { - const client = new Client('wss://s:1') - const privateConnectionUrl = (client.connection as any)._url - assert.deepEqual(privateConnectionUrl, 'wss://s:1') - }) + it("Client valid options", function () { + const client = new Client("wss://s:1"); + const privateConnectionUrl = (client.connection as any)._url; + assert.deepEqual(privateConnectionUrl, "wss://s:1"); + }); - it('Client invalid server uri', function () { - assert.throws(() => new Client('wss//s:1')) - }) + it("Client invalid server uri", function () { + assert.throws(() => new Client("wss//s:1")); + }); - it('Client connect() times out after 2 seconds', function () { + it("Client connect() times out after 2 seconds", function () { // TODO: Use a timer mock like https://jestjs.io/docs/en/timer-mocks // to test that connect() times out after 2 seconds. - }) + }); - describe('[private] schema-validator', function () { - it('valid', function () { + describe("[private] schema-validator", function () { + it("valid", function () { assert.doesNotThrow(function () { schemaValidator.schemaValidate( - 'hash256', - '0F7ED9F40742D8A513AE86029462B7A6768325583DF8EE21B7EC663019DD6A0F' - ) - }) - }) + "hash256", + "0F7ED9F40742D8A513AE86029462B7A6768325583DF8EE21B7EC663019DD6A0F" + ); + }); + }); - it('invalid', function () { + it("invalid", function () { assert.throws(function () { - schemaValidator.schemaValidate('hash256', 'invalid') - }, this.client.errors.ValidationError) - }) + schemaValidator.schemaValidate("hash256", "invalid"); + }, this.client.errors.ValidationError); + }); - it('invalid - empty value', function () { + it("invalid - empty value", function () { assert.throws(function () { - schemaValidator.schemaValidate('hash256', '') - }, this.client.errors.ValidationError) - }) + schemaValidator.schemaValidate("hash256", ""); + }, this.client.errors.ValidationError); + }); - it('schema not found error', function () { + it("schema not found error", function () { assert.throws(function () { - schemaValidator.schemaValidate('unexisting', 'anything') - }, /no schema/) - }) - }) + schemaValidator.schemaValidate("unexisting", "anything"); + }, /no schema/); + }); + }); - describe('[private] validator', function () { - it('validateLedgerRange', function () { + describe("[private] validator", function () { + it("validateLedgerRange", function () { const options = { minLedgerVersion: 20000, - maxLedgerVersion: 10000 - } - const thunk = _.partial(validate.getTransactions, {address, options}) - assert.throws(thunk, this.client.errors.ValidationError) + maxLedgerVersion: 10000, + }; + const thunk = _.partial(validate.getTransactions, { address, options }); + assert.throws(thunk, this.client.errors.ValidationError); assert.throws( thunk, /minLedgerVersion must not be greater than maxLedgerVersion/ - ) - }) + ); + }); - it('secret', function () { + it("secret", function () { function validateSecret(secret) { - validate.sign({txJSON: '', secret}) + validate.sign({ txJSON: "", secret }); } assert.doesNotThrow( - _.partial(validateSecret, 'shzjfakiK79YQdMjy4h8cGGfQSV6u') - ) + _.partial(validateSecret, "shzjfakiK79YQdMjy4h8cGGfQSV6u") + ); assert.throws( - _.partial(validateSecret, 'shzjfakiK79YQdMjy4h8cGGfQSV6v'), + _.partial(validateSecret, "shzjfakiK79YQdMjy4h8cGGfQSV6v"), this.client.errors.ValidationError - ) + ); assert.throws( _.partial(validateSecret, 1), this.client.errors.ValidationError - ) + ); assert.throws( - _.partial(validateSecret, ''), + _.partial(validateSecret, ""), this.client.errors.ValidationError - ) + ); assert.throws( - _.partial(validateSecret, 's!!!'), + _.partial(validateSecret, "s!!!"), this.client.errors.ValidationError - ) + ); assert.throws( - _.partial(validateSecret, 'passphrase'), + _.partial(validateSecret, "passphrase"), this.client.errors.ValidationError - ) + ); // 32 0s is a valid hex repr of seed bytes - const hex = new Array(33).join('0') + const hex = new Array(33).join("0"); assert.throws( _.partial(validateSecret, hex), this.client.errors.ValidationError - ) - }) - }) + ); + }); + }); - it('common utils - toRippledAmount', async () => { - const amount = {issuer: 'is', currency: 'c', value: 'v'} + it("common utils - toRippledAmount", async function () { + const amount = { issuer: "is", currency: "c", value: "v" }; assert.deepEqual(toRippledAmount(amount), { - issuer: 'is', - currency: 'c', - value: 'v' - }) - }) + issuer: "is", + currency: "c", + value: "v", + }); + }); - it('ledger utils - renameCounterpartyToIssuerInOrder', async () => { + it("ledger utils - renameCounterpartyToIssuerInOrder", async function () { const order = { - taker_gets: {counterparty: '1', currency: 'XRP'}, - taker_pays: {counterparty: '1', currency: 'XRP'} - } + taker_gets: { counterparty: "1", currency: "XRP" }, + taker_pays: { counterparty: "1", currency: "XRP" }, + }; const expected = { - taker_gets: {issuer: '1', currency: 'XRP'}, - taker_pays: {issuer: '1', currency: 'XRP'} - } - assert.deepEqual( - renameCounterpartyToIssuerInOrder(order), - expected - ) - }) + taker_gets: { issuer: "1", currency: "XRP" }, + taker_pays: { issuer: "1", currency: "XRP" }, + }; + assert.deepEqual(renameCounterpartyToIssuerInOrder(order), expected); + }); - it('ledger utils - compareTransactions', async () => { - // @ts-ignore - assert.strictEqual(compareTransactions({}, {}), 0) - let first: any = {outcome: {ledgerVersion: 1, indexInLedger: 100}} - let second: any = {outcome: {ledgerVersion: 1, indexInLedger: 200}} - assert.strictEqual(compareTransactions(first, second), -1) - first = {outcome: {ledgerVersion: 1, indexInLedger: 100}} - second = {outcome: {ledgerVersion: 1, indexInLedger: 100}} - assert.strictEqual(compareTransactions(first, second), 0) - first = {outcome: {ledgerVersion: 1, indexInLedger: 200}} - second = {outcome: {ledgerVersion: 1, indexInLedger: 100}} - assert.strictEqual(compareTransactions(first, second), 1) - }) + it("ledger utils - compareTransactions", async function () { + // @ts-expect-error + assert.strictEqual(compareTransactions({}, {}), 0); + let first: any = { outcome: { ledgerVersion: 1, indexInLedger: 100 } }; + let second: any = { outcome: { ledgerVersion: 1, indexInLedger: 200 } }; + assert.strictEqual(compareTransactions(first, second), -1); + first = { outcome: { ledgerVersion: 1, indexInLedger: 100 } }; + second = { outcome: { ledgerVersion: 1, indexInLedger: 100 } }; + assert.strictEqual(compareTransactions(first, second), 0); + first = { outcome: { ledgerVersion: 1, indexInLedger: 200 } }; + second = { outcome: { ledgerVersion: 1, indexInLedger: 100 } }; + assert.strictEqual(compareTransactions(first, second), 1); + }); - it('ledger utils - getRecursive', async () => { + it("ledger utils - getRecursive", async function () { function getter(marker) { return new Promise((resolve, reject) => { if (marker != null) { - reject(new Error()) - return + reject(new Error()); + return; } - resolve({marker: 'A', results: [1]}) - }) + resolve({ marker: "A", results: [1] }); + }); } - await assertRejects(getRecursive(getter, 10), Error) - }) -}) + await assertRejects(getRecursive(getter, 10), Error); + }); +}); diff --git a/test/setupClient.ts b/test/setupClient.ts index 153902cd..618495db 100644 --- a/test/setupClient.ts +++ b/test/setupClient.ts @@ -1,41 +1,36 @@ -import {Client, BroadcastClient} from 'xrpl-local' -import {createMockRippled} from './mockRippled' -import {getFreePort} from './testUtils' +import { Client, BroadcastClient } from "xrpl-local"; + +import { createMockRippled } from "./mockRippled"; +import { getFreePort } from "./testUtils"; function setupMockRippledConnection(testcase, port) { return new Promise((resolve, reject) => { - testcase.mockRippled = createMockRippled(port) - testcase._mockedServerPort = port - testcase.client = new Client('ws://localhost:' + port) - testcase.client - .connect() - .then(resolve) - .catch(reject) - }) + testcase.mockRippled = createMockRippled(port); + testcase._mockedServerPort = port; + testcase.client = new Client(`ws://localhost:${port}`); + testcase.client.connect().then(resolve).catch(reject); + }); } function setupMockRippledConnectionForBroadcast(testcase, ports) { return new Promise((resolve, reject) => { - const servers = ports.map((port) => 'ws://localhost:' + port) - testcase.mocks = ports.map((port) => createMockRippled(port)) - testcase.client = new BroadcastClient(servers) - testcase.client - .connect() - .then(resolve) - .catch(reject) - }) + const servers = ports.map((port) => `ws://localhost:${port}`); + testcase.mocks = ports.map((port) => createMockRippled(port)); + testcase.client = new BroadcastClient(servers); + testcase.client.connect().then(resolve).catch(reject); + }); } function setup(this: any) { return getFreePort().then((port) => { - return setupMockRippledConnection(this, port) - }) + return setupMockRippledConnection(this, port); + }); } function setupBroadcast(this: any) { return Promise.all([getFreePort(), getFreePort()]).then((ports) => { - return setupMockRippledConnectionForBroadcast(this, ports) - }) + return setupMockRippledConnectionForBroadcast(this, ports); + }); } function teardown(this: any, done) { @@ -43,18 +38,18 @@ function teardown(this: any, done) { .disconnect() .then(() => { if (this.mockRippled != null) { - this.mockRippled.close() + this.mockRippled.close(); } else { - this.mocks.forEach((mock) => mock.close()) + this.mocks.forEach((mock) => mock.close()); } - setImmediate(done) + setImmediate(done); }) - .catch(done) + .catch(done); } export default { - setup: setup, - teardown: teardown, - setupBroadcast: setupBroadcast, - createMockRippled: createMockRippled -} + setup, + teardown, + setupBroadcast, + createMockRippled, +}; diff --git a/test/setupClientWeb.ts b/test/setupClientWeb.ts index c0424133..06700905 100644 --- a/test/setupClientWeb.ts +++ b/test/setupClientWeb.ts @@ -1,55 +1,46 @@ -import {Client, BroadcastClient} from 'xrpl-local' +import { Client, BroadcastClient } from "xrpl-local"; -const port = 34371 -const baseUrl = 'ws://testripple.circleci.com:' +const port = 34371; +const baseUrl = "ws://testripple.circleci.com:"; function setup(this: any, port_ = port) { - const tclient = new Client(baseUrl + port_) + const tclient = new Client(baseUrl + port_); return tclient .connect() .then(() => { return tclient.connection.request({ - // TODO: resolve when we redo the testing framework - // @ts-ignore - command: 'test_command', - data: {openOnOtherPort: true} - }) + command: "test_command", + data: { openOnOtherPort: true }, + }); }) .then((got) => { return new Promise((resolve, reject) => { - // @ts-ignore - this.client = new Client(baseUrl + got.port) - this.client - .connect() - .then(resolve) - .catch(reject) - }) + this.client = new Client(baseUrl + got.port); + this.client.connect().then(resolve).catch(reject); + }); }) .then(() => { - return tclient.disconnect() - }) + return tclient.disconnect(); + }); } function setupBroadcast(this: any) { - const servers = [port, port + 1].map((port_) => baseUrl + port_) - this.client = new BroadcastClient(servers) + const servers = [port, port + 1].map((port_) => baseUrl + port_); + this.client = new BroadcastClient(servers); return new Promise((resolve, reject) => { - this.client - .connect() - .then(resolve) - .catch(reject) - }) + this.client.connect().then(resolve).catch(reject); + }); } function teardown(this: any) { if (this.client.isConnected()) { - return this.client.disconnect() + return this.client.disconnect(); } - return undefined + return undefined; } export default { - setup: setup, - teardown: teardown, - setupBroadcast: setupBroadcast -} + setup, + teardown, + setupBroadcast, +}; diff --git a/test/shamap.ts b/test/shamap.ts index 1e4eb989..50c98034 100644 --- a/test/shamap.ts +++ b/test/shamap.ts @@ -1,59 +1,63 @@ -import assert from 'assert' -import {SHAMap, NodeType} from '../src/utils/hashes/shamap' -const TYPE_TRANSACTION_NO_METADATA = NodeType.TRANSACTION_NO_METADATA +import assert from "assert"; -var HEX_ZERO = - '00000000000000000000000000000000' + '00000000000000000000000000000000' +import { SHAMap, NodeType } from "../src/utils/hashes/shamap"; + +const TYPE_TRANSACTION_NO_METADATA = NodeType.TRANSACTION_NO_METADATA; + +const HEX_ZERO = + "00000000000000000000000000000000" + "00000000000000000000000000000000"; /** - * Generates data to hash for testing + * Generates data to hash for testing. + * + * @param v */ function intToVuc(v: number): string { - var ret = '' + let ret = ""; - for (var i = 0; i < 32; i++) { - ret += '0' - ret += v.toString(16).toUpperCase() + for (let i = 0; i < 32; i++) { + ret += "0"; + ret += v.toString(16).toUpperCase(); } - return ret + return ret; } function fillShamapTest(shamap: any, keys: string[], hashes: string[]) { - for (var i = 0; i < keys.length; i++) { - var data = intToVuc(i) - shamap.addItem(keys[i].toUpperCase(), data, TYPE_TRANSACTION_NO_METADATA) - assert.equal(shamap.hash, hashes[i]) + for (let i = 0; i < keys.length; i++) { + const data = intToVuc(i); + shamap.addItem(keys[i].toUpperCase(), data, TYPE_TRANSACTION_NO_METADATA); + assert.equal(shamap.hash, hashes[i]); } } -describe('SHAMap', function () { - describe('#addItem', function () { - it('will add new nodes to v1', function () { - var keys = [ - 'b92891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8', - 'b92881fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8', - 'b92691fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8', - 'b92791fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8', - 'b91891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8', - 'b99891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8', - 'f22891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8', - '292891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8' - ] +describe("SHAMap", function () { + describe("#addItem", function () { + it("will add new nodes to v1", function () { + const keys = [ + "b92891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8", + "b92881fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8", + "b92691fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8", + "b92791fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8", + "b91891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8", + "b99891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8", + "f22891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8", + "292891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8", + ]; - var hashesv1 = [ - 'B7387CFEA0465759ADC718E8C42B52D2309D179B326E239EB5075C64B6281F7F', - 'FBC195A9592A54AB44010274163CB6BA95F497EC5BA0A8831845467FB2ECE266', - '4E7D2684B65DFD48937FFB775E20175C43AF0C94066F7D5679F51AE756795B75', - '7A2F312EB203695FFD164E038E281839EEF06A1B99BFC263F3CECC6C74F93E07', - '395A6691A372387A703FB0F2C6D2C405DAF307D0817F8F0E207596462B0E3A3E', - 'D044C0A696DE3169CC70AE216A1564D69DE96582865796142CE7D98A84D9DDE4', - '76DCC77C4027309B5A91AD164083264D70B77B5E43E08AEDA5EBF94361143615', - 'DF4220E93ADC6F5569063A01B4DC79F8DB9553B6A3222ADE23DEA02BBE7230E5' - ] + const hashesv1 = [ + "B7387CFEA0465759ADC718E8C42B52D2309D179B326E239EB5075C64B6281F7F", + "FBC195A9592A54AB44010274163CB6BA95F497EC5BA0A8831845467FB2ECE266", + "4E7D2684B65DFD48937FFB775E20175C43AF0C94066F7D5679F51AE756795B75", + "7A2F312EB203695FFD164E038E281839EEF06A1B99BFC263F3CECC6C74F93E07", + "395A6691A372387A703FB0F2C6D2C405DAF307D0817F8F0E207596462B0E3A3E", + "D044C0A696DE3169CC70AE216A1564D69DE96582865796142CE7D98A84D9DDE4", + "76DCC77C4027309B5A91AD164083264D70B77B5E43E08AEDA5EBF94361143615", + "DF4220E93ADC6F5569063A01B4DC79F8DB9553B6A3222ADE23DEA02BBE7230E5", + ]; - var shamapv1 = new SHAMap() - assert.equal(shamapv1.hash, HEX_ZERO) - fillShamapTest(shamapv1, keys, hashesv1) - }) - }) -}) + const shamapv1 = new SHAMap(); + assert.equal(shamapv1.hash, HEX_ZERO); + fillShamapTest(shamapv1, keys, hashesv1); + }); + }); +}); diff --git a/test/testUtils.ts b/test/testUtils.ts index 17a2b2f4..a3480b28 100644 --- a/test/testUtils.ts +++ b/test/testUtils.ts @@ -1,9 +1,11 @@ -import net from 'net' -import _ from 'lodash' -import fs from 'fs' -import path from 'path' -import {Client} from 'xrpl-local' -import assert from 'assert-diff' +import fs from "fs"; +import net from "net"; +import path from "path"; + +import assert from "assert-diff"; +import _ from "lodash"; + +import { Client } from "xrpl-local"; /** * The test function. It takes a Client object and then some other data to @@ -14,13 +16,13 @@ export type TestFn = ( client: Client, address: string, mockRippled?: any -) => void | PromiseLike +) => void | PromiseLike; /** * A suite of tests to run. Maps the test name to the test function. */ export interface TestSuite { - [testName: string]: TestFn + [testName: string]: TestFn; } /** @@ -30,17 +32,21 @@ export interface TestSuite { * so that we can report it. */ interface LoadedTestSuite { - name: string - tests: [string, TestFn][] + name: string; + tests: Array<[string, TestFn]>; config: { /** Set to true to skip re-running tests with an X-address. */ - skipXAddress?: boolean - } + skipXAddress?: boolean; + }; } /** * Check the response against the expected result. Optionally validate * that response against a given schema as well. + * + * @param response - Response received from the method. + * @param expected - Expected response from the method. + * @param schemaName - Name of the schema used to validate the shape of the response. */ export function assertResultMatch( response: any, @@ -48,29 +54,33 @@ export function assertResultMatch( schemaName?: string ) { if (expected.txJSON) { - assert(response.txJSON) + assert(response.txJSON); assert.deepEqual( JSON.parse(response.txJSON), JSON.parse(expected.txJSON), - 'checkResult: txJSON must match' - ) + "checkResult: txJSON must match" + ); } if (expected.tx_json) { - assert(response.tx_json) + assert(response.tx_json); assert.deepEqual( response.tx_json, expected.tx_json, - 'checkResult: tx_json must match' - ) + "checkResult: tx_json must match" + ); } assert.deepEqual( - _.omit(response, ['txJSON', 'tx_json']), - _.omit(expected, ['txJSON', 'tx_json']) - ) + _.omit(response, ["txJSON", "tx_json"]), + _.omit(expected, ["txJSON", "tx_json"]) + ); } /** * Check that the promise rejects with an expected error. + * + * @param promise - The promise returned by the method. + * @param instanceOf - Expected error type that the method will throw. + * @param message - Expected error message/substring of the error message. */ export async function assertRejects( promise: PromiseLike, @@ -78,14 +88,14 @@ export async function assertRejects( message?: string | RegExp ) { try { - await promise - assert(false, 'Expected an error to be thrown') + await promise; + assert(false, "Expected an error to be thrown"); } catch (error) { - assert(error instanceof instanceOf, error.message) - if (typeof message === 'string') { - assert.strictEqual(error.message, message) + assert(error instanceof instanceOf, error.message); + if (typeof message === "string") { + assert.strictEqual(error.message, message); } else if (message instanceof RegExp) { - assert(message.test(error.message)) + assert(message.test(error.message)); } } } @@ -93,61 +103,63 @@ export async function assertRejects( // using a free port instead of a constant port enables parallelization export function getFreePort() { return new Promise((resolve, reject) => { - const server = net.createServer() - let port - server.on('listening', function () { - port = (server.address() as any).port - server.close() - }) - server.on('close', function () { - resolve(port) - }) - server.on('error', function (error) { - reject(error) - }) - server.listen(0) - }) + const server = net.createServer(); + let port; + server.on("listening", function () { + port = (server.address() as any).port; + server.close(); + }); + server.on("close", function () { + resolve(port); + }); + server.on("error", function (error) { + reject(error); + }); + server.listen(0); + }); } export function getAllPublicMethods(client: Client) { return Array.from( new Set([ ...Object.getOwnPropertyNames(client), - ...Object.getOwnPropertyNames(Client.prototype) + ...Object.getOwnPropertyNames(Client.prototype), ]) - ).filter((key) => !key.startsWith('_')) + ).filter((key) => !key.startsWith("_")); } export function loadTestSuites(): LoadedTestSuite[] { - const allTests = fs.readdirSync(path.join(__dirname, 'client'), { - encoding: 'utf8' - }) + const allTests: any[] = fs.readdirSync(path.join(__dirname, "client"), { + encoding: "utf8", + }); return allTests .map((methodName) => { - if (methodName.startsWith('.DS_Store')) { - return null + if (methodName.startsWith(".DS_Store")) { + return null; } - if (methodName.endsWith('.ts')) { - methodName = methodName.slice(0, -3) + if (methodName.endsWith(".ts")) { + methodName = methodName.slice(0, -3); } - const testSuite = require(`./client/${methodName}`) + const testSuite = require(`./client/${methodName}`); return { name: methodName, config: testSuite.config || {}, - tests: Object.entries(testSuite.default || {}) - } as LoadedTestSuite + tests: Object.entries(testSuite.default || {}), + } as LoadedTestSuite; }) - .filter(Boolean) + .filter(Boolean) as LoadedTestSuite[]; } /** * Ignore WebSocket DisconnectErrors. Useful for making requests where we don't * care about the response and plan to teardown the test before the response * has come back. + * + * @param error - Thrown error. */ export function ignoreWebSocketDisconnect(error: Error): void { - if (error.message === 'websocket was closed') { - return + if (error.message === "websocket was closed") { + return; } - throw error -} \ No newline at end of file + throw error; +} diff --git a/test/tsconfig.json b/test/tsconfig.json deleted file mode 100644 index 2aed768e..00000000 --- a/test/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../tsconfig-base.json", -} \ No newline at end of file diff --git a/test/utils/computeLedgerHash.ts b/test/utils/computeLedgerHash.ts index 75055cd8..4db2d05b 100644 --- a/test/utils/computeLedgerHash.ts +++ b/test/utils/computeLedgerHash.ts @@ -1,147 +1,147 @@ -import assert from 'assert-diff' -import {computeLedgerHeaderHash} from '../../src/utils' -import {ValidationError} from '../../src/common/errors' -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import {assertResultMatch} from '../testUtils' -const {computeLedgerHash: REQUEST_FIXTURES} = requests +import assert from "assert-diff"; + +import { ValidationError } from "../../src/common/errors"; +import { computeLedgerHeaderHash } from "../../src/utils"; +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import { assertResultMatch } from "../testUtils"; + +const { computeLedgerHash: REQUEST_FIXTURES } = requests; function getNewLedger() { - return JSON.parse(JSON.stringify(responses.getLedger.full)) + return JSON.parse(JSON.stringify(responses.getLedger.full)); } -describe('Compute Ledger Hash', function () { - it('given corrupt data - should fail', () => { - const ledger = getNewLedger() - // @ts-ignore - Change Amount to 12000000000 +describe("Compute Ledger Hash", function () { + it("given corrupt data - should fail", function () { + const ledger = getNewLedger(); ledger.transactions[0].rawTransaction = - '{"Account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","Amount":"12000000000","Destination":"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj","Fee":"10","Flags":0,"Sequence":62,"SigningPubKey":"034AADB09CFF4A4804073701EC53C3510CDC95917C2BB0150FB742D0C66E6CEE9E","TransactionType":"Payment","TxnSignature":"3045022022EB32AECEF7C644C891C19F87966DF9C62B1F34BABA6BE774325E4BB8E2DD62022100A51437898C28C2B297112DF8131F2BB39EA5FE613487DDD611525F1796264639","hash":"3B1A4E1C9BB6A7208EB146BCDB86ECEA6068ED01466D933528CA2B4C64F753EF","meta":{"AffectedNodes":[{"CreatedNode":{"LedgerEntryType":"AccountRoot","LedgerIndex":"4C6ACBD635B0F07101F7FA25871B0925F8836155462152172755845CE691C49E","NewFields":{"Account":"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj","Balance":"10000000000","Sequence":1}}},{"ModifiedNode":{"FinalFields":{"Account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","Balance":"981481999380","Flags":0,"OwnerCount":0,"Sequence":63},"LedgerEntryType":"AccountRoot","LedgerIndex":"B33FDD5CF3445E1A7F2BE9B06336BEBD73A5E3EE885D3EF93F7E3E2992E46F1A","PreviousFields":{"Balance":"991481999390","Sequence":62},"PreviousTxnID":"2485FDC606352F1B0785DA5DE96FB9DBAF43EB60ECBB01B7F6FA970F512CDA5F","PreviousTxnLgrSeq":31317}}],"TransactionIndex":0,"TransactionResult":"tesSUCCESS"},"ledger_index":38129}' - ledger.parentCloseTime = ledger.closeTime - let hash + '{"Account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","Amount":"12000000000","Destination":"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj","Fee":"10","Flags":0,"Sequence":62,"SigningPubKey":"034AADB09CFF4A4804073701EC53C3510CDC95917C2BB0150FB742D0C66E6CEE9E","TransactionType":"Payment","TxnSignature":"3045022022EB32AECEF7C644C891C19F87966DF9C62B1F34BABA6BE774325E4BB8E2DD62022100A51437898C28C2B297112DF8131F2BB39EA5FE613487DDD611525F1796264639","hash":"3B1A4E1C9BB6A7208EB146BCDB86ECEA6068ED01466D933528CA2B4C64F753EF","meta":{"AffectedNodes":[{"CreatedNode":{"LedgerEntryType":"AccountRoot","LedgerIndex":"4C6ACBD635B0F07101F7FA25871B0925F8836155462152172755845CE691C49E","NewFields":{"Account":"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj","Balance":"10000000000","Sequence":1}}},{"ModifiedNode":{"FinalFields":{"Account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","Balance":"981481999380","Flags":0,"OwnerCount":0,"Sequence":63},"LedgerEntryType":"AccountRoot","LedgerIndex":"B33FDD5CF3445E1A7F2BE9B06336BEBD73A5E3EE885D3EF93F7E3E2992E46F1A","PreviousFields":{"Balance":"991481999390","Sequence":62},"PreviousTxnID":"2485FDC606352F1B0785DA5DE96FB9DBAF43EB60ECBB01B7F6FA970F512CDA5F","PreviousTxnLgrSeq":31317}}],"TransactionIndex":0,"TransactionResult":"tesSUCCESS"},"ledger_index":38129}'; + ledger.parentCloseTime = ledger.closeTime; + let hash; try { - hash = computeLedgerHeaderHash(ledger, {computeTreeHashes: true}) + hash = computeLedgerHeaderHash(ledger, { computeTreeHashes: true }); } catch (error) { - assert(error instanceof ValidationError) + assert(error instanceof ValidationError); assert.strictEqual( error.message, - 'transactionHash in header does not match computed hash of transactions' - ) + "transactionHash in header does not match computed hash of transactions" + ); assert.deepStrictEqual(error.data, { transactionHashInHeader: - 'DB83BF807416C5B3499A73130F843CF615AB8E797D79FE7D330ADF1BFA93951A', + "DB83BF807416C5B3499A73130F843CF615AB8E797D79FE7D330ADF1BFA93951A", computedHashOfTransactions: - 'EAA1ADF4D627339450F0E95EA88B7069186DD64230BAEBDCF3EEC4D616A9FC68' - }) - return + "EAA1ADF4D627339450F0E95EA88B7069186DD64230BAEBDCF3EEC4D616A9FC68", + }); + return; } assert( false, - 'Should throw ValidationError instead of producing hash: ' + hash - ) - }) + `Should throw ValidationError instead of producing hash: ${hash}` + ); + }); - it('given ledger without raw transactions - should throw', () => { - const ledger = getNewLedger() - // @ts-ignore - Delete rawTransaction - delete ledger.transactions[0].rawTransaction - ledger.parentCloseTime = ledger.closeTime - let hash + it("given ledger without raw transactions - should throw", function () { + const ledger = getNewLedger(); + delete ledger.transactions[0].rawTransaction; + ledger.parentCloseTime = ledger.closeTime; + let hash; try { - hash = computeLedgerHeaderHash(ledger, {computeTreeHashes: true}) + hash = computeLedgerHeaderHash(ledger, { computeTreeHashes: true }); } catch (error) { - assert(error instanceof ValidationError) + assert(error instanceof ValidationError); assert.strictEqual( error.message, - 'ledger' + ' is missing raw transactions' - ) - return + "ledger" + " is missing raw transactions" + ); + return; } assert( false, - 'Should throw ValidationError instead of producing hash: ' + hash - ) - }) + `Should throw ValidationError instead of producing hash: ${hash}` + ); + }); - it('given ledger without state or transactions - only compute ledger hash', () => { - const ledger = getNewLedger() + it("given ledger without state or transactions - only compute ledger hash", function () { + const ledger = getNewLedger(); assert.strictEqual( - // @ts-ignore ledger.transactions[0].rawTransaction, '{"Account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","Amount":"10000000000","Destination":"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj","Fee":"10","Flags":0,"Sequence":62,"SigningPubKey":"034AADB09CFF4A4804073701EC53C3510CDC95917C2BB0150FB742D0C66E6CEE9E","TransactionType":"Payment","TxnSignature":"3045022022EB32AECEF7C644C891C19F87966DF9C62B1F34BABA6BE774325E4BB8E2DD62022100A51437898C28C2B297112DF8131F2BB39EA5FE613487DDD611525F1796264639","hash":"3B1A4E1C9BB6A7208EB146BCDB86ECEA6068ED01466D933528CA2B4C64F753EF","meta":{"AffectedNodes":[{"CreatedNode":{"LedgerEntryType":"AccountRoot","LedgerIndex":"4C6ACBD635B0F07101F7FA25871B0925F8836155462152172755845CE691C49E","NewFields":{"Account":"rLQBHVhFnaC5gLEkgr6HgBJJ3bgeZHg9cj","Balance":"10000000000","Sequence":1}}},{"ModifiedNode":{"FinalFields":{"Account":"r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV","Balance":"981481999380","Flags":0,"OwnerCount":0,"Sequence":63},"LedgerEntryType":"AccountRoot","LedgerIndex":"B33FDD5CF3445E1A7F2BE9B06336BEBD73A5E3EE885D3EF93F7E3E2992E46F1A","PreviousFields":{"Balance":"991481999390","Sequence":62},"PreviousTxnID":"2485FDC606352F1B0785DA5DE96FB9DBAF43EB60ECBB01B7F6FA970F512CDA5F","PreviousTxnLgrSeq":31317}}],"TransactionIndex":0,"TransactionResult":"tesSUCCESS"},"ledger_index":38129}' - ) - ledger.parentCloseTime = ledger.closeTime - const computeLedgerHash = computeLedgerHeaderHash + ); + ledger.parentCloseTime = ledger.closeTime; + const computeLedgerHash = computeLedgerHeaderHash; function testCompute(ledger, expectedError) { - let hash = computeLedgerHash(ledger) + let hash = computeLedgerHash(ledger); assert.strictEqual( hash, - 'E6DB7365949BF9814D76BCC730B01818EB9136A89DB224F3F9F5AAE4569D758E' - ) + "E6DB7365949BF9814D76BCC730B01818EB9136A89DB224F3F9F5AAE4569D758E" + ); // fail if required to compute tree hashes try { - hash = computeLedgerHash(ledger, {computeTreeHashes: true}) + hash = computeLedgerHash(ledger, { computeTreeHashes: true }); } catch (error) { - assert(error instanceof ValidationError) - assert.strictEqual(error.message, expectedError) - return + assert(error instanceof ValidationError); + assert.strictEqual(error.message, expectedError); + return; } assert( false, - 'Should throw ValidationError instead of producing hash: ' + hash - ) + `Should throw ValidationError instead of producing hash: ${hash}` + ); } - const transactions = ledger.transactions - delete ledger.transactions - testCompute(ledger, 'transactions property is missing from the ledger') - delete ledger.rawState - testCompute(ledger, 'transactions property is missing from the ledger') - ledger.transactions = transactions - testCompute(ledger, 'rawState property is missing from the ledger') - }) + const transactions = ledger.transactions; + delete ledger.transactions; + testCompute(ledger, "transactions property is missing from the ledger"); + delete ledger.rawState; + testCompute(ledger, "transactions property is missing from the ledger"); + ledger.transactions = transactions; + testCompute(ledger, "rawState property is missing from the ledger"); + }); - it('wrong hash', () => { - const ledger = getNewLedger() - assertResultMatch(ledger, responses.getLedger.full, 'getLedger') + it("wrong hash", function () { + const ledger = getNewLedger(); + assertResultMatch(ledger, responses.getLedger.full, "getLedger"); const newLedger = { ...ledger, parentCloseTime: ledger.closeTime, stateHash: - 'D9ABF622DA26EEEE48203085D4BC23B0F77DC6F8724AC33D975DA3CA492D2E44' - } + "D9ABF622DA26EEEE48203085D4BC23B0F77DC6F8724AC33D975DA3CA492D2E44", + }; assert.throws(() => { - computeLedgerHeaderHash(newLedger) - }, /does not match computed hash of state/) - }) + computeLedgerHeaderHash(newLedger); + }, /does not match computed hash of state/); + }); - it('computeLedgerHash', () => { - const header = REQUEST_FIXTURES.header - const ledgerHash = computeLedgerHeaderHash(header) + it("computeLedgerHash", function () { + const header = REQUEST_FIXTURES.header; + const ledgerHash = computeLedgerHeaderHash(header); assert.strictEqual( ledgerHash, - 'F4D865D83EB88C1A1911B9E90641919A1314F36E1B099F8E95FE3B7C77BE3349' - ) - }) + "F4D865D83EB88C1A1911B9E90641919A1314F36E1B099F8E95FE3B7C77BE3349" + ); + }); - it('computeLedgerHash - with transactions', () => { + it("computeLedgerHash - with transactions", function () { const header = { ...REQUEST_FIXTURES.header, transactionHash: undefined, - rawTransactions: JSON.stringify(REQUEST_FIXTURES.transactions) - } - const ledgerHash = computeLedgerHeaderHash(header) + rawTransactions: JSON.stringify(REQUEST_FIXTURES.transactions), + }; + const ledgerHash = computeLedgerHeaderHash(header); assert.strictEqual( ledgerHash, - 'F4D865D83EB88C1A1911B9E90641919A1314F36E1B099F8E95FE3B7C77BE3349' - ) - }) + "F4D865D83EB88C1A1911B9E90641919A1314F36E1B099F8E95FE3B7C77BE3349" + ); + }); - it('computeLedgerHash - incorrent transaction_hash', () => { - const header = Object.assign({}, REQUEST_FIXTURES.header, { + it("computeLedgerHash - incorrent transaction_hash", function () { + const header = { + ...REQUEST_FIXTURES.header, transactionHash: - '325EACC5271322539EEEC2D6A5292471EF1B3E72AE7180533EFC3B8F0AD435C9' - }) - header.rawTransactions = JSON.stringify(REQUEST_FIXTURES.transactions) - assert.throws(() => computeLedgerHeaderHash(header)) - }) -}) + "325EACC5271322539EEEC2D6A5292471EF1B3E72AE7180533EFC3B8F0AD435C9", + }; + header.rawTransactions = JSON.stringify(REQUEST_FIXTURES.transactions); + assert.throws(() => computeLedgerHeaderHash(header)); + }); +}); diff --git a/test/utils/dropsToXrp.ts b/test/utils/dropsToXrp.ts index ed55e655..c2e24f5f 100644 --- a/test/utils/dropsToXrp.ts +++ b/test/utils/dropsToXrp.ts @@ -1,123 +1,124 @@ -import assert from 'assert-diff' -import BigNumber from 'bignumber.js' -import {dropsToXrp} from '../../src/utils' +import assert from "assert-diff"; +import BigNumber from "bignumber.js"; -describe('Drops To XRP', function () { - it('works with a typical amount', () => { - const xrp = dropsToXrp('2000000') - assert.strictEqual(xrp, '2', '2 million drops equals 2 XRP') - }) +import { dropsToXrp } from "../../src/utils"; - it('works with fractions', () => { - let xrp = dropsToXrp('3456789') - assert.strictEqual(xrp, '3.456789', '3,456,789 drops equals 3.456789 XRP') +describe("Drops To XRP", function () { + it("works with a typical amount", function () { + const xrp = dropsToXrp("2000000"); + assert.strictEqual(xrp, "2", "2 million drops equals 2 XRP"); + }); - xrp = dropsToXrp('3400000') - assert.strictEqual(xrp, '3.4', '3,400,000 drops equals 3.4 XRP') + it("works with fractions", function () { + let xrp = dropsToXrp("3456789"); + assert.strictEqual(xrp, "3.456789", "3,456,789 drops equals 3.456789 XRP"); - xrp = dropsToXrp('1') - assert.strictEqual(xrp, '0.000001', '1 drop equals 0.000001 XRP') + xrp = dropsToXrp("3400000"); + assert.strictEqual(xrp, "3.4", "3,400,000 drops equals 3.4 XRP"); - xrp = dropsToXrp('1.0') - assert.strictEqual(xrp, '0.000001', '1.0 drops equals 0.000001 XRP') + xrp = dropsToXrp("1"); + assert.strictEqual(xrp, "0.000001", "1 drop equals 0.000001 XRP"); - xrp = dropsToXrp('1.00') - assert.strictEqual(xrp, '0.000001', '1.00 drops equals 0.000001 XRP') - }) + xrp = dropsToXrp("1.0"); + assert.strictEqual(xrp, "0.000001", "1.0 drops equals 0.000001 XRP"); - it('works with zero', () => { - let xrp = dropsToXrp('0') - assert.strictEqual(xrp, '0', '0 drops equals 0 XRP') + xrp = dropsToXrp("1.00"); + assert.strictEqual(xrp, "0.000001", "1.00 drops equals 0.000001 XRP"); + }); + + it("works with zero", function () { + let xrp = dropsToXrp("0"); + assert.strictEqual(xrp, "0", "0 drops equals 0 XRP"); // negative zero is equivalent to zero - xrp = dropsToXrp('-0') - assert.strictEqual(xrp, '0', '-0 drops equals 0 XRP') + xrp = dropsToXrp("-0"); + assert.strictEqual(xrp, "0", "-0 drops equals 0 XRP"); - xrp = dropsToXrp('0.00') - assert.strictEqual(xrp, '0', '0.00 drops equals 0 XRP') + xrp = dropsToXrp("0.00"); + assert.strictEqual(xrp, "0", "0.00 drops equals 0 XRP"); - xrp = dropsToXrp('000000000') - assert.strictEqual(xrp, '0', '000000000 drops equals 0 XRP') - }) + xrp = dropsToXrp("000000000"); + assert.strictEqual(xrp, "0", "000000000 drops equals 0 XRP"); + }); - it('works with a negative value', () => { - const xrp = dropsToXrp('-2000000') - assert.strictEqual(xrp, '-2', '-2 million drops equals -2 XRP') - }) + it("works with a negative value", function () { + const xrp = dropsToXrp("-2000000"); + assert.strictEqual(xrp, "-2", "-2 million drops equals -2 XRP"); + }); - it('works with a value ending with a decimal point', () => { - let xrp = dropsToXrp('2000000.') - assert.strictEqual(xrp, '2', '2000000. drops equals 2 XRP') + it("works with a value ending with a decimal point", function () { + let xrp = dropsToXrp("2000000."); + assert.strictEqual(xrp, "2", "2000000. drops equals 2 XRP"); - xrp = dropsToXrp('-2000000.') - assert.strictEqual(xrp, '-2', '-2000000. drops equals -2 XRP') - }) + xrp = dropsToXrp("-2000000."); + assert.strictEqual(xrp, "-2", "-2000000. drops equals -2 XRP"); + }); - it('works with BigNumber objects', () => { - let xrp = dropsToXrp(new BigNumber(2000000)) - assert.strictEqual(xrp, '2', '(BigNumber) 2 million drops equals 2 XRP') + it("works with BigNumber objects", function () { + let xrp = dropsToXrp(new BigNumber(2000000)); + assert.strictEqual(xrp, "2", "(BigNumber) 2 million drops equals 2 XRP"); - xrp = dropsToXrp(new BigNumber(-2000000)) - assert.strictEqual(xrp, '-2', '(BigNumber) -2 million drops equals -2 XRP') + xrp = dropsToXrp(new BigNumber(-2000000)); + assert.strictEqual(xrp, "-2", "(BigNumber) -2 million drops equals -2 XRP"); - xrp = dropsToXrp(new BigNumber(2345678)) + xrp = dropsToXrp(new BigNumber(2345678)); assert.strictEqual( xrp, - '2.345678', - '(BigNumber) 2,345,678 drops equals 2.345678 XRP' - ) + "2.345678", + "(BigNumber) 2,345,678 drops equals 2.345678 XRP" + ); - xrp = dropsToXrp(new BigNumber(-2345678)) + xrp = dropsToXrp(new BigNumber(-2345678)); assert.strictEqual( xrp, - '-2.345678', - '(BigNumber) -2,345,678 drops equals -2.345678 XRP' - ) - }) + "-2.345678", + "(BigNumber) -2,345,678 drops equals -2.345678 XRP" + ); + }); - it('works with a number', () => { + it("works with a number", function () { // This is not recommended. Use strings or BigNumber objects to avoid precision errors. - let xrp = dropsToXrp(2000000) - assert.strictEqual(xrp, '2', '(number) 2 million drops equals 2 XRP') - xrp = dropsToXrp(-2000000) - assert.strictEqual(xrp, '-2', '(number) -2 million drops equals -2 XRP') - }) + let xrp = dropsToXrp(2000000); + assert.strictEqual(xrp, "2", "(number) 2 million drops equals 2 XRP"); + xrp = dropsToXrp(-2000000); + assert.strictEqual(xrp, "-2", "(number) -2 million drops equals -2 XRP"); + }); - it('throws with an amount with too many decimal places', () => { + it("throws with an amount with too many decimal places", function () { assert.throws(() => { - dropsToXrp('1.2') - }, /has too many decimal places/) + dropsToXrp("1.2"); + }, /has too many decimal places/); assert.throws(() => { - dropsToXrp('0.10') - }, /has too many decimal places/) - }) + dropsToXrp("0.10"); + }, /has too many decimal places/); + }); - it('throws with an invalid value', () => { + it("throws with an invalid value", function () { assert.throws(() => { - dropsToXrp('FOO') - }, /invalid value/) + dropsToXrp("FOO"); + }, /invalid value/); assert.throws(() => { - dropsToXrp('1e-7') - }, /invalid value/) + dropsToXrp("1e-7"); + }, /invalid value/); assert.throws(() => { - dropsToXrp('2,0') - }, /invalid value/) + dropsToXrp("2,0"); + }, /invalid value/); assert.throws(() => { - dropsToXrp('.') - }, /dropsToXrp: invalid value '\.', should be a BigNumber or string-encoded number\./) - }) + dropsToXrp("."); + }, /dropsToXrp: invalid value '\.', should be a BigNumber or string-encoded number\./); + }); - it('throws with an amount more than one decimal point', () => { + it("throws with an amount more than one decimal point", function () { assert.throws(() => { - dropsToXrp('1.0.0') - }, /dropsToXrp: invalid value '1\.0\.0'/) + dropsToXrp("1.0.0"); + }, /dropsToXrp: invalid value '1\.0\.0'/); assert.throws(() => { - dropsToXrp('...') - }, /dropsToXrp: invalid value '\.\.\.'/) - }) -}) + dropsToXrp("..."); + }, /dropsToXrp: invalid value '\.\.\.'/); + }); +}); diff --git a/test/utils/generateAddress.ts b/test/utils/generateAddress.ts index 329bb3a8..7c883de8 100644 --- a/test/utils/generateAddress.ts +++ b/test/utils/generateAddress.ts @@ -1,231 +1,247 @@ -import assert from 'assert-diff' -import responses from '../fixtures/responses' -import {generateXAddress, GenerateAddressOptions} from '../../src/utils/generateAddress' -import ECDSA from '../../src/common/ecdsa' -import {UnexpectedError} from '../../src/common/errors' +import assert from "assert-diff"; -describe('Generate Address', function () { - it('generateAddress', () => { +import ECDSA from "../../src/common/ecdsa"; +import { UnexpectedError } from "../../src/common/errors"; +import { + generateXAddress, + GenerateAddressOptions, +} from "../../src/utils/generateAddress"; +import responses from "../fixtures/responses"; + +describe("Generate Address", function () { + it("generateAddress", function () { // GIVEN entropy of all zeros function random() { - return new Array(16).fill(0) + return new Array(16).fill(0); } assert.deepEqual( // WHEN generating an address - generateXAddress({entropy: random()}), + generateXAddress({ entropy: random() }), // THEN we get the expected return value responses.generateXAddress - ) - }) + ); + }); - it('generateAddress invalid entropy', () => { + it("generateAddress invalid entropy", function () { assert.throws(() => { // GIVEN entropy of 1 byte function random() { - return new Array(1).fill(0) + return new Array(1).fill(0); } // WHEN generating an address - generateXAddress({entropy: random()}) + generateXAddress({ entropy: random() }); // THEN an UnexpectedError is thrown // because 16 bytes of entropy are required - }, UnexpectedError) - }) + }, UnexpectedError); + }); - it('generateAddress with no options object', () => { + it("generateAddress with no options object", function () { // GIVEN no options // WHEN generating an address - const account = generateXAddress() + const account = generateXAddress(); // THEN we get an object with an xAddress starting with 'x' and a secret starting with 's' - assert(account.xAddress.startsWith('X'), 'Address must start with `X`') - assert(account.secret.startsWith('s'), 'Secret must start with `s`') - }) + assert(account.xAddress.startsWith("X"), "Address must start with `X`"); + assert(account.secret.startsWith("s"), "Secret must start with `s`"); + }); - it('generateAddress with empty options object', () => { + it("generateAddress with empty options object", function () { // GIVEN an empty options object - const options = {} + const options = {}; // WHEN generating an address - const account = generateXAddress(options) + const account = generateXAddress(options); // THEN we get an object with an xAddress starting with 'x' and a secret starting with 's' - assert(account.xAddress.startsWith('X'), 'Address must start with `X`') - assert(account.secret.startsWith('s'), 'Secret must start with `s`') - }) + assert(account.xAddress.startsWith("X"), "Address must start with `X`"); + assert(account.secret.startsWith("s"), "Secret must start with `s`"); + }); - it('generateAddress with algorithm `ecdsa-secp256k1`', () => { + it("generateAddress with algorithm `ecdsa-secp256k1`", function () { // GIVEN we want to use 'ecdsa-secp256k1' - const options: GenerateAddressOptions = {algorithm: ECDSA.secp256k1, includeClassicAddress: true} + const options: GenerateAddressOptions = { + algorithm: ECDSA.secp256k1, + includeClassicAddress: true, + }; // WHEN generating an address - const account = generateXAddress(options) + const account = generateXAddress(options); // THEN we get an object with an address starting with 'r' and a secret starting with 's' (not 'sEd') - assert(account.classicAddress.startsWith('r'), 'Address must start with `r`') + assert( + account.classicAddress?.startsWith("r"), + "Address must start with `r`" + ); assert.deepEqual( account.secret.slice(0, 1), - 's', + "s", `Secret ${account.secret} must start with 's'` - ) + ); assert.notStrictEqual( account.secret.slice(0, 3), - 'sEd', + "sEd", `secp256k1 secret ${account.secret} must not start with 'sEd'` - ) - }) + ); + }); - it('generateAddress with algorithm `ed25519`', () => { + it("generateAddress with algorithm `ed25519`", function () { // GIVEN we want to use 'ed25519' - const options: GenerateAddressOptions = {algorithm: ECDSA.ed25519, includeClassicAddress: true} + const options: GenerateAddressOptions = { + algorithm: ECDSA.ed25519, + includeClassicAddress: true, + }; // WHEN generating an address - const account = generateXAddress(options) + const account = generateXAddress(options); // THEN we get an object with an address starting with 'r' and a secret starting with 'sEd' - assert(account.classicAddress.startsWith('r'), 'Address must start with `r`') + assert( + account.classicAddress?.startsWith("r"), + "Address must start with `r`" + ); assert.deepEqual( account.secret.slice(0, 3), - 'sEd', + "sEd", `Ed25519 secret ${account.secret} must start with 'sEd'` - ) - }) + ); + }); - it('generateAddress with algorithm `ecdsa-secp256k1` and given entropy', () => { - // GIVEN we want to use 'ecdsa-secp256k1' with entropy of zero - const options: GenerateAddressOptions = { - algorithm: ECDSA.secp256k1, - entropy: new Array(16).fill(0) - } - - // WHEN generating an address - const account = generateXAddress(options) - - // THEN we get the expected return value - assert.deepEqual(account, responses.generateXAddress) - }) - - it('generateAddress with algorithm `ed25519` and given entropy', () => { - // GIVEN we want to use 'ed25519' with entropy of zero - const options: GenerateAddressOptions = { - algorithm: ECDSA.ed25519, - entropy: new Array(16).fill(0) - } - - // WHEN generating an address - const account = generateXAddress(options) - - // THEN we get the expected return value - assert.deepEqual(account, { - // generateAddress return value always includes xAddress to encourage X-address adoption - xAddress: 'X7xq1YJ4xmLSGGLhuakFQB9CebWYthQkgsvFC4LGFH871HB', - secret: 'sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE' - }) - }) - - it('generateAddress with algorithm `ecdsa-secp256k1` and given entropy; include classic address', () => { + it("generateAddress with algorithm `ecdsa-secp256k1` and given entropy", function () { // GIVEN we want to use 'ecdsa-secp256k1' with entropy of zero const options: GenerateAddressOptions = { algorithm: ECDSA.secp256k1, entropy: new Array(16).fill(0), - includeClassicAddress: true - } + }; // WHEN generating an address - const account = generateXAddress(options) + const account = generateXAddress(options); // THEN we get the expected return value - assert.deepEqual(account, responses.generateAddress) - }) + assert.deepEqual(account, responses.generateXAddress); + }); - it('generateAddress with algorithm `ed25519` and given entropy; include classic address', () => { + it("generateAddress with algorithm `ed25519` and given entropy", function () { // GIVEN we want to use 'ed25519' with entropy of zero const options: GenerateAddressOptions = { algorithm: ECDSA.ed25519, entropy: new Array(16).fill(0), - includeClassicAddress: true - } + }; // WHEN generating an address - const account = generateXAddress(options) + const account = generateXAddress(options); // THEN we get the expected return value assert.deepEqual(account, { // generateAddress return value always includes xAddress to encourage X-address adoption - xAddress: 'X7xq1YJ4xmLSGGLhuakFQB9CebWYthQkgsvFC4LGFH871HB', + xAddress: "X7xq1YJ4xmLSGGLhuakFQB9CebWYthQkgsvFC4LGFH871HB", + secret: "sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE", + }); + }); - secret: 'sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE', - classicAddress: 'r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7', - address: 'r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7' - }) - }) - - it('generateAddress with algorithm `ecdsa-secp256k1` and given entropy; include classic address; for test network use', () => { + it("generateAddress with algorithm `ecdsa-secp256k1` and given entropy; include classic address", function () { // GIVEN we want to use 'ecdsa-secp256k1' with entropy of zero const options: GenerateAddressOptions = { algorithm: ECDSA.secp256k1, entropy: new Array(16).fill(0), includeClassicAddress: true, - test: true - } + }; // WHEN generating an address - const account = generateXAddress(options) + const account = generateXAddress(options); // THEN we get the expected return value - const response = Object.assign({}, responses.generateAddress, { - // generateAddress return value always includes xAddress to encourage X-address adoption - xAddress: 'TVG3TcCD58BD6MZqsNuTihdrhZwR8SzvYS8U87zvHsAcNw4' - }) - assert.deepEqual(account, response) - }) + assert.deepEqual(account, responses.generateAddress); + }); - it('generateAddress with algorithm `ed25519` and given entropy; include classic address; for test network use', () => { + it("generateAddress with algorithm `ed25519` and given entropy; include classic address", function () { // GIVEN we want to use 'ed25519' with entropy of zero const options: GenerateAddressOptions = { algorithm: ECDSA.ed25519, entropy: new Array(16).fill(0), includeClassicAddress: true, - test: true - } + }; // WHEN generating an address - const account = generateXAddress(options) + const account = generateXAddress(options); // THEN we get the expected return value assert.deepEqual(account, { // generateAddress return value always includes xAddress to encourage X-address adoption - xAddress: 'T7t4HeTMF5tT68agwuVbJwu23ssMPeh8dDtGysZoQiij1oo', - secret: 'sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE', - classicAddress: 'r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7', - address: 'r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7' - }) - }) + xAddress: "X7xq1YJ4xmLSGGLhuakFQB9CebWYthQkgsvFC4LGFH871HB", - it('generateAddress for test network use', () => { + secret: "sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE", + classicAddress: "r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7", + address: "r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7", + }); + }); + + it("generateAddress with algorithm `ecdsa-secp256k1` and given entropy; include classic address; for test network use", function () { + // GIVEN we want to use 'ecdsa-secp256k1' with entropy of zero + const options: GenerateAddressOptions = { + algorithm: ECDSA.secp256k1, + entropy: new Array(16).fill(0), + includeClassicAddress: true, + test: true, + }; + + // WHEN generating an address + const account = generateXAddress(options); + + // THEN we get the expected return value + const response = { + ...responses.generateAddress, // generateAddress return value always includes xAddress to encourage X-address adoption + xAddress: "TVG3TcCD58BD6MZqsNuTihdrhZwR8SzvYS8U87zvHsAcNw4", + }; + assert.deepEqual(account, response); + }); + + it("generateAddress with algorithm `ed25519` and given entropy; include classic address; for test network use", function () { + // GIVEN we want to use 'ed25519' with entropy of zero + const options: GenerateAddressOptions = { + algorithm: ECDSA.ed25519, + entropy: new Array(16).fill(0), + includeClassicAddress: true, + test: true, + }; + + // WHEN generating an address + const account = generateXAddress(options); + + // THEN we get the expected return value + assert.deepEqual(account, { + // generateAddress return value always includes xAddress to encourage X-address adoption + xAddress: "T7t4HeTMF5tT68agwuVbJwu23ssMPeh8dDtGysZoQiij1oo", + secret: "sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE", + classicAddress: "r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7", + address: "r9zRhGr7b6xPekLvT6wP4qNdWMryaumZS7", + }); + }); + + it("generateAddress for test network use", function () { // GIVEN we want an address for test network use - const options: GenerateAddressOptions = {test: true} + const options: GenerateAddressOptions = { test: true }; // WHEN generating an address - const account = generateXAddress(options) + const account = generateXAddress(options); // THEN we get an object with xAddress starting with 'T' and a secret starting with 's' // generateAddress return value always includes xAddress to encourage X-address adoption assert.deepEqual( account.xAddress.slice(0, 1), - 'T', - 'Test addresses start with T' - ) + "T", + "Test addresses start with T" + ); assert.deepEqual( account.secret.slice(0, 1), - 's', + "s", `Secret ${account.secret} must start with 's'` - ) - }) -}) \ No newline at end of file + ); + }); +}); diff --git a/test/utils/hashes.ts b/test/utils/hashes.ts index cb463015..7929a4e3 100644 --- a/test/utils/hashes.ts +++ b/test/utils/hashes.ts @@ -1,161 +1,163 @@ -import assert from 'assert' -import fs from 'fs' +import assert from "assert"; +import fs from "fs"; + import { - computeStateTreeHash, - computeTransactionTreeHash, - computeAccountRootIndex, + computeStateTreeHash, + computeTransactionTreeHash, + computeAccountRootIndex, computeTrustlineHash, computeOfferIndex, computeSignerListIndex, computeEscrowHash, - computePaymentChannelHash -} from '../../src/utils/hashes' + computePaymentChannelHash, +} from "../../src/utils/hashes"; /** - * Expects a corresponding ledger dump in $repo/test/fixtures/rippled folder + * Expects a corresponding ledger dump in $repo/test/fixtures/rippled folder. + * + * @param ledgerIndex */ function createLedgerTest(ledgerIndex: number) { describe(String(ledgerIndex), function () { - var path = - __dirname + '/../fixtures/rippled/ledgerFull' + ledgerIndex + '.json' + const path = `${__dirname}/../fixtures/rippled/ledgerFull${ledgerIndex}.json`; - var ledgerRaw = fs.readFileSync(path, {encoding: 'utf8'}) - var ledgerJSON = JSON.parse(ledgerRaw) + const ledgerRaw = fs.readFileSync(path, { encoding: "utf8" }); + const ledgerJSON = JSON.parse(ledgerRaw); - var hasAccounts = + const hasAccounts = Array.isArray(ledgerJSON.accountState) && - ledgerJSON.accountState.length > 0 + ledgerJSON.accountState.length > 0; if (hasAccounts) { - it('has account_hash of ' + ledgerJSON.account_hash, function () { + it(`has account_hash of ${ledgerJSON.account_hash}`, function () { assert.equal( ledgerJSON.account_hash, computeStateTreeHash(ledgerJSON.accountState) - ) - }) + ); + }); } - it('has transaction_hash of ' + ledgerJSON.transaction_hash, function () { + it(`has transaction_hash of ${ledgerJSON.transaction_hash}`, function () { assert.equal( ledgerJSON.transaction_hash, computeTransactionTreeHash(ledgerJSON.transactions) - ) - }) - }) + ); + }); + }); } -describe('Ledger', function () { +describe("Ledger", function () { // This is the first recorded ledger with a non empty transaction set - createLedgerTest(38129) + createLedgerTest(38129); // Because, why not. - createLedgerTest(40000) + createLedgerTest(40000); // 1311 AffectedNodes, no accounts - createLedgerTest(7501326) + createLedgerTest(7501326); - describe('calcAccountRootEntryHash', function () { - it('will calculate the AccountRoot entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', function () { - var account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh' - var expectedEntryHash = - '2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8' - var actualEntryHash = computeAccountRootIndex(account) + describe("calcAccountRootEntryHash", function () { + it("will calculate the AccountRoot entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", function () { + const account = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; + const expectedEntryHash = + "2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8"; + const actualEntryHash = computeAccountRootIndex(account); - assert.equal(actualEntryHash, expectedEntryHash) - }) - }) + assert.equal(actualEntryHash, expectedEntryHash); + }); + }); - describe('calcRippleStateEntryHash', function () { - it('will calculate the RippleState entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh and rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY in USD', function () { - var account1 = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh' - var account2 = 'rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY' - var currency = 'USD' + describe("calcRippleStateEntryHash", function () { + it("will calculate the RippleState entry hash for rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh and rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY in USD", function () { + const account1 = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; + const account2 = "rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY"; + const currency = "USD"; - var expectedEntryHash = - 'C683B5BB928F025F1E860D9D69D6C554C2202DE0D45877ADB3077DA4CB9E125C' - var actualEntryHash1 = computeTrustlineHash( + const expectedEntryHash = + "C683B5BB928F025F1E860D9D69D6C554C2202DE0D45877ADB3077DA4CB9E125C"; + const actualEntryHash1 = computeTrustlineHash( account1, account2, currency - ) - var actualEntryHash2 = computeTrustlineHash( + ); + const actualEntryHash2 = computeTrustlineHash( account2, account1, currency - ) + ); - assert.equal(actualEntryHash1, expectedEntryHash) - assert.equal(actualEntryHash2, expectedEntryHash) - }) + assert.equal(actualEntryHash1, expectedEntryHash); + assert.equal(actualEntryHash2, expectedEntryHash); + }); - it('will calculate the RippleState entry hash for r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV and rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj in UAM', function () { - var account1 = 'r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV' - var account2 = 'rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj' - var currency = 'UAM' + it("will calculate the RippleState entry hash for r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV and rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj in UAM", function () { + const account1 = "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV"; + const account2 = "rUAMuQTfVhbfqUDuro7zzy4jj4Wq57MPTj"; + const currency = "UAM"; - var expectedEntryHash = - 'AE9ADDC584358E5847ADFC971834E471436FC3E9DE6EA1773DF49F419DC0F65E' - var actualEntryHash1 = computeTrustlineHash( + const expectedEntryHash = + "AE9ADDC584358E5847ADFC971834E471436FC3E9DE6EA1773DF49F419DC0F65E"; + const actualEntryHash1 = computeTrustlineHash( account1, account2, currency - ) - var actualEntryHash2 = computeTrustlineHash( + ); + const actualEntryHash2 = computeTrustlineHash( account2, account1, currency - ) + ); - assert.equal(actualEntryHash1, expectedEntryHash) - assert.equal(actualEntryHash2, expectedEntryHash) - }) - }) + assert.equal(actualEntryHash1, expectedEntryHash); + assert.equal(actualEntryHash2, expectedEntryHash); + }); + }); - describe('calcOfferEntryHash', function () { - it('will calculate the Offer entry hash for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw, sequence 137', function () { - var account = 'r32UufnaCGL82HubijgJGDmdE5hac7ZvLw' - var sequence = 137 - var expectedEntryHash = - '03F0AED09DEEE74CEF85CD57A0429D6113507CF759C597BABB4ADB752F734CE3' - var actualEntryHash = computeOfferIndex(account, sequence) + describe("calcOfferEntryHash", function () { + it("will calculate the Offer entry hash for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw, sequence 137", function () { + const account = "r32UufnaCGL82HubijgJGDmdE5hac7ZvLw"; + const sequence = 137; + const expectedEntryHash = + "03F0AED09DEEE74CEF85CD57A0429D6113507CF759C597BABB4ADB752F734CE3"; + const actualEntryHash = computeOfferIndex(account, sequence); - assert.equal(actualEntryHash, expectedEntryHash) - }) - }) + assert.equal(actualEntryHash, expectedEntryHash); + }); + }); - describe('computeSignerListIndex', function () { - it('will calculate the SignerList index for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw', function () { - var account = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh' - var expectedEntryHash = - '778365D5180F5DF3016817D1F318527AD7410D83F8636CF48C43E8AF72AB49BF' - var actualEntryHash = computeSignerListIndex(account) - assert.equal(actualEntryHash, expectedEntryHash) - }) - }) + describe("computeSignerListIndex", function () { + it("will calculate the SignerList index for r32UufnaCGL82HubijgJGDmdE5hac7ZvLw", function () { + const account = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; + const expectedEntryHash = + "778365D5180F5DF3016817D1F318527AD7410D83F8636CF48C43E8AF72AB49BF"; + const actualEntryHash = computeSignerListIndex(account); + assert.equal(actualEntryHash, expectedEntryHash); + }); + }); - describe('calcEscrowEntryHash', function () { - it('will calculate the Escrow entry hash for rDx69ebzbowuqztksVDmZXjizTd12BVr4x, sequence 84', function () { - var account = 'rDx69ebzbowuqztksVDmZXjizTd12BVr4x' - var sequence = 84 - var expectedEntryHash = - '61E8E8ED53FA2CEBE192B23897071E9A75217BF5A410E9CB5B45AAB7AECA567A' - var actualEntryHash = computeEscrowHash(account, sequence) + describe("calcEscrowEntryHash", function () { + it("will calculate the Escrow entry hash for rDx69ebzbowuqztksVDmZXjizTd12BVr4x, sequence 84", function () { + const account = "rDx69ebzbowuqztksVDmZXjizTd12BVr4x"; + const sequence = 84; + const expectedEntryHash = + "61E8E8ED53FA2CEBE192B23897071E9A75217BF5A410E9CB5B45AAB7AECA567A"; + const actualEntryHash = computeEscrowHash(account, sequence); - assert.equal(actualEntryHash, expectedEntryHash) - }) - }) + assert.equal(actualEntryHash, expectedEntryHash); + }); + }); - describe('calcPaymentChannelEntryHash', function () { - it('will calculate the PaymentChannel entry hash for rDx69ebzbowuqztksVDmZXjizTd12BVr4x and rLFtVprxUEfsH54eCWKsZrEQzMDsx1wqso, sequence 82', function () { - var account = 'rDx69ebzbowuqztksVDmZXjizTd12BVr4x' - var dstAccount = 'rLFtVprxUEfsH54eCWKsZrEQzMDsx1wqso' - var sequence = 82 - var expectedEntryHash = - 'E35708503B3C3143FB522D749AAFCC296E8060F0FB371A9A56FAE0B1ED127366' - var actualEntryHash = computePaymentChannelHash( + describe("calcPaymentChannelEntryHash", function () { + it("will calculate the PaymentChannel entry hash for rDx69ebzbowuqztksVDmZXjizTd12BVr4x and rLFtVprxUEfsH54eCWKsZrEQzMDsx1wqso, sequence 82", function () { + const account = "rDx69ebzbowuqztksVDmZXjizTd12BVr4x"; + const dstAccount = "rLFtVprxUEfsH54eCWKsZrEQzMDsx1wqso"; + const sequence = 82; + const expectedEntryHash = + "E35708503B3C3143FB522D749AAFCC296E8060F0FB371A9A56FAE0B1ED127366"; + const actualEntryHash = computePaymentChannelHash( account, dstAccount, sequence - ) + ); - assert.equal(actualEntryHash, expectedEntryHash) - }) - }) -}) + assert.equal(actualEntryHash, expectedEntryHash); + }); + }); +}); diff --git a/test/utils/signPaymentChannelClaim.ts b/test/utils/signPaymentChannelClaim.ts index f2e0d4cb..9e48ba7f 100644 --- a/test/utils/signPaymentChannelClaim.ts +++ b/test/utils/signPaymentChannelClaim.ts @@ -1,26 +1,21 @@ -import {assertResultMatch} from '../testUtils' -import responses from '../fixtures/responses' -import signPaymentChannelClaim from '../../src/utils/signPaymentChannelClaim' +import signPaymentChannelClaim from "../../src/utils/signPaymentChannelClaim"; +import responses from "../fixtures/responses"; +import { assertResultMatch } from "../testUtils"; +describe("signPaymentChannelClaim", function () { + it("basic signature matches", function () { + const channel = + "3E18C05AD40319B809520F1A136370C4075321B285217323396D6FD9EE1E9037"; + const amount = ".00001"; + const privateKey = + "ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A"; + const result = signPaymentChannelClaim(channel, amount, privateKey); -describe('signPaymentChannelClaim', function () { - it('basic signature matches', () => { - - const channel = "3E18C05AD40319B809520F1A136370C4075321B285217323396D6FD9EE1E9037" - const amount = ".00001" - const privateKey = 'ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A' - - const result = signPaymentChannelClaim( - channel, - amount, - privateKey - ) - assertResultMatch( result, responses.signPaymentChannelClaim, - 'signPaymentChannelClaim' - ) - }) -}) + "signPaymentChannelClaim" + ); + }); +}); diff --git a/test/utils/verifyPaymentChannelClaim.ts b/test/utils/verifyPaymentChannelClaim.ts index 534c228b..35511f23 100644 --- a/test/utils/verifyPaymentChannelClaim.ts +++ b/test/utils/verifyPaymentChannelClaim.ts @@ -1,30 +1,30 @@ -import {verifyPaymentChannelClaim} from '../../src' -import requests from '../fixtures/requests' -import responses from '../fixtures/responses' -import {assertResultMatch} from '../testUtils' +import { verifyPaymentChannelClaim } from "../../src"; +import requests from "../fixtures/requests"; +import responses from "../fixtures/responses"; +import { assertResultMatch } from "../testUtils"; -describe('Verify Payment Channel Claim', function () { - it('basic verification works', () => { +describe("Verify Payment Channel Claim", function () { + it("basic verification works", function () { const publicKey = - '02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8' + "02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"; const result = verifyPaymentChannelClaim( requests.signPaymentChannelClaim.channel, requests.signPaymentChannelClaim.amount, responses.signPaymentChannelClaim, publicKey - ) - assertResultMatch(result, true, 'verifyPaymentChannelClaim') - }) + ); + assertResultMatch(result, true, "verifyPaymentChannelClaim"); + }); - it('invalid payment channel claim fails', () => { + it("invalid payment channel claim fails", function () { const publicKey = - '03A6523FE4281DA48A6FD77FAF3CB77F5C7001ABA0B32BCEDE0369AC009758D7D9' + "03A6523FE4281DA48A6FD77FAF3CB77F5C7001ABA0B32BCEDE0369AC009758D7D9"; const result = verifyPaymentChannelClaim( requests.signPaymentChannelClaim.channel, requests.signPaymentChannelClaim.amount, responses.signPaymentChannelClaim, publicKey - ) - assertResultMatch(result, false, 'verifyPaymentChannelClaim') - }) -}) + ); + assertResultMatch(result, false, "verifyPaymentChannelClaim"); + }); +}); diff --git a/test/utils/xrpToDrops.ts b/test/utils/xrpToDrops.ts index a72086ea..b072d86d 100644 --- a/test/utils/xrpToDrops.ts +++ b/test/utils/xrpToDrops.ts @@ -1,108 +1,109 @@ -import assert from 'assert-diff' -import BigNumber from 'bignumber.js' -import {xrpToDrops} from '../../src/utils' +import assert from "assert-diff"; +import BigNumber from "bignumber.js"; -describe('XRP To Drops', function () { - it('works with a typical amount', () => { - const drops = xrpToDrops('2') - assert.strictEqual(drops, '2000000', '2 XRP equals 2 million drops') - }) +import { xrpToDrops } from "../../src/utils"; - it('works with fractions', () => { - let drops = xrpToDrops('3.456789') - assert.strictEqual(drops, '3456789', '3.456789 XRP equals 3,456,789 drops') - drops = xrpToDrops('3.400000') - assert.strictEqual(drops, '3400000', '3.400000 XRP equals 3,400,000 drops') - drops = xrpToDrops('0.000001') - assert.strictEqual(drops, '1', '0.000001 XRP equals 1 drop') - drops = xrpToDrops('0.0000010') - assert.strictEqual(drops, '1', '0.0000010 XRP equals 1 drop') - }) +describe("XRP To Drops", function () { + it("works with a typical amount", function () { + const drops = xrpToDrops("2"); + assert.strictEqual(drops, "2000000", "2 XRP equals 2 million drops"); + }); - it('works with zero', () => { - let drops = xrpToDrops('0') - assert.strictEqual(drops, '0', '0 XRP equals 0 drops') - drops = xrpToDrops('-0') // negative zero is equivalent to zero - assert.strictEqual(drops, '0', '-0 XRP equals 0 drops') - drops = xrpToDrops('0.000000') - assert.strictEqual(drops, '0', '0.000000 XRP equals 0 drops') - drops = xrpToDrops('0.0000000') - assert.strictEqual(drops, '0', '0.0000000 XRP equals 0 drops') - }) + it("works with fractions", function () { + let drops = xrpToDrops("3.456789"); + assert.strictEqual(drops, "3456789", "3.456789 XRP equals 3,456,789 drops"); + drops = xrpToDrops("3.400000"); + assert.strictEqual(drops, "3400000", "3.400000 XRP equals 3,400,000 drops"); + drops = xrpToDrops("0.000001"); + assert.strictEqual(drops, "1", "0.000001 XRP equals 1 drop"); + drops = xrpToDrops("0.0000010"); + assert.strictEqual(drops, "1", "0.0000010 XRP equals 1 drop"); + }); - it('works with a negative value', () => { - const drops = xrpToDrops('-2') - assert.strictEqual(drops, '-2000000', '-2 XRP equals -2 million drops') - }) + it("works with zero", function () { + let drops = xrpToDrops("0"); + assert.strictEqual(drops, "0", "0 XRP equals 0 drops"); + drops = xrpToDrops("-0"); // negative zero is equivalent to zero + assert.strictEqual(drops, "0", "-0 XRP equals 0 drops"); + drops = xrpToDrops("0.000000"); + assert.strictEqual(drops, "0", "0.000000 XRP equals 0 drops"); + drops = xrpToDrops("0.0000000"); + assert.strictEqual(drops, "0", "0.0000000 XRP equals 0 drops"); + }); - it('works with a value ending with a decimal point', () => { - let drops = xrpToDrops('2.') - assert.strictEqual(drops, '2000000', '2. XRP equals 2000000 drops') - drops = xrpToDrops('-2.') - assert.strictEqual(drops, '-2000000', '-2. XRP equals -2000000 drops') - }) + it("works with a negative value", function () { + const drops = xrpToDrops("-2"); + assert.strictEqual(drops, "-2000000", "-2 XRP equals -2 million drops"); + }); - it('works with BigNumber objects', () => { - let drops = xrpToDrops(new BigNumber(2)) + it("works with a value ending with a decimal point", function () { + let drops = xrpToDrops("2."); + assert.strictEqual(drops, "2000000", "2. XRP equals 2000000 drops"); + drops = xrpToDrops("-2."); + assert.strictEqual(drops, "-2000000", "-2. XRP equals -2000000 drops"); + }); + + it("works with BigNumber objects", function () { + let drops = xrpToDrops(new BigNumber(2)); assert.strictEqual( drops, - '2000000', - '(BigNumber) 2 XRP equals 2 million drops' - ) - drops = xrpToDrops(new BigNumber(-2)) + "2000000", + "(BigNumber) 2 XRP equals 2 million drops" + ); + drops = xrpToDrops(new BigNumber(-2)); assert.strictEqual( drops, - '-2000000', - '(BigNumber) -2 XRP equals -2 million drops' - ) - }) + "-2000000", + "(BigNumber) -2 XRP equals -2 million drops" + ); + }); - it('works with a number', () => { + it("works with a number", function () { // This is not recommended. Use strings or BigNumber objects to avoid precision errors. - let drops = xrpToDrops(2) + let drops = xrpToDrops(2); assert.strictEqual( drops, - '2000000', - '(number) 2 XRP equals 2 million drops' - ) - drops = xrpToDrops(-2) + "2000000", + "(number) 2 XRP equals 2 million drops" + ); + drops = xrpToDrops(-2); assert.strictEqual( drops, - '-2000000', - '(number) -2 XRP equals -2 million drops' - ) - }) + "-2000000", + "(number) -2 XRP equals -2 million drops" + ); + }); - it('throws with an amount with too many decimal places', () => { + it("throws with an amount with too many decimal places", function () { assert.throws(() => { - xrpToDrops('1.1234567') - }, /has too many decimal places/) + xrpToDrops("1.1234567"); + }, /has too many decimal places/); assert.throws(() => { - xrpToDrops('0.0000001') - }, /has too many decimal places/) - }) + xrpToDrops("0.0000001"); + }, /has too many decimal places/); + }); - it('throws with an invalid value', () => { + it("throws with an invalid value", function () { assert.throws(() => { - xrpToDrops('FOO') - }, /invalid value/) + xrpToDrops("FOO"); + }, /invalid value/); assert.throws(() => { - xrpToDrops('1e-7') - }, /invalid value/) + xrpToDrops("1e-7"); + }, /invalid value/); assert.throws(() => { - xrpToDrops('2,0') - }, /invalid value/) + xrpToDrops("2,0"); + }, /invalid value/); assert.throws(() => { - xrpToDrops('.') - }, /xrpToDrops: invalid value '\.', should be a BigNumber or string-encoded number\./) - }) + xrpToDrops("."); + }, /xrpToDrops: invalid value '\.', should be a BigNumber or string-encoded number\./); + }); - it('throws with an amount more than one decimal point', () => { + it("throws with an amount more than one decimal point", function () { assert.throws(() => { - xrpToDrops('1.0.0') - }, /xrpToDrops: invalid value '1\.0\.0'/) + xrpToDrops("1.0.0"); + }, /xrpToDrops: invalid value '1\.0\.0'/); assert.throws(() => { - xrpToDrops('...') - }, /xrpToDrops: invalid value '\.\.\.'/) - }) -}) + xrpToDrops("..."); + }, /xrpToDrops: invalid value '\.\.\.'/); + }); +}); diff --git a/test/wallet/fromEntropy.ts b/test/wallet/fromEntropy.ts index 6b01e133..1bc35513 100644 --- a/test/wallet/fromEntropy.ts +++ b/test/wallet/fromEntropy.ts @@ -1,17 +1,18 @@ -import assert from 'assert-diff' -import {TestSuite} from '../testUtils' -import ECDSA from '../../src/common/ecdsa' -import Wallet from '../../src/Wallet' +import assert from "assert-diff"; -const entropy: number[] = new Array(16).fill(0) -const publicKey: string = - '0390A196799EE412284A5D80BF78C3E84CBB80E1437A0AECD9ADF94D7FEAAFA284' -const privateKey: string = - '002512BBDFDBB77510883B7DCCBEF270B86DEAC8B64AC762873D75A1BEE6298665' -const publicKeyED25519: string = - 'ED1A7C082846CFF58FF9A892BA4BA2593151CCF1DBA59F37714CC9ED39824AF85F' -const privateKeyED25519: string = - 'ED0B6CBAC838DFE7F47EA1BD0DF00EC282FDF45510C92161072CCFB84035390C4D' +import ECDSA from "../../src/common/ecdsa"; +import Wallet from "../../src/Wallet"; +import { TestSuite } from "../testUtils"; + +const entropy: number[] = new Array(16).fill(0); +const publicKey = + "0390A196799EE412284A5D80BF78C3E84CBB80E1437A0AECD9ADF94D7FEAAFA284"; +const privateKey = + "002512BBDFDBB77510883B7DCCBEF270B86DEAC8B64AC762873D75A1BEE6298665"; +const publicKeyED25519 = + "ED1A7C082846CFF58FF9A892BA4BA2593151CCF1DBA59F37714CC9ED39824AF85F"; +const privateKeyED25519 = + "ED0B6CBAC838DFE7F47EA1BD0DF00EC282FDF45510C92161072CCFB84035390C4D"; /** * Every test suite exports their tests in the default object. @@ -19,36 +20,36 @@ const privateKeyED25519: string = * - Check out "test/api/index.ts" for more information about the test runner. */ export default { - 'Wallet.fromEntropy with entropy only': async (api) => { + "Wallet.fromEntropy with entropy only": async (api) => { // WHEN deriving a wallet from an entropy - const wallet = Wallet.fromEntropy(entropy) + const wallet = Wallet.fromEntropy(entropy); // THEN we get a wallet with a keypair (publicKey/privateKey) - assert.equal(wallet.publicKey, publicKeyED25519) - assert.equal(wallet.privateKey, privateKeyED25519) + assert.equal(wallet.publicKey, publicKeyED25519); + assert.equal(wallet.privateKey, privateKeyED25519); }, - 'Wallet.fromEntropy with algorithm ecdsa-secp256k1': async (api) => { + "Wallet.fromEntropy with algorithm ecdsa-secp256k1": async (api) => { // GIVEN an entropy using ecdsa-secp256k1 - const algorithm = ECDSA.secp256k1 + const algorithm = ECDSA.secp256k1; // WHEN deriving a wallet from an entropy - const wallet = Wallet.fromEntropy(entropy, algorithm) + const wallet = Wallet.fromEntropy(entropy, algorithm); // THEN we get a wallet with a keypair (publicKey/privateKey) - assert.equal(wallet.publicKey, publicKey) - assert.equal(wallet.privateKey, privateKey) + assert.equal(wallet.publicKey, publicKey); + assert.equal(wallet.privateKey, privateKey); }, - 'Wallet.fromEntropy with algorithm ed25519': async (api) => { + "Wallet.fromEntropy with algorithm ed25519": async (api) => { // GIVEN an entropy using ed25519 - const algorithm = ECDSA.ed25519 + const algorithm = ECDSA.ed25519; // WHEN deriving a wallet from an entropy - const wallet = Wallet.fromEntropy(entropy, algorithm) + const wallet = Wallet.fromEntropy(entropy, algorithm); // THEN we get a wallet with a keypair (publicKey/privateKey) - assert.equal(wallet.publicKey, publicKeyED25519) - assert.equal(wallet.privateKey, privateKeyED25519) + assert.equal(wallet.publicKey, publicKeyED25519); + assert.equal(wallet.privateKey, privateKeyED25519); }, -} +}; diff --git a/test/wallet/fromMnemonic.ts b/test/wallet/fromMnemonic.ts index 81b7afcd..988acb93 100644 --- a/test/wallet/fromMnemonic.ts +++ b/test/wallet/fromMnemonic.ts @@ -1,13 +1,14 @@ -import assert from 'assert-diff' -import {TestSuite} from '../testUtils' -import Wallet from '../../src/Wallet' +import assert from "assert-diff"; + +import Wallet from "../../src/Wallet"; +import { TestSuite } from "../testUtils"; const mnemonic = - 'try milk link drift aware pass obtain again music stick pluck fold' + "try milk link drift aware pass obtain again music stick pluck fold"; const publicKey = - '0257B550BA2FDCCF0ADDA3DEB2A5411700F3ADFDCC7C68E1DCD1E2B63E6B0C63E6' + "0257B550BA2FDCCF0ADDA3DEB2A5411700F3ADFDCC7C68E1DCD1E2B63E6B0C63E6"; const privateKey = - '008F942B6E229C0E9CEE47E7A94253DABB6A9855F4BA2D8A741FA31851A1D423C3' + "008F942B6E229C0E9CEE47E7A94253DABB6A9855F4BA2D8A741FA31851A1D423C3"; /** * Every test suite exports their tests in the default object. @@ -15,25 +16,25 @@ const privateKey = * - Check out "test/api/index.ts" for more information about the test runner. */ export default { - 'Wallet.fromMnemonic using default derivation path': async (api) => { + "Wallet.fromMnemonic using default derivation path": async (api) => { // GIVEN no derivation path // WHEN deriving a wallet from a mnemonic without a derivation path - const wallet = Wallet.fromMnemonic(mnemonic) + const wallet = Wallet.fromMnemonic(mnemonic); // THEN we get a wallet with a keypair (publicKey/privateKey) - assert.equal(wallet.publicKey, publicKey) - assert.equal(wallet.privateKey, privateKey) + assert.equal(wallet.publicKey, publicKey); + assert.equal(wallet.privateKey, privateKey); }, - 'Wallet.fromMnemonic using an input derivation path': async (api) => { + "Wallet.fromMnemonic using an input derivation path": async (api) => { // GIVEN a derivation path - const derivationPath = "m/44'/144'/0'/0/0" + const derivationPath = "m/44'/144'/0'/0/0"; // WHEN deriving a wallet from a mnemonic without a derivation path - const wallet = Wallet.fromMnemonic(mnemonic, derivationPath) + const wallet = Wallet.fromMnemonic(mnemonic, derivationPath); // THEN we get a wallet with a keypair (publicKey/privateKey) - assert.equal(wallet.publicKey, publicKey) - assert.equal(wallet.privateKey, privateKey) + assert.equal(wallet.publicKey, publicKey); + assert.equal(wallet.privateKey, privateKey); }, -} +}; diff --git a/test/wallet/fromSeed.ts b/test/wallet/fromSeed.ts index e2abfc9c..7197aa5e 100644 --- a/test/wallet/fromSeed.ts +++ b/test/wallet/fromSeed.ts @@ -1,13 +1,14 @@ -import assert from 'assert-diff' -import {TestSuite} from '../testUtils' -import ECDSA from '../../src/common/ecdsa' -import Wallet from '../../src/Wallet' +import assert from "assert-diff"; -const seed = 'ssL9dv2W5RK8L3tuzQxYY6EaZhSxW' +import ECDSA from "../../src/common/ecdsa"; +import Wallet from "../../src/Wallet"; +import { TestSuite } from "../testUtils"; + +const seed = "ssL9dv2W5RK8L3tuzQxYY6EaZhSxW"; const publicKey = - '030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D' + "030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D"; const privateKey = - '00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F' + "00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F"; /** * Every test suite exports their tests in the default object. @@ -15,36 +16,36 @@ const privateKey = * - Check out "test/api/index.ts" for more information about the test runner. */ export default { - 'Wallet.fromSeed with empty options object': async (api) => { + "Wallet.fromSeed with empty options object": async (api) => { // WHEN deriving a wallet from a seed - const wallet = Wallet.fromSeed(seed) + const wallet = Wallet.fromSeed(seed); // THEN we get a wallet with a keypair (publicKey/privateKey) - assert.equal(wallet.publicKey, publicKey) - assert.equal(wallet.privateKey, privateKey) + assert.equal(wallet.publicKey, publicKey); + assert.equal(wallet.privateKey, privateKey); }, - 'Wallet.fromSeed with algorithm ecdsa-secp256k1': async (api) => { + "Wallet.fromSeed with algorithm ecdsa-secp256k1": async (api) => { // GIVEN we want to use ecdsa-secp256k1 - const algorithm = ECDSA.secp256k1 + const algorithm = ECDSA.secp256k1; // WHEN deriving a wallet from a seed - const wallet = Wallet.fromSeed(seed, algorithm) + const wallet = Wallet.fromSeed(seed, algorithm); // THEN we get a wallet with a keypair (publicKey/privateKey) - assert.equal(wallet.publicKey, publicKey) - assert.equal(wallet.privateKey, privateKey) + assert.equal(wallet.publicKey, publicKey); + assert.equal(wallet.privateKey, privateKey); }, - 'Wallet.fromSeed with algorithm ed25519': async (api) => { + "Wallet.fromSeed with algorithm ed25519": async (api) => { // GIVEN we want to use ed25519 - const algorithm = ECDSA.ed25519 + const algorithm = ECDSA.ed25519; // WHEN deriving a wallet from a seed - const wallet = Wallet.fromSeed(seed, algorithm) + const wallet = Wallet.fromSeed(seed, algorithm); // THEN we get a wallet with a keypair (publicKey/privateKey) - assert.equal(wallet.publicKey, publicKey) - assert.equal(wallet.privateKey, privateKey) + assert.equal(wallet.publicKey, publicKey); + assert.equal(wallet.privateKey, privateKey); }, -} +}; diff --git a/test/wallet/signTransaction.ts b/test/wallet/signTransaction.ts index 19cef892..adc0a6c9 100644 --- a/test/wallet/signTransaction.ts +++ b/test/wallet/signTransaction.ts @@ -1,12 +1,13 @@ -import {TestSuite} from '../testUtils' -import Wallet from '../../src/Wallet' -import * as schemaValidator from 'xrpl-local/common/schema-validator' +import * as schemaValidator from "xrpl-local/common/schema-validator"; + +import Wallet from "../../src/Wallet"; +import { TestSuite } from "../testUtils"; const publicKey = - '030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D' + "030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D"; const privateKey = - '00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F' -const address = 'rhvh5SrgBL5V8oeV9EpDuVszeJSSCEkbPc' + "00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F"; +const address = "rhvh5SrgBL5V8oeV9EpDuVszeJSSCEkbPc"; /** * Every test suite exports their tests in the default object. @@ -14,24 +15,24 @@ const address = 'rhvh5SrgBL5V8oeV9EpDuVszeJSSCEkbPc' * - Check out "test/api/index.ts" for more information about the test runner. */ export default { - 'sign transaction offline with txJSON': async (api) => { + "sign transaction offline with txJSON": async (api) => { // GIVEN a transaction const txJSON = { - TransactionType: 'Payment', + TransactionType: "Payment", Account: address, - Destination: 'rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r', - Amount: '20000000', + Destination: "rQ3PTWGLCbPz8ZCicV5tCX3xuymojTng5r", + Amount: "20000000", Sequence: 1, - Fee: '12', - SigningPubKey: publicKey - } - const wallet = new Wallet(publicKey, privateKey) + Fee: "12", + SigningPubKey: publicKey, + }; + const wallet = new Wallet(publicKey, privateKey); // WHEN signing a transaction offline - const signedTx: {signedTransaction: string; id: string} = - wallet.signTransaction(txJSON) + const signedTx: { signedTransaction: string; id: string } = + wallet.signTransaction(txJSON); // THEN we get a signedTransaction - schemaValidator.schemaValidate('sign', signedTx) + schemaValidator.schemaValidate("sign", signedTx); }, -} +}; diff --git a/test/wallet/verifyTransaction.ts b/test/wallet/verifyTransaction.ts index 829eb419..28379be7 100644 --- a/test/wallet/verifyTransaction.ts +++ b/test/wallet/verifyTransaction.ts @@ -1,16 +1,18 @@ -import assert from 'assert-diff' -import {TestSuite} from '../testUtils' -import Wallet from 'xrpl-local/Wallet' +import assert from "assert-diff"; + +import Wallet from "xrpl-local/Wallet"; + +import { TestSuite } from "../testUtils"; const publicKey = - '030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D' + "030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D"; const privateKey = - '00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F' + "00141BA006D3363D2FB2785E8DF4E44D3A49908780CB4FB51F6D217C08C021429F"; const prepared = { signedTransaction: - '1200002400000001614000000001312D0068400000000000000C7321030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D74473045022100CAF99A63B241F5F62B456C68A593D2835397101533BB5D0C4DC17362AC22046F022016A2CA2CF56E777B10E43B56541A4C2FB553E7E298CDD39F7A8A844DA491E51D81142AF1861DEC1316AEEC995C94FF9E2165B1B784608314FDB08D07AAA0EB711793A3027304D688E10C3648', - id: '30D9ECA2A7FB568C5A8607E5850D9567572A9E7C6094C26BEFD4DC4C2CF2657A' -} + "1200002400000001614000000001312D0068400000000000000C7321030E58CDD076E798C84755590AAF6237CA8FAE821070A59F648B517A30DC6F589D74473045022100CAF99A63B241F5F62B456C68A593D2835397101533BB5D0C4DC17362AC22046F022016A2CA2CF56E777B10E43B56541A4C2FB553E7E298CDD39F7A8A844DA491E51D81142AF1861DEC1316AEEC995C94FF9E2165B1B784608314FDB08D07AAA0EB711793A3027304D688E10C3648", + id: "30D9ECA2A7FB568C5A8607E5850D9567572A9E7C6094C26BEFD4DC4C2CF2657A", +}; /** * Every test suite exports their tests in the default object. @@ -18,29 +20,37 @@ const prepared = { * - Check out "test/api/index.ts" for more information about the test runner. */ export default { - 'verify transaction offline when a signed transaction is valid': async (api) => { + "verify transaction offline when a signed transaction is valid": async ( + api + ) => { // GIVEN a transaction that has been signed by the same wallet - const wallet = new Wallet(publicKey, privateKey) + const wallet = new Wallet(publicKey, privateKey); // WHEN verifying a signed transaction - const isVerified: boolean = wallet.verifyTransaction(prepared.signedTransaction) + const isVerified: boolean = wallet.verifyTransaction( + prepared.signedTransaction + ); // THEN we get a valid response - assert.equal(isVerified, true) + assert.equal(isVerified, true); }, - "verify transaction offline when signed transaction isn't valid": async (api) => { + "verify transaction offline when signed transaction isn't valid": async ( + api + ) => { // GIVEN a transaction that has been signed by a different wallet const diffPublicKey = - '02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8' + "02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8"; const diffPrivateKey = - '00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A' - const wallet = new Wallet(diffPublicKey, diffPrivateKey) + "00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A"; + const wallet = new Wallet(diffPublicKey, diffPrivateKey); // WHEN verifying a signed transaction - const isVerified: boolean = wallet.verifyTransaction(prepared.signedTransaction) + const isVerified: boolean = wallet.verifyTransaction( + prepared.signedTransaction + ); // THEN we get an invalid response - assert.equal(isVerified, false) + assert.equal(isVerified, false); }, -} +}; diff --git a/test/walletGeneration.ts b/test/walletGeneration.ts index 9649372a..2677d03d 100644 --- a/test/walletGeneration.ts +++ b/test/walletGeneration.ts @@ -1,35 +1,36 @@ -import assert from 'assert-diff' +import assert from "assert-diff"; -import setupClient from './setupClient' -import {getFaucetUrl, FaucetNetwork} from '../src/wallet/wallet-generation' +import { getFaucetUrl, FaucetNetwork } from "../src/wallet/wallet-generation"; -describe('Get Faucet URL', function () { - beforeEach(setupClient.setup) - afterEach(setupClient.teardown) +import setupClient from "./setupClient"; - it('returns the Devnet URL', function () { - const expectedFaucet = FaucetNetwork.Devnet - this.client.connection._url = FaucetNetwork.Devnet +describe("Get Faucet URL", function () { + beforeEach(setupClient.setup); + afterEach(setupClient.teardown); - assert.strictEqual(getFaucetUrl(this.client), expectedFaucet) - }) + it("returns the Devnet URL", function () { + const expectedFaucet = FaucetNetwork.Devnet; + this.client.connection._url = FaucetNetwork.Devnet; - it('returns the Testnet URL', function () { - const expectedFaucet = FaucetNetwork.Testnet - this.client.connection._url = FaucetNetwork.Testnet + assert.strictEqual(getFaucetUrl(this.client), expectedFaucet); + }); - assert.strictEqual(getFaucetUrl(this.client), expectedFaucet) - }) + it("returns the Testnet URL", function () { + const expectedFaucet = FaucetNetwork.Testnet; + this.client.connection._url = FaucetNetwork.Testnet; - it('returns the Testnet URL with the XRPL Labs server', function () { - const expectedFaucet = FaucetNetwork.Testnet - this.client.connection._url = 'wss://testnet.xrpl-labs.com' + assert.strictEqual(getFaucetUrl(this.client), expectedFaucet); + }); - assert.strictEqual(getFaucetUrl(this.client), expectedFaucet) - }) + it("returns the Testnet URL with the XRPL Labs server", function () { + const expectedFaucet = FaucetNetwork.Testnet; + this.client.connection._url = "wss://testnet.xrpl-labs.com"; - it('returns undefined if not a Testnet or Devnet server URL', function () { + assert.strictEqual(getFaucetUrl(this.client), expectedFaucet); + }); + + it("returns undefined if not a Testnet or Devnet server URL", function () { // Info: setupClient.setup creates a connection to 'localhost' - assert.strictEqual(getFaucetUrl(this.client), undefined) - }) -}) + assert.strictEqual(getFaucetUrl(this.client), undefined); + }); +}); diff --git a/tsconfig-base.json b/tsconfig-base.json deleted file mode 100644 index c0bb0249..00000000 --- a/tsconfig-base.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "pretty": true, - "target": "es6", - "module": "commonjs", - "moduleResolution": "node", - - "declaration": true, - "declarationMap": true, - "sourceMap": true, - - "strict": true, - "strictNullChecks": false, - "noImplicitAny": false, - "noUnusedLocals": true, - "removeComments": true, - "preserveConstEnums": false, - "esModuleInterop": true, - "suppressImplicitAnyIndexErrors": false, - "resolveJsonModule": true, - "preserveSymlinks": true - } -} diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 00000000..b2ba4df8 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"] +} \ No newline at end of file diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json new file mode 100644 index 00000000..dc042cd6 --- /dev/null +++ b/tsconfig.eslint.json @@ -0,0 +1,11 @@ + +{ + "extends": "./tsconfig.json", + "include": [ + "./src/**/*.ts", + "./test/**/*.ts", + "./snippets/src/**/*.ts", + ".prettierrc.js", + "jest.config.js" + ] +} diff --git a/tsconfig.json b/tsconfig.json index 682549f8..01415cbd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,24 @@ { - "files": [], - "include": [], - "references": [ - { "path": "./src" }, - { "path": "./snippets" } - ] -} \ No newline at end of file + "compilerOptions": { + "pretty": true, + "target": "es6", + "module": "commonjs", + "moduleResolution": "node", + "outDir": "./dist/npm", + + "declaration": true, + "declarationMap": true, + "sourceMap": true, + + "strict": true, + "strictNullChecks": true, + "noImplicitAny": false, + "noUnusedLocals": true, + "removeComments": true, + "preserveConstEnums": false, + "esModuleInterop": true, + "suppressImplicitAnyIndexErrors": false, + "resolveJsonModule": true, + "preserveSymlinks": true + } +} diff --git a/webpack.config.js b/webpack.config.js index 0b5215b0..4f610454 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,58 +1,66 @@ -'use strict'; -const path = require('path'); -const webpack = require('webpack'); -const assert = require('assert'); -const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer'); +'use strict' +const path = require('path') +const webpack = require('webpack') +const assert = require('assert') +const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer') function getDefaultConfiguration() { return { - cache: true, - performance: { hints: false }, - stats: 'errors-only', - entry: './dist/npm/index.js', - output: { - library: 'ripple', - path: path.join(__dirname, 'build/'), - filename: `ripple-lib.default.js`, - }, - plugins: [ - new webpack.NormalModuleReplacementPlugin(/^ws$/, './wsWrapper'), - new webpack.NormalModuleReplacementPlugin(/^\.\/wallet$/, './wallet-web'), - new webpack.NormalModuleReplacementPlugin(/^.*setup-api$/, './setup-api-web'), - new webpack.ProvidePlugin({ process: 'process/browser' }), - new webpack.ProvidePlugin({ Buffer: ['buffer', 'Buffer'] }) - ], - module: { - rules: [] - }, - resolve: { - extensions: ['.js', '.json'], - fallback: { - "buffer": require.resolve("buffer/"), - "assert": require.resolve("assert/"), - "url": require.resolve("url/"), - "stream": require.resolve("stream-browserify"), - "crypto": require.resolve("crypto-browserify"), - "https": require.resolve("https-browserify"), - "http": require.resolve('stream-http') + cache: true, + performance: {hints: false}, + stats: 'errors-only', + entry: './dist/npm/index.js', + output: { + library: 'ripple', + path: path.join(__dirname, 'build/'), + filename: `ripple-lib.default.js` + }, + plugins: [ + new webpack.NormalModuleReplacementPlugin(/^ws$/, './wsWrapper'), + new webpack.NormalModuleReplacementPlugin(/^\.\/wallet$/, './wallet-web'), + new webpack.NormalModuleReplacementPlugin( + /^.*setup-api$/, + './setup-api-web' + ), + new webpack.ProvidePlugin({process: 'process/browser'}), + new webpack.ProvidePlugin({Buffer: ['buffer', 'Buffer']}) + ], + module: { + rules: [] + }, + resolve: { + alias: { + 'ws': './dist/npm/client/wsWrapper.js', + 'https-proxy-agent': false + }, + extensions: ['.js', '.json'], + fallback: { + buffer: require.resolve('buffer/'), + assert: require.resolve('assert/'), + url: require.resolve('url/'), + stream: require.resolve('stream-browserify'), + crypto: require.resolve('crypto-browserify'), + https: require.resolve('https-browserify'), + http: require.resolve('stream-http') + } } - }, -}; + } } function webpackForTest(testFileName) { - const match = testFileName.match(/\/?([^\/]*).ts$/); + const match = testFileName.match(/\/?([^\/]*).ts$/) if (!match) { - assert(false, 'wrong filename:' + testFileName); + assert(false, 'wrong filename:' + testFileName) } const test = { cache: true, - externals: [{ - 'lodash': '_', - 'xrpl-local': 'ripple', - 'net': 'null' - }], + externals: [ + { + 'xrpl-local': 'ripple', + 'net': 'null' + } + ], entry: testFileName, output: { library: match[1].replace(/-/g, '_'), @@ -60,64 +68,72 @@ function webpackForTest(testFileName) { filename: match[1] + '.js' }, plugins: [ - new webpack.ProvidePlugin({ process: 'process/browser' }), - new webpack.ProvidePlugin({ Buffer: ['buffer', 'Buffer'] }) + new webpack.ProvidePlugin({process: 'process/browser'}), + new webpack.ProvidePlugin({Buffer: ['buffer', 'Buffer']}) ], module: { - rules: [{ - test: /jayson/, - use: 'null', - }, { - test: /\.ts$/, - use: [{ - loader: 'ts-loader', - options: { - compilerOptions: { - composite: false, - declaration: false, - declarationMap: false + rules: [ + { + test: /jayson/, + use: 'null' + }, + { + test: /\.ts$/, + use: [ + { + loader: 'ts-loader', + options: { + compilerOptions: { + composite: false, + declaration: false, + declarationMap: false + } + } } - }, - }], - }] + ] + } + ] }, node: { global: true, __filename: false, - __dirname: true, + __dirname: true }, resolve: { - extensions: [ '.ts', '.js', '.json' ], - fallback: { - "buffer": require.resolve("buffer/"), - "assert": require.resolve("assert/"), - "url": require.resolve("url/"), - "stream": require.resolve("stream-browserify"), - "crypto": require.resolve("crypto-browserify"), - "path": require.resolve("path-browserify"), - "http": require.resolve("stream-http"), - "fs": false + alias: { + 'ws': './dist/npm/client/wsWrapper.js', + 'https-proxy-agent': false + }, + extensions: ['.ts', '.js', '.json'], + fallback: { + buffer: require.resolve('buffer/'), + assert: require.resolve('assert/'), + url: require.resolve('url/'), + stream: require.resolve('stream-browserify'), + crypto: require.resolve('crypto-browserify'), + path: require.resolve('path-browserify'), + http: require.resolve('stream-http') } } - }; - return Object.assign({}, getDefaultConfiguration(), test); + } + return Object.assign({}, getDefaultConfiguration(), test) } module.exports = [ (env, argv) => { - const config = getDefaultConfiguration(); - config.mode = 'development'; - config.output.filename = `ripple-latest.js`; - return config; + const config = getDefaultConfiguration() + config.mode = 'development' + config.output.filename = `ripple-latest.js` + return config }, (env, argv) => { - const config = getDefaultConfiguration(); - config.mode = 'production'; - config.output.filename = `ripple-latest-min.js`; + const config = getDefaultConfiguration() + config.mode = 'production' + config.output.filename = `ripple-latest-min.js` if (process.argv.includes('--analyze')) { - config.plugins.push(new BundleAnalyzerPlugin()); + config.plugins.push(new BundleAnalyzerPlugin()) } - return config; + return config }, - (env, argv) => webpackForTest('./test/integration/integration.ts'), -]; \ No newline at end of file + (env, argv) => webpackForTest('./test/integration/integration.ts') +] diff --git a/yarn.lock b/yarn.lock index 9f215d05..111b6235 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,14 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.14.5": +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/code-frame@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== @@ -155,7 +162,7 @@ "@babel/traverse" "^7.15.4" "@babel/types" "^7.15.4" -"@babel/highlight@^7.14.5": +"@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== @@ -218,6 +225,35 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.4.tgz#d8f0f394dec7be40b5113cd78088339c42ee811f" integrity sha512-8szzeplTi6qw+dbzBB/I3T5TzU9GM7AxzQkiiWdakKsCnaMlMLUMElfEhqT1S3PfdSjHBwzPUTcfWyFHdf9FaQ== +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^13.9.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf" + integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -234,6 +270,21 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== +"@microsoft/tsdoc-config@0.15.2": + version "0.15.2" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz#eb353c93f3b62ab74bdc9ab6f4a82bcf80140f14" + integrity sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA== + dependencies: + "@microsoft/tsdoc" "0.13.2" + ajv "~6.12.6" + jju "~1.4.0" + resolve "~1.19.0" + +"@microsoft/tsdoc@0.13.2": + version "0.13.2" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz#3b0efb6d3903bd49edb073696f60e90df08efb26" + integrity sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg== + "@polka/url@^1.0.0-next.20": version "1.0.0-next.20" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.20.tgz#111b5db0f501aa89b05076fa31f0ea0e0c292cd3" @@ -313,6 +364,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + "@types/lodash@^4.14.136": version "4.14.172" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.172.tgz#aad774c28e7bfd7a67de25408e03ee5a8c3d028a" @@ -338,6 +394,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a" integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ== +"@types/puppeteer@5.4.4": + version "5.4.4" + resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-5.4.4.tgz#e92abeccc4f46207c3e1b38934a1246be080ccd0" + integrity sha512-3Nau+qi69CN55VwZb0ATtdUAlYlqOOQ3OfQfq0Hqgc4JMFXiQT/XInlwQ9g6LbicDslE6loIFsXFklGh5XmI6Q== + dependencies: + "@types/node" "*" + "@types/ws@^7.2.0": version "7.4.7" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" @@ -352,49 +415,66 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^2.3.3": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz#6f8ce8a46c7dea4a6f1d171d2bb8fbae6dac2be9" - integrity sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ== +"@typescript-eslint/eslint-plugin@^3.7.0": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz#7e061338a1383f59edc204c605899f93dc2e2c8f" + integrity sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ== dependencies: - "@typescript-eslint/experimental-utils" "2.34.0" + "@typescript-eslint/experimental-utils" "3.10.1" + debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" + semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@2.34.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz#d3524b644cdb40eebceca67f8cf3e4cc9c8f980f" - integrity sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA== +"@typescript-eslint/experimental-utils@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" + integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.34.0" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/typescript-estree" "3.10.1" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^2.27.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.34.0.tgz#50252630ca319685420e9a39ca05fe185a256bc8" - integrity sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA== +"@typescript-eslint/parser@^3.7.0": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" + integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.34.0" - "@typescript-eslint/typescript-estree" "2.34.0" + "@typescript-eslint/experimental-utils" "3.10.1" + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/typescript-estree" "3.10.1" eslint-visitor-keys "^1.1.0" -"@typescript-eslint/typescript-estree@2.34.0": - version "2.34.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz#14aeb6353b39ef0732cc7f1b8285294937cf37d5" - integrity sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg== +"@typescript-eslint/types@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" + integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== + +"@typescript-eslint/typescript-estree@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" + integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== dependencies: + "@typescript-eslint/types" "3.10.1" + "@typescript-eslint/visitor-keys" "3.10.1" debug "^4.1.1" - eslint-visitor-keys "^1.1.0" glob "^7.1.6" is-glob "^4.0.1" lodash "^4.17.15" semver "^7.3.2" tsutils "^3.17.1" +"@typescript-eslint/visitor-keys@3.10.1": + version "3.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" + integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== + dependencies: + eslint-visitor-keys "^1.1.0" + "@ungap/promise-all-settled@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" @@ -538,6 +618,15 @@ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.5.2.tgz#ea584b637ff63c5a477f6f21604b5a205b72c9ec" integrity sha512-vgJ5OLWadI8aKjDlOH3rb+dYyPd2GTZuQC/Tihjct6F9GpXGZINo3Y/IVuZVTM1eDQB+/AOsjPUWH/WySDaXvw== +"@xrplf/eslint-config@^1.1.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@xrplf/eslint-config/-/eslint-config-1.3.0.tgz#c20cb12f72d549157e2c5563bf2bd464be7720e5" + integrity sha512-Zk3ZgzHxj8vozA87LF6Gv4B9v8KXH51Q4oW2sG4fCFHsqiSWVG+n4ZPr7DhTqPNhaxV21yL3OqsT7G6FgD1wXg== + dependencies: + confusing-browser-globals "^1.0.9" + eslint-config-airbnb "^18.2.1" + eslint-config-prettier "8.3.0" + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -553,7 +642,7 @@ acorn-import-assertions@^1.7.6: resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.7.6.tgz#580e3ffcae6770eebeec76c3b9723201e9d01f78" integrity sha512-FlVvVFA1TX6l3lp8VjDnYYq7R1nyW6x3svAt4nDgrWQ9SBaSh9CnbwgSUTasgfNfOG5HlM1ehugCvM+hjo56LA== -acorn-jsx@^5.2.0: +acorn-jsx@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== @@ -563,7 +652,7 @@ acorn-walk@^8.0.0, acorn-walk@^8.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^7.1.1: +acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== @@ -593,7 +682,7 @@ ajv-keywords@^3.5.2: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.5: +ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5, ajv@~6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -603,6 +692,16 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.0.1: + version "8.6.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.3.tgz#11a66527761dc3e9a3845ea775d2d3c0414e8764" + integrity sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + anchor-markdown-header@~0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/anchor-markdown-header/-/anchor-markdown-header-0.5.7.tgz#045063d76e6a1f9cd327a57a0126aa0fdec371a7" @@ -610,34 +709,22 @@ anchor-markdown-header@~0.5.7: dependencies: emoji-regex "~6.1.0" -ansi-colors@4.1.1: +ansi-colors@4.1.1, ansi-colors@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - ansi-regex@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -688,6 +775,26 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +array-includes@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.3.tgz#c7f619b382ad2afaf5326cddfdc0afc61af7690a" + integrity sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.2" + get-intrinsic "^1.1.1" + is-string "^1.0.5" + +array.prototype.flat@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" + integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + asn1.js@^5.2.0: version "5.4.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" @@ -726,10 +833,10 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== async@0.9.x: version "0.9.2" @@ -1032,7 +1139,7 @@ chai@^4.3.4: pathval "^1.1.1" type-detect "^4.0.5" -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1041,7 +1148,7 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1064,11 +1171,6 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" @@ -1119,18 +1221,6 @@ cli-color@~0.1.6: dependencies: es5-ext "0.8.x" -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== - cliui@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" @@ -1207,6 +1297,11 @@ commander@^7.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== +comment-parser@^0.7.5: + version "0.7.6" + resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.7.6.tgz#0e743a53c8e646c899a1323db31f6cd337b10f12" + integrity sha512-GKNxVA7/iuTnAqGADlTWX4tkhzxZKXp5fLJqKTlQLHkE65XDUKutZ3BHaJC5IGcper2tT3QRD1xr4o3jNpgXXg== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -1217,6 +1312,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +confusing-browser-globals@^1.0.10, confusing-browser-globals@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz#30d1e7f3d1b882b25ec4933d1d1adac353d20a59" + integrity sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA== + convert-source-map@^1.7.0: version "1.8.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" @@ -1260,18 +1360,7 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^7.0.0, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -1311,6 +1400,20 @@ debug@4.3.1: dependencies: ms "2.1.2" +debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1333,7 +1436,7 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" -deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -1403,6 +1506,13 @@ doctoc@^2.0.0: underscore "~1.12.1" update-section "~0.3.3" +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -1484,11 +1594,6 @@ elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -1514,6 +1619,13 @@ enhanced-resolve@^5.0.0, enhanced-resolve@^5.8.0: graceful-fs "^4.2.4" tapable "^2.2.0" +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" @@ -1524,7 +1636,14 @@ envinfo@^7.7.3: resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== -es-abstract@^1.18.5: +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2, es-abstract@^1.18.5: version "1.18.6" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.6.tgz#2c44e3ea7a6255039164d26559777a6d978cb456" integrity sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ== @@ -1582,7 +1701,7 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@4.0.0: +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== @@ -1592,7 +1711,136 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -eslint-scope@5.1.1, eslint-scope@^5.0.0: +eslint-config-airbnb-base@^14.2.1: + version "14.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz#8a2eb38455dc5a312550193b319cdaeef042cd1e" + integrity sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA== + dependencies: + confusing-browser-globals "^1.0.10" + object.assign "^4.1.2" + object.entries "^1.1.2" + +eslint-config-airbnb@^18.2.1: + version "18.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-18.2.1.tgz#b7fe2b42f9f8173e825b73c8014b592e449c98d9" + integrity sha512-glZNDEZ36VdlZWoxn/bUR1r/sdFKPd1mHPbqUtkctgNG4yT2DLLtJ3D+yCV+jzZCc2V1nBVkmdknOJBZ5Hc0fg== + dependencies: + eslint-config-airbnb-base "^14.2.1" + object.assign "^4.1.2" + object.entries "^1.1.2" + +eslint-config-prettier@8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" + integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew== + +eslint-import-resolver-node@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" + integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== + dependencies: + debug "^3.2.7" + resolve "^1.20.0" + +eslint-module-utils@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz#94e5540dd15fe1522e8ffa3ec8db3b7fa7e7a534" + integrity sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q== + dependencies: + debug "^3.2.7" + pkg-dir "^2.0.0" + +eslint-plugin-array-func@^3.1.7: + version "3.1.7" + resolved "https://registry.yarnpkg.com/eslint-plugin-array-func/-/eslint-plugin-array-func-3.1.7.tgz#c47ce735eed2d9cb4129984d514898df4e0393ba" + integrity sha512-fB5TBICjHSTGToNTbCCgR8zsngpUkoCM31EMh/M/NEAyNg90i5rUuG0dnNNBML2n0BzM0nBE3sPvo2SEWf6jlA== + +eslint-plugin-es@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" + integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + +eslint-plugin-eslint-comments@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz#9e1cd7b4413526abb313933071d7aba05ca12ffa" + integrity sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ== + dependencies: + escape-string-regexp "^1.0.5" + ignore "^5.0.5" + +eslint-plugin-import@^2.24.1: + version "2.24.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz#2c8cd2e341f3885918ee27d18479910ade7bb4da" + integrity sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q== + dependencies: + array-includes "^3.1.3" + array.prototype.flat "^1.2.4" + debug "^2.6.9" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.6" + eslint-module-utils "^2.6.2" + find-up "^2.0.0" + has "^1.0.3" + is-core-module "^2.6.0" + minimatch "^3.0.4" + object.values "^1.1.4" + pkg-up "^2.0.0" + read-pkg-up "^3.0.0" + resolve "^1.20.0" + tsconfig-paths "^3.11.0" + +eslint-plugin-jsdoc@^29.0.0: + version "29.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-29.2.0.tgz#40b1da463847750fe5aafea7182145c4108e0ab7" + integrity sha512-B1a8LWPkkxyxIp4y3pnRQR18j03Wp+V9gDE7IjQG/MvWAzp5gqXM0q71gXRAZMvWUjujAsNg8B9v1csl+/zkvw== + dependencies: + comment-parser "^0.7.5" + debug "^4.1.1" + jsdoctypeparser "^8.0.0" + lodash "^4.17.15" + regextras "^0.7.1" + semver "^7.3.2" + spdx-expression-parse "^3.0.1" + +eslint-plugin-mocha@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-9.0.0.tgz#b4457d066941eecb070dc06ed301c527d9c61b60" + integrity sha512-d7knAcQj1jPCzZf3caeBIn3BnW6ikcvfz0kSqQpwPYcVGLoJV5sz0l0OJB2LR8I7dvTDbqq1oV6ylhSgzA10zg== + dependencies: + eslint-utils "^3.0.0" + ramda "^0.27.1" + +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + +eslint-plugin-prettier@^3.4.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" + integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-tsdoc@^0.2.14: + version "0.2.14" + resolved "https://registry.yarnpkg.com/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.14.tgz#e32e7c1df8af7b3009c252590bec07a1030afbf2" + integrity sha512-fJ3fnZRsdIoBZgzkQjv8vAj6NeeOoFkTfgosj6mKsFjX70QV256sA/wq+y/R2+OL4L8E79VVaVWrPeZnKNe8Ng== + dependencies: + "@microsoft/tsdoc" "0.13.2" + "@microsoft/tsdoc-config" "0.15.2" + +eslint-scope@5.1.1, eslint-scope@^5.0.0, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -1600,83 +1848,91 @@ eslint-scope@5.1.1, eslint-scope@^5.0.0: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-utils@^2.0.0: +eslint-utils@^2.0.0, eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.1.0: +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint@^6.5.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint@^7.5.0: + version "7.32.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" + integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== dependencies: - "@babel/code-frame" "^7.0.0" + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" + chalk "^4.0.0" + cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" + enquirer "^2.3.5" + escape-string-regexp "^4.0.0" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.4.0" esutils "^2.0.2" - file-entry-cache "^5.0.1" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" + glob-parent "^5.1.2" + globals "^13.6.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^7.0.0" is-glob "^4.0.0" js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" + levn "^0.4.1" + lodash.merge "^4.6.2" minimatch "^3.0.4" - mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.3" + optionator "^0.9.1" progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" - table "^5.2.3" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.9" text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^6.1.2: - version "6.2.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" - integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== dependencies: - acorn "^7.1.1" - acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.1.0" + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: +esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== @@ -1743,15 +1999,6 @@ extend@^3.0.0: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - extract-zip@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" @@ -1763,17 +2010,22 @@ extract-zip@2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" -fast-deep-equal@^3.1.1: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= @@ -1797,19 +2049,12 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" -figures@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" + flat-cache "^3.0.4" file-uri-to-path@1.0.0: version "1.0.0" @@ -1847,6 +2092,13 @@ find-up@5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -1855,24 +2107,23 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" + flatted "^3.1.0" + rimraf "^3.0.2" flat@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== +flatted@^3.1.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" + integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== foreach@^2.0.5: version "2.0.5" @@ -1971,7 +2222,7 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -glob-parent@^5.0.0, glob-parent@~5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -2000,12 +2251,12 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^12.1.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" - integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== +globals@^13.6.0, globals@^13.9.0: + version "13.11.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.11.0.tgz#40ef678da117fe7bd2e28f1fab24951bd0255be7" + integrity sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g== dependencies: - type-fest "^0.8.1" + type-fest "^0.20.2" graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.2.4: version "4.2.8" @@ -2102,6 +2353,11 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -2135,13 +2391,6 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -2152,7 +2401,12 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -import-fresh@^3.0.0: +ignore@^5.0.5, ignore@^5.1.1: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + +import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -2191,25 +2445,6 @@ inherits@2, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inquirer@^7.0.0: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" - integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.19" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.6.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -2245,6 +2480,11 @@ is-arguments@^1.0.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -2277,7 +2517,7 @@ is-callable@^1.1.4, is-callable@^1.2.4: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== -is-core-module@^2.2.0: +is-core-module@^2.1.0, is-core-module@^2.2.0, is-core-module@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" integrity sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ== @@ -2525,6 +2765,11 @@ jest-worker@^27.0.6: merge-stream "^2.0.0" supports-color "^8.0.0" +jju@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" + integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo= + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -2545,6 +2790,11 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +jsdoctypeparser@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/jsdoctypeparser/-/jsdoctypeparser-8.0.0.tgz#a04a944539d3f86e30040c1ece6f6730f865f81a" + integrity sha512-eLCs6s4JqN8TjFJfgdiLHRvogLhOAJz+5RIA2FtoMe6ZDyuvghvppnlIToqAEnVbxRqLMrfnNXpW8FpmR6IMBw== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -2559,7 +2809,7 @@ json-diff@0.5.4: difflib "~0.2.1" dreamopt "~0.6.0" -json-parse-better-errors@^1.0.2: +json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== @@ -2574,11 +2824,23 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + json5@^2.1.2: version "2.2.0" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" @@ -2596,19 +2858,37 @@ kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" + prelude-ls "^1.2.1" + type-check "~0.4.0" + +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" loader-runner@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -2623,12 +2903,27 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + lodash.flattendeep@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= -lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4: +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= + +lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -2734,7 +3029,7 @@ minimatch@3.0.4, minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@^1.2.5, minimist@~1.2.5: +minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -2777,21 +3072,21 @@ mocha@^9: yargs-parser "20.2.4" yargs-unparser "2.0.0" +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3: +ms@2.1.3, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - nan@^2.13.2: version "2.15.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" @@ -2812,11 +3107,6 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - node-fetch@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" @@ -2834,6 +3124,16 @@ node-releases@^1.1.75: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.75.tgz#6dd8c876b9897a1b8e5a02de26afa79bb54ebbfe" integrity sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw== +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -2907,6 +3207,24 @@ object.assign@^4.1.2: has-symbols "^1.0.1" object-keys "^1.1.1" +object.entries@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.4.tgz#43ccf9a50bc5fd5b649d45ab1a579f24e088cafd" + integrity sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.18.2" + +object.values@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30" + integrity sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.18.2" + once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -2914,7 +3232,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0, onetime@^5.1.2: +onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -2926,22 +3244,24 @@ opener@^1.5.2: resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== -optionator@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" p-limit@^2.2.0: version "2.3.0" @@ -2957,6 +3277,13 @@ p-limit@^3.0.2, p-limit@^3.1.0: dependencies: yocto-queue "^0.1.0" +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + p-locate@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" @@ -2978,6 +3305,11 @@ p-map@^3.0.0: dependencies: aggregate-error "^3.0.0" +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -3023,11 +3355,24 @@ parse-entities@^1.1.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + path-browserify@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -3038,11 +3383,6 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -3053,6 +3393,13 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + pathval@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" @@ -3079,6 +3426,11 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + pkg-dir@4.2.0, pkg-dir@^4.1.0, pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -3086,12 +3438,33 @@ pkg-dir@4.2.0, pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" -prettier@^2.0.5: +pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" + integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= + dependencies: + find-up "^2.1.0" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^2.3.2: version "2.4.0" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.4.0.tgz#85bdfe0f70c3e777cf13a4ffff39713ca6f64cba" integrity sha512-DsEPLY1dE5HF3BxCRBmD4uYZ+5DCbvatnolqTqcxEgKVZnL2kUfyu7b8pPQ5+hTBkdhU9SLUmK0/pHb07RE4WQ== @@ -3176,6 +3549,11 @@ querystring@0.2.0: resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= +ramda@^0.27.1: + version "0.27.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9" + integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw== + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -3191,6 +3569,23 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" +read-pkg-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" + integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= + dependencies: + find-up "^2.0.0" + read-pkg "^3.0.0" + +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= + dependencies: + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" + readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -3214,16 +3609,16 @@ rechoir@^0.7.0: dependencies: resolve "^1.9.0" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -regexpp@^3.0.0: +regexpp@^3.0.0, regexpp@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== +regextras@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/regextras/-/regextras-0.7.1.tgz#be95719d5f43f9ef0b9fa07ad89b7c606995a3b2" + integrity sha512-9YXf6xtW+qzQ+hcMQXx95MOvfqXFgsKDZodX3qZB0x2n5Z94ioetIITsBtvJbiOyxa/6s9AtyweBLCdPmPko/w== + release-zalgo@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" @@ -3275,6 +3670,11 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" @@ -3297,7 +3697,7 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve@^1.9.0: +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.20.0, resolve@^1.9.0: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -3305,22 +3705,15 @@ resolve@^1.9.0: is-core-module "^2.2.0" path-parse "^1.0.6" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== +resolve@~1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" + is-core-module "^2.1.0" + path-parse "^1.0.6" -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rimraf@3.0.2, rimraf@^3.0.0: +rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -3374,18 +3767,6 @@ ripple-lib-transactionparser@0.8.2: bignumber.js "^9.0.0" lodash "^4.17.15" -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - -rxjs@^6.6.0: - version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" - integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== - dependencies: - tslib "^1.9.0" - safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -3396,7 +3777,7 @@ safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0: +safer-buffer@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -3410,17 +3791,17 @@ schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" -semver@^5.5.0: +"semver@2 || 3 || 4 || 5": version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.3.2, semver@^7.3.4: +semver@^7.2.1, semver@^7.3.2, semver@^7.3.4: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -3454,13 +3835,6 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -3468,11 +3842,6 @@ shebang-command@^2.0.0: dependencies: shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - shebang-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" @@ -3501,14 +3870,14 @@ sirv@^1.0.7: mime "^2.3.1" totalist "^1.0.0" -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" source-map-support@~0.5.20: version "0.5.20" @@ -3545,6 +3914,32 @@ spawn-wrap@^2.0.0: signal-exit "^3.0.2" which "^2.0.1" +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0, spdx-expression-parse@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.10" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz#0d9becccde7003d6c658d487dd48a32f0bf3014b" + integrity sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -3581,15 +3976,6 @@ stream-http@3.2.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - string-width@^4.1.0, string-width@^4.2.0: version "4.2.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" @@ -3629,13 +4015,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -3643,6 +4022,11 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + strip-bom@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" @@ -3653,7 +4037,7 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-json-comments@3.1.1, strip-json-comments@^3.0.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -3686,15 +4070,17 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== +table@^6.0.9: + version "6.7.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" + integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" + ajv "^8.0.1" + lodash.clonedeep "^4.5.0" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.0" + strip-ansi "^6.0.0" tapable@^2.1.1, tapable@^2.2.0: version "2.2.1" @@ -3757,7 +4143,7 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -through@^2.3.6, through@^2.3.8: +through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -3773,13 +4159,6 @@ tiny-secp256k1@^1.1.3: elliptic "^6.4.0" nan "^2.13.2" -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -3845,7 +4224,17 @@ ts-node@^10.1.0: make-error "^1.1.1" yn "3.1.1" -tslib@^1.8.1, tslib@^1.9.0: +tsconfig-paths@^3.11.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz#954c1fe973da6339c78e06b03ce2e48810b65f36" + integrity sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + +tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -3857,24 +4246,24 @@ tsutils@^3.17.1: dependencies: tslib "^1.8.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: - prelude-ls "~1.1.2" + prelude-ls "^1.2.1" type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -type-fest@^0.8.0, type-fest@^0.8.1: +type-fest@^0.8.0: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== @@ -3891,7 +4280,7 @@ typeforce@^1.11.5: resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc" integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g== -typescript@^3.9.9: +typescript@^3.9.10: version "3.9.10" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== @@ -4017,6 +4406,14 @@ v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + vfile-location@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.6.tgz#8a274f39411b8719ea5728802e10d9e0dff1519e" @@ -4159,13 +4556,6 @@ which@2.0.2, which@^2.0.1: dependencies: isexe "^2.0.0" -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - wide-align@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" @@ -4185,7 +4575,7 @@ wildcard@^2.0.0: resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== -word-wrap@~1.2.3: +word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== @@ -4233,13 +4623,6 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - ws@7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"