diff --git a/.circleci/config.yml b/.circleci/config.yml index 59ad88eeaa..d3cec40e5f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -29,7 +29,7 @@ jobs: - checkout - run: name: 'Yarn install' - command: 'yarn install' + command: 'yarn install --frozen-lockfile' - persist_to_workspace: root: *working_directory paths: . @@ -58,8 +58,8 @@ jobs: name: 'Lint request-client.js' command: 'yarn workspace @requestnetwork/request-client.js run lint ' - run: - name: 'Deploy test contract from ethereum-storage' - command: 'yarn workspace @requestnetwork/ethereum-storage run deploy' + name: 'Deploy test contracts from smart-contracts' + command: 'yarn workspace @requestnetwork/smart-contracts run deploy' - run: name: 'Test request-client.js' command: 'yarn workspace @requestnetwork/request-client.js run test' @@ -138,29 +138,46 @@ jobs: at: *working_directory - run: name: 'Build ethereum-storage' - command: 'yarn workspace @requestnetwork/ethereum-storage run build:lib' + command: 'yarn workspace @requestnetwork/ethereum-storage run build' - run: name: 'Lint ethereum-storage' - command: 'yarn workspace @requestnetwork/ethereum-storage run lint:lib' + command: 'yarn workspace @requestnetwork/ethereum-storage run lint' - run: - name: 'Deploy contracs ethereum-storage' - command: 'yarn workspace @requestnetwork/ethereum-storage run deploy' + name: 'Deploy contracs smart-contracts' + command: 'yarn workspace @requestnetwork/smart-contracts run deploy' - run: name: 'Test ethereum-storage' - command: 'yarn workspace @requestnetwork/ethereum-storage run test:lib' - - run: - name: 'Build smart contracts ethereum-storage' - command: 'yarn workspace @requestnetwork/ethereum-storage run build:sol' - - run: - name: 'Lint smart contracts ethereum-storage' - command: 'yarn workspace @requestnetwork/ethereum-storage run lint:sol' - - run: - name: 'Test smart contracts ethereum-storage' - command: 'yarn workspace @requestnetwork/ethereum-storage run test:sol' + command: 'yarn workspace @requestnetwork/ethereum-storage run test' - persist_to_workspace: root: *working_directory paths: - packages/ethereum-storage/coverage/ + test-smart-contracts: + docker: + - *node_image + - *ganache_image + working_directory: *working_directory + steps: + - attach_workspace: + at: *working_directory + - run: + name: 'Build smart-contracts' + command: 'yarn workspace @requestnetwork/smart-contracts run build:lib' + - run: + name: 'Lint smart-contracts' + command: 'yarn workspace @requestnetwork/smart-contracts run lint:lib' + - run: + name: 'Deploy contracs smart-contracts' + command: 'yarn workspace @requestnetwork/smart-contracts run deploy' + - run: + name: 'Build smart contracts smart-contracts' + command: 'yarn workspace @requestnetwork/smart-contracts run build:sol' + - run: + name: 'Lint smart contracts smart-contracts' + command: 'yarn workspace @requestnetwork/smart-contracts run lint:sol' + - run: + name: 'Test smart contracts smart-contracts' + command: 'yarn workspace @requestnetwork/smart-contracts run test' test-request-logic: docker: - *node_image @@ -217,8 +234,8 @@ jobs: name: 'Lint request-node' command: 'yarn workspace @requestnetwork/request-node run lint' - run: - name: 'Deploy test contract from ethereum-storage' - command: 'yarn workspace @requestnetwork/ethereum-storage run deploy' + name: 'Deploy test contract from smart-contracts' + command: 'yarn workspace @requestnetwork/smart-contracts run deploy' - run: name: 'Test request-node' command: 'yarn workspace @requestnetwork/request-node run test' @@ -335,8 +352,8 @@ jobs: name: 'Lint integration-test' command: 'yarn workspace @requestnetwork/integration-test run lint' - run: - name: 'Deploy test contract from ethereum-storage' - command: 'yarn workspace @requestnetwork/ethereum-storage run deploy' + name: 'Deploy test contract from smart-contracts' + command: 'yarn workspace @requestnetwork/smart-contracts run deploy' - run: name: 'Start request-node' command: 'yarn workspace @requestnetwork/request-node run start' @@ -450,7 +467,6 @@ jobs: name: 'Build prototype-estimator' command: 'yarn workspace @requestnetwork/prototype-estimator run build' test-nightly: - test-integration-test: docker: - *node_image - *ipfs_image @@ -466,8 +482,8 @@ jobs: name: 'Lint integration-test' command: 'yarn workspace @requestnetwork/integration-test run lint' - run: - name: 'Deploy test contract from ethereum-storage' - command: 'yarn workspace @requestnetwork/ethereum-storage run deploy' + name: 'Deploy test contract from smart-contracts' + command: 'yarn workspace @requestnetwork/smart-contracts run deploy' - run: name: 'Start request-node' command: 'yarn workspace @requestnetwork/request-node run start' @@ -486,6 +502,21 @@ jobs: name: 'Test integration-test' command: 'yarn workspace @requestnetwork/integration-test run test:scheduled' + # Release a next version package everytime we merge to master + next-release: + docker: + - *node_image + working_directory: *working_directory + steps: + - attach_workspace: + at: *working_directory + - run: + name: 'Authenticate with registry' + command: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/repo/.npmrc + - run: + name: 'publish' + command: '$(yarn bin)/lerna publish --conventional-commits --exact --canary --no-git-tag-version --no-push --preid next --dist-tag next --yes' + workflows: version: 2 push-request-network-image: @@ -513,6 +544,9 @@ workflows: - test-ethereum-storage: requires: - build + - test-smart-contracts: + requires: + - build - test-request-logic: requires: - build @@ -570,6 +604,30 @@ workflows: - test-utils - test-multi-format + # Release a next version package everytime we merge to master + - next-release: + requires: + - test-advanced-logic + - test-data-access + - test-data-format + - test-epk-decryption + - test-epk-signature + - test-ethereum-storage + - test-smart-contracts + - test-multi-format + - test-request-client + - test-request-logic + - test-request-node + - test-transaction-manager + - test-types + - test-utils + - test-web3-signature + context: protocol-release + filters: + branches: + only: + - master + nightly: triggers: - schedule: @@ -579,7 +637,6 @@ workflows: branches: only: - master - - development jobs: - build - lint-package-json: diff --git a/.eslintrc b/.eslintrc index d6ebd857d4..f56fb8e2a7 100644 --- a/.eslintrc +++ b/.eslintrc @@ -57,6 +57,7 @@ "ethers", "etherchain", "ethereum", + "etherscan", "ethgasstation", "fau", "fetchable", diff --git a/.gitignore b/.gitignore index 82a9098656..ef92ee3c9e 100644 --- a/.gitignore +++ b/.gitignore @@ -11,12 +11,6 @@ coverage .nyc_output coverage.lcov -# IDE - VSCode -.vscode/* -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json - # logs lerna-debug.log yarn-error.log diff --git a/.vscode/launch.json b/.vscode/launch.json index 5ccf563269..64099ab9d1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -23,7 +23,7 @@ "--no-timeouts", "--require", "ts-node/register", - "${workspaceFolder}/packages/request-client.js/test/*.test.ts", + "${workspaceFolder}/packages/request-client.js/test/index.test.ts", "--colors" ], "cwd": "${workspaceFolder}/packages/request-client.js/", diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..0e7c85fa6e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.files": "**/test/**/*.test.ts", + "mochaExplorer.cwd": "./" +} \ No newline at end of file diff --git a/README.md b/README.md index cf0d67f643..8af9f2db3a 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,9 @@ --- -[![CircleCI](https://img.shields.io/circleci/project/github/RequestNetwork/requestNetwork/development.svg)](https://circleci.com/gh/RequestNetwork/requestNetwork) -[![Codecov](https://codecov.io/gh/RequestNetwork/requestNetwork/branch/master/graph/badge.svg)](https://codecov.io/gh/RequestNetwork/requestNetwork) +[![CircleCI](https://img.shields.io/circleci/project/github/RequestNetwork/requestNetwork/master.svg)](https://circleci.com/gh/RequestNetwork/requestNetwork) +[![Coverage Status](https://coveralls.io/repos/github/RequestNetwork/requestNetwork/badge.svg?branch=master)](https://coveralls.io/github/RequestNetwork/requestNetwork?branch=master) [![Commit Activity](https://img.shields.io/github.amrom.workers.devmit-activity/m/RequestNetwork/requestNetwork.svg?color=green)](https://github.com/RequestNetwork/requestNetwork/pulse/monthly) -[![pullreminders](https://pullreminders.com/badge.svg)](https://pullreminders.com?ref=badge) [Request][website-url] is a decentralized network built on top of Ethereum, which allows anyone, anywhere to request a payment. A full description of the protocol may be found in our [whitepaper][whitepaper-url]. diff --git a/package.json b/package.json index ec6a308559..ced33ee358 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "scripts": { "build": "lerna run build", "clean": "lerna run clean", - "build:tsc": "tsc -b packages/advanced-logic packages/data-access packages/data-format packages/epk-decryption packages/epk-signature packages/ethereum-storage packages/integration-test packages/prototype-estimator packages/request-client.js packages/request-logic packages/request-node packages/toolbox packages/transaction-manager packages/types packages/usage-examples packages/utils packages/web3-signature packages/multi-format", + "build:tsc": "tsc -b packages/advanced-logic packages/data-access packages/data-format packages/epk-decryption packages/epk-signature packages/ethereum-storage packages/integration-test packages/multi-format packages/prototype-estimator packages/request-client.js packages/request-logic packages/request-node packages/smart-contracts packages/toolbox packages/transaction-manager packages/types packages/usage-examples packages/utils packages/web3-signature", "lint": "lerna run lint", "lint-staged": "lerna run lint-staged", "lerna": "lerna", diff --git a/packages/advanced-logic/.vscode/settings.json b/packages/advanced-logic/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/advanced-logic/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/advanced-logic/CHANGELOG.md b/packages/advanced-logic/CHANGELOG.md index c48598bdff..96a209f651 100644 --- a/packages/advanced-logic/CHANGELOG.md +++ b/packages/advanced-logic/CHANGELOG.md @@ -3,6 +3,71 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.9.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/advanced-logic@0.6.0...@requestnetwork/advanced-logic@0.9.0) (2020-01-16) + + +### Bug Fixes + +* use lowercase for payment reference ([#83](https://github.com/RequestNetwork/requestNetwork/issues/83)) ([6cbedeb](https://github.com/RequestNetwork/requestNetwork/commit/6cbedeb4d2e130d7ece1ba526cea9c17d6e545e0)) + + +### Features + +* **advanced-logic:** add ERC20 proxy contract payment network ([#74](https://github.com/RequestNetwork/requestNetwork/issues/74)) ([031a374](https://github.com/RequestNetwork/requestNetwork/commit/031a3742d2dddc0324e75b7853287d252bf43c6c)) +* deploy ERC20 proxy smart contract to mainnet ([#97](https://github.com/RequestNetwork/requestNetwork/issues/97)) ([84a7d2a](https://github.com/RequestNetwork/requestNetwork/commit/84a7d2ae9c06a3c6e457c8583e44e8df01676b2a)) +* deploy ERC20 proxy smart contract to Rinkeby ([#95](https://github.com/RequestNetwork/requestNetwork/issues/95)) ([39e6a6a](https://github.com/RequestNetwork/requestNetwork/commit/39e6a6a0ea62fd4ee9e6343d03770711638b698b)) + + + +# 0.10.0 (2019-12-04) + + +### Features + +* ETH payment detection in request-client.js ([#626](https://github.com/RequestNetwork/requestNetwork/issues/626)) ([dc3b238](https://github.com/RequestNetwork/requestNetwork/commit/dc3b23827cff7d5466c27d5575515887c461c3b4)) + + + + + +# [0.8.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/advanced-logic@0.6.0...@requestnetwork/advanced-logic@0.8.0) (2019-12-18) + + +### Bug Fixes + +* use lowercase for payment reference ([#83](https://github.com/RequestNetwork/requestNetwork/issues/83)) ([6cbedeb](https://github.com/RequestNetwork/requestNetwork/commit/6cbedeb4d2e130d7ece1ba526cea9c17d6e545e0)) + + +### Features + +* **advanced-logic:** add ERC20 proxy contract payment network ([#74](https://github.com/RequestNetwork/requestNetwork/issues/74)) ([031a374](https://github.com/RequestNetwork/requestNetwork/commit/031a3742d2dddc0324e75b7853287d252bf43c6c)) +* deploy ERC20 proxy smart contract to mainnet ([#97](https://github.com/RequestNetwork/requestNetwork/issues/97)) ([84a7d2a](https://github.com/RequestNetwork/requestNetwork/commit/84a7d2ae9c06a3c6e457c8583e44e8df01676b2a)) +* deploy ERC20 proxy smart contract to Rinkeby ([#95](https://github.com/RequestNetwork/requestNetwork/issues/95)) ([39e6a6a](https://github.com/RequestNetwork/requestNetwork/commit/39e6a6a0ea62fd4ee9e6343d03770711638b698b)) + + + +# 0.10.0 (2019-12-04) + + +### Features + +* ETH payment detection in request-client.js ([#626](https://github.com/RequestNetwork/requestNetwork/issues/626)) ([dc3b238](https://github.com/RequestNetwork/requestNetwork/commit/dc3b23827cff7d5466c27d5575515887c461c3b4)) + + + + + +# [0.7.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/advanced-logic@0.6.0...@requestnetwork/advanced-logic@0.7.0) (2019-12-04) + + +### Features + +* ETH payment detection in request-client.js ([#626](https://github.com/RequestNetwork/requestNetwork/issues/626)) ([dc3b238](https://github.com/RequestNetwork/requestNetwork/commit/dc3b23827cff7d5466c27d5575515887c461c3b4)) + + + + + # [0.6.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/advanced-logic@0.5.0...@requestnetwork/advanced-logic@0.6.0) (2019-11-20) diff --git a/packages/advanced-logic/package.json b/packages/advanced-logic/package.json index 9556b72413..c52040eb61 100644 --- a/packages/advanced-logic/package.json +++ b/packages/advanced-logic/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/advanced-logic", - "version": "0.6.0", + "version": "0.9.0", "publishConfig": { "access": "public" }, @@ -32,30 +32,30 @@ ], "scripts": { "build": "tsc -b", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", "stryker": "stryker run", - "test": "nyc mocha --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", - "test:watch": "nyc mocha --watch --watch-extensions ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"" + "test": "nyc mocha --extension ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", + "test:watch": "yarn test --watch" }, "dependencies": { - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0", + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0", "@types/node": "11.9.0", "lodash": "4.17.13", "wallet-address-validator": "0.2.4" }, "devDependencies": { - "@stryker-mutator/core": "2.1.0", + "@stryker-mutator/core": "2.4.0", "@stryker-mutator/html-reporter": "2.1.0", "@stryker-mutator/mocha-framework": "2.1.0", "@stryker-mutator/mocha-runner": "2.1.0", - "@stryker-mutator/typescript": "2.1.0", + "@stryker-mutator/typescript": "2.3.0", "@types/chai": "4.1.7", "@types/chai-spies": "1.0.0", "@types/lodash": "4.14.120", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", "@typescript-eslint/parser": "1.2.0", "chai": "4.2.0", "chai-spies": "1.0.0", @@ -63,7 +63,7 @@ "eslint-plugin-spellcheck": "0.0.11", "eslint-plugin-typescript": "0.14.0", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "nyc": "13.2.0", "prettier": "1.16.4", "shx": "0.3.2", diff --git a/packages/advanced-logic/specs/payment-network-btc-address-based-0.1.0-DRAFT.md b/packages/advanced-logic/specs/payment-network-btc-address-based-0.1.0-DRAFT.md index ed6b6e7883..31989415a5 100644 --- a/packages/advanced-logic/specs/payment-network-btc-address-based-0.1.0-DRAFT.md +++ b/packages/advanced-logic/specs/payment-network-btc-address-based-0.1.0-DRAFT.md @@ -50,7 +50,7 @@ Note: to use the bitcoin testnet just replace the id by "pn-testnet-bitcoin-addr This action is valid, if: -- The request `currency` must be "BTC" +- The request `currency.type` must be "BTC" #### Warnings diff --git a/packages/advanced-logic/specs/payment-network-erc20-proxy-contract-0.1.0-DRAFT.md b/packages/advanced-logic/specs/payment-network-erc20-proxy-contract-0.1.0-DRAFT.md new file mode 100644 index 0000000000..06621d73fa --- /dev/null +++ b/packages/advanced-logic/specs/payment-network-erc20-proxy-contract-0.1.0-DRAFT.md @@ -0,0 +1,223 @@ +# Payment Network - ERC20 - proxy contract + +You may be interested in this document if: + +- you want to create your own implementation of the Request protocol +- you are curious enough to dive and see what is under the hood of the Request protocol + +Prerequisite: Having read the advanced logic specification (see [here](./advanced-logic-specs-0.1.0-DRAFT.md)). + +## Description + +This extension allows the payments and the refunds to be made in ERC20 tokens on the Ethereum blockchain. +The payment is made through a proxy contract. This proxy contract does the ERC20 token transfer on behalf of +the user. The contract ensures a link between an ERC20 transfer and a request through a `paymentReference`. +This `paymentReference` consists of the last 8 bytes of a salted hash of the requestId: `last8Bytes(hash(lowercase(requestId + salt + address)))`: + +- `requestId` is the id of the request +- `salt` is a random number with at least 8 bytes of randomness. It must be unique to each request +- `address` is the payment address for payments, the refund address for refunds +- `lowercase()` transforms all characters to lowercase +- `hash()` is a keccak256 hash function +- `last8Bytes()` take the last 8 bytes + +As a payment network, this extension allows to deduce a payment `balance` for the request. (see +[Interpretation](#Interpretation)) + +## Contract + +The contract contains one function called `transferFromWithReference` which takes 4 arguments: + +- `tokenAddress` is the address of the ERC20 contract +- `to` is the destination address for the tokens +- `amount` is the amount of tokens +- `paymentReference` is the reference data used to track the transfer (see `paymentReference`) + +The `TransferWithReference` event is emitted when the tokens are transfered. This event contains the same 4 arguments as the `transferFromWithReference` function. + +[See smart contract source](https://github.com/RequestNetwork/requestNetwork/blob/master/packages/smart-contracts/src/contracts/ERC20Proxy.sol) + +| Network | Contract Address | +|---------|--------------------------------------------| +| Mainnet | 0x5f821c20947ff9be22e823edc5b3c709b33121b3 | +| Rinkeby | 0x162edb802fae75b9ee4288345735008ba51a4ec9 | + +## Properties + +| Property | Type | Description | Requirement | +| ------------------------- | ------ | ---------------------------------------------- | ------------- | +| **id** | String | constant value: "pn-erc20-proxy-contract" | **Mandatory** | +| **type** | String | constant value: "paymentNetwork" | **Mandatory** | +| **version** | String | constant value: "0.1.0" | **Mandatory** | +| **events** | Array | List of the actions performed by the extension | **Mandatory** | +| **values** | Object | | | +| **values.salt** | String | Salt for the request | **Mandatory** | +| **values.paymentAddress** | String | Ethereum address for the payment | Optional | +| **values.refundAddress** | String | Ethereum address for the refund | Optional | + + +Note: to use the Rinkeby testnet, create a request with `currency.network` as `rinkeby`. + +--- + +## Actions + +### Creation + +#### Parameters + +| | Type | Description | Requirement | +| ----------------------------- | ------ | -------------------------------- | ------------- | +| **id** | String | Constant value: "pn-erc20-proxy-contract" | **Mandatory** | +| **type** | String | Constant value: "paymentNetwork" | **Mandatory** | +| **version** | String | Constant value: "0.1.0" | **Mandatory** | +| **parameters** | Object | | | +| **parameters.salt** | String | Salt for the request | **Mandatory** | +| **parameters.paymentAddress** | String | Ethereum address for the payment | Optional | +| **parameters.refundAddress** | String | Ethereum address for the refund | Optional | + + +#### Conditions + +This action is valid if: + +- The `salt` is not empty and long enough (8 bytes of randomness minimum). +- The `currency.type` is ERC20. + +#### Warnings + +This action must trigger the warnings: + +| Warning | Condition | +| --------------------------------------- | ----------------------------------------------------------- | +| "paymentAddress is given by the payer"  | If `signer` is the payer **and** `paymentAddress` is given  | +| "refundAddress is given by the payee"  | If `signer` is the payee **and** `refundAddress` is given | + +Note: These warnings are necessary to highlight to avoid attempts of fake payments and refunds. For example, a payer could create a request using as the payment address one of his own addresses. A system could interpret a transaction to this address as a payment while the payee did not receive the funds. + +#### Results + +An extension state is created with the following properties: + +|  Property |  Value | +| ------------------------- | -------------------------------------------------------------- | +| **id** | "pn-erc20-proxy-contract" | +| **type** | "paymentNetwork" | +| **version** | "0.1.0" | +| **values** | | +| **values.paymentAddress** | `paymentAddress` from parameters if given, undefined otherwise | +| **values.refundAddress** | `refundAddress` from parameters if given, undefined otherwise | +| **values.salt** | Salt for the request | +| **events** | Array with one 'create' event (see below) | + +the 'create' event: + +|  Property |  Value | +| ----------------------------- | -------------------------------------------------------------- | +| **name** | 'create' | +| **parameters** | | +| **parameters.paymentAddress** | `paymentAddress` from parameters if given, undefined otherwise | +| **parameters.refundAddress** | `refundAddress` from parameters if given, undefined otherwise | +| **parameters.salt** | Salt for the request | + +--- + +### Updates + +#### addPaymentAddress + +##### Parameters + +| | Type | Description | Requirement | +| ----------------------------- | ------ | ----------------------------------- | ------------- | +| **id** | String | Constant value: "pn-erc20-proxy-contract" | **Mandatory** | +| **action** | String | Constant value: "addPaymentAddress" | **Mandatory** | +| **parameters** | Object | | | +| **parameters.paymentAddress** | String | Ethereum address for the payment | **Mandatory** | + +##### Conditions + +This action is valid, if: + +- The extension state with the id "pn-erc20-proxy-contract" exists +- The signer is the `payee` +- The extension property `paymentAddress` is undefined + +##### Warnings + +None. + +##### Results + +An extension state is updated with the following properties: + +|  Property |  Value | +| -------------------------- | ---------------------------------------------------- | +| **values.paymentAddress** | `paymentAddress` from parameters | +| **events** | Add an 'paymentAddress' event (see below) at its end | + +the 'addPaymentAddress' event: + +|  Property |  Value | +| ----------------------------- | ----------------------------------- | +| **name** | Constant value: "addPaymentAddress" | +| **parameters** | | +| **parameters.paymentAddress** | `paymentAddress` from parameters | + +#### addRefundAddress + +##### Parameters + +| | Type | Description | Requirement | +| ---------------------------- | ------ | ---------------------------------- | ------------- | +| **id** | String | Constant value: "pn-erc20-proxy-contract" | **Mandatory** | +| **action** | String | Constant value: "addRefundAddress" | **Mandatory** | +| **parameters** | Object | | | +| **parameters.refundAddress** | String | Ethereum address for the refund | **Mandatory** | + +##### Conditions + +This action is valid if: + +- The extension state with the id "pn-erc20-proxy-contract" exists +- The signer is the `payer` +- The extension property `refundAddress` is undefined + +##### Warnings + +None. + +##### Results + +An extension state is updated with the following properties: + +|  Property |  Value | +| ------------------------ | ------------------------------------------------------ | +| **values.refundAddress** | `refundAddress` from parameters | +| **events** | Add an 'addRefundAddress' event (see below) at its end | + +The 'addRefundAddress' event: + +|  Property |  Value | +| ---------------------------- | ------------------------------- | +| **name** | 'addRefundAddress' | +| **parameters** | | +| **parameters.refundAddress** | `refundAddress` from parameters | + +--- + +## Interpretation + +The proxy contract address is determined by the `request.currency.network` (see (table)[#Contract] with proxy contract addresses). + +Any `TransferWithReference` events emitted from the proxy contract with the following arguments are considered as a payment: +- `tokenAddress` `===` `request.currency.value` +- `to` `===` `paymentAddress` +- `paymentReference` `===` `last8Bytes(hash(lowercase(requestId + salt + payment address)))` + +Any `TransferWithReference` events emitted from the proxy contract with the following arguments are considered as a refund: +- `tokenAddress` `===` `request.currency.value` +- `to` `===` `refundAddress` +- `paymentReference` `===` `last8Bytes(hash(lowercase(requestId + salt + refund address)))` + +The sum of payment amounts minus the sum of refund amounts is considered the balance. diff --git a/packages/advanced-logic/specs/payment-network-eth-input-data-0.1.0-DRAFT.md b/packages/advanced-logic/specs/payment-network-eth-input-data-0.1.0-DRAFT.md index 092dd7c9d3..fcf67a6e94 100644 --- a/packages/advanced-logic/specs/payment-network-eth-input-data-0.1.0-DRAFT.md +++ b/packages/advanced-logic/specs/payment-network-eth-input-data-0.1.0-DRAFT.md @@ -10,8 +10,8 @@ Prerequisite: Having read the advanced logic specification (see [here](./advance ## Description This extension allows the payments and the refunds to be made in Ether on the Ethereum blockchain. -A specific value has to be given in input data when making the transfer to link the payment to the request. -The value is the last 8 bytes of a salted hash of the requestId: `last8Bytes(hash(requestId + salt + address))`: +A payment reference has to be given in input data when making the transfer to link the payment to the request. +The payment reference is the last 8 bytes of a salted hash of the requestId: `last8Bytes(hash(lowercase(requestId + salt + address)))`: - `requestId` is the id of the request - `salt` is a random number with at least 8 bytes of randomness. It must be unique to each request @@ -26,16 +26,16 @@ As a payment network, this extension allows to deduce a payment `balance` for th | Property | Type | Description | Requirement | | ------------------------- | ------ | ---------------------------------------------- | ------------- | -| **id** | String | constant value: "pn-eth-tx-data" | **Mandatory** | +| **id** | String | constant value: "pn-eth-input-data" | **Mandatory** | | **type** | String | constant value: "paymentNetwork" | **Mandatory** | | **version** | String | constant value: "0.1.0" | **Mandatory** | | **events** | Array | List of the actions performed by the extension | **Mandatory** | | **values** | Object | | | | **values.paymentAddress** | String | Ethereum address for the payment | Optional | | **values.refundAddress** | String | Ethereum address for the refund | Optional | -| **values.salt** | String | Salt for the request | Optional | +| **values.salt** | String | Salt for the request | **Mandatory** | -Note: to use the Rinkeby testnet just replace the id by "pn-rinkeby-eth-tx-data" +Note: to use the Rinkeby testnet just set the `currency.network` to "rinkeby" --- @@ -45,20 +45,22 @@ Note: to use the Rinkeby testnet just replace the id by "pn-rinkeby-eth-tx-data" #### Parameters -| | Type | Description | Requirement | -| ----------------------------- | ------ | -------------------------------- | ------------- | -| **id** | String | Constant value: "pn-eth-tx-data" | **Mandatory** | -| **type** | String | Constant value: "paymentNetwork" | **Mandatory** | -| **version** | String | Constant value: "0.1.0" | **Mandatory** | -| **parameters** | Object | | | -| **parameters.paymentAddress** | String | Ethereum address for the payment | Optional | -| **parameters.refundAddress** | String | Ethereum address for the refund | Optional | -| **parameters.salt** | String | Salt for the request | **Mandatory** | +| | Type | Description | Requirement | +| ----------------------------- | ------ | ----------------------------------- | ------------- | +| **id** | String | Constant value: "pn-eth-input-data" | **Mandatory** | +| **type** | String | Constant value: "paymentNetwork" | **Mandatory** | +| **version** | String | Constant value: "0.1.0" | **Mandatory** | +| **parameters** | Object | | | +| **parameters.paymentAddress** | String | Ethereum address for the payment | Optional | +| **parameters.refundAddress** | String | Ethereum address for the refund | Optional | +| **parameters.salt** | String | Salt for the request | **Mandatory** | #### Conditions This action is valid if: +- The request `currency.type` must be "ETH" +- The request `currency.network` must be "mainnet" or 'rinkeby" - The `salt` is not empty and long enough (8 bytes of randomness minimum). #### Warnings @@ -78,7 +80,7 @@ A extension state is created with the following properties: |  Property |  Value | | ------------------------- | -------------------------------------------------------------- | -| **id** | "pn-eth-tx-data" | +| **id** | "pn-eth-input-data" | | **type** | "paymentNetwork" | | **version** | "0.1.0" | | **values** | | @@ -107,7 +109,7 @@ the 'create' event: | | Type | Description | Requirement | | ----------------------------- | ------ | ----------------------------------- | ------------- | -| **id** | String | Constant value: "pn-eth-tx-data" | **Mandatory** | +| **id** | String | Constant value: "pn-eth-input-data" | **Mandatory** | | **action** | String | Constant value: "addPaymentAddress" | **Mandatory** | | **parameters** | Object | | | | **parameters.paymentAddress** | String | Ethereum address for the payment | **Mandatory** | @@ -116,7 +118,7 @@ the 'create' event: This action is valid, if: -- The extension state with the id "pn-eth-tx-data" exists +- The extension state with the id "pn-eth-input-data" exists - The signer is the `payee` - The extension property `paymentAddress` is undefined @@ -146,18 +148,18 @@ the 'addPaymentAddress' event: ##### Parameters -| | Type | Description | Requirement | -| ---------------------------- | ------ | ---------------------------------- | ------------- | -| **id** | String | Constant value: "pn-eth-tx-data" | **Mandatory** | -| **action** | String | Constant value: "addRefundAddress" | **Mandatory** | -| **parameters** | Object | | | -| **parameters.refundAddress** | String | Ethereum address for the refund | **Mandatory** | +| | Type | Description | Requirement | +| ---------------------------- | ------ | ----------------------------------- | ------------- | +| **id** | String | Constant value: "pn-eth-input-data" | **Mandatory** | +| **action** | String | Constant value: "addRefundAddress" | **Mandatory** | +| **parameters** | Object | | | +| **parameters.refundAddress** | String | Ethereum address for the refund | **Mandatory** | ##### Conditions This action is valid if: -- The extension state with the id "pn-eth-tx-data" exists +- The extension state with the id "pn-eth-input-data" exists - The signer is the `payer` - The extension property `refundAddress` is undefined diff --git a/packages/advanced-logic/src/advanced-logic.ts b/packages/advanced-logic/src/advanced-logic.ts index 2115a7d4a5..eebf032bb2 100644 --- a/packages/advanced-logic/src/advanced-logic.ts +++ b/packages/advanced-logic/src/advanced-logic.ts @@ -10,6 +10,7 @@ import addressBasedBtc from './extensions/payment-network/bitcoin/mainnet-addres import addressBasedTestnetBtc from './extensions/payment-network/bitcoin/testnet-address-based'; import declarative from './extensions/payment-network/declarative'; import addressBasedErc20 from './extensions/payment-network/erc20/address-based'; +import proxyContractErc20 from './extensions/payment-network/erc20/proxy-contract'; import ethereumInputData from './extensions/payment-network/ethereum/input-data'; /** @@ -25,6 +26,7 @@ export default class AdvancedLogic implements AdvancedLogicTypes.IAdvancedLogic contentData, declarative, ethereumInputData, + proxyContractErc20, }; /** @@ -92,6 +94,15 @@ export default class AdvancedLogic implements AdvancedLogicTypes.IAdvancedLogic timestamp, ); } + if (id === ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT) { + return proxyContractErc20.applyActionToExtension( + extensionsState, + extensionAction, + requestState, + actionSigner, + timestamp, + ); + } if (id === ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA) { return ethereumInputData.applyActionToExtension( extensionsState, diff --git a/packages/advanced-logic/src/extensions/payment-network/erc20/proxy-contract.ts b/packages/advanced-logic/src/extensions/payment-network/erc20/proxy-contract.ts new file mode 100644 index 0000000000..2caa0ce2c0 --- /dev/null +++ b/packages/advanced-logic/src/extensions/payment-network/erc20/proxy-contract.ts @@ -0,0 +1,144 @@ +import { ExtensionTypes, IdentityTypes, RequestLogicTypes } from '@requestnetwork/types'; + +import ReferenceBased from '../reference-based'; + +const walletAddressValidator = require('wallet-address-validator'); + +/** + * Implementation of the payment network to pay in ERC20 based on a reference provided to a proxy contract. + * With this extension, one request can have two Ethereum addresses (one for payment and one for refund) and a specific value to give as input data + * Every ERC20 ethereum transaction that reaches these addresses through the proxy contract and has the correct reference will be interpreted as a payment or a refund. + * The value to give as input data is the last 8 bytes of a salted hash of the requestId and the address: `last8Bytes(hash(requestId + salt + address))`: + * The salt should have at least 8 bytes of randomness. A way to generate it is: + * `Math.floor(Math.random() * Math.pow(2, 4 * 8)).toString(16) + Math.floor(Math.random() * Math.pow(2, 4 * 8)).toString(16)` + */ +const erc20ProxyContract: ExtensionTypes.PnReferenceBased.IReferenceBased = { + applyActionToExtension, + createAddPaymentAddressAction, + createAddRefundAddressAction, + createCreationAction, + isValidAddress, +}; + +const supportedNetworks = ['mainnet', 'rinkeby', 'private']; + +/** + * Creates the extensionsData to create the extension ERC20 proxy contract payment detection + * + * @param creationParameters extensions parameters to create + * + * @returns IExtensionCreationAction the extensionsData to be stored in the request + */ +function createCreationAction( + creationParameters: ExtensionTypes.PnReferenceBased.ICreationParameters, +): ExtensionTypes.IAction { + if (creationParameters.paymentAddress && !isValidAddress(creationParameters.paymentAddress)) { + throw Error('paymentAddress is not a valid ethereum address'); + } + + if (creationParameters.refundAddress && !isValidAddress(creationParameters.refundAddress)) { + throw Error('refundAddress is not a valid ethereum address'); + } + + return ReferenceBased.createCreationAction( + ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + creationParameters, + ); +} + +/** + * Creates the extensionsData to add a payment address + * + * @param addPaymentAddressParameters extensions parameters to create + * + * @returns IAction the extensionsData to be stored in the request + */ +function createAddPaymentAddressAction( + addPaymentAddressParameters: ExtensionTypes.PnReferenceBased.IAddPaymentAddressParameters, +): ExtensionTypes.IAction { + if ( + addPaymentAddressParameters.paymentAddress && + !isValidAddress(addPaymentAddressParameters.paymentAddress) + ) { + throw Error('paymentAddress is not a valid ethereum address'); + } + + return ReferenceBased.createAddPaymentAddressAction( + ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + addPaymentAddressParameters, + ); +} + +/** + * Creates the extensionsData to add a refund address + * + * @param addRefundAddressParameters extensions parameters to create + * + * @returns IAction the extensionsData to be stored in the request + */ +function createAddRefundAddressAction( + addRefundAddressParameters: ExtensionTypes.PnReferenceBased.IAddRefundAddressParameters, +): ExtensionTypes.IAction { + if ( + addRefundAddressParameters.refundAddress && + !isValidAddress(addRefundAddressParameters.refundAddress) + ) { + throw Error('refundAddress is not a valid ethereum address'); + } + + return ReferenceBased.createAddRefundAddressAction( + ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + addRefundAddressParameters, + ); +} + +/** + * Applies the extension action to the request + * Is called to interpret the extensions data when applying the transaction + * + * @param extensionsState previous state of the extensions + * @param extensionAction action to apply + * @param requestState request state read-only + * @param actionSigner identity of the signer + * + * @returns state of the request updated + */ +function applyActionToExtension( + extensionsState: RequestLogicTypes.IExtensionStates, + extensionAction: ExtensionTypes.IAction, + requestState: RequestLogicTypes.IRequest, + actionSigner: IdentityTypes.IIdentity, + timestamp: number, +): RequestLogicTypes.IExtensionStates { + if ( + requestState.currency.type !== RequestLogicTypes.CURRENCY.ERC20 || + (requestState.currency.network && !supportedNetworks.includes(requestState.currency.network)) + ) { + throw Error( + `This extension can be used only on ERC20 requests and on supported networks ${supportedNetworks.join( + ', ', + )}`, + ); + } + + return ReferenceBased.applyActionToExtension( + isValidAddress, + extensionsState, + extensionAction, + requestState, + actionSigner, + timestamp, + ); +} + +/** + * Check if an ethereum address is valid + * + * @param {string} address address to check + * @returns {boolean} true if address is valid + */ +function isValidAddress(address: string): boolean { + return walletAddressValidator.validate(address, 'ethereum'); +} + +export default erc20ProxyContract; diff --git a/packages/advanced-logic/src/extensions/payment-network/ethereum/input-data.ts b/packages/advanced-logic/src/extensions/payment-network/ethereum/input-data.ts index 86c6a956b3..b64292c6b5 100644 --- a/packages/advanced-logic/src/extensions/payment-network/ethereum/input-data.ts +++ b/packages/advanced-logic/src/extensions/payment-network/ethereum/input-data.ts @@ -1,5 +1,6 @@ import { ExtensionTypes, IdentityTypes, RequestLogicTypes } from '@requestnetwork/types'; -import Utils from '@requestnetwork/utils'; + +import ReferenceBased from '../reference-based'; const walletAddressValidator = require('wallet-address-validator'); @@ -11,7 +12,7 @@ const walletAddressValidator = require('wallet-address-validator'); * The salt should have at least 8 bytes of randomness. A way to generate it is: * `Math.floor(Math.random() * Math.pow(2, 4 * 8)).toString(16) + Math.floor(Math.random() * Math.pow(2, 4 * 8)).toString(16)` */ -const ethInputData: ExtensionTypes.PnEthInputData.IEthInputData = { +const ethInputData: ExtensionTypes.PnReferenceBased.IReferenceBased = { applyActionToExtension, createAddPaymentAddressAction, createAddRefundAddressAction, @@ -21,11 +22,6 @@ const ethInputData: ExtensionTypes.PnEthInputData.IEthInputData = { const supportedNetworks = ['mainnet', 'rinkeby']; -// Regex for "at least 16 hexadecimal numbers". Used to validate the salt -const eightHexRegex = /[0-9a-f]{16,}/; - -const CURRENT_VERSION = '0.1.0'; - /** * Creates the extensionsData to create the ETH payment detection extension * @@ -34,7 +30,7 @@ const CURRENT_VERSION = '0.1.0'; * @returns IExtensionCreationAction the extensionsData to be stored in the request */ function createCreationAction( - creationParameters: ExtensionTypes.PnEthInputData.ICreationParameters, + creationParameters: ExtensionTypes.PnReferenceBased.ICreationParameters, ): ExtensionTypes.IAction { if (creationParameters.paymentAddress && !isValidAddress(creationParameters.paymentAddress)) { throw Error('paymentAddress is not a valid ethereum address'); @@ -44,23 +40,10 @@ function createCreationAction( throw Error('refundAddress is not a valid ethereum address'); } - if (!creationParameters.salt) { - throw Error('salt should not be empty'); - } - - if (!eightHexRegex.test(creationParameters.salt)) { - /* eslint-disable spellcheck/spell-checker */ - throw Error( - `salt be a string of minimum 16 hexadecimal characters. Example: 'ea3bc7caf64110ca'`, - ); - } - - return { - action: ExtensionTypes.PnAddressBased.ACTION.CREATE, - id: ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA, - parameters: creationParameters, - version: CURRENT_VERSION, - }; + return ReferenceBased.createCreationAction( + ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA, + creationParameters, + ); } /** @@ -71,7 +54,7 @@ function createCreationAction( * @returns IAction the extensionsData to be stored in the request */ function createAddPaymentAddressAction( - addPaymentAddressParameters: ExtensionTypes.PnEthInputData.IAddPaymentAddressParameters, + addPaymentAddressParameters: ExtensionTypes.PnReferenceBased.IAddPaymentAddressParameters, ): ExtensionTypes.IAction { if ( addPaymentAddressParameters.paymentAddress && @@ -80,11 +63,10 @@ function createAddPaymentAddressAction( throw Error('paymentAddress is not a valid ethereum address'); } - return { - action: ExtensionTypes.PnAddressBased.ACTION.ADD_PAYMENT_ADDRESS, - id: ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA, - parameters: addPaymentAddressParameters, - }; + return ReferenceBased.createAddPaymentAddressAction( + ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA, + addPaymentAddressParameters, + ); } /** @@ -95,7 +77,7 @@ function createAddPaymentAddressAction( * @returns IAction the extensionsData to be stored in the request */ function createAddRefundAddressAction( - addRefundAddressParameters: ExtensionTypes.PnEthInputData.IAddRefundAddressParameters, + addRefundAddressParameters: ExtensionTypes.PnReferenceBased.IAddRefundAddressParameters, ): ExtensionTypes.IAction { if ( addRefundAddressParameters.refundAddress && @@ -104,11 +86,10 @@ function createAddRefundAddressAction( throw Error('refundAddress is not a valid ethereum address'); } - return { - action: ExtensionTypes.PnAddressBased.ACTION.ADD_REFUND_ADDRESS, - id: ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA, - parameters: addRefundAddressParameters, - }; + return ReferenceBased.createAddRefundAddressAction( + ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA, + addRefundAddressParameters, + ); } /** @@ -140,191 +121,14 @@ function applyActionToExtension( ); } - const copiedExtensionState: RequestLogicTypes.IExtensionStates = Utils.deepCopy(extensionsState); - - if (extensionAction.action === ExtensionTypes.PnEthInputData.ACTION.CREATE) { - if (requestState.extensions[extensionAction.id]) { - throw Error(`This extension has already been created`); - } - - copiedExtensionState[extensionAction.id] = applyCreation(extensionAction, timestamp); - - return copiedExtensionState; - } - - // if the action is not "create", the state must have been created before - if (!requestState.extensions[extensionAction.id]) { - throw Error(`The extension should be created before receiving any other action`); - } - - if (extensionAction.action === ExtensionTypes.PnEthInputData.ACTION.ADD_PAYMENT_ADDRESS) { - copiedExtensionState[extensionAction.id] = applyAddPaymentAddress( - copiedExtensionState[extensionAction.id], - extensionAction, - requestState, - actionSigner, - timestamp, - ); - - return copiedExtensionState; - } - - if (extensionAction.action === ExtensionTypes.PnEthInputData.ACTION.ADD_REFUND_ADDRESS) { - copiedExtensionState[extensionAction.id] = applyAddRefundAddress( - copiedExtensionState[extensionAction.id], - extensionAction, - requestState, - actionSigner, - timestamp, - ); - - return copiedExtensionState; - } - - throw Error(`Unknown action: ${extensionAction.action}`); -} - -/** - * Applies a creation - * - * @param isValidAddress address validator function - * @param extensionAction action to apply - * - * @returns state of the extension created - */ -function applyCreation( - extensionAction: ExtensionTypes.IAction, - timestamp: number, -): ExtensionTypes.IState { - if ( - extensionAction.parameters.paymentAddress && - !isValidAddress(extensionAction.parameters.paymentAddress) - ) { - throw Error('paymentAddress is not a valid address'); - } - if ( - extensionAction.parameters.refundAddress && - !isValidAddress(extensionAction.parameters.refundAddress) - ) { - throw Error('refundAddress is not a valid address'); - } - return { - events: [ - { - name: 'create', - parameters: { - paymentAddress: extensionAction.parameters.paymentAddress, - refundAddress: extensionAction.parameters.refundAddress, - salt: extensionAction.parameters.salt, - }, - timestamp, - }, - ], - id: extensionAction.id, - type: ExtensionTypes.TYPE.PAYMENT_NETWORK, - values: { - paymentAddress: extensionAction.parameters.paymentAddress, - refundAddress: extensionAction.parameters.refundAddress, - salt: extensionAction.parameters.salt, - }, - version: CURRENT_VERSION, - }; -} - -/** - * Applies add payment address - * - * @param isValidAddress address validator function - * @param extensionState previous state of the extension - * @param extensionAction action to apply - * @param requestState request state read-only - * @param actionSigner identity of the signer - * - * @returns state of the extension updated - */ -function applyAddPaymentAddress( - extensionState: ExtensionTypes.IState, - extensionAction: ExtensionTypes.IAction, - requestState: RequestLogicTypes.IRequest, - actionSigner: IdentityTypes.IIdentity, - timestamp: number, -): ExtensionTypes.IState { - if ( - extensionAction.parameters.paymentAddress && - !isValidAddress(extensionAction.parameters.paymentAddress) - ) { - throw Error('paymentAddress is not a valid address'); - } - if (extensionState.values.paymentAddress) { - throw Error(`Payment address already given`); - } - if (!requestState.payee) { - throw Error(`The request must have a payee`); - } - if (!Utils.identity.areEqual(actionSigner, requestState.payee)) { - throw Error(`The signer must be the payee`); - } - - const copiedExtensionState: ExtensionTypes.IState = Utils.deepCopy(extensionState); - - // update payment address - copiedExtensionState.values.paymentAddress = extensionAction.parameters.paymentAddress; - // update events - copiedExtensionState.events.push({ - name: ExtensionTypes.PnAddressBased.ACTION.ADD_PAYMENT_ADDRESS, - parameters: { paymentAddress: extensionAction.parameters.paymentAddress }, - timestamp, - }); - - return copiedExtensionState; -} - -/** - * Applies add refund address - * - * @param isValidAddress address validator function - * @param extensionState previous state of the extension - * @param extensionAction action to apply - * @param requestState request state read-only - * @param actionSigner identity of the signer - * - * @returns state of the extension updated - */ -function applyAddRefundAddress( - extensionState: ExtensionTypes.IState, - extensionAction: ExtensionTypes.IAction, - requestState: RequestLogicTypes.IRequest, - actionSigner: IdentityTypes.IIdentity, - timestamp: number, -): ExtensionTypes.IState { - if ( - extensionAction.parameters.refundAddress && - !isValidAddress(extensionAction.parameters.refundAddress) - ) { - throw Error('refundAddress is not a valid address'); - } - if (extensionState.values.refundAddress) { - throw Error(`Refund address already given`); - } - if (!requestState.payer) { - throw Error(`The request must have a payer`); - } - if (!Utils.identity.areEqual(actionSigner, requestState.payer)) { - throw Error(`The signer must be the payer`); - } - - const copiedExtensionState: ExtensionTypes.IState = Utils.deepCopy(extensionState); - - // update refund address - copiedExtensionState.values.refundAddress = extensionAction.parameters.refundAddress; - // update events - copiedExtensionState.events.push({ - name: ExtensionTypes.PnAddressBased.ACTION.ADD_REFUND_ADDRESS, - parameters: { refundAddress: extensionAction.parameters.refundAddress }, + return ReferenceBased.applyActionToExtension( + isValidAddress, + extensionsState, + extensionAction, + requestState, + actionSigner, timestamp, - }); - - return copiedExtensionState; + ); } /** diff --git a/packages/advanced-logic/src/extensions/payment-network/reference-based.ts b/packages/advanced-logic/src/extensions/payment-network/reference-based.ts new file mode 100644 index 0000000000..757eab9b0e --- /dev/null +++ b/packages/advanced-logic/src/extensions/payment-network/reference-based.ts @@ -0,0 +1,299 @@ +import { ExtensionTypes, IdentityTypes, RequestLogicTypes } from '@requestnetwork/types'; +import Utils from '@requestnetwork/utils'; + +/** + * Core of the reference based payment networks + * This module is called by the reference based payment networks to avoid code redundancy + */ +export default { + applyActionToExtension, + createAddPaymentAddressAction, + createAddRefundAddressAction, + createCreationAction, +}; + +const CURRENT_VERSION = '0.1.0'; + +// Regex for "at least 16 hexadecimal numbers". Used to validate the salt +const eightHexRegex = /[0-9a-f]{16,}/; + +/** + * Creates the extensionsData to create the ETH payment detection extension + * + * @param creationParameters extensions parameters to create + * + * @returns IExtensionCreationAction the extensionsData to be stored in the request + */ +function createCreationAction( + extensionId: ExtensionTypes.ID, + creationParameters: ExtensionTypes.PnReferenceBased.ICreationParameters, +): ExtensionTypes.IAction { + if (!creationParameters.salt) { + throw Error('salt should not be empty'); + } + + if (!eightHexRegex.test(creationParameters.salt)) { + /* eslint-disable spellcheck/spell-checker */ + throw Error( + `The salt must be a string of minimum 16 hexadecimal characters. Example: 'ea3bc7caf64110ca'`, + ); + } + + return { + action: ExtensionTypes.PnReferenceBased.ACTION.CREATE, + id: extensionId, + parameters: creationParameters, + version: CURRENT_VERSION, + }; +} + +/** + * Creates the extensionsData to add a payment address + * + * @param addPaymentAddressParameters extensions parameters to create + * + * @returns IAction the extensionsData to be stored in the request + */ +function createAddPaymentAddressAction( + extensionId: ExtensionTypes.ID, + addPaymentAddressParameters: ExtensionTypes.PnReferenceBased.IAddPaymentAddressParameters, +): ExtensionTypes.IAction { + return { + action: ExtensionTypes.PnReferenceBased.ACTION.ADD_PAYMENT_ADDRESS, + id: extensionId, + parameters: addPaymentAddressParameters, + }; +} + +/** + * Creates the extensionsData to add a refund address + * + * @param addRefundAddressParameters extensions parameters to create + * + * @returns IAction the extensionsData to be stored in the request + */ +function createAddRefundAddressAction( + extensionId: ExtensionTypes.ID, + addRefundAddressParameters: ExtensionTypes.PnReferenceBased.IAddRefundAddressParameters, +): ExtensionTypes.IAction { + return { + action: ExtensionTypes.PnReferenceBased.ACTION.ADD_REFUND_ADDRESS, + id: extensionId, + parameters: addRefundAddressParameters, + }; +} + +/** + * Applies the extension action to the request + * Is called to interpret the extensions data when applying the transaction + * + * @param extensionsState previous state of the extensions + * @param extensionAction action to apply + * @param requestState request state read-only + * @param actionSigner identity of the signer + * + * @returns state of the request updated + */ +function applyActionToExtension( + isValidAddress: (address: string) => boolean, + extensionsState: RequestLogicTypes.IExtensionStates, + extensionAction: ExtensionTypes.IAction, + requestState: RequestLogicTypes.IRequest, + actionSigner: IdentityTypes.IIdentity, + timestamp: number, +): RequestLogicTypes.IExtensionStates { + const copiedExtensionState: RequestLogicTypes.IExtensionStates = Utils.deepCopy(extensionsState); + + if (extensionAction.action === ExtensionTypes.PnReferenceBased.ACTION.CREATE) { + if (requestState.extensions[extensionAction.id]) { + throw Error(`This extension has already been created`); + } + + copiedExtensionState[extensionAction.id] = applyCreation( + isValidAddress, + extensionAction, + timestamp, + ); + + return copiedExtensionState; + } + + // if the action is not "create", the state must have been created before + if (!requestState.extensions[extensionAction.id]) { + throw Error(`The extension should be created before receiving any other action`); + } + + if (extensionAction.action === ExtensionTypes.PnReferenceBased.ACTION.ADD_PAYMENT_ADDRESS) { + copiedExtensionState[extensionAction.id] = applyAddPaymentAddress( + isValidAddress, + copiedExtensionState[extensionAction.id], + extensionAction, + requestState, + actionSigner, + timestamp, + ); + + return copiedExtensionState; + } + + if (extensionAction.action === ExtensionTypes.PnReferenceBased.ACTION.ADD_REFUND_ADDRESS) { + copiedExtensionState[extensionAction.id] = applyAddRefundAddress( + isValidAddress, + copiedExtensionState[extensionAction.id], + extensionAction, + requestState, + actionSigner, + timestamp, + ); + + return copiedExtensionState; + } + + throw Error(`Unknown action: ${extensionAction.action}`); +} + +/** + * Applies a creation extension action + * + * @param isValidAddress address validator function + * @param extensionAction action to apply + * + * @returns state of the extension created + */ +function applyCreation( + isValidAddress: (address: string) => boolean, + extensionAction: ExtensionTypes.IAction, + timestamp: number, +): ExtensionTypes.IState { + if ( + extensionAction.parameters.paymentAddress && + !isValidAddress(extensionAction.parameters.paymentAddress) + ) { + throw Error('paymentAddress is not a valid address'); + } + if ( + extensionAction.parameters.refundAddress && + !isValidAddress(extensionAction.parameters.refundAddress) + ) { + throw Error('refundAddress is not a valid address'); + } + return { + events: [ + { + name: 'create', + parameters: { + paymentAddress: extensionAction.parameters.paymentAddress, + refundAddress: extensionAction.parameters.refundAddress, + salt: extensionAction.parameters.salt, + }, + timestamp, + }, + ], + id: extensionAction.id, + type: ExtensionTypes.TYPE.PAYMENT_NETWORK, + values: { + paymentAddress: extensionAction.parameters.paymentAddress, + refundAddress: extensionAction.parameters.refundAddress, + salt: extensionAction.parameters.salt, + }, + version: CURRENT_VERSION, + }; +} + +/** + * Applies an add payment address extension action + * + * @param isValidAddress address validator function + * @param extensionState previous state of the extension + * @param extensionAction action to apply + * @param requestState request state read-only + * @param actionSigner identity of the signer + * + * @returns state of the extension updated + */ +function applyAddPaymentAddress( + isValidAddress: (address: string) => boolean, + extensionState: ExtensionTypes.IState, + extensionAction: ExtensionTypes.IAction, + requestState: RequestLogicTypes.IRequest, + actionSigner: IdentityTypes.IIdentity, + timestamp: number, +): ExtensionTypes.IState { + if ( + extensionAction.parameters.paymentAddress && + !isValidAddress(extensionAction.parameters.paymentAddress) + ) { + throw Error('paymentAddress is not a valid address'); + } + if (extensionState.values.paymentAddress) { + throw Error(`Payment address already given`); + } + if (!requestState.payee) { + throw Error(`The request must have a payee`); + } + if (!Utils.identity.areEqual(actionSigner, requestState.payee)) { + throw Error(`The signer must be the payee`); + } + + const copiedExtensionState: ExtensionTypes.IState = Utils.deepCopy(extensionState); + + // update payment address + copiedExtensionState.values.paymentAddress = extensionAction.parameters.paymentAddress; + // update events + copiedExtensionState.events.push({ + name: ExtensionTypes.PnReferenceBased.ACTION.ADD_PAYMENT_ADDRESS, + parameters: { paymentAddress: extensionAction.parameters.paymentAddress }, + timestamp, + }); + + return copiedExtensionState; +} + +/** + * Applies an add refund address extension action + * + * @param isValidAddress address validator function + * @param extensionState previous state of the extension + * @param extensionAction action to apply + * @param requestState request state read-only + * @param actionSigner identity of the signer + * + * @returns state of the extension updated + */ +function applyAddRefundAddress( + isValidAddress: (address: string) => boolean, + extensionState: ExtensionTypes.IState, + extensionAction: ExtensionTypes.IAction, + requestState: RequestLogicTypes.IRequest, + actionSigner: IdentityTypes.IIdentity, + timestamp: number, +): ExtensionTypes.IState { + if ( + extensionAction.parameters.refundAddress && + !isValidAddress(extensionAction.parameters.refundAddress) + ) { + throw Error('refundAddress is not a valid address'); + } + if (extensionState.values.refundAddress) { + throw Error(`Refund address already given`); + } + if (!requestState.payer) { + throw Error(`The request must have a payer`); + } + if (!Utils.identity.areEqual(actionSigner, requestState.payer)) { + throw Error(`The signer must be the payer`); + } + + const copiedExtensionState: ExtensionTypes.IState = Utils.deepCopy(extensionState); + + // update refund address + copiedExtensionState.values.refundAddress = extensionAction.parameters.refundAddress; + // update events + copiedExtensionState.events.push({ + name: ExtensionTypes.PnReferenceBased.ACTION.ADD_REFUND_ADDRESS, + parameters: { refundAddress: extensionAction.parameters.refundAddress }, + timestamp, + }); + + return copiedExtensionState; +} diff --git a/packages/advanced-logic/test/extensions/payment-network/erc20/mainnet-address-based.test.ts b/packages/advanced-logic/test/extensions/payment-network/erc20/address-based.test.ts similarity index 99% rename from packages/advanced-logic/test/extensions/payment-network/erc20/mainnet-address-based.test.ts rename to packages/advanced-logic/test/extensions/payment-network/erc20/address-based.test.ts index 81d359f50e..b5a998f538 100644 --- a/packages/advanced-logic/test/extensions/payment-network/erc20/mainnet-address-based.test.ts +++ b/packages/advanced-logic/test/extensions/payment-network/erc20/address-based.test.ts @@ -6,8 +6,8 @@ import Utils from '@requestnetwork/utils'; import { expect } from 'chai'; -import * as DataERC20AddPaymentAddress from '../../../utils/payment-network/erc20/add-payment-address-data-generator'; -import * as DataERC20Create from '../../../utils/payment-network/erc20/create-data-generator'; +import * as DataERC20AddPaymentAddress from '../../../utils/payment-network/erc20/address-based-add-payment-address-data-generator'; +import * as DataERC20Create from '../../../utils/payment-network/erc20/address-based-create-data-generator'; import * as TestData from '../../../utils/test-data-generator'; /* tslint:disable:no-unused-expression */ diff --git a/packages/advanced-logic/test/extensions/payment-network/erc20/proxy-contract.test.ts b/packages/advanced-logic/test/extensions/payment-network/erc20/proxy-contract.test.ts new file mode 100644 index 0000000000..485dfae372 --- /dev/null +++ b/packages/advanced-logic/test/extensions/payment-network/erc20/proxy-contract.test.ts @@ -0,0 +1,393 @@ +import { ExtensionTypes, RequestLogicTypes } from '@requestnetwork/types'; +import Utils from '@requestnetwork/utils'; +import 'mocha'; + +import erc20ProxyContract from '../../../../src/extensions/payment-network/erc20/proxy-contract'; + +import { expect } from 'chai'; + +import * as DataERC20AddPaymentAddress from '../../../utils/payment-network/erc20/proxy-contract-add-payment-address-data-generator'; +import * as DataERC20Create from '../../../utils/payment-network/erc20/proxy-contract-create-data-generator'; +import * as TestData from '../../../utils/test-data-generator'; + +/* tslint:disable:no-unused-expression */ +describe('extensions/payment-network/erc20/proxy-contract', () => { + describe('createCreationAction', () => { + it('can create a create action', () => { + expect( + erc20ProxyContract.createCreationAction({ + paymentAddress: '0x0000000000000000000000000000000000000001', + refundAddress: '0x0000000000000000000000000000000000000002', + salt: 'ea3bc7caf64110ca', + }), + 'extensionsdata is wrong', + ).to.deep.equal({ + action: 'create', + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + parameters: { + paymentAddress: '0x0000000000000000000000000000000000000001', + refundAddress: '0x0000000000000000000000000000000000000002', + salt: 'ea3bc7caf64110ca', + }, + version: '0.1.0', + }); + }); + + it('can create a create action with only salt', () => { + expect( + erc20ProxyContract.createCreationAction({ + salt: 'ea3bc7caf64110ca', + }), + 'extensionsdata is wrong', + ).to.deep.equal({ + action: 'create', + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + parameters: { + salt: 'ea3bc7caf64110ca', + }, + version: '0.1.0', + }); + }); + + it('cannot createCreationAction with payment address not an ethereum address', () => { + expect(() => { + erc20ProxyContract.createCreationAction({ + paymentAddress: 'not an ethereum address', + refundAddress: '0x0000000000000000000000000000000000000002', + salt: 'ea3bc7caf64110ca', + }); + }, 'must throw').to.throw('paymentAddress is not a valid ethereum address'); + }); + + it('cannot createCreationAction with refund address not an ethereum address', () => { + expect(() => { + erc20ProxyContract.createCreationAction({ + paymentAddress: '0x0000000000000000000000000000000000000001', + refundAddress: 'not an ethereum address', + salt: 'ea3bc7caf64110ca', + }); + }, 'must throw').to.throw('refundAddress is not a valid ethereum address'); + }); + }); + + describe('createAddPaymentAddressAction', () => { + it('can createAddPaymentAddressAction', () => { + expect( + erc20ProxyContract.createAddPaymentAddressAction({ + paymentAddress: '0x0000000000000000000000000000000000000001', + }), + 'extensionsdata is wrong', + ).to.deep.equal({ + action: ExtensionTypes.PnReferenceBased.ACTION.ADD_PAYMENT_ADDRESS, + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + parameters: { + paymentAddress: '0x0000000000000000000000000000000000000001', + }, + }); + }); + + it('cannot createAddPaymentAddressAction with payment address not an ethereum address', () => { + expect(() => { + erc20ProxyContract.createAddPaymentAddressAction({ + paymentAddress: 'not an ethereum address', + }); + }, 'must throw').to.throw('paymentAddress is not a valid ethereum address'); + }); + }); + + describe('createAddRefundAddressAction', () => { + it('can createAddRefundAddressAction', () => { + expect( + erc20ProxyContract.createAddRefundAddressAction({ + refundAddress: '0x0000000000000000000000000000000000000002', + }), + 'extensionsdata is wrong', + ).to.deep.equal({ + action: ExtensionTypes.PnReferenceBased.ACTION.ADD_REFUND_ADDRESS, + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + parameters: { + refundAddress: '0x0000000000000000000000000000000000000002', + }, + }); + }); + it('cannot createAddRefundAddressAction with payment address not an ethereum address', () => { + expect(() => { + erc20ProxyContract.createAddRefundAddressAction({ + refundAddress: 'not an ethereum address', + }); + }, 'must throw').to.throw('refundAddress is not a valid ethereum address'); + }); + }); + + describe('applyActionToExtension', () => { + describe('applyActionToExtension/unknown action', () => { + it('cannot applyActionToExtensions of unknown action', () => { + const unknownAction = Utils.deepCopy(DataERC20AddPaymentAddress.actionAddPaymentAddress); + unknownAction.action = 'unknown action'; + expect(() => { + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateCreatedEmpty.extensions, + unknownAction, + DataERC20Create.requestStateCreatedEmpty, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw('Unknown action: unknown action'); + }); + + it('cannot applyActionToExtensions of unknown id', () => { + const unknownAction = Utils.deepCopy(DataERC20AddPaymentAddress.actionAddPaymentAddress); + unknownAction.id = 'unknown id'; + expect(() => { + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateCreatedEmpty.extensions, + unknownAction, + DataERC20Create.requestStateCreatedEmpty, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw( + 'The extension should be created before receiving any other action', + ); + }); + }); + + describe('applyActionToExtension/create', () => { + it('can applyActionToExtensions of creation', () => { + expect( + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateNoExtensions.extensions, + DataERC20Create.actionCreationWithPaymentAndRefund, + DataERC20Create.requestStateNoExtensions, + TestData.otherIdRaw.identity, + TestData.arbitraryTimestamp, + ), + 'new extension state wrong', + ).to.deep.equal(DataERC20Create.extensionStateWithPaymentAndRefund); + }); + + it('cannot applyActionToExtensions of creation with a previous state', () => { + expect(() => { + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateCreatedWithPaymentAndRefund.extensions, + DataERC20Create.actionCreationWithPaymentAndRefund, + DataERC20Create.requestStateCreatedWithPaymentAndRefund, + TestData.otherIdRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw('This extension has already been created'); + }); + + it('cannot applyActionToExtensions of creation on a not Eth request', () => { + const requestCreatedNoExtension: RequestLogicTypes.IRequest = Utils.deepCopy( + TestData.requestCreatedNoExtension, + ); + requestCreatedNoExtension.currency = { + type: RequestLogicTypes.CURRENCY.BTC, + value: 'BTC', + }; + expect(() => { + erc20ProxyContract.applyActionToExtension( + TestData.requestCreatedNoExtension.extensions, + DataERC20Create.actionCreationWithPaymentAndRefund, + requestCreatedNoExtension, + TestData.otherIdRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw( + 'This extension can be used only on ERC20 requests and on supported networks mainnet, rinkeby, private', + ); + }); + + it('cannot applyActionToExtensions of creation with payment address not valid', () => { + const testnetPaymentAddress = Utils.deepCopy( + DataERC20Create.actionCreationWithPaymentAndRefund, + ); + testnetPaymentAddress.parameters.paymentAddress = DataERC20AddPaymentAddress.invalidAddress; + expect(() => { + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateNoExtensions.extensions, + testnetPaymentAddress, + DataERC20Create.requestStateNoExtensions, + TestData.otherIdRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw('paymentAddress is not a valid address'); + }); + + it('cannot applyActionToExtensions of creation with refund address not valid', () => { + const testnetRefundAddress = Utils.deepCopy( + DataERC20Create.actionCreationWithPaymentAndRefund, + ); + testnetRefundAddress.parameters.refundAddress = DataERC20AddPaymentAddress.invalidAddress; + expect(() => { + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateNoExtensions.extensions, + testnetRefundAddress, + DataERC20Create.requestStateNoExtensions, + TestData.otherIdRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw('refundAddress is not a valid address'); + }); + }); + + describe('applyActionToExtension/addPaymentAddress', () => { + it('can applyActionToExtensions of addPaymentAddress', () => { + expect( + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateCreatedEmpty.extensions, + DataERC20AddPaymentAddress.actionAddPaymentAddress, + DataERC20Create.requestStateCreatedEmpty, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ), + 'new extension state wrong', + ).to.deep.equal(DataERC20AddPaymentAddress.extensionStateWithPaymentAfterCreation); + }); + it('cannot applyActionToExtensions of addPaymentAddress without a previous state', () => { + expect(() => { + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateNoExtensions.extensions, + DataERC20AddPaymentAddress.actionAddPaymentAddress, + DataERC20Create.requestStateNoExtensions, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw( + `The extension should be created before receiving any other action`, + ); + }); + it('cannot applyActionToExtensions of addPaymentAddress without a payee', () => { + const previousState = Utils.deepCopy(DataERC20Create.requestStateCreatedEmpty); + previousState.payee = undefined; + expect(() => { + erc20ProxyContract.applyActionToExtension( + previousState.extensions, + DataERC20AddPaymentAddress.actionAddPaymentAddress, + previousState, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw(`The request must have a payee`); + }); + it('cannot applyActionToExtensions of addPaymentAddress signed by someone else than the payee', () => { + const previousState = Utils.deepCopy(DataERC20Create.requestStateCreatedEmpty); + expect(() => { + erc20ProxyContract.applyActionToExtension( + previousState.extensions, + DataERC20AddPaymentAddress.actionAddPaymentAddress, + previousState, + TestData.payerRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw(`The signer must be the payee`); + }); + it('cannot applyActionToExtensions of addPaymentAddress with payment address already given', () => { + expect(() => { + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateCreatedWithPaymentAndRefund.extensions, + DataERC20AddPaymentAddress.actionAddPaymentAddress, + DataERC20Create.requestStateCreatedWithPaymentAndRefund, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw(`Payment address already given`); + }); + it('cannot applyActionToExtensions of addPaymentAddress with payment address not valid', () => { + const testnetPaymentAddress = Utils.deepCopy( + DataERC20AddPaymentAddress.actionAddPaymentAddress, + ); + testnetPaymentAddress.parameters.paymentAddress = DataERC20AddPaymentAddress.invalidAddress; + expect(() => { + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateCreatedEmpty.extensions, + testnetPaymentAddress, + DataERC20Create.requestStateCreatedEmpty, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw('paymentAddress is not a valid address'); + }); + }); + + describe('applyActionToExtension/addRefundAddress', () => { + it('can applyActionToExtensions of addRefundAddress', () => { + expect( + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateCreatedEmpty.extensions, + DataERC20AddPaymentAddress.actionAddRefundAddress, + DataERC20Create.requestStateCreatedEmpty, + TestData.payerRaw.identity, + TestData.arbitraryTimestamp, + ), + 'new extension state wrong', + ).to.deep.equal(DataERC20AddPaymentAddress.extensionStateWithRefundAfterCreation); + }); + it('cannot applyActionToExtensions of addRefundAddress without a previous state', () => { + expect(() => { + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateNoExtensions.extensions, + DataERC20AddPaymentAddress.actionAddRefundAddress, + DataERC20Create.requestStateNoExtensions, + TestData.payerRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw( + `The extension should be created before receiving any other action`, + ); + }); + it('cannot applyActionToExtensions of addRefundAddress without a payer', () => { + const previousState = Utils.deepCopy(DataERC20Create.requestStateCreatedEmpty); + previousState.payer = undefined; + expect(() => { + erc20ProxyContract.applyActionToExtension( + previousState.extensions, + DataERC20AddPaymentAddress.actionAddRefundAddress, + previousState, + TestData.payerRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw(`The request must have a payer`); + }); + it('cannot applyActionToExtensions of addRefundAddress signed by someone else than the payer', () => { + const previousState = Utils.deepCopy(DataERC20Create.requestStateCreatedEmpty); + expect(() => { + erc20ProxyContract.applyActionToExtension( + previousState.extensions, + DataERC20AddPaymentAddress.actionAddRefundAddress, + previousState, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw(`The signer must be the payer`); + }); + it('cannot applyActionToExtensions of addRefundAddress with payment address already given', () => { + expect(() => { + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateCreatedWithPaymentAndRefund.extensions, + DataERC20AddPaymentAddress.actionAddRefundAddress, + DataERC20Create.requestStateCreatedWithPaymentAndRefund, + TestData.payerRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw(`Refund address already given`); + }); + it('cannot applyActionToExtensions of addRefundAddress with refund address not valid', () => { + const testnetPaymentAddress = Utils.deepCopy( + DataERC20AddPaymentAddress.actionAddRefundAddress, + ); + testnetPaymentAddress.parameters.refundAddress = DataERC20AddPaymentAddress.invalidAddress; + expect(() => { + erc20ProxyContract.applyActionToExtension( + DataERC20Create.requestStateCreatedEmpty.extensions, + testnetPaymentAddress, + DataERC20Create.requestStateCreatedEmpty, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw('refundAddress is not a valid address'); + }); + }); + }); +}); diff --git a/packages/advanced-logic/test/extensions/payment-network/ethereum/input-data.test.ts b/packages/advanced-logic/test/extensions/payment-network/ethereum/input-data.test.ts index 12f8fb5219..4390028e13 100644 --- a/packages/advanced-logic/test/extensions/payment-network/ethereum/input-data.test.ts +++ b/packages/advanced-logic/test/extensions/payment-network/ethereum/input-data.test.ts @@ -78,7 +78,7 @@ describe('extensions/payment-network/ethereum/input-data', () => { }), 'extensionsdata is wrong', ).to.deep.equal({ - action: ExtensionTypes.PnAddressBased.ACTION.ADD_PAYMENT_ADDRESS, + action: ExtensionTypes.PnReferenceBased.ACTION.ADD_PAYMENT_ADDRESS, id: ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA, parameters: { paymentAddress: '0x0000000000000000000000000000000000000001', @@ -103,7 +103,7 @@ describe('extensions/payment-network/ethereum/input-data', () => { }), 'extensionsdata is wrong', ).to.deep.equal({ - action: ExtensionTypes.PnAddressBased.ACTION.ADD_REFUND_ADDRESS, + action: ExtensionTypes.PnReferenceBased.ACTION.ADD_REFUND_ADDRESS, id: ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA, parameters: { refundAddress: '0x0000000000000000000000000000000000000002', diff --git a/packages/advanced-logic/test/extensions/payment-network/reference-based.test.ts b/packages/advanced-logic/test/extensions/payment-network/reference-based.test.ts new file mode 100644 index 0000000000..586d5a0323 --- /dev/null +++ b/packages/advanced-logic/test/extensions/payment-network/reference-based.test.ts @@ -0,0 +1,300 @@ +import 'mocha'; + +import referenceBasedManager from '../../../src/extensions/payment-network/reference-based'; + +import { ExtensionTypes } from '@requestnetwork/types'; + +import Utils from '@requestnetwork/utils'; + +import { expect } from 'chai'; + +import * as DataAddPaymentAddress from '../../utils/payment-network/reference-based-add-payment-address-data-generator'; +import * as DataCreate from '../../utils/payment-network/reference-based-data-generator'; +import * as TestData from '../../utils/test-data-generator'; + +const isValidAddressMock = (valid = true): (() => boolean) => (): boolean => valid; + +const PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED = 'do-not-use!-pn-test-reference-based' as ExtensionTypes.ID; + +/* tslint:disable:no-unused-expression */ +describe('extensions/payment-network/reference-based', () => { + describe('createCreationAction', () => { + it('can createCreationAction with payment and refund', () => { + expect( + referenceBasedManager.createCreationAction(PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, { + paymentAddress: DataCreate.paymentAddress, + refundAddress: DataCreate.refundAddress, + salt: DataCreate.salt, + }), + 'extensionsdata is wrong', + ).to.deep.equal(DataCreate.actionCreationWithPaymentAndRefund); + }); + + it('can createCreationAction with paymentAddress', () => { + // deep copy to remove the undefined properties to comply deep.equal() + expect( + Utils.deepCopy( + referenceBasedManager.createCreationAction(PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, { + paymentAddress: DataCreate.paymentAddress, + salt: DataCreate.salt, + }), + ), + 'extensionsdata is wrong', + ).to.deep.equal(DataCreate.actionCreationOnlyPayment); + }); + it('can createCreationAction with refundAddress', () => { + // deep copy to remove the undefined properties to comply deep.equal() + expect( + Utils.deepCopy( + referenceBasedManager.createCreationAction(PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, { + refundAddress: DataCreate.refundAddress, + salt: DataCreate.salt, + }), + ), + 'extensionsdata is wrong', + ).to.deep.equal(DataCreate.actionCreationOnlyRefund); + }); + it('can createCreationAction with only salt', () => { + // deep copy to remove the undefined properties to comply deep.equal() + expect( + Utils.deepCopy( + referenceBasedManager.createCreationAction(PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, { + salt: DataCreate.salt, + }), + ), + 'extensionsdata is wrong', + ).to.deep.equal(DataCreate.actionCreationEmpty); + }); + it('prevent createCreationAction with no salt', () => { + expect(() => { + referenceBasedManager.createCreationAction( + PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + {} as ExtensionTypes.PnReferenceBased.ICreationParameters, + ); + }, 'must throw').to.throw('salt should not be empty'); + }); + it('prevent createCreationAction with invalid salt', () => { + expect(() => { + referenceBasedManager.createCreationAction(PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, { + salt: DataCreate.invalidSalt, + }); + }, 'must throw').to.throw( + `The salt must be a string of minimum 16 hexadecimal characters. Example: 'ea3bc7caf64110ca'`, + ); + }); + }); + + describe('createAddPaymentAddressAction', () => { + it('can createAddPaymentAddressAction', () => { + expect( + referenceBasedManager.createAddPaymentAddressAction( + PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + { + paymentAddress: DataAddPaymentAddress.paymentAddress, + }, + ), + 'extensionsdata is wrong', + ).to.deep.equal(DataAddPaymentAddress.actionAddPaymentAddress); + }); + }); + + describe('createAddRefundAddressAction', () => { + it('can createAddRefundAddressAction', () => { + expect( + referenceBasedManager.createAddRefundAddressAction( + PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + { + refundAddress: DataAddPaymentAddress.refundAddress, + }, + ), + 'extensionsdata is wrong', + ).to.deep.equal(DataAddPaymentAddress.actionAddRefundAddress); + }); + }); + + describe('applyActionToExtension', () => { + describe('applyActionToExtension/unknown action', () => { + it('cannot applyActionToExtensions of unknown action', () => { + const unknownAction = Utils.deepCopy(DataAddPaymentAddress.actionAddPaymentAddress); + unknownAction.action = 'unknown action'; + expect(() => { + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + DataCreate.requestStateCreatedEmpty.extensions, + unknownAction, + DataCreate.requestStateCreatedEmpty, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw('Unknown action: unknown action'); + }); + }); + + describe('applyActionToExtension/create', () => { + it('can applyActionToExtensions of creation', () => { + expect( + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + DataCreate.requestStateNoExtensions.extensions, + DataCreate.actionCreationWithPaymentAndRefund, + DataCreate.requestStateNoExtensions, + TestData.otherIdRaw.identity, + TestData.arbitraryTimestamp, + ), + 'new extension state wrong', + ).to.deep.equal(DataCreate.extensionStateWithPaymentAndRefund); + }); + + it('cannot applyActionToExtensions of creation with a previous state', () => { + expect(() => { + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + DataCreate.requestStateCreatedWithPaymentAndRefund.extensions, + DataCreate.actionCreationWithPaymentAndRefund, + DataCreate.requestStateCreatedWithPaymentAndRefund, + TestData.otherIdRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw('This extension has already been created'); + }); + }); + + describe('applyActionToExtension/addPaymentAddress', () => { + it('can applyActionToExtensions of addPaymentAddress', () => { + expect( + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + DataCreate.requestStateCreatedEmpty.extensions, + DataAddPaymentAddress.actionAddPaymentAddress, + DataCreate.requestStateCreatedEmpty, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ), + 'new extension state wrong', + ).to.deep.equal(DataAddPaymentAddress.extensionStateWithPaymentAfterCreation); + }); + it('cannot applyActionToExtensions of addPaymentAddress without a previous state', () => { + expect(() => { + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + DataCreate.requestStateNoExtensions.extensions, + DataAddPaymentAddress.actionAddPaymentAddress, + DataCreate.requestStateNoExtensions, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw( + `The extension should be created before receiving any other action`, + ); + }); + it('cannot applyActionToExtensions of addPaymentAddress without a payee', () => { + const previousState = Utils.deepCopy(DataCreate.requestStateCreatedEmpty); + previousState.payee = undefined; + expect(() => { + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + previousState.extensions, + DataAddPaymentAddress.actionAddPaymentAddress, + previousState, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw(`The request must have a payee`); + }); + it('cannot applyActionToExtensions of addPaymentAddress signed by someone else than the payee', () => { + const previousState = Utils.deepCopy(DataCreate.requestStateCreatedEmpty); + expect(() => { + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + previousState.extensions, + DataAddPaymentAddress.actionAddPaymentAddress, + previousState, + TestData.payerRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw(`The signer must be the payee`); + }); + it('cannot applyActionToExtensions of addPaymentAddress with payment address already given', () => { + expect(() => { + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + DataCreate.requestStateCreatedWithPaymentAndRefund.extensions, + DataAddPaymentAddress.actionAddPaymentAddress, + DataCreate.requestStateCreatedWithPaymentAndRefund, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw(`Payment address already given`); + }); + }); + + describe('applyActionToExtension/addRefundAddress', () => { + it('can applyActionToExtensions of addRefundAddress', () => { + expect( + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + DataCreate.requestStateCreatedEmpty.extensions, + DataAddPaymentAddress.actionAddRefundAddress, + DataCreate.requestStateCreatedEmpty, + TestData.payerRaw.identity, + TestData.arbitraryTimestamp, + ), + 'new extension state wrong', + ).to.deep.equal(DataAddPaymentAddress.extensionStateWithRefundAfterCreation); + }); + it('cannot applyActionToExtensions of addRefundAddress without a previous state', () => { + expect(() => { + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + DataCreate.requestStateNoExtensions.extensions, + DataAddPaymentAddress.actionAddRefundAddress, + DataCreate.requestStateNoExtensions, + TestData.payerRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw( + `The extension should be created before receiving any other action`, + ); + }); + it('cannot applyActionToExtensions of addRefundAddress without a payer', () => { + const previousState = Utils.deepCopy(DataCreate.requestStateCreatedEmpty); + previousState.payer = undefined; + expect(() => { + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + previousState.extensions, + DataAddPaymentAddress.actionAddRefundAddress, + previousState, + TestData.payerRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw(`The request must have a payer`); + }); + it('cannot applyActionToExtensions of addRefundAddress signed by someone else than the payer', () => { + const previousState = Utils.deepCopy(DataCreate.requestStateCreatedEmpty); + expect(() => { + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + previousState.extensions, + DataAddPaymentAddress.actionAddRefundAddress, + previousState, + TestData.payeeRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw(`The signer must be the payer`); + }); + it('cannot applyActionToExtensions of addRefundAddress with payment address already given', () => { + expect(() => { + referenceBasedManager.applyActionToExtension( + isValidAddressMock(), + DataCreate.requestStateCreatedWithPaymentAndRefund.extensions, + DataAddPaymentAddress.actionAddRefundAddress, + DataCreate.requestStateCreatedWithPaymentAndRefund, + TestData.payerRaw.identity, + TestData.arbitraryTimestamp, + ); + }, 'must throw').to.throw(`Refund address already given`); + }); + }); + }); +}); diff --git a/packages/advanced-logic/test/utils/payment-network/erc20/add-payment-address-data-generator.ts b/packages/advanced-logic/test/utils/payment-network/erc20/address-based-add-payment-address-data-generator.ts similarity index 98% rename from packages/advanced-logic/test/utils/payment-network/erc20/add-payment-address-data-generator.ts rename to packages/advanced-logic/test/utils/payment-network/erc20/address-based-add-payment-address-data-generator.ts index b6fa7cb523..61a702e7b4 100644 --- a/packages/advanced-logic/test/utils/payment-network/erc20/add-payment-address-data-generator.ts +++ b/packages/advanced-logic/test/utils/payment-network/erc20/address-based-add-payment-address-data-generator.ts @@ -1,4 +1,4 @@ -import * as TestDataCreate from './create-data-generator'; +import * as TestDataCreate from './address-based-create-data-generator'; import * as TestData from '../../test-data-generator'; diff --git a/packages/advanced-logic/test/utils/payment-network/erc20/create-data-generator.ts b/packages/advanced-logic/test/utils/payment-network/erc20/address-based-create-data-generator.ts similarity index 95% rename from packages/advanced-logic/test/utils/payment-network/erc20/create-data-generator.ts rename to packages/advanced-logic/test/utils/payment-network/erc20/address-based-create-data-generator.ts index 0fa424e62f..5797317272 100644 --- a/packages/advanced-logic/test/utils/payment-network/erc20/create-data-generator.ts +++ b/packages/advanced-logic/test/utils/payment-network/erc20/address-based-create-data-generator.ts @@ -15,8 +15,8 @@ export const actionCreationWithPaymentAndRefund = { action: 'create', id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED, parameters: { - paymentAddress: paymentAddress, - refundAddress: refundAddress, + paymentAddress, + refundAddress, }, version: '0.1.0', }; @@ -24,7 +24,7 @@ export const actionCreationOnlyPayment = { action: 'create', id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED, parameters: { - paymentAddress: paymentAddress, + paymentAddress, }, version: '0.1.0', }; @@ -32,7 +32,7 @@ export const actionCreationOnlyRefund = { action: 'create', id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED, parameters: { - refundAddress: refundAddress, + refundAddress, }, version: '0.1.0', }; @@ -51,8 +51,8 @@ export const extensionStateWithPaymentAndRefund = { { name: 'create', parameters: { - paymentAddress: paymentAddress, - refundAddress: refundAddress, + paymentAddress, + refundAddress, }, timestamp: arbitraryTimestamp, }, @@ -60,8 +60,8 @@ export const extensionStateWithPaymentAndRefund = { id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED, type: ExtensionTypes.TYPE.PAYMENT_NETWORK, values: { - paymentAddress: paymentAddress, - refundAddress: refundAddress, + paymentAddress, + refundAddress, }, version: '0.1.0', }, diff --git a/packages/advanced-logic/test/utils/payment-network/erc20/proxy-contract-add-payment-address-data-generator.ts b/packages/advanced-logic/test/utils/payment-network/erc20/proxy-contract-add-payment-address-data-generator.ts new file mode 100644 index 0000000000..7d22ebf98b --- /dev/null +++ b/packages/advanced-logic/test/utils/payment-network/erc20/proxy-contract-add-payment-address-data-generator.ts @@ -0,0 +1,168 @@ +import * as TestDataCreate from './proxy-contract-create-data-generator'; + +import * as TestData from '../../test-data-generator'; + +import { ExtensionTypes, IdentityTypes, RequestLogicTypes } from '@requestnetwork/types'; + +export const arbitraryTimestamp = 1544426030; + +// --------------------------------------------------------------------- +// Mock addresses for testing generic address based payment networks +export const paymentAddress = '0x627306090abaB3A6e1400e9345bC60c78a8BEf57'; +export const refundAddress = '0xf17f52151EbEF6C7334FAD080c5704D77216b732'; +export const invalidAddress = '0xnotandaddress'; +// --------------------------------------------------------------------- +export const salt = 'ea3bc7caf64110ca'; +// actions +export const actionAddPaymentAddress = { + action: ExtensionTypes.PnReferenceBased.ACTION.ADD_PAYMENT_ADDRESS, + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + parameters: { + paymentAddress, + }, +}; +export const actionAddRefundAddress = { + action: ExtensionTypes.PnReferenceBased.ACTION.ADD_REFUND_ADDRESS, + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + parameters: { + refundAddress, + }, +}; + +// --------------------------------------------------------------------- +// extensions states +export const extensionStateWithPaymentAfterCreation = { + [ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT as string]: { + events: [ + { + name: ExtensionTypes.PnReferenceBased.ACTION.CREATE, + parameters: {}, + timestamp: arbitraryTimestamp, + }, + { + name: ExtensionTypes.PnReferenceBased.ACTION.ADD_PAYMENT_ADDRESS, + parameters: { + paymentAddress, + }, + timestamp: arbitraryTimestamp, + }, + ], + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + type: ExtensionTypes.TYPE.PAYMENT_NETWORK, + values: { + paymentAddress, + }, + version: '0.1.0', + }, +}; + +export const extensionStateWithRefundAfterCreation = { + [ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT as string]: { + events: [ + { + name: ExtensionTypes.PnReferenceBased.ACTION.CREATE, + parameters: {}, + timestamp: arbitraryTimestamp, + }, + { + name: ExtensionTypes.PnReferenceBased.ACTION.ADD_REFUND_ADDRESS, + parameters: { + refundAddress, + }, + timestamp: arbitraryTimestamp, + }, + ], + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + type: ExtensionTypes.TYPE.PAYMENT_NETWORK, + values: { + refundAddress, + }, + version: '0.1.0', + }, +}; + +// --------------------------------------------------------------------- +// request states +export const requestStateCreatedEmptyThenAddPayment: RequestLogicTypes.IRequest = { + creator: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + currency: { + network: 'mainnet', + type: RequestLogicTypes.CURRENCY.ERC20, + value: '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', // SAI + }, + events: [ + { + actionSigner: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + name: RequestLogicTypes.ACTION_NAME.CREATE, + parameters: { + expectedAmount: '123400000000000000', + extensionsDataLength: 2, + isSignedRequest: false, + }, + timestamp: arbitraryTimestamp, + }, + ], + expectedAmount: TestData.arbitraryExpectedAmount, + extensions: extensionStateWithPaymentAfterCreation, + extensionsData: [TestDataCreate.actionCreationEmpty, actionAddPaymentAddress], + payee: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + payer: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payerRaw.address, + }, + requestId: TestData.requestIdMock, + state: RequestLogicTypes.STATE.CREATED, + timestamp: TestData.arbitraryTimestamp, + version: '0.1.0', +}; + +export const requestStateCreatedEmptyThenAddRefund: RequestLogicTypes.IRequest = { + creator: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + currency: { + network: 'mainnet', + type: RequestLogicTypes.CURRENCY.ERC20, + value: '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', // SAI + }, + events: [ + { + actionSigner: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + name: RequestLogicTypes.ACTION_NAME.CREATE, + parameters: { + expectedAmount: '123400000000000000', + extensionsDataLength: 2, + isSignedRequest: false, + }, + timestamp: arbitraryTimestamp, + }, + ], + expectedAmount: TestData.arbitraryExpectedAmount, + extensions: extensionStateWithRefundAfterCreation, + extensionsData: [TestDataCreate.actionCreationEmpty, actionAddRefundAddress], + payee: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + payer: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payerRaw.address, + }, + requestId: TestData.requestIdMock, + state: RequestLogicTypes.STATE.CREATED, + timestamp: TestData.arbitraryTimestamp, + version: '0.1.0', +}; diff --git a/packages/advanced-logic/test/utils/payment-network/erc20/proxy-contract-create-data-generator.ts b/packages/advanced-logic/test/utils/payment-network/erc20/proxy-contract-create-data-generator.ts new file mode 100644 index 0000000000..e7e304071f --- /dev/null +++ b/packages/advanced-logic/test/utils/payment-network/erc20/proxy-contract-create-data-generator.ts @@ -0,0 +1,215 @@ +import * as TestData from '../../test-data-generator'; + +import { ExtensionTypes, IdentityTypes, RequestLogicTypes } from '@requestnetwork/types'; + +export const arbitraryTimestamp = 1544426030; + +// --------------------------------------------------------------------- +// Mock addresses for testing ETH payment networks +export const paymentAddress = '0x627306090abaB3A6e1400e9345bC60c78a8BEf57'; +export const refundAddress = '0xf17f52151EbEF6C7334FAD080c5704D77216b732'; +export const invalidAddress = '0xnotandaddress'; +// --------------------------------------------------------------------- +export const salt = 'ea3bc7caf64110ca'; +// actions +export const actionCreationWithPaymentAndRefund = { + action: 'create', + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + parameters: { + paymentAddress, + refundAddress, + salt, + }, + version: '0.1.0', +}; +export const actionCreationOnlyPayment = { + action: 'create', + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + parameters: { + paymentAddress, + }, + version: '0.1.0', +}; +export const actionCreationOnlyRefund = { + action: 'create', + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + parameters: { + refundAddress, + }, + version: '0.1.0', +}; +export const actionCreationEmpty = { + action: 'create', + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + parameters: {}, + version: '0.1.0', +}; + +// --------------------------------------------------------------------- +// extensions states +export const extensionStateWithPaymentAndRefund = { + [ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT as string]: { + events: [ + { + name: 'create', + parameters: { + paymentAddress, + refundAddress, + salt, + }, + timestamp: arbitraryTimestamp, + }, + ], + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + type: ExtensionTypes.TYPE.PAYMENT_NETWORK, + values: { + paymentAddress, + refundAddress, + salt, + }, + version: '0.1.0', + }, +}; +export const extensionStateCreatedEmpty = { + [ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT as string]: { + events: [ + { + name: 'create', + parameters: {}, + timestamp: arbitraryTimestamp, + }, + ], + id: ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + type: ExtensionTypes.TYPE.PAYMENT_NETWORK, + values: {}, + version: '0.1.0', + }, +}; + +// --------------------------------------------------------------------- +// request states +export const requestStateNoExtensions: RequestLogicTypes.IRequest = { + creator: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + currency: { + network: 'mainnet', + type: RequestLogicTypes.CURRENCY.ERC20, + value: '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', // SAI + }, + events: [ + { + actionSigner: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + name: RequestLogicTypes.ACTION_NAME.CREATE, + parameters: { + expectedAmount: '123400000000000000', + extensionsDataLength: 0, + isSignedRequest: false, + }, + timestamp: arbitraryTimestamp, + }, + ], + expectedAmount: TestData.arbitraryExpectedAmount, + extensions: {}, + extensionsData: [], + payee: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + payer: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payerRaw.address, + }, + requestId: TestData.requestIdMock, + state: RequestLogicTypes.STATE.CREATED, + timestamp: TestData.arbitraryTimestamp, + version: '0.1.0', +}; + +export const requestStateCreatedWithPaymentAndRefund: RequestLogicTypes.IRequest = { + creator: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + currency: { + network: 'mainnet', + type: RequestLogicTypes.CURRENCY.ERC20, + value: '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', // SAI + }, + events: [ + { + actionSigner: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + name: RequestLogicTypes.ACTION_NAME.CREATE, + parameters: { + expectedAmount: '123400000000000000', + extensionsDataLength: 1, + isSignedRequest: false, + }, + timestamp: arbitraryTimestamp, + }, + ], + expectedAmount: TestData.arbitraryExpectedAmount, + extensions: extensionStateWithPaymentAndRefund, + extensionsData: [actionCreationWithPaymentAndRefund], + payee: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + payer: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payerRaw.address, + }, + requestId: TestData.requestIdMock, + state: RequestLogicTypes.STATE.CREATED, + timestamp: TestData.arbitraryTimestamp, + version: '0.1.0', +}; + +export const requestStateCreatedEmpty: RequestLogicTypes.IRequest = { + creator: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + currency: { + network: 'mainnet', + type: RequestLogicTypes.CURRENCY.ERC20, + value: '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', // SAI + }, + events: [ + { + actionSigner: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + name: RequestLogicTypes.ACTION_NAME.CREATE, + parameters: { + expectedAmount: '123400000000000000', + extensionsDataLength: 1, + isSignedRequest: false, + }, + timestamp: arbitraryTimestamp, + }, + ], + expectedAmount: TestData.arbitraryExpectedAmount, + extensions: extensionStateCreatedEmpty, + extensionsData: [actionCreationEmpty], + payee: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + payer: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payerRaw.address, + }, + requestId: TestData.requestIdMock, + state: RequestLogicTypes.STATE.CREATED, + timestamp: TestData.arbitraryTimestamp, + version: '0.1.0', +}; diff --git a/packages/advanced-logic/test/utils/payment-network/ethereum/add-payment-address-data-generator.ts b/packages/advanced-logic/test/utils/payment-network/ethereum/add-payment-address-data-generator.ts index 98082ef7d2..f36ff2c677 100644 --- a/packages/advanced-logic/test/utils/payment-network/ethereum/add-payment-address-data-generator.ts +++ b/packages/advanced-logic/test/utils/payment-network/ethereum/add-payment-address-data-generator.ts @@ -15,14 +15,14 @@ export const invalidAddress = '0xnotandaddress'; export const salt = 'ea3bc7caf64110ca'; // actions export const actionAddPaymentAddress = { - action: ExtensionTypes.PnAddressBased.ACTION.ADD_PAYMENT_ADDRESS, + action: ExtensionTypes.PnReferenceBased.ACTION.ADD_PAYMENT_ADDRESS, id: ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA, parameters: { paymentAddress, }, }; export const actionAddRefundAddress = { - action: ExtensionTypes.PnAddressBased.ACTION.ADD_REFUND_ADDRESS, + action: ExtensionTypes.PnReferenceBased.ACTION.ADD_REFUND_ADDRESS, id: ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA, parameters: { refundAddress, @@ -35,12 +35,12 @@ export const extensionStateWithPaymentAfterCreation = { [ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA as string]: { events: [ { - name: ExtensionTypes.PnAddressBased.ACTION.CREATE, + name: ExtensionTypes.PnReferenceBased.ACTION.CREATE, parameters: {}, timestamp: arbitraryTimestamp, }, { - name: ExtensionTypes.PnAddressBased.ACTION.ADD_PAYMENT_ADDRESS, + name: ExtensionTypes.PnReferenceBased.ACTION.ADD_PAYMENT_ADDRESS, parameters: { paymentAddress, }, @@ -60,12 +60,12 @@ export const extensionStateWithRefundAfterCreation = { [ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA as string]: { events: [ { - name: ExtensionTypes.PnAddressBased.ACTION.CREATE, + name: ExtensionTypes.PnReferenceBased.ACTION.CREATE, parameters: {}, timestamp: arbitraryTimestamp, }, { - name: ExtensionTypes.PnAddressBased.ACTION.ADD_REFUND_ADDRESS, + name: ExtensionTypes.PnReferenceBased.ACTION.ADD_REFUND_ADDRESS, parameters: { refundAddress, }, diff --git a/packages/advanced-logic/test/utils/payment-network/reference-based-add-payment-address-data-generator.ts b/packages/advanced-logic/test/utils/payment-network/reference-based-add-payment-address-data-generator.ts new file mode 100644 index 0000000000..f8fef9e36f --- /dev/null +++ b/packages/advanced-logic/test/utils/payment-network/reference-based-add-payment-address-data-generator.ts @@ -0,0 +1,170 @@ +import * as TestDataCreate from './reference-based-data-generator'; + +import * as TestData from '../test-data-generator'; + +import { ExtensionTypes, IdentityTypes, RequestLogicTypes } from '@requestnetwork/types'; + +export const arbitraryTimestamp = 1544426030; + +const PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED = 'do-not-use!-pn-test-reference-based' as ExtensionTypes.ID; +// --------------------------------------------------------------------- +// Mock addresses for testing generic address based payment networks +export const paymentAddress = '0x627306090abaB3A6e1400e9345bC60c78a8BEf57'; +export const refundAddress = '0xf17f52151EbEF6C7334FAD080c5704D77216b732'; + +export const salt = 'ea3bc7caf64110ca'; + +// --------------------------------------------------------------------- +// actions +export const actionAddPaymentAddress = { + action: ExtensionTypes.PnReferenceBased.ACTION.ADD_PAYMENT_ADDRESS, + id: PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + parameters: { + paymentAddress, + }, +}; +export const actionAddRefundAddress = { + action: ExtensionTypes.PnReferenceBased.ACTION.ADD_REFUND_ADDRESS, + id: PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + parameters: { + refundAddress, + }, +}; + +// --------------------------------------------------------------------- +// extensions states +export const extensionStateWithPaymentAfterCreation = { + [PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED as string]: { + events: [ + { + name: ExtensionTypes.PnReferenceBased.ACTION.CREATE, + parameters: { salt }, + timestamp: arbitraryTimestamp, + }, + { + name: ExtensionTypes.PnReferenceBased.ACTION.ADD_PAYMENT_ADDRESS, + parameters: { + paymentAddress, + }, + timestamp: arbitraryTimestamp, + }, + ], + id: PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + type: ExtensionTypes.TYPE.PAYMENT_NETWORK, + values: { + paymentAddress, + salt, + }, + version: '0.1.0', + }, +}; + +export const extensionStateWithRefundAfterCreation = { + [PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED as string]: { + events: [ + { + name: ExtensionTypes.PnReferenceBased.ACTION.CREATE, + parameters: { salt }, + timestamp: arbitraryTimestamp, + }, + { + name: ExtensionTypes.PnReferenceBased.ACTION.ADD_REFUND_ADDRESS, + parameters: { + refundAddress, + }, + timestamp: arbitraryTimestamp, + }, + ], + id: PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + type: ExtensionTypes.TYPE.PAYMENT_NETWORK, + values: { + refundAddress, + salt, + }, + version: '0.1.0', + }, +}; + +// --------------------------------------------------------------------- +// request states +export const requestStateCreatedEmptyThenAddPayment: RequestLogicTypes.IRequest = { + creator: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + currency: { + type: RequestLogicTypes.CURRENCY.ISO4217, + value: 'EUR', + }, + events: [ + { + actionSigner: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + name: RequestLogicTypes.ACTION_NAME.CREATE, + parameters: { + expectedAmount: '123400000000000000', + extensionsDataLength: 2, + isSignedRequest: false, + }, + timestamp: arbitraryTimestamp, + }, + ], + expectedAmount: TestData.arbitraryExpectedAmount, + extensions: extensionStateWithPaymentAfterCreation, + extensionsData: [TestDataCreate.actionCreationEmpty, actionAddPaymentAddress], + payee: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + payer: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payerRaw.address, + }, + requestId: TestData.requestIdMock, + state: RequestLogicTypes.STATE.CREATED, + timestamp: TestData.arbitraryTimestamp, + version: '0.1.0', +}; + +export const requestStateCreatedEmptyThenAddRefund: RequestLogicTypes.IRequest = { + creator: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + currency: { + type: RequestLogicTypes.CURRENCY.ISO4217, + value: 'EUR', + }, + events: [ + { + actionSigner: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + name: RequestLogicTypes.ACTION_NAME.CREATE, + parameters: { + expectedAmount: '123400000000000000', + extensionsDataLength: 2, + isSignedRequest: false, + }, + timestamp: arbitraryTimestamp, + }, + ], + expectedAmount: TestData.arbitraryExpectedAmount, + extensions: extensionStateWithRefundAfterCreation, + extensionsData: [TestDataCreate.actionCreationEmpty, actionAddRefundAddress], + payee: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + payer: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payerRaw.address, + }, + requestId: TestData.requestIdMock, + state: RequestLogicTypes.STATE.CREATED, + timestamp: TestData.arbitraryTimestamp, + version: '0.1.0', +}; diff --git a/packages/advanced-logic/test/utils/payment-network/reference-based-data-generator.ts b/packages/advanced-logic/test/utils/payment-network/reference-based-data-generator.ts new file mode 100644 index 0000000000..24de03ee10 --- /dev/null +++ b/packages/advanced-logic/test/utils/payment-network/reference-based-data-generator.ts @@ -0,0 +1,219 @@ +import * as TestData from '../test-data-generator'; + +import { ExtensionTypes, IdentityTypes, RequestLogicTypes } from '@requestnetwork/types'; + +export const arbitraryTimestamp = 1544426030; + +const PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED = 'do-not-use!-pn-test-reference-based' as ExtensionTypes.ID; +// --------------------------------------------------------------------- +// Mock addresses for testing generic address based payment networks +export const paymentAddress = '0x627306090abaB3A6e1400e9345bC60c78a8BEf57'; +export const refundAddress = '0xf17f52151EbEF6C7334FAD080c5704D77216b732'; + +export const salt = 'ea3bc7caf64110ca'; + +// This salt is not valid, it contains a 'z' +export const invalidSalt = 'ea3bc7czf64110ca'; + +// --------------------------------------------------------------------- +// actions +export const actionCreationWithPaymentAndRefund = { + action: 'create', + id: PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + parameters: { + paymentAddress, + refundAddress, + salt, + }, + version: '0.1.0', +}; +export const actionCreationOnlyPayment = { + action: 'create', + id: PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + parameters: { + paymentAddress, + salt, + }, + version: '0.1.0', +}; +export const actionCreationOnlyRefund = { + action: 'create', + id: PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + parameters: { + refundAddress, + salt, + }, + version: '0.1.0', +}; +export const actionCreationEmpty = { + action: 'create', + id: PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + parameters: { salt }, + version: '0.1.0', +}; + +// --------------------------------------------------------------------- +// extensions states +export const extensionStateWithPaymentAndRefund = { + [PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED as string]: { + events: [ + { + name: 'create', + parameters: { + paymentAddress, + refundAddress, + salt, + }, + timestamp: arbitraryTimestamp, + }, + ], + id: PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + type: ExtensionTypes.TYPE.PAYMENT_NETWORK, + values: { + paymentAddress, + refundAddress, + salt, + }, + version: '0.1.0', + }, +}; +export const extensionStateCreatedEmpty = { + [PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED as string]: { + events: [ + { + name: 'create', + parameters: { salt }, + timestamp: arbitraryTimestamp, + }, + ], + id: PAYMENT_NETWORK_TEST_GENERIC_REFERENCE_BASED, + type: ExtensionTypes.TYPE.PAYMENT_NETWORK, + values: { salt }, + version: '0.1.0', + }, +}; + +// --------------------------------------------------------------------- +// request states +export const requestStateNoExtensions: RequestLogicTypes.IRequest = { + creator: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + currency: { + type: RequestLogicTypes.CURRENCY.ISO4217, + value: 'EUR', + }, + events: [ + { + actionSigner: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + name: RequestLogicTypes.ACTION_NAME.CREATE, + parameters: { + expectedAmount: '123400000000000000', + extensionsDataLength: 0, + isSignedRequest: false, + }, + timestamp: arbitraryTimestamp, + }, + ], + expectedAmount: TestData.arbitraryExpectedAmount, + extensions: {}, + extensionsData: [], + payee: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + payer: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payerRaw.address, + }, + requestId: TestData.requestIdMock, + state: RequestLogicTypes.STATE.CREATED, + timestamp: TestData.arbitraryTimestamp, + version: '0.1.0', +}; + +export const requestStateCreatedWithPaymentAndRefund: RequestLogicTypes.IRequest = { + creator: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + currency: { + type: RequestLogicTypes.CURRENCY.ISO4217, + value: 'EUR', + }, + events: [ + { + actionSigner: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + name: RequestLogicTypes.ACTION_NAME.CREATE, + parameters: { + expectedAmount: '123400000000000000', + extensionsDataLength: 1, + isSignedRequest: false, + }, + timestamp: arbitraryTimestamp, + }, + ], + expectedAmount: TestData.arbitraryExpectedAmount, + extensions: extensionStateWithPaymentAndRefund, + extensionsData: [actionCreationWithPaymentAndRefund], + payee: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + payer: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payerRaw.address, + }, + requestId: TestData.requestIdMock, + state: RequestLogicTypes.STATE.CREATED, + timestamp: TestData.arbitraryTimestamp, + version: '0.1.0', +}; + +export const requestStateCreatedEmpty: RequestLogicTypes.IRequest = { + creator: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + currency: { + type: RequestLogicTypes.CURRENCY.ISO4217, + value: 'EUR', + }, + events: [ + { + actionSigner: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + name: RequestLogicTypes.ACTION_NAME.CREATE, + parameters: { + expectedAmount: '123400000000000000', + extensionsDataLength: 1, + isSignedRequest: false, + }, + timestamp: arbitraryTimestamp, + }, + ], + expectedAmount: TestData.arbitraryExpectedAmount, + extensions: extensionStateCreatedEmpty, + extensionsData: [actionCreationEmpty], + payee: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payeeRaw.address, + }, + payer: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: TestData.payerRaw.address, + }, + requestId: TestData.requestIdMock, + state: RequestLogicTypes.STATE.CREATED, + timestamp: TestData.arbitraryTimestamp, + version: '0.1.0', +}; diff --git a/packages/data-access/.vscode/settings.json b/packages/data-access/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/data-access/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/data-access/CHANGELOG.md b/packages/data-access/CHANGELOG.md index f4a4411d2f..1971c922ea 100644 --- a/packages/data-access/CHANGELOG.md +++ b/packages/data-access/CHANGELOG.md @@ -3,6 +3,38 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.5.5](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/data-access@0.5.2...@requestnetwork/data-access@0.5.5) (2020-01-16) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/data-access + + + + + +## [0.5.4](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/data-access@0.5.2...@requestnetwork/data-access@0.5.4) (2019-12-18) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/data-access + + + + + +## [0.5.3](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/data-access@0.5.2...@requestnetwork/data-access@0.5.3) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/data-access + + + + + ## [0.5.2](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/data-access@0.5.1...@requestnetwork/data-access@0.5.2) (2019-11-20) **Note:** Version bump only for package @requestnetwork/data-access diff --git a/packages/data-access/package.json b/packages/data-access/package.json index b2ca1a2604..bb3edd3958 100644 --- a/packages/data-access/package.json +++ b/packages/data-access/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/data-access", - "version": "0.5.2", + "version": "0.5.5", "publishConfig": { "access": "public" }, @@ -32,33 +32,33 @@ ], "scripts": { "build": "tsc -b", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", "stryker": "stryker run", - "test": "nyc mocha --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", - "test:watch": "nyc mocha --watch --watch-extensions ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"" + "test": "nyc mocha --extension ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", + "test:watch": "yarn test --watch" }, "dependencies": { - "@requestnetwork/multi-format": "0.2.1", - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0", + "@requestnetwork/multi-format": "0.2.4", + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0", "bluebird": "3.5.5", "keyv": "3.1.0" }, "devDependencies": { - "@stryker-mutator/core": "2.1.0", + "@stryker-mutator/core": "2.4.0", "@stryker-mutator/html-reporter": "2.1.0", "@stryker-mutator/mocha-framework": "2.1.0", "@stryker-mutator/mocha-runner": "2.1.0", - "@stryker-mutator/typescript": "2.1.0", + "@stryker-mutator/typescript": "2.3.0", "@types/bluebird": "3.5.27", "@types/chai": "4.1.7", "@types/chai-spies": "1.0.0", "@types/keyv": "3.1.0", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", "@types/node": "12.0.3", - "@types/sinon": "7.0.5", + "@types/sinon": "7.5.0", "@typescript-eslint/parser": "1.2.0", "chai": "4.2.0", "chai-as-promised": "7.1.1", @@ -67,13 +67,13 @@ "eslint-plugin-spellcheck": "0.0.11", "eslint-plugin-typescript": "0.14.0", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "nyc": "13.2.0", "prettier": "1.16.4", "shx": "0.3.2", - "sinon": "7.2.3", + "sinon": "7.5.0", "source-map-support": "0.5.13", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "tslint": "5.12.1", "typescript": "3.7.2" }, diff --git a/packages/data-access/test/interval-timer.test.ts b/packages/data-access/test/interval-timer.test.ts index 1f58e813f9..4715a73761 100644 --- a/packages/data-access/test/interval-timer.test.ts +++ b/packages/data-access/test/interval-timer.test.ts @@ -27,9 +27,9 @@ const flushCallStack = (): Promise => { const emptyLogger = { debug: (_string: string): void => {}, - error: (_string: string): void => {}, - info: (_string: string): void => {}, - warn: (_string: string): void => {}, + error: (_string: string): void => {}, + info: (_string: string): void => {}, + warn: (_string: string): void => {}, } as LogTypes.ILogger; let intervalFunctionWithErrorCount: number; @@ -85,7 +85,7 @@ describe('interval-timer', () => { }); it('should periodically call the interval function provided when start() is called', async () => { - const callback = sinon.spy(async () => 0); + const callback = sinon.spy(async () => {}); intervalTimer = new IntervalTimer(callback, 1000, emptyLogger); intervalTimer.start(); @@ -168,7 +168,7 @@ describe('interval-timer', () => { hasBeenRejected = true; throw Error('makeReject set'); } - return 0; + return; }); intervalTimer = new IntervalTimer(callback, 1000, emptyLogger); diff --git a/packages/data-format/.vscode/settings.json b/packages/data-format/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/data-format/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/data-format/CHANGELOG.md b/packages/data-format/CHANGELOG.md index 66bd080165..4532da2f95 100644 --- a/packages/data-format/CHANGELOG.md +++ b/packages/data-format/CHANGELOG.md @@ -3,6 +3,38 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.4.8](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/data-format@0.4.5...@requestnetwork/data-format@0.4.8) (2020-01-16) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/data-format + + + + + +## [0.4.7](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/data-format@0.4.5...@requestnetwork/data-format@0.4.7) (2019-12-18) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/data-format + + + + + +## [0.4.6](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/data-format@0.4.5...@requestnetwork/data-format@0.4.6) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/data-format + + + + + ## [0.4.5](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/data-format@0.4.4...@requestnetwork/data-format@0.4.5) (2019-11-20) **Note:** Version bump only for package @requestnetwork/data-format diff --git a/packages/data-format/package.json b/packages/data-format/package.json index 9cd3e446a9..2487370bea 100644 --- a/packages/data-format/package.json +++ b/packages/data-format/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/data-format", - "version": "0.4.5", + "version": "0.4.8", "publishConfig": { "access": "public" }, @@ -33,20 +33,20 @@ ], "scripts": { "build": "tsc -b", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", - "test": "nyc mocha --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", - "test:watch": "nyc mocha --watch --watch-extensions json --require ts-node/register --require source-map-support/register \"test/**/*.ts\"" + "test": "nyc mocha --extension ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", + "test:watch": "yarn test --watch" }, "dependencies": { "ajv": "6.8.1", - "tslib": "1.9.3", + "tslib": "1.10.0", "typescript": "3.7.2" }, "devDependencies": { "@types/chai": "4.1.7", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", "@types/node": "10.12.21", "chai": "4.2.0", "chai-as-promised": "7.1.1", @@ -56,12 +56,12 @@ "eslint-plugin-spellcheck": "0.0.11", "eslint-plugin-typescript": "0.14.0", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "nyc": "13.2.0", "prettier": "1.16.4", "rimraf": "2.6.3", "shx": "0.3.2", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "tslint": "5.12.1" }, "gitHead": "6155223cfce769e48ccae480c510b35b4f54b4d0" diff --git a/packages/epk-decryption/.vscode/settings.json b/packages/epk-decryption/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/epk-decryption/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/epk-decryption/CHANGELOG.md b/packages/epk-decryption/CHANGELOG.md index 484fdbaf0b..058b30c27a 100644 --- a/packages/epk-decryption/CHANGELOG.md +++ b/packages/epk-decryption/CHANGELOG.md @@ -3,6 +3,38 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.3.6](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/epk-decryption@0.3.3...@requestnetwork/epk-decryption@0.3.6) (2020-01-16) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/epk-decryption + + + + + +## [0.3.5](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/epk-decryption@0.3.3...@requestnetwork/epk-decryption@0.3.5) (2019-12-18) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/epk-decryption + + + + + +## [0.3.4](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/epk-decryption@0.3.3...@requestnetwork/epk-decryption@0.3.4) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/epk-decryption + + + + + ## [0.3.3](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/epk-decryption@0.3.2...@requestnetwork/epk-decryption@0.3.3) (2019-11-20) **Note:** Version bump only for package @requestnetwork/epk-decryption diff --git a/packages/epk-decryption/package.json b/packages/epk-decryption/package.json index e35f0a1259..9dc9c76134 100644 --- a/packages/epk-decryption/package.json +++ b/packages/epk-decryption/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/epk-decryption", - "version": "0.3.3", + "version": "0.3.6", "publishConfig": { "access": "public" }, @@ -34,20 +34,20 @@ "build": "run-s build:commonjs build:umd", "build:commonjs": "tsc -b", "build:umd": "webpack", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", - "test": "nyc mocha --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", - "test:watch": "nyc mocha --watch --watch-extensions ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"" + "test": "nyc mocha --extension ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", + "test:watch": "yarn test --watch" }, "dependencies": { - "@requestnetwork/multi-format": "0.2.1", - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0" + "@requestnetwork/multi-format": "0.2.4", + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0" }, "devDependencies": { "@types/chai": "4.1.7", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", "@typescript-eslint/parser": "1.2.0", "amd-loader": "0.0.8", "awesome-typescript-loader": "5.2.1", @@ -58,18 +58,18 @@ "eslint-plugin-spellcheck": "0.0.11", "eslint-plugin-typescript": "0.14.0", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "npm-run-all": "4.1.5", "nyc": "13.2.0", "prettier": "1.16.4", "shx": "0.3.2", "source-map-support": "0.5.13", "terser-webpack-plugin": "1.3.0", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "tslint": "5.12.1", "typescript": "3.7.2", "webpack": "4.38.0", "webpack-bundle-analyzer": "3.3.2", - "webpack-cli": "3.3.6" + "webpack-cli": "3.3.10" } } diff --git a/packages/epk-signature/.vscode/settings.json b/packages/epk-signature/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/epk-signature/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/epk-signature/CHANGELOG.md b/packages/epk-signature/CHANGELOG.md index 5d069dc313..d82e0161cd 100644 --- a/packages/epk-signature/CHANGELOG.md +++ b/packages/epk-signature/CHANGELOG.md @@ -3,6 +3,38 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.5.7](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/epk-signature@0.5.4...@requestnetwork/epk-signature@0.5.7) (2020-01-16) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/epk-signature + + + + + +## [0.5.6](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/epk-signature@0.5.4...@requestnetwork/epk-signature@0.5.6) (2019-12-18) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/epk-signature + + + + + +## [0.5.5](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/epk-signature@0.5.4...@requestnetwork/epk-signature@0.5.5) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/epk-signature + + + + + ## [0.5.4](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/epk-signature@0.5.3...@requestnetwork/epk-signature@0.5.4) (2019-11-20) **Note:** Version bump only for package @requestnetwork/epk-signature diff --git a/packages/epk-signature/package.json b/packages/epk-signature/package.json index 1e6e86910a..eca9b9d668 100644 --- a/packages/epk-signature/package.json +++ b/packages/epk-signature/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/epk-signature", - "version": "0.5.4", + "version": "0.5.7", "publishConfig": { "access": "public" }, @@ -34,19 +34,19 @@ "build": "run-s build:commonjs build:umd", "build:commonjs": "tsc -b", "build:umd": "webpack", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", - "test": "nyc mocha --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", - "test:watch": "nyc mocha --watch --watch-extensions ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"" + "test": "nyc mocha --extension ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", + "test:watch": "yarn test --watch" }, "dependencies": { - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0" + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0" }, "devDependencies": { "@types/chai": "4.1.7", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", "@typescript-eslint/parser": "1.2.0", "amd-loader": "0.0.8", "awesome-typescript-loader": "5.2.1", @@ -57,19 +57,19 @@ "eslint-plugin-spellcheck": "0.0.11", "eslint-plugin-typescript": "0.14.0", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "npm-run-all": "4.1.5", "nyc": "13.2.0", "prettier": "1.16.4", "shx": "0.3.2", "source-map-support": "0.5.13", "terser-webpack-plugin": "1.3.0", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "tslint": "5.12.1", "typescript": "3.7.2", "webpack": "4.38.0", "webpack-bundle-analyzer": "3.3.2", - "webpack-cli": "3.3.6" + "webpack-cli": "3.3.10" }, "gitHead": "6155223cfce769e48ccae480c510b35b4f54b4d0" } diff --git a/packages/ethereum-storage/.vscode/settings.json b/packages/ethereum-storage/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/ethereum-storage/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/ethereum-storage/CHANGELOG.md b/packages/ethereum-storage/CHANGELOG.md index 71f2389738..d8b714f3a1 100644 --- a/packages/ethereum-storage/CHANGELOG.md +++ b/packages/ethereum-storage/CHANGELOG.md @@ -3,6 +3,38 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.4.8](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/ethereum-storage@0.4.5...@requestnetwork/ethereum-storage@0.4.8) (2020-01-16) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/ethereum-storage + + + + + +## [0.4.7](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/ethereum-storage@0.4.5...@requestnetwork/ethereum-storage@0.4.7) (2019-12-18) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/ethereum-storage + + + + + +## [0.4.6](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/ethereum-storage@0.4.5...@requestnetwork/ethereum-storage@0.4.6) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/ethereum-storage + + + + + ## [0.4.5](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/ethereum-storage@0.4.4...@requestnetwork/ethereum-storage@0.4.5) (2019-11-20) **Note:** Version bump only for package @requestnetwork/ethereum-storage diff --git a/packages/ethereum-storage/README.md b/packages/ethereum-storage/README.md index c868ddd390..b205a9b6e0 100644 --- a/packages/ethereum-storage/README.md +++ b/packages/ethereum-storage/README.md @@ -3,8 +3,6 @@ `@requestnetwork/ethereum-storage` is a package part of the [Request Network protocol](https://github.com/RequestNetwork/requestNetwork). It is an implementation of the Storage layer of Request Network protocol that uses IPFS to immutably store the data and uses the Ethereum network to persist the IPFS hash of the data and make them permanently available to everyone. -The package also stores the source and artifacts of the smart contract deployed on Ethereum. - To use Infura to connect to an Ethereum node, get an infura token on [infura.io](infura.io) and use as provider `"NETWORK_YOU_WANT.infura.io/v3/YOUR_INFURA_TOKEN"`. @@ -46,11 +44,13 @@ await ethereumStorage.append(data); ## Smart Contract -ethereum-storage source can be downloaded in order to deploy the smart contract on a local environment: +ethereum-storage uses smart contracts to store IPFS hashes. + +The smart contracts can be downloaded in order to deploy them on a local environment: ```bash git clone https://github.com/RequestNetwork/requestNetwork.git -cd requestNetwork/packages/ethereum-storage +cd requestNetwork/packages/smart-contracts yarn install yarn run build yarn run ganache @@ -68,7 +68,7 @@ There are 3 smart contracts: - `RequestOpenHashSubmitter` entry point to add hashes in `RequestHashStorage`. It gives the rules to get the right to submit hashes and collect the fees. This contract must be whitelisted in `RequestHashStorage`. The only condition for adding hash is to pay the fees. - `StorageFeeCollector` parent contract (not deployed) of `RequestOpenHashSubmitter`, computes the fees and send them to the burner. -## Configuring the provider using Truffle and the development network +#### Configuring the provider using Truffle and the development network When deploying the smart contracts for development you can manually set the provider host and port via env variables: diff --git a/packages/ethereum-storage/package.json b/packages/ethereum-storage/package.json index 7a82b8c4f0..4ed6cfa601 100644 --- a/packages/ethereum-storage/package.json +++ b/packages/ethereum-storage/package.json @@ -1,14 +1,13 @@ { "name": "@requestnetwork/ethereum-storage", - "version": "0.4.5", + "version": "0.4.8", "publishConfig": { "access": "public" }, "description": "Request Network storage layer based on ethereum.", "keywords": [ "requestnetwork", - "ethereum-storage", - "smart-contracts" + "ethereum-storage" ], "repository": { "type": "git", @@ -22,37 +21,28 @@ "engines": { "node": ">=8.0.0" }, - "main": "dist/src/lib/index.js", - "types": "dist/src/lib/index.d.ts", + "main": "dist/src/index.js", + "types": "dist/src/index.d.ts", "directories": { - "lib": "src/lib", - "test": "test/lib" + "lib": "src", + "test": "test" }, "files": [ "dist" ], "scripts": { - "build:lib": "tsc -b", - "build:sol": "truffle compile --contracts_directory=./src", - "build": "yarn run build:lib && yarn run build:sol", - "clean:lib": "shx rm -rf dist", - "clean:sol": "shx rm -rf build", - "clean": "yarn run clean:lib && yarn run clean:sol", - "lint:lib": "tslint --project . && eslint \"src/lib/**/*.ts\"", - "lint:sol": "solium --dir src/contracts", - "lint": "yarn run lint:lib && yarn run lint:sol", + "build": "tsc -b", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", + "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", - "ganache": "ganache-cli -l 90000000 -p 8545 -m \"candy maple cake sugar pudding cream honey rich smooth crumble sweet treat\"", - "deploy": "truffle --contracts_directory=./src deploy", - "test:lib": "nyc mocha --timeout=5000 --require ts-node/register --require source-map-support/register \"test/lib/**/*.ts\"", - "test:lib:watch": "nyc mocha --watch --watch-extensions ts --timeout=5000 --require ts-node/register --require source-map-support/register \"test/lib/**/*.ts\"", - "test:sol": "truffle test --contracts_directory=./src test/contracts/*.js", - "test": "yarn run test:lib && yarn run test:sol", + "test": "nyc mocha --timeout=5000 --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", + "test:watch": "nyc mocha --watch --watch-extensions ts --timeout=5000 --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", "init-ipfs": "node scripts/init-ipfs.js" }, "dependencies": { - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0", + "@requestnetwork/smart-contracts": "0.3.0", + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0", "bluebird": "3.5.3", "bn.js": "4.11.8", "form-data": "2.3.3", @@ -60,13 +50,11 @@ "keyv": "3.1.0", "node-fetch": "2.6.0", "shelljs": "0.8.3", - "sinon": "7.3.2", "web3-eth": "1.0.0-beta.37", "web3-utils": "1.2.1", "yargs": "12.0.5" }, "devDependencies": { - "@openzeppelin/contracts": "2.4.0", "@truffle/hdwallet-provider": "1.0.18", "@types/bluebird": "3.5.27", "@types/chai": "4.1.7", @@ -75,7 +63,8 @@ "@types/fetch-mock": "7.3.1", "@types/form-data": "2.2.1", "@types/keyv": "3.1.0", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", + "@types/sinon": "7.5.0", "@typescript-eslint/parser": "1.2.0", "chai": "4.2.0", "chai-as-promised": "7.1.1", @@ -85,18 +74,17 @@ "eslint-plugin-spellcheck": "0.0.11", "eslint-plugin-typescript": "0.14.0", "fetch-mock": "7.3.3", - "ganache-cli": "6.3.0", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "nyc": "13.2.0", "openzeppelin-solidity": "2.1.2", "openzeppelin-test-helpers": "0.1.2", "prettier": "1.16.4", "shx": "0.3.2", + "sinon": "7.5.0", "solium": "1.2.2", "source-map-support": "0.5.13", - "truffle": "5.0.3", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "tslint": "5.12.1", "typescript": "3.7.2", "web3-providers-http": "1.2.1" diff --git a/packages/ethereum-storage/src/lib/config.ts b/packages/ethereum-storage/src/config.ts similarity index 100% rename from packages/ethereum-storage/src/lib/config.ts rename to packages/ethereum-storage/src/config.ts diff --git a/packages/ethereum-storage/src/lib/ethereum-blocks.ts b/packages/ethereum-storage/src/ethereum-blocks.ts similarity index 100% rename from packages/ethereum-storage/src/lib/ethereum-blocks.ts rename to packages/ethereum-storage/src/ethereum-blocks.ts diff --git a/packages/ethereum-storage/src/lib/ethereum-metadata-cache.ts b/packages/ethereum-storage/src/ethereum-metadata-cache.ts similarity index 100% rename from packages/ethereum-storage/src/lib/ethereum-metadata-cache.ts rename to packages/ethereum-storage/src/ethereum-metadata-cache.ts diff --git a/packages/ethereum-storage/src/lib/ethereum-storage.ts b/packages/ethereum-storage/src/ethereum-storage.ts similarity index 100% rename from packages/ethereum-storage/src/lib/ethereum-storage.ts rename to packages/ethereum-storage/src/ethereum-storage.ts diff --git a/packages/ethereum-storage/src/lib/ethereum-utils.ts b/packages/ethereum-storage/src/ethereum-utils.ts similarity index 100% rename from packages/ethereum-storage/src/lib/ethereum-utils.ts rename to packages/ethereum-storage/src/ethereum-utils.ts diff --git a/packages/ethereum-storage/src/lib/gas-price-definer.ts b/packages/ethereum-storage/src/gas-price-definer.ts similarity index 100% rename from packages/ethereum-storage/src/lib/gas-price-definer.ts rename to packages/ethereum-storage/src/gas-price-definer.ts diff --git a/packages/ethereum-storage/src/lib/gas-price-providers/etherchain-provider.ts b/packages/ethereum-storage/src/gas-price-providers/etherchain-provider.ts similarity index 100% rename from packages/ethereum-storage/src/lib/gas-price-providers/etherchain-provider.ts rename to packages/ethereum-storage/src/gas-price-providers/etherchain-provider.ts diff --git a/packages/ethereum-storage/src/lib/gas-price-providers/ethgasstation-provider.ts b/packages/ethereum-storage/src/gas-price-providers/ethgasstation-provider.ts similarity index 100% rename from packages/ethereum-storage/src/lib/gas-price-providers/ethgasstation-provider.ts rename to packages/ethereum-storage/src/gas-price-providers/ethgasstation-provider.ts diff --git a/packages/ethereum-storage/src/lib/index.ts b/packages/ethereum-storage/src/index.ts similarity index 100% rename from packages/ethereum-storage/src/lib/index.ts rename to packages/ethereum-storage/src/index.ts diff --git a/packages/ethereum-storage/src/lib/ipfs-connection-error.ts b/packages/ethereum-storage/src/ipfs-connection-error.ts similarity index 100% rename from packages/ethereum-storage/src/lib/ipfs-connection-error.ts rename to packages/ethereum-storage/src/ipfs-connection-error.ts diff --git a/packages/ethereum-storage/src/lib/ipfs-manager.ts b/packages/ethereum-storage/src/ipfs-manager.ts similarity index 100% rename from packages/ethereum-storage/src/lib/ipfs-manager.ts rename to packages/ethereum-storage/src/ipfs-manager.ts diff --git a/packages/ethereum-storage/src/lib/smart-contract-manager.ts b/packages/ethereum-storage/src/smart-contract-manager.ts similarity index 97% rename from packages/ethereum-storage/src/lib/smart-contract-manager.ts rename to packages/ethereum-storage/src/smart-contract-manager.ts index a3d67ca914..2af4c775c7 100644 --- a/packages/ethereum-storage/src/lib/smart-contract-manager.ts +++ b/packages/ethereum-storage/src/smart-contract-manager.ts @@ -1,8 +1,7 @@ +import * as SmartContracts from '@requestnetwork/smart-contracts'; import { LogTypes, StorageTypes } from '@requestnetwork/types'; import Utils from '@requestnetwork/utils'; import * as Bluebird from 'bluebird'; -import * as artifactsRequestHashStorageUtils from './artifacts-request-hash-storage-utils'; -import * as artifactsRequestHashSubmitterUtils from './artifacts-request-hash-submitter-utils'; import * as config from './config'; import EthereumBlocks from './ethereum-blocks'; import EthereumUtils from './ethereum-utils'; @@ -124,23 +123,28 @@ export default class SmartContractManager { throw Error(`The network id ${web3Connection.networkId} doesn't exist`); } - this.hashStorageAddress = artifactsRequestHashStorageUtils.getAddress(this.networkName); - this.hashSubmitterAddress = artifactsRequestHashSubmitterUtils.getAddress(this.networkName); + this.hashStorageAddress = SmartContracts.requestHashStorageArtifact.getAddress( + this.networkName, + ); + + this.hashSubmitterAddress = SmartContracts.requestHashSubmitterArtifact.getAddress( + this.networkName, + ); // Initialize smart contract instance this.requestHashStorage = new this.eth.Contract( - artifactsRequestHashStorageUtils.getContractAbi(), + SmartContracts.requestHashStorageArtifact.getContractAbi(), this.hashStorageAddress, ); this.requestHashSubmitter = new this.eth.Contract( - artifactsRequestHashSubmitterUtils.getContractAbi(), + SmartContracts.requestHashSubmitterArtifact.getContractAbi(), this.hashSubmitterAddress, ); this.timeout = web3Connection.timeout || config.getDefaultEthereumProviderTimeout(); this.creationBlockNumberHashStorage = - artifactsRequestHashStorageUtils.getCreationBlockNumber(this.networkName) || 0; + SmartContracts.requestHashStorageArtifact.getCreationBlockNumber(this.networkName) || 0; this.ethereumBlocks = new EthereumBlocks( this.eth, diff --git a/packages/ethereum-storage/test/lib/ethereum-blocks.test.ts b/packages/ethereum-storage/test/ethereum-blocks.test.ts similarity index 99% rename from packages/ethereum-storage/test/lib/ethereum-blocks.test.ts rename to packages/ethereum-storage/test/ethereum-blocks.test.ts index 713e3ca059..534636c294 100644 --- a/packages/ethereum-storage/test/lib/ethereum-blocks.test.ts +++ b/packages/ethereum-storage/test/ethereum-blocks.test.ts @@ -3,7 +3,7 @@ import 'mocha'; import * as chaiAsPromised from 'chai-as-promised'; import * as sinon from 'sinon'; -import EthereumBlocks from '../../src/lib/ethereum-blocks'; +import EthereumBlocks from '../src/ethereum-blocks'; const chai = require('chai'); const spies = require('chai-spies'); diff --git a/packages/ethereum-storage/test/lib/ethereum-metadata-cache.ts b/packages/ethereum-storage/test/ethereum-metadata-cache.ts similarity index 97% rename from packages/ethereum-storage/test/lib/ethereum-metadata-cache.ts rename to packages/ethereum-storage/test/ethereum-metadata-cache.ts index 2fd51710f1..a71a1c1348 100644 --- a/packages/ethereum-storage/test/lib/ethereum-metadata-cache.ts +++ b/packages/ethereum-storage/test/ethereum-metadata-cache.ts @@ -4,8 +4,8 @@ import * as chai from 'chai'; import * as chaiAsPromised from 'chai-as-promised'; import { StorageTypes } from '@requestnetwork/types'; -import EthereumMetadataCache from '../../src/lib/ethereum-metadata-cache'; -import SmartContractManager from '../../src/lib/smart-contract-manager'; +import EthereumMetadataCache from '../src/ethereum-metadata-cache'; +import SmartContractManager from '../src/smart-contract-manager'; const spies = require('chai-spies'); chai.use(spies); diff --git a/packages/ethereum-storage/test/lib/ethereum-storage.test.ts b/packages/ethereum-storage/test/ethereum-storage.test.ts similarity index 96% rename from packages/ethereum-storage/test/lib/ethereum-storage.test.ts rename to packages/ethereum-storage/test/ethereum-storage.test.ts index 5e8250f4f8..487a41890b 100644 --- a/packages/ethereum-storage/test/lib/ethereum-storage.test.ts +++ b/packages/ethereum-storage/test/ethereum-storage.test.ts @@ -1,15 +1,12 @@ import 'mocha'; +import * as SmartContracts from '@requestnetwork/smart-contracts'; import { StorageTypes } from '@requestnetwork/types'; import * as chai from 'chai'; import * as chaiAsPromised from 'chai-as-promised'; -import EthereumStorage from '../../src/lib/ethereum-storage'; -import IpfsConnectionError from '../../src/lib/ipfs-connection-error'; - -import * as artifactsRequestHashStorageUtils from '../../src/lib/artifacts-request-hash-storage-utils'; -import * as artifactsRequestHashSubmitterUtils from '../../src/lib/artifacts-request-hash-submitter-utils'; -import { IEthereumEntriesWithLastTimestamp } from '@requestnetwork/types/src/storage-types'; +import EthereumStorage from '../src/ethereum-storage'; +import IpfsConnectionError from '../src/ipfs-connection-error'; // tslint:disable:no-magic-numbers @@ -56,8 +53,8 @@ const web3Eth = require('web3-eth'); const eth = new web3Eth(provider); const contractHashSubmitter = new eth.Contract( - artifactsRequestHashSubmitterUtils.getContractAbi(), - artifactsRequestHashSubmitterUtils.getAddress('private'), + SmartContracts.requestHashSubmitterArtifact.getContractAbi(), + SmartContracts.requestHashSubmitterArtifact.getAddress('private'), ); const addressRequestHashSubmitter = contractHashSubmitter._address; @@ -77,7 +74,7 @@ const realSize2Bytes32Hex = web3Utils.padLeft(web3Utils.toHex(realSize2), 64); const fakeSize2 = 0; const fakeSize2Bytes32Hex = web3Utils.padLeft(web3Utils.toHex(fakeSize2), 64); -// Define a mock for getPastEvents to be independant of the state of ganache instance +// Define a mock for getPastEvents to be independent of the state of ganache instance const pastEventsMock = [ { blockNumber: 1, @@ -208,11 +205,11 @@ describe('EthereumStorage', () => { // Initialize smart contract instance ethereumStorageNotInitialized.smartContractManager.requestHashStorage = new eth.Contract( - artifactsRequestHashStorageUtils.getContractAbi(), + SmartContracts.requestHashStorageArtifact.getContractAbi(), invalidHashStorageAddress, ); ethereumStorageNotInitialized.smartContractManager.requestHashSubmitter = new eth.Contract( - artifactsRequestHashSubmitterUtils.getContractAbi(), + SmartContracts.requestHashSubmitterArtifact.getContractAbi(), invalidHashSubmitterAddress, ); @@ -297,12 +294,10 @@ describe('EthereumStorage', () => { > => { throw Error('fake error'); }; - try { - await ethereumStorage.append(content1); - assert.fail('result.meta.ethereum does not exist'); - } catch (e) { - assert.equal(e.message, 'Smart contract error: Error: fake error'); - } + + await expect(ethereumStorage.append(content1), 'should throw').to.eventually.be.rejectedWith( + 'Smart contract error: Error: fake error', + ); }); it(`allows to save dataId's Ethereum metadata into the metadata cache when append is called`, async () => { await expect(ethereumStorage.ethereumMetadataCache.metadataCache.get(hash1)).to.eventually.be @@ -529,7 +524,7 @@ describe('EthereumStorage', () => { // We want to force the retrieval of metadata with getPastEvents function ethereumStorage.ethereumMetadataCache.saveDataIdMeta = async (_dataId, _meta) => {}; ethereumStorage.smartContractManager.getEntriesFromEthereum = async (): Promise< - IEthereumEntriesWithLastTimestamp + StorageTypes.IEthereumEntriesWithLastTimestamp > => { return { ethereumEntries: [ @@ -610,7 +605,7 @@ describe('EthereumStorage', () => { // Test with no meta ethereumStorage.smartContractManager.getEntriesFromEthereum = (): Promise< - IEthereumEntriesWithLastTimestamp + StorageTypes.IEthereumEntriesWithLastTimestamp > => { return Promise.resolve({ ethereumEntries: [ @@ -685,7 +680,7 @@ describe('EthereumStorage', () => { it('allows to read hash on IPFS with retries', async () => { // Mock to test IPFS read retry ethereumStorage.smartContractManager.getEntriesFromEthereum = (): Promise< - IEthereumEntriesWithLastTimestamp + StorageTypes.IEthereumEntriesWithLastTimestamp > => { return Promise.resolve({ ethereumEntries: [ diff --git a/packages/ethereum-storage/test/lib/ethereum-utils.test.ts b/packages/ethereum-storage/test/ethereum-utils.test.ts similarity index 93% rename from packages/ethereum-storage/test/lib/ethereum-utils.test.ts rename to packages/ethereum-storage/test/ethereum-utils.test.ts index 059542c6b6..bfd2b6080b 100644 --- a/packages/ethereum-storage/test/lib/ethereum-utils.test.ts +++ b/packages/ethereum-storage/test/ethereum-utils.test.ts @@ -2,8 +2,8 @@ import { expect } from 'chai'; import 'mocha'; import { StorageTypes } from '@requestnetwork/types'; -import { getSafeGasPriceLimit } from '../../src/lib/config'; -import EthereumUtils from '../../src/lib/ethereum-utils'; +import { getSafeGasPriceLimit } from '../src/config'; +import EthereumUtils from '../src/ethereum-utils'; const bigNumber: any = require('bn.js'); diff --git a/packages/ethereum-storage/test/lib/gas-price-definer.test.ts b/packages/ethereum-storage/test/gas-price-definer.test.ts similarity index 95% rename from packages/ethereum-storage/test/lib/gas-price-definer.test.ts rename to packages/ethereum-storage/test/gas-price-definer.test.ts index 0578105031..cdf853f05a 100644 --- a/packages/ethereum-storage/test/lib/gas-price-definer.test.ts +++ b/packages/ethereum-storage/test/gas-price-definer.test.ts @@ -1,8 +1,8 @@ import { StorageTypes } from '@requestnetwork/types'; -import EthereumUtils from '../../src/lib/ethereum-utils'; +import EthereumUtils from '../src/ethereum-utils'; -import * as config from '../../src/lib/config'; -import GasPriceDefiner from '../../src/lib/gas-price-definer'; +import * as config from '../src/config'; +import GasPriceDefiner from '../src/gas-price-definer'; import * as chai from 'chai'; import * as chaiAsPromised from 'chai-as-promised'; diff --git a/packages/ethereum-storage/test/lib/gas-price-providers/etherchain-provider.test.ts b/packages/ethereum-storage/test/gas-price-providers/etherchain-provider.test.ts similarity index 97% rename from packages/ethereum-storage/test/lib/gas-price-providers/etherchain-provider.test.ts rename to packages/ethereum-storage/test/gas-price-providers/etherchain-provider.test.ts index 83003b42af..9e83fcbf1c 100644 --- a/packages/ethereum-storage/test/lib/gas-price-providers/etherchain-provider.test.ts +++ b/packages/ethereum-storage/test/gas-price-providers/etherchain-provider.test.ts @@ -1,5 +1,5 @@ import { StorageTypes } from '@requestnetwork/types'; -import EtherchainProvider from '../../../src/lib/gas-price-providers/etherchain-provider'; +import EtherchainProvider from '../../src/gas-price-providers/etherchain-provider'; import * as chai from 'chai'; import * as chaiAsPromised from 'chai-as-promised'; diff --git a/packages/ethereum-storage/test/lib/gas-price-providers/ethgasstation-provider.test.ts b/packages/ethereum-storage/test/gas-price-providers/ethgasstation-provider.test.ts similarity index 97% rename from packages/ethereum-storage/test/lib/gas-price-providers/ethgasstation-provider.test.ts rename to packages/ethereum-storage/test/gas-price-providers/ethgasstation-provider.test.ts index 6e37d8eada..e9452916fa 100644 --- a/packages/ethereum-storage/test/lib/gas-price-providers/ethgasstation-provider.test.ts +++ b/packages/ethereum-storage/test/gas-price-providers/ethgasstation-provider.test.ts @@ -1,5 +1,5 @@ import { StorageTypes } from '@requestnetwork/types'; -import EthGasStationProvider from '../../../src/lib/gas-price-providers/ethgasstation-provider'; +import EthGasStationProvider from '../../src/gas-price-providers/ethgasstation-provider'; import * as chai from 'chai'; import * as chaiAsPromised from 'chai-as-promised'; diff --git a/packages/ethereum-storage/test/lib/ipfs-manager.test.ts b/packages/ethereum-storage/test/ipfs-manager.test.ts similarity index 99% rename from packages/ethereum-storage/test/lib/ipfs-manager.test.ts rename to packages/ethereum-storage/test/ipfs-manager.test.ts index 10e8b149f2..a6140b17d9 100644 --- a/packages/ethereum-storage/test/lib/ipfs-manager.test.ts +++ b/packages/ethereum-storage/test/ipfs-manager.test.ts @@ -5,7 +5,7 @@ import * as chai from 'chai'; import * as chaiAsPromised from 'chai-as-promised'; import { EventEmitter } from 'events'; import * as http from 'http'; -import IpfsManager from '../../src/lib/ipfs-manager'; +import IpfsManager from '../src/ipfs-manager'; const spies = require('chai-spies'); diff --git a/packages/ethereum-storage/test/lib/smartcontract-manager.test.ts b/packages/ethereum-storage/test/smartcontract-manager.test.ts similarity index 95% rename from packages/ethereum-storage/test/lib/smartcontract-manager.test.ts rename to packages/ethereum-storage/test/smartcontract-manager.test.ts index af2bb7ce14..b1340877be 100644 --- a/packages/ethereum-storage/test/lib/smartcontract-manager.test.ts +++ b/packages/ethereum-storage/test/smartcontract-manager.test.ts @@ -1,19 +1,18 @@ import 'mocha'; +import * as SmartContracts from '@requestnetwork/smart-contracts'; import { StorageTypes } from '@requestnetwork/types'; import * as chai from 'chai'; import * as chaiAsPromised from 'chai-as-promised'; -import EthereumBlocks from '../../src/lib/ethereum-blocks'; -import SmartContractManager from '../../src/lib/smart-contract-manager'; - -import * as artifactsRequestHashStorageUtils from '../../src/lib/artifacts-request-hash-storage-utils'; -import * as artifactsRequestHashSubmitterUtils from '../../src/lib/artifacts-request-hash-submitter-utils'; +import EthereumBlocks from '../src/ethereum-blocks'; +import SmartContractManager from '../src/smart-contract-manager'; // tslint:disable:no-magic-numbers // Extends chai for promises chai.use(chaiAsPromised); const assert = chai.assert; +const expect = chai.expect; const web3HttpProvider = require('web3-providers-http'); @@ -63,13 +62,13 @@ const otherSize = 100000; const otherSizeBytes32Hex = web3Utils.padLeft(web3Utils.toHex(otherSize), 64); const contractHashStorage = new eth.Contract( - artifactsRequestHashStorageUtils.getContractAbi(), - artifactsRequestHashStorageUtils.getAddress('private'), + SmartContracts.requestHashStorageArtifact.getContractAbi(), + SmartContracts.requestHashStorageArtifact.getAddress('private'), ); const contractHashSubmitter = new eth.Contract( - artifactsRequestHashSubmitterUtils.getContractAbi(), - artifactsRequestHashSubmitterUtils.getAddress('private'), + SmartContracts.requestHashSubmitterArtifact.getContractAbi(), + SmartContracts.requestHashSubmitterArtifact.getAddress('private'), ); const addressRequestHashSubmitter = contractHashSubmitter._address; @@ -406,7 +405,7 @@ describe('SmartContractManager', () => { it('getAddress in artifactsRequestHashStorageUtils with a invalid host network should throw an error', async () => { assert.throws( - () => artifactsRequestHashStorageUtils.getAddress('nonexistent'), + () => SmartContracts.requestHashStorageArtifact.getAddress('nonexistent'), Error, 'No deployment for network', ); @@ -414,14 +413,14 @@ describe('SmartContractManager', () => { it('getAddress in artifactsRequestHashSubmitterUtils with a invalid host network should throw an error', async () => { assert.throws( - () => artifactsRequestHashSubmitterUtils.getAddress('nonexistent'), + () => SmartContracts.requestHashSubmitterArtifact.getAddress('nonexistent'), Error, 'No deployment for network', ); }); it('getCreationBlockNumber in artifactsRequestHashSubmitterUtils', async () => { - assert.equal(artifactsRequestHashSubmitterUtils.getCreationBlockNumber('private'), 1); + assert.equal(SmartContracts.requestHashSubmitterArtifact.getCreationBlockNumber('private'), 1); }); it('allows to getMetaFromEthereum() a hash', async () => { @@ -442,12 +441,10 @@ describe('SmartContractManager', () => { }); it('allows to getMetaFromEthereum() a hash not indexed', async () => { - try { - await smartContractManager.getMetaFromEthereum('empty'); - assert.fail('must have exception'); - } catch (e) { - assert.equal(e.message, 'contentHash not indexed on ethereum'); - } + await expect( + smartContractManager.getMetaFromEthereum('empty'), + 'should throw', + ).to.eventually.be.rejectedWith('contentHash not indexed on ethereum'); }); it('badly formatted events from web3 should throw an error', async () => { diff --git a/packages/ethereum-storage/tsconfig.json b/packages/ethereum-storage/tsconfig.json index 3c7594cfc5..5c52df843a 100644 --- a/packages/ethereum-storage/tsconfig.json +++ b/packages/ethereum-storage/tsconfig.json @@ -5,12 +5,6 @@ "rootDir": ".", "resolveJsonModule": true }, - "include": ["./src/lib/**/*", "./artifacts/**/*"], - "references": [{ "path": "../types" }, { "path": "../utils" }], - "files": [ - "./artifacts/RequestHashStorage/0.1.0.json", - "./artifacts/RequestHashStorage/artifacts.json", - "./artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/0.1.0.json", - "./artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/artifacts.json" - ] + "include": ["./src/**/*"], + "references": [{ "path": "../types" }, { "path": "../utils" }, { "path": "../smart-contracts" }] } diff --git a/packages/ethereum-storage/tslint.json b/packages/ethereum-storage/tslint.json index 86908345b4..0946f20963 100644 --- a/packages/ethereum-storage/tslint.json +++ b/packages/ethereum-storage/tslint.json @@ -1,6 +1,3 @@ { - "extends": "../../tslint.json", - "linterOptions": { - "exclude": ["artifacts/**/*"] - } + "extends": "../../tslint.json" } diff --git a/packages/integration-test/.vscode/settings.json b/packages/integration-test/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/integration-test/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/integration-test/CHANGELOG.md b/packages/integration-test/CHANGELOG.md index 5f2f0e5bf4..b42dbe8830 100644 --- a/packages/integration-test/CHANGELOG.md +++ b/packages/integration-test/CHANGELOG.md @@ -3,6 +3,64 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.9.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/integration-test@0.6.0...@requestnetwork/integration-test@0.9.0) (2020-01-16) + + +### Bug Fixes + +* mock BTC provider on tests ([#103](https://github.com/RequestNetwork/requestNetwork/issues/103)) ([d17f5bd](https://github.com/RequestNetwork/requestNetwork/commit/d17f5bd841690dcbb2615af126e66116685ee3be)) + + +### Features + +* balance event timestamps ([#78](https://github.com/RequestNetwork/requestNetwork/issues/78)) ([ee2a78f](https://github.com/RequestNetwork/requestNetwork/commit/ee2a78ff5ba83d84739b743db283bb8abfca6b63)) +* **request-client.js:** get balance from request ERC20 with proxy contract ([#94](https://github.com/RequestNetwork/requestNetwork/issues/94)) ([08758ae](https://github.com/RequestNetwork/requestNetwork/commit/08758ae83e3834db06c0f1441e51bc6c2b897669)) + + + +# 0.10.0 (2019-12-04) + + +### Features + +* **request-client.js:** add an explanation when request not found ([#609](https://github.com/RequestNetwork/requestNetwork/issues/609)) ([3909958](https://github.com/RequestNetwork/requestNetwork/commit/39099580b65b86282d19a71ffad77f1b89767cca)) + + + + + +# [0.8.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/integration-test@0.6.0...@requestnetwork/integration-test@0.8.0) (2019-12-18) + + +### Features + +* balance event timestamps ([#78](https://github.com/RequestNetwork/requestNetwork/issues/78)) ([ee2a78f](https://github.com/RequestNetwork/requestNetwork/commit/ee2a78ff5ba83d84739b743db283bb8abfca6b63)) +* **request-client.js:** get balance from request ERC20 with proxy contract ([#94](https://github.com/RequestNetwork/requestNetwork/issues/94)) ([08758ae](https://github.com/RequestNetwork/requestNetwork/commit/08758ae83e3834db06c0f1441e51bc6c2b897669)) + + + +# 0.10.0 (2019-12-04) + + +### Features + +* **request-client.js:** add an explanation when request not found ([#609](https://github.com/RequestNetwork/requestNetwork/issues/609)) ([3909958](https://github.com/RequestNetwork/requestNetwork/commit/39099580b65b86282d19a71ffad77f1b89767cca)) + + + + + +# [0.7.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/integration-test@0.6.0...@requestnetwork/integration-test@0.7.0) (2019-12-04) + + +### Features + +* **request-client.js:** add an explanation when request not found ([#609](https://github.com/RequestNetwork/requestNetwork/issues/609)) ([3909958](https://github.com/RequestNetwork/requestNetwork/commit/39099580b65b86282d19a71ffad77f1b89767cca)) + + + + + # [0.6.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/integration-test@0.5.0...@requestnetwork/integration-test@0.6.0) (2019-11-20) diff --git a/packages/integration-test/package.json b/packages/integration-test/package.json index 885db8ebc2..c4c24735ca 100644 --- a/packages/integration-test/package.json +++ b/packages/integration-test/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/integration-test", - "version": "0.6.0", + "version": "0.9.0", "private": true, "description": "Integration tests for the request system.", "keywords": [ @@ -27,36 +27,38 @@ ], "scripts": { "build": "tsc -b", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"test/**/*.ts\"", "lint-staged": "lint-staged", "test": "run-s test:node test:layers", - "test:scheduled": "run-s test:erc20", - "test:layers": "mocha --timeout=10000 --require ts-node/register \"test/layers.test.ts\"", - "test:node": "mocha --timeout=10000 --require ts-node/register \"test/node-client.test.ts\"", - "test:erc20": "mocha --timeout=10000 --require ts-node/register \"test/erc20.test.ts\"" + "test:scheduled": "run-s test:erc20 test:btc", + "test:layers": "mocha --timeout=10000 --extension ts --require ts-node/register \"test/layers.test.ts\"", + "test:node": "mocha --timeout=10000 --extension ts --require ts-node/register \"test/node-client.test.ts\"", + "test:erc20": "mocha --timeout=10000 --extension ts --require ts-node/register \"test/scheduled/erc20.test.ts\"", + "test:btc": "mocha --timeout=10000 --extension ts --require ts-node/register \"test/scheduled/btc.test.ts\"" }, "devDependencies": { - "@requestnetwork/advanced-logic": "0.6.0", - "@requestnetwork/data-access": "0.5.2", - "@requestnetwork/epk-decryption": "0.3.3", - "@requestnetwork/epk-signature": "0.5.4", - "@requestnetwork/ethereum-storage": "0.4.5", - "@requestnetwork/multi-format": "0.2.1", - "@requestnetwork/request-client.js": "0.9.0", - "@requestnetwork/request-logic": "0.8.0", - "@requestnetwork/transaction-manager": "0.8.1", - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0", + "@requestnetwork/advanced-logic": "0.9.0", + "@requestnetwork/data-access": "0.5.5", + "@requestnetwork/epk-decryption": "0.3.6", + "@requestnetwork/epk-signature": "0.5.7", + "@requestnetwork/ethereum-storage": "0.4.8", + "@requestnetwork/multi-format": "0.2.4", + "@requestnetwork/request-client.js": "0.12.0", + "@requestnetwork/request-logic": "0.8.3", + "@requestnetwork/transaction-manager": "0.8.4", + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0", "@truffle/hdwallet-provider": "1.0.18", "@types/chai": "4.1.7", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", "chai": "4.2.0", + "chai-as-promised": "7.1.1", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "npm-run-all": "4.1.5", "prettier": "1.16.4", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "tslint": "5.12.1", "typescript": "3.7.2", "web3-eth": "1.0.0-beta.37" diff --git a/packages/integration-test/test/node-client.test.ts b/packages/integration-test/test/node-client.test.ts index 44aedf42fa..0bf7e02eaf 100644 --- a/packages/integration-test/test/node-client.test.ts +++ b/packages/integration-test/test/node-client.test.ts @@ -4,8 +4,12 @@ import MultiFormat from '@requestnetwork/multi-format'; import { Request, RequestNetwork, Types } from '@requestnetwork/request-client.js'; import Utils from '@requestnetwork/utils'; -import { assert } from 'chai'; -import 'mocha'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +const assert = chai.assert; const payeeIdentity: Types.Identity.IIdentity = { type: Types.Identity.TYPE.ETHEREUM_ADDRESS, @@ -97,7 +101,9 @@ describe('Request client using a request node', () => { const paymentNetwork: Types.IPaymentNetworkCreateParameters = { id: Types.PAYMENT_NETWORK_ID.DECLARATIVE, parameters: { - paymentInstruction: 'Arbitrary payment instruction', + paymentInfo: { + paymentInstruction: 'Arbitrary payment instruction', + }, }, }; @@ -127,6 +133,11 @@ describe('Request client using a request node', () => { assert.exists(requestData.meta); + const paymentExtension = requestData.extensions[Types.PAYMENT_NETWORK_ID.DECLARATIVE]; + assert.exists(paymentExtension); + assert.equal(paymentExtension.events[0].name, 'create'); + assert.deepEqual(paymentExtension.events[0].parameters, paymentNetwork.parameters); + requestData = await request.declareSentPayment('100', 'bank transfer initiated', payerIdentity); assert.exists(requestData.balance); @@ -370,13 +381,9 @@ it('cannot decrypt a request with the wrong decryption provider', async () => { [encryptionData.encryptionParams], ); - let error = ''; - try { - await badRequestNetwork.fromRequestId(request.requestId); - } catch (e) { - error = e.message; - } - assert.include(error, 'No request found for the id:'); + expect(badRequestNetwork.fromRequestId(request.requestId)).to.eventually.be.rejectedWith( + 'Invalid transaction(s) found: [', + ); const requests = await badRequestNetwork.fromTopic('my nice topic'); assert.isEmpty(requests); diff --git a/packages/integration-test/test/scheduled/btc-test-data.ts b/packages/integration-test/test/scheduled/btc-test-data.ts new file mode 100644 index 0000000000..20470ddee7 --- /dev/null +++ b/packages/integration-test/test/scheduled/btc-test-data.ts @@ -0,0 +1,48 @@ +import { IdentityTypes, RequestLogicTypes, SignatureTypes } from '@requestnetwork/types'; + +const arbitraryTimestamp = 1549953337; + +export const payee = { + identity: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: '0x627306090abab3a6e1400e9345bc60c78a8bef57', + }, + signatureParams: { + method: SignatureTypes.METHOD.ECDSA, + privateKey: '0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3', + }, +}; + +export const payer = { + identity: { + type: IdentityTypes.TYPE.ETHEREUM_ADDRESS, + value: '0xf17f52151ebef6c7334fad080c5704d77216b732', + }, + signatureParams: { + method: SignatureTypes.METHOD.ECDSA, + privateKey: '0xae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f', + }, +}; + +export const testnetRequestData = { + currency: { + network: 'testnet', + type: RequestLogicTypes.CURRENCY.BTC, + value: 'BTC', + }, + expectedAmount: '100000000000', + payee: payee.identity, + payer: payer.identity, + timestamp: arbitraryTimestamp, +}; + +export const requestData = { + currency: { + type: RequestLogicTypes.CURRENCY.BTC, + value: 'BTC', + }, + expectedAmount: '100000000000', + payee: payee.identity, + payer: payer.identity, + timestamp: arbitraryTimestamp, +}; diff --git a/packages/integration-test/test/scheduled/btc.test.ts b/packages/integration-test/test/scheduled/btc.test.ts new file mode 100644 index 0000000000..11b4b6c3f2 --- /dev/null +++ b/packages/integration-test/test/scheduled/btc.test.ts @@ -0,0 +1,56 @@ +/* eslint-disable spellcheck/spell-checker */ +import { EthereumPrivateKeySignatureProvider } from '@requestnetwork/epk-signature'; +import { RequestNetwork, Types } from '@requestnetwork/request-client.js'; +import * as chai from 'chai'; +import { payee, requestData, testnetRequestData } from './btc-test-data'; + +const expect = chai.expect; + +const signatureProvider = new EthereumPrivateKeySignatureProvider({ + method: Types.Signature.METHOD.ECDSA, + privateKey: '0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3', +}); +signatureProvider.addSignatureParameters({ + method: Types.Signature.METHOD.ECDSA, + privateKey: '0xae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f', +}); +describe('BTC detection test-suite', () => { + + it('Can create a BTC testnet payment provider request and detect the payment', async () => { + const requestNetwork = new RequestNetwork({ signatureProvider }); + + const paymentNetwork: Types.IPaymentNetworkCreateParameters = { + id: Types.PAYMENT_NETWORK_ID.TESTNET_BITCOIN_ADDRESS_BASED, + parameters: { + paymentAddress: 'mgPKDuVmuS9oeE2D9VPiCQriyU14wxWS1v', + }, + }; + + const request = await requestNetwork.createRequest({ + paymentNetwork, + requestInfo: testnetRequestData, + signer: payee.identity, + }); + + expect(request.getData().balance?.balance).to.be.equal('50500000'); + }); + + it('Can create a BTC mainnet payment provider request and detect the payment', async () => { + const requestNetwork = new RequestNetwork({ signatureProvider }); + + const paymentNetwork: Types.IPaymentNetworkCreateParameters = { + id: Types.PAYMENT_NETWORK_ID.BITCOIN_ADDRESS_BASED, + parameters: { + paymentAddress: '1FersucwSqufU26w9GrGz9M3KcwuNmy6a9', + }, + }; + + const request = await requestNetwork.createRequest({ + paymentNetwork, + requestInfo: requestData, + signer: payee.identity, + }); + + expect(request.getData().balance?.balance).to.be.equal('666743'); + }); +}); diff --git a/packages/integration-test/test/erc20-mainnet-test-data.ts b/packages/integration-test/test/scheduled/erc20-mainnet-test-data.ts similarity index 100% rename from packages/integration-test/test/erc20-mainnet-test-data.ts rename to packages/integration-test/test/scheduled/erc20-mainnet-test-data.ts diff --git a/packages/integration-test/test/erc20.test.ts b/packages/integration-test/test/scheduled/erc20.test.ts similarity index 64% rename from packages/integration-test/test/erc20.test.ts rename to packages/integration-test/test/scheduled/erc20.test.ts index a1757c33cf..fdc3c91eea 100644 --- a/packages/integration-test/test/erc20.test.ts +++ b/packages/integration-test/test/scheduled/erc20.test.ts @@ -1,7 +1,8 @@ // tslint:disable: no-magic-numbers // tslint:disable: no-invalid-this +import { Types } from '@requestnetwork/request-client.js'; import ERC20AddressedBased from '@requestnetwork/request-client.js/src/api/payment-network/erc20/address-based'; -import ERC20InfoRetriever from '@requestnetwork/request-client.js/src/api/payment-network/erc20/info-retriever'; +import ERC20AddressBasedInfoRetriever from '@requestnetwork/request-client.js/src/api/payment-network/erc20/address-based-info-retriever'; import { AdvancedLogicTypes, ExtensionTypes, RequestLogicTypes } from '@requestnetwork/types'; import { account, tokens } from './erc20-mainnet-test-data'; @@ -27,23 +28,28 @@ const mockAdvancedLogic: AdvancedLogicTypes.IAdvancedLogic = { }, }; -describe('ERC20 detection test-suite', function(): void { - this.timeout(10000); - +describe('ERC20 detection test-suite', () => { describe('check mainnet payment detection', () => { - Object.entries(tokens).forEach(([symbol, { address, amount, decimals }]) => { + Object.entries(tokens).forEach(([symbol, { address, amount }]) => { it(`can detect the balance of ${symbol}`, async () => { - const balanceObject = await ERC20InfoRetriever(address, account, 'mainnet'); + const infoRetriever = new ERC20AddressBasedInfoRetriever( + address, + account, + Types.EVENTS_NAMES.PAYMENT, + 'mainnet', + ); + const events = await infoRetriever.getTransferEvents(); - expect(balanceObject.decimals).to.be.equal(decimals); // if this assert fails it means this address received another transaction - expect(balanceObject.tokenEvents).to.have.lengthOf(1); - const event = balanceObject.tokenEvents[0]; - delete event.from; - expect(event).to.deep.equal({ - to: account, - value: amount, - }); + expect(events).to.have.lengthOf(1); + const event = events[0]; + expect(event.name).to.equal('payment'); + expect(event.amount).to.equal(amount); + expect(event.timestamp).to.be.a('number'); + expect(event.parameters!.to).to.equal(account); + expect(event.parameters!.from).to.be.a('string'); + expect(event.parameters!.block).to.be.a('number'); + expect(event.parameters!.txHash).to.be.a('string'); }); }); }); @@ -82,12 +88,13 @@ describe('ERC20 detection test-suite', function(): void { expect(balance.balance).to.be.equal('510000000000000000'); expect(balance.events).to.have.lengthOf(1); expect(balance.events[0].name).to.be.equal('payment'); - expect(balance.events[0].parameters.to).to.be.equal( + expect(balance.events[0].parameters!.to).to.be.equal( '0x6A08D2C8f251AF1f17B5943f7f7Bb7078c50e29A', ); - expect(balance.events[0].parameters.from).to.be.equal( + expect(balance.events[0].parameters!.from).to.be.equal( '0x708416775B69E3D3d6c634FfdF91778A161d30Bd', ); - expect(balance.events[0].parameters.value).to.be.equal('510000000000000000'); + expect(balance.events[0].amount).to.be.equal('510000000000000000'); + expect(balance.events[0].timestamp).to.be.a('number'); }); }); diff --git a/packages/multi-format/.vscode/settings.json b/packages/multi-format/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/multi-format/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/multi-format/CHANGELOG.md b/packages/multi-format/CHANGELOG.md index 2892f9facb..e4c38facbe 100644 --- a/packages/multi-format/CHANGELOG.md +++ b/packages/multi-format/CHANGELOG.md @@ -3,6 +3,38 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.4](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/multi-format@0.2.1...@requestnetwork/multi-format@0.2.4) (2020-01-16) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/multi-format + + + + + +## [0.2.3](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/multi-format@0.2.1...@requestnetwork/multi-format@0.2.3) (2019-12-18) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/multi-format + + + + + +## [0.2.2](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/multi-format@0.2.1...@requestnetwork/multi-format@0.2.2) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/multi-format + + + + + ## [0.2.1](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/multi-format@0.2.0...@requestnetwork/multi-format@0.2.1) (2019-11-20) **Note:** Version bump only for package @requestnetwork/multi-format diff --git a/packages/multi-format/package.json b/packages/multi-format/package.json index 58fed4eae4..fbc503731b 100644 --- a/packages/multi-format/package.json +++ b/packages/multi-format/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/multi-format", - "version": "0.2.1", + "version": "0.2.4", "publishConfig": { "access": "public" }, @@ -32,19 +32,20 @@ ], "scripts": { "build": "tsc -b", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", "prepare": "yarn run build", - "test": "nyc mocha --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", - "test:watch": "nyc mocha --watch --watch-extensions ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"" + "test": "nyc mocha --extension ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", + "test:watch": "yarn test --watch" }, "dependencies": { - "@requestnetwork/types": "0.9.0" + "@requestnetwork/types": "0.11.0" }, "devDependencies": { "@types/chai": "4.1.7", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", + "@types/sinon": "7.5.0", "@typescript-eslint/parser": "1.2.0", "chai": "4.2.0", "chai-as-promised": "7.1.1", @@ -53,11 +54,11 @@ "eslint-plugin-spellcheck": "0.0.11", "eslint-plugin-typescript": "0.14.0", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "nyc": "13.2.0", "prettier": "1.16.4", "shx": "0.3.2", - "sinon": "7.3.2", + "sinon": "7.5.0", "source-map-support": "0.5.13", "tslint": "5.12.1", "typescript": "3.7.2" diff --git a/packages/prototype-estimator/.vscode/settings.json b/packages/prototype-estimator/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/prototype-estimator/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/prototype-estimator/CHANGELOG.md b/packages/prototype-estimator/CHANGELOG.md index 6d8adc1cd1..19619130d5 100644 --- a/packages/prototype-estimator/CHANGELOG.md +++ b/packages/prototype-estimator/CHANGELOG.md @@ -3,6 +3,38 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.3.8](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/prototype-estimator@1.3.5...@requestnetwork/prototype-estimator@1.3.8) (2020-01-16) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/prototype-estimator + + + + + +## [1.3.7](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/prototype-estimator@1.3.5...@requestnetwork/prototype-estimator@1.3.7) (2019-12-18) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/prototype-estimator + + + + + +## [1.3.6](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/prototype-estimator@1.3.5...@requestnetwork/prototype-estimator@1.3.6) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/prototype-estimator + + + + + ## [1.3.5](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/prototype-estimator@1.3.4...@requestnetwork/prototype-estimator@1.3.5) (2019-11-20) **Note:** Version bump only for package @requestnetwork/prototype-estimator diff --git a/packages/prototype-estimator/package.json b/packages/prototype-estimator/package.json index bcd0e1f059..8df1db2ce2 100644 --- a/packages/prototype-estimator/package.json +++ b/packages/prototype-estimator/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/prototype-estimator", - "version": "1.3.5", + "version": "1.3.8", "private": true, "description": "Tool to estimate size and throughput of v2 system.", "keywords": [ @@ -26,23 +26,23 @@ "start": "ts-node src/index.ts" }, "dependencies": { - "@requestnetwork/advanced-logic": "0.6.0", - "@requestnetwork/data-access": "0.5.2", - "@requestnetwork/epk-signature": "0.5.4", - "@requestnetwork/ethereum-storage": "0.4.5", - "@requestnetwork/multi-format": "0.2.1", - "@requestnetwork/request-client.js": "0.9.0", - "@requestnetwork/request-logic": "0.8.0", - "@requestnetwork/request-node": "0.5.4", - "@requestnetwork/transaction-manager": "0.8.1", - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0", + "@requestnetwork/advanced-logic": "0.9.0", + "@requestnetwork/data-access": "0.5.5", + "@requestnetwork/epk-signature": "0.5.7", + "@requestnetwork/ethereum-storage": "0.4.8", + "@requestnetwork/multi-format": "0.2.4", + "@requestnetwork/request-client.js": "0.12.0", + "@requestnetwork/request-logic": "0.8.3", + "@requestnetwork/request-node": "0.5.7", + "@requestnetwork/transaction-manager": "0.8.4", + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0", "benchmark": "2.1.4", "simple-statistics": "7.0.2" }, "devDependencies": { "prettier": "1.16.4", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "typescript": "3.7.2" } } diff --git a/packages/request-client.js/.vscode/settings.json b/packages/request-client.js/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/request-client.js/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/request-client.js/CHANGELOG.md b/packages/request-client.js/CHANGELOG.md index db4733471d..45e78745f3 100644 --- a/packages/request-client.js/CHANGELOG.md +++ b/packages/request-client.js/CHANGELOG.md @@ -3,6 +3,98 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.12.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/request-client.js@0.9.0...@requestnetwork/request-client.js@0.12.0) (2020-01-16) + + +### Bug Fixes + +* create an ETH request without refund address ([#82](https://github.com/RequestNetwork/requestNetwork/issues/82)) ([61664cd](https://github.com/RequestNetwork/requestNetwork/commit/61664cd41eef5341678b357a153379dfe2aae14e)) +* mock BTC provider on tests ([#103](https://github.com/RequestNetwork/requestNetwork/issues/103)) ([d17f5bd](https://github.com/RequestNetwork/requestNetwork/commit/d17f5bd841690dcbb2615af126e66116685ee3be)) +* use lowercase for payment reference ([#83](https://github.com/RequestNetwork/requestNetwork/issues/83)) ([6cbedeb](https://github.com/RequestNetwork/requestNetwork/commit/6cbedeb4d2e130d7ece1ba526cea9c17d6e545e0)) + + +### Features + +* balance event timestamps ([#78](https://github.com/RequestNetwork/requestNetwork/issues/78)) ([ee2a78f](https://github.com/RequestNetwork/requestNetwork/commit/ee2a78ff5ba83d84739b743db283bb8abfca6b63)) +* **request-client.js:** add erc20 proxy contract PN in request-client.js ([#80](https://github.com/RequestNetwork/requestNetwork/issues/80)) ([53e8839](https://github.com/RequestNetwork/requestNetwork/commit/53e8839fad5a369257b4ba7908bc80abfa53c5f6)) +* **request-client.js:** get balance from request ERC20 with proxy contract ([#94](https://github.com/RequestNetwork/requestNetwork/issues/94)) ([08758ae](https://github.com/RequestNetwork/requestNetwork/commit/08758ae83e3834db06c0f1441e51bc6c2b897669)) + + + +# 0.10.0 (2019-12-04) + + +### Bug Fixes + +* use ERC20 default network ([#623](https://github.com/RequestNetwork/requestNetwork/issues/623)) ([772dd37](https://github.com/RequestNetwork/requestNetwork/commit/772dd37877497a38b9cc74a08c70a6c5aecefa2d)) + + +### Features + +* **request-client.js:** add an explanation when request not found ([#609](https://github.com/RequestNetwork/requestNetwork/issues/609)) ([3909958](https://github.com/RequestNetwork/requestNetwork/commit/39099580b65b86282d19a71ffad77f1b89767cca)) +* add ETH paymentNetwork to request-client ([#617](https://github.com/RequestNetwork/requestNetwork/issues/617)) ([84ed64e](https://github.com/RequestNetwork/requestNetwork/commit/84ed64ebf96a296155dc2d4d5e6c538344fb881b)) +* ETH payment detection in request-client.js ([#626](https://github.com/RequestNetwork/requestNetwork/issues/626)) ([dc3b238](https://github.com/RequestNetwork/requestNetwork/commit/dc3b23827cff7d5466c27d5575515887c461c3b4)) +* exposes currency utilities and list of all supported currencies ([#625](https://github.com/RequestNetwork/requestNetwork/issues/625)) ([eeac838](https://github.com/RequestNetwork/requestNetwork/commit/eeac8385025274fdada39ca3fb2182fc54d470d5)) + + + + + +# [0.11.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/request-client.js@0.9.0...@requestnetwork/request-client.js@0.11.0) (2019-12-18) + + +### Bug Fixes + +* create an ETH request without refund address ([#82](https://github.com/RequestNetwork/requestNetwork/issues/82)) ([61664cd](https://github.com/RequestNetwork/requestNetwork/commit/61664cd41eef5341678b357a153379dfe2aae14e)) +* use lowercase for payment reference ([#83](https://github.com/RequestNetwork/requestNetwork/issues/83)) ([6cbedeb](https://github.com/RequestNetwork/requestNetwork/commit/6cbedeb4d2e130d7ece1ba526cea9c17d6e545e0)) + + +### Features + +* balance event timestamps ([#78](https://github.com/RequestNetwork/requestNetwork/issues/78)) ([ee2a78f](https://github.com/RequestNetwork/requestNetwork/commit/ee2a78ff5ba83d84739b743db283bb8abfca6b63)) +* **request-client.js:** add erc20 proxy contract PN in request-client.js ([#80](https://github.com/RequestNetwork/requestNetwork/issues/80)) ([53e8839](https://github.com/RequestNetwork/requestNetwork/commit/53e8839fad5a369257b4ba7908bc80abfa53c5f6)) +* **request-client.js:** get balance from request ERC20 with proxy contract ([#94](https://github.com/RequestNetwork/requestNetwork/issues/94)) ([08758ae](https://github.com/RequestNetwork/requestNetwork/commit/08758ae83e3834db06c0f1441e51bc6c2b897669)) + + + +# 0.10.0 (2019-12-04) + + +### Bug Fixes + +* use ERC20 default network ([#623](https://github.com/RequestNetwork/requestNetwork/issues/623)) ([772dd37](https://github.com/RequestNetwork/requestNetwork/commit/772dd37877497a38b9cc74a08c70a6c5aecefa2d)) + + +### Features + +* **request-client.js:** add an explanation when request not found ([#609](https://github.com/RequestNetwork/requestNetwork/issues/609)) ([3909958](https://github.com/RequestNetwork/requestNetwork/commit/39099580b65b86282d19a71ffad77f1b89767cca)) +* add ETH paymentNetwork to request-client ([#617](https://github.com/RequestNetwork/requestNetwork/issues/617)) ([84ed64e](https://github.com/RequestNetwork/requestNetwork/commit/84ed64ebf96a296155dc2d4d5e6c538344fb881b)) +* ETH payment detection in request-client.js ([#626](https://github.com/RequestNetwork/requestNetwork/issues/626)) ([dc3b238](https://github.com/RequestNetwork/requestNetwork/commit/dc3b23827cff7d5466c27d5575515887c461c3b4)) +* exposes currency utilities and list of all supported currencies ([#625](https://github.com/RequestNetwork/requestNetwork/issues/625)) ([eeac838](https://github.com/RequestNetwork/requestNetwork/commit/eeac8385025274fdada39ca3fb2182fc54d470d5)) + + + + + +# [0.10.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/request-client.js@0.9.0...@requestnetwork/request-client.js@0.10.0) (2019-12-04) + + +### Bug Fixes + +* use ERC20 default network ([#623](https://github.com/RequestNetwork/requestNetwork/issues/623)) ([772dd37](https://github.com/RequestNetwork/requestNetwork/commit/772dd37877497a38b9cc74a08c70a6c5aecefa2d)) + + +### Features + +* **request-client.js:** add an explanation when request not found ([#609](https://github.com/RequestNetwork/requestNetwork/issues/609)) ([3909958](https://github.com/RequestNetwork/requestNetwork/commit/39099580b65b86282d19a71ffad77f1b89767cca)) +* add ETH paymentNetwork to request-client ([#617](https://github.com/RequestNetwork/requestNetwork/issues/617)) ([84ed64e](https://github.com/RequestNetwork/requestNetwork/commit/84ed64ebf96a296155dc2d4d5e6c538344fb881b)) +* ETH payment detection in request-client.js ([#626](https://github.com/RequestNetwork/requestNetwork/issues/626)) ([dc3b238](https://github.com/RequestNetwork/requestNetwork/commit/dc3b23827cff7d5466c27d5575515887c461c3b4)) +* exposes currency utilities and list of all supported currencies ([#625](https://github.com/RequestNetwork/requestNetwork/issues/625)) ([eeac838](https://github.com/RequestNetwork/requestNetwork/commit/eeac8385025274fdada39ca3fb2182fc54d470d5)) + + + + + # [0.9.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/request-client.js@0.8.0...@requestnetwork/request-client.js@0.9.0) (2019-11-20) diff --git a/packages/request-client.js/package.json b/packages/request-client.js/package.json index c3b206d99a..7f35ff4156 100644 --- a/packages/request-client.js/package.json +++ b/packages/request-client.js/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/request-client.js", - "version": "0.9.0", + "version": "0.12.0", "publishConfig": { "access": "public" }, @@ -34,7 +34,7 @@ "build": "run-s build:commonjs build:umd", "build:commonjs": "tsc -b", "build:umd": "webpack", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "docs": "shx rm -rf ./docs && compodoc -p tsconfig.json --output docs --disablePrivate --gaID UA-105153327-8", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", @@ -43,16 +43,16 @@ "test:watch": "nyc mocha --watch --watch-extensions ts --require source-map-support/register --require amd-loader \"test/**/*.ts\"" }, "dependencies": { - "@requestnetwork/advanced-logic": "0.6.0", - "@requestnetwork/data-access": "0.5.2", - "@requestnetwork/data-format": "0.4.5", - "@requestnetwork/epk-signature": "0.5.4", - "@requestnetwork/multi-format": "0.2.1", - "@requestnetwork/request-logic": "0.8.0", - "@requestnetwork/transaction-manager": "0.8.1", - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0", - "axios": "0.18.1", + "@requestnetwork/advanced-logic": "0.9.0", + "@requestnetwork/data-access": "0.5.5", + "@requestnetwork/data-format": "0.4.8", + "@requestnetwork/epk-signature": "0.5.7", + "@requestnetwork/multi-format": "0.2.4", + "@requestnetwork/request-logic": "0.8.3", + "@requestnetwork/transaction-manager": "0.8.4", + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0", + "axios": "0.19.0", "bn.js": "4.11.8", "currency-codes": "1.5.1", "eth-contract-metadata": "1.11.0", @@ -65,8 +65,9 @@ "@types/bn.js": "4.11.5", "@types/chai": "4.1.7", "@types/chai-spies": "1.0.0", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", "@types/node-fetch": "2.1.4", + "@types/sinon": "7.5.0", "@typescript-eslint/parser": "1.2.0", "amd-loader": "0.0.8", "awesome-typescript-loader": "5.2.1", @@ -79,7 +80,7 @@ "eslint-plugin-spellcheck": "0.0.11", "eslint-plugin-typescript": "0.14.0", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "npm-run-all": "4.1.5", "nyc": "13.2.0", "prettier": "1.16.4", @@ -87,12 +88,12 @@ "sinon": "7.5.0", "source-map-support": "0.5.13", "terser-webpack-plugin": "1.3.0", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "tslint": "5.12.1", "typescript": "3.7.2", "webpack": "4.38.0", "webpack-bundle-analyzer": "3.3.2", - "webpack-cli": "3.3.6" + "webpack-cli": "3.3.10" }, "gitHead": "6155223cfce769e48ccae480c510b35b4f54b4d0" } diff --git a/packages/request-client.js/src/api/currency.ts b/packages/request-client.js/src/api/currency.ts index af33beef79..2152d6fae3 100644 --- a/packages/request-client.js/src/api/currency.ts +++ b/packages/request-client.js/src/api/currency.ts @@ -1,6 +1,11 @@ import { RequestLogicTypes } from '@requestnetwork/types'; -import * as currencyCodes from 'currency-codes'; -import { getErc20Currency, getErc20Decimals, getErc20Symbol } from './currency/erc20'; +import * as isoCurrencyCodes from 'currency-codes'; +import { + getErc20Currency, + getErc20Decimals, + getErc20Symbol, + getSupportedERC20Tokens, +} from './currency/erc20'; // List of our supported cryptocurrencies const currencyList = new Map([ @@ -52,7 +57,7 @@ export function stringToCurrency(currencyString: string): RequestLogicTypes.ICur } // Check if it's one of ISO4217 currencies - if (currencyCodes.codes().includes(value)) { + if (isoCurrencyCodes.codes().includes(value)) { return { type: RequestLogicTypes.CURRENCY.ISO4217, value, @@ -65,7 +70,7 @@ export function stringToCurrency(currencyString: string): RequestLogicTypes.ICur // If a network was declared, add it to the currency object if (network) { - if (currency.network !== network) { + if (currency.network && currency.network !== network) { throw new Error( `You can't declare a network with currency ${value}. It's only available on the network: ${ currency.network @@ -119,19 +124,17 @@ export function currencyToString(currency: RequestLogicTypes.ICurrency): string * @param currency The currency * @returns The number of decimals */ -export async function getDecimalsForCurrency( - currency: RequestLogicTypes.ICurrency, -): Promise { +export function getDecimalsForCurrency(currency: RequestLogicTypes.ICurrency): number { if (currency.type === RequestLogicTypes.CURRENCY.ERC20) { return getErc20Decimals(currency); } // Return the number of decimals for ISO-4217 currencies if (currency.type === RequestLogicTypes.CURRENCY.ISO4217) { - const iso = currencyCodes.code(currency.value); + const iso = isoCurrencyCodes.code(currency.value); if (!iso) { throw new Error(`Unsupported ISO currency ${currency.value}`); } - return Promise.resolve(iso.digits); + return iso.digits; } const decimals = { @@ -140,7 +143,53 @@ export async function getDecimalsForCurrency( }[currency.type]; if (!decimals) { - throw new Error(`Currency ${currency} not implemented`); + throw new Error(`Currency ${currency.type} not implemented`); } - return Promise.resolve(decimals); + return decimals; } + +/** + * Returns an object with all the supported currency by type + * + * @returns List of all supported currencies + */ +export function getAllSupportedCurrencies(): { + [type: string]: Array<{ name: string; symbol: string; decimals: number; address?: string }>; +} { + // Creates the list of ISO currencies + const isoCurrencyData = require('currency-codes/data') as isoCurrencyCodes.CurrencyCodeRecord[]; + const isoCurrencies = isoCurrencyData.map(cc => ({ + decimals: cc.digits, + name: cc.currency, + symbol: cc.code, + })); + + // Gets the list of ERC20 currencies + const erc20Currencies = getSupportedERC20Tokens(); + + return { + [RequestLogicTypes.CURRENCY.ETH]: [ + { + decimals: 18, + name: 'Ether', + symbol: 'ETH', + }, + ], + [RequestLogicTypes.CURRENCY.BTC]: [ + { + decimals: 8, + name: 'Bitcoin', + symbol: 'BTC', + }, + ], + [RequestLogicTypes.CURRENCY.ISO4217]: isoCurrencies, + [RequestLogicTypes.CURRENCY.ERC20]: erc20Currencies, + }; +} + +export default { + currencyToString, + getAllSupportedCurrencies, + getDecimalsForCurrency, + stringToCurrency, +}; diff --git a/packages/request-client.js/src/api/currency/erc20.ts b/packages/request-client.js/src/api/currency/erc20.ts index 33cf2ee1e8..a17e6bca52 100644 --- a/packages/request-client.js/src/api/currency/erc20.ts +++ b/packages/request-client.js/src/api/currency/erc20.ts @@ -1,6 +1,5 @@ import { RequestLogicTypes } from '@requestnetwork/types'; import { utils } from 'ethers'; -import { getDecimals } from '../payment-network/erc20/info-retriever'; // These interfaces are declared here because they should be used only in this context // A Token description from the eth-contract-metadata list @@ -43,6 +42,24 @@ export const supportedRinkebyERC20 = new Map([ ], ]); +// Additional details about the supported rinkeby ERC20 tokens. +const supportedRinkebyERC20Details = { + // Request Central Bank token, used for testing on rinkeby. + CTBK: { + // Faucet URL: https://central.request.network + address: '0x995d6a8c21f24be1dd04e105dd0d83758343e258', + decimals: 18, + name: 'Central Bank Token', + }, + // Faucet Token on rinkeby network. + FAU: { + // Faucet URL: https://erc20faucet.com/ + address: '0xFab46E002BbF0b4509813474841E0716E6730136', + decimals: 18, + name: 'Faucet Token', + }, +}; + /** * Returns a Currency object for an ERC20, if found * @param symbol The ERC20 token symbol @@ -81,17 +98,26 @@ export function getErc20Currency( * @param currency The ERC20 Currency object * @returns The number of decimals for the ERC20 currency */ -export function getErc20Decimals(currency: RequestLogicTypes.ICurrency): Promise { +export function getErc20Decimals(currency: RequestLogicTypes.ICurrency): number { + let erc20Token; + // Get the decimals from the supported mainnet ERC20 if (!currency.network || currency.network === 'mainnet') { - // Tries to get the decimals from the supported ERC20 currencies list - const erc20Token = getMainnetErc20FromAddress(currency.value); - if (erc20Token) { - return Promise.resolve(erc20Token.decimals); - } + erc20Token = getMainnetErc20FromAddress(currency.value); + } + + // Get the decimals from the supported rinkeby ERC20 + if (currency.network === 'rinkeby') { + erc20Token = Object.values(supportedRinkebyERC20Details).find( + ({ address }) => address === currency.value, + ); + } + + if (erc20Token) { + return erc20Token.decimals; } - // For un-supported ERC20 currencies, we get the decimals from the smart contract - return getDecimals(currency.value, currency.network || 'mainnet'); + // If no supported ERC20 is found, throw error + throw new Error(`Unsupported ERC20 address: ${currency.value}`); } /** @@ -160,3 +186,25 @@ export function getErc20Symbol(currency: RequestLogicTypes.ICurrency): string | return null; } + +/** + * Returns a list of supported ERC20 currencies + * + * @returns List of supported ERC20 currencies + */ +export function getSupportedERC20Tokens(): Array<{ + name: string; + symbol: string; + decimals: number; + address: string; +}> { + return Object.entries(supportedERC20Tokens) + .filter(([, { erc20 }]) => !!erc20) + .map(([address, { name, symbol, decimals }]) => ({ name, symbol, decimals, address })) + .concat( + Object.entries(supportedRinkebyERC20Details).map(([symbol, token]) => ({ + ...token, + symbol: symbol + '-rinkeby', + })), + ); +} diff --git a/packages/request-client.js/src/api/payment-network/btc/address-based.ts b/packages/request-client.js/src/api/payment-network/btc/address-based.ts index dc42d78e4d..6b358f714c 100644 --- a/packages/request-client.js/src/api/payment-network/btc/address-based.ts +++ b/packages/request-client.js/src/api/payment-network/btc/address-based.ts @@ -77,14 +77,14 @@ export default class PaymentNetworkBTCAddressBased { request: RequestLogicTypes.IRequest, paymentNetworkId: ExtensionTypes.ID, networkId: number, - ): Promise { + ): Promise { if (!request.extensions[paymentNetworkId]) { throw new Error(`The request do not have the extension : ̀${paymentNetworkId}`); } const paymentAddress = request.extensions[paymentNetworkId].values.paymentAddress; const refundAddress = request.extensions[paymentNetworkId].values.refundAddress; - let payments: Types.IBalanceWithEvents = { balance: '0', events: [] }; + let payments: Types.BTCBalanceWithEvents = { balance: '0', events: [] }; if (paymentAddress) { payments = await this.extractBalanceAndEvents( paymentAddress, @@ -93,7 +93,7 @@ export default class PaymentNetworkBTCAddressBased { ); } - let refunds: Types.IBalanceWithEvents = { balance: '0', events: [] }; + let refunds: Types.BTCBalanceWithEvents = { balance: '0', events: [] }; if (refundAddress) { refunds = await this.extractBalanceAndEvents( refundAddress, @@ -106,9 +106,8 @@ export default class PaymentNetworkBTCAddressBased { .sub(new bigNumber(refunds.balance || 0)) .toString(); - const events: Types.IPaymentNetworkEvent[] = [...payments.events, ...refunds.events].sort( - (a: Types.IPaymentNetworkEvent, b: Types.IPaymentNetworkEvent) => - a.parameters.timestamp - b.parameters.timestamp, + const events: Types.BTCPaymentNetworkEvent[] = [...payments.events, ...refunds.events].sort( + (a, b) => (a.timestamp || 0) - (b.timestamp || 0), ); return { @@ -129,7 +128,7 @@ export default class PaymentNetworkBTCAddressBased { address: string, eventName: Types.EVENTS_NAMES, networkId: number, - ): Promise { + ): Promise { return this.bitcoinDetectionProvider.getAddressBalanceWithEvents(networkId, address, eventName); } } diff --git a/packages/request-client.js/src/api/payment-network/btc/default-bitcoin-detection-provider.ts b/packages/request-client.js/src/api/payment-network/btc/default-bitcoin-detection-provider.ts index 150329ffc8..353ee2d5ee 100644 --- a/packages/request-client.js/src/api/payment-network/btc/default-bitcoin-detection-provider.ts +++ b/packages/request-client.js/src/api/payment-network/btc/default-bitcoin-detection-provider.ts @@ -35,7 +35,7 @@ export default class DefaultBitcoinDetectionProvider implements Types.IBitcoinDe bitcoinNetworkId: number, address: string, eventName: Types.EVENTS_NAMES, - ): Promise { + ): Promise { if (this.providers.length < 2) { throw new Error('At least two bitcoin providers are needed'); } @@ -84,19 +84,19 @@ export default class DefaultBitcoinDetectionProvider implements Types.IBitcoinDe * @returns Object containing IBalanceWithEvents and the count */ private getMostCommonBalance( - array: Types.IBalanceWithEvents[], - ): { count: number; value: Types.IBalanceWithEvents } | undefined { + array: Types.BTCBalanceWithEvents[], + ): { count: number; value: Types.BTCBalanceWithEvents } | undefined { // Reduce the array to an object indexed by balance with the count const duplicatesWithCount: { - [key: string]: { count: number; value: Types.IBalanceWithEvents }; + [key: string]: { count: number; value: Types.BTCBalanceWithEvents }; } = array .filter(info => info.balance !== '-1') .reduce( ( accumulator: { - [key: string]: { count: number; value: Types.IBalanceWithEvents }; + [key: string]: { count: number; value: Types.BTCBalanceWithEvents }; }, - elem: Types.IBalanceWithEvents, + elem: Types.BTCBalanceWithEvents, ) => { if (!accumulator[elem.balance]) { accumulator[elem.balance] = { count: 0, value: elem }; diff --git a/packages/request-client.js/src/api/payment-network/btc/default-providers/blockchain-info.ts b/packages/request-client.js/src/api/payment-network/btc/default-providers/blockchain-info.ts index a25edd525d..2b5ec8dfd7 100644 --- a/packages/request-client.js/src/api/payment-network/btc/default-providers/blockchain-info.ts +++ b/packages/request-client.js/src/api/payment-network/btc/default-providers/blockchain-info.ts @@ -30,7 +30,7 @@ export default class BlockchainInfo implements Types.IBitcoinDetectionProvider { bitcoinNetworkId: number, address: string, eventName: Types.EVENTS_NAMES, - ): Promise { + ): Promise { const blockchainInfoUrl = this.getBlockchainInfoUrl(bitcoinNetworkId); const queryUrl = `${blockchainInfoUrl}/rawaddr/${address}?cors=true`; @@ -87,11 +87,11 @@ export default class BlockchainInfo implements Types.IBitcoinDetectionProvider { * @param eventName Indicates if it is an address for payment or refund * @returns Balance with events */ - public parse(addressInfo: any, eventName: Types.EVENTS_NAMES): Types.IBalanceWithEvents { + public parse(addressInfo: any, eventName: Types.EVENTS_NAMES): Types.BTCBalanceWithEvents { const address = addressInfo.address; const balance = new bigNumber(addressInfo.total_received).toString(); - const events: Types.IPaymentNetworkEvent[] = addressInfo.txs + const events: Types.BTCPaymentNetworkEvent[] = addressInfo.txs // exclude the transactions coming from the same address .filter((tx: any) => { const selfInputs = tx.inputs.filter( @@ -112,14 +112,14 @@ export default class BlockchainInfo implements Types.IBitcoinDetectionProvider { }, []) .filter((output: any) => output.output.addr === address) .map( - (output: any): Types.IPaymentNetworkEvent => ({ + (output: any): Types.BTCPaymentNetworkEvent => ({ + amount: output.output.value.toString(), name: eventName, parameters: { - amount: output.output.value.toString(), block: output.blockHeight, - timestamp: output.timestamp, txHash: output.txHash, }, + timestamp: output.timestamp, }), ); diff --git a/packages/request-client.js/src/api/payment-network/btc/default-providers/blockcypher-com.ts b/packages/request-client.js/src/api/payment-network/btc/default-providers/blockcypher-com.ts index 8c6c3d461a..fd4a06378b 100644 --- a/packages/request-client.js/src/api/payment-network/btc/default-providers/blockcypher-com.ts +++ b/packages/request-client.js/src/api/payment-network/btc/default-providers/blockcypher-com.ts @@ -27,7 +27,7 @@ export default class BlockcypherCom implements Types.IBitcoinDetectionProvider { bitcoinNetworkId: number, address: string, eventName: Types.EVENTS_NAMES, - ): Promise { + ): Promise { const baseUrl = this.getBaseUrl(bitcoinNetworkId); const queryUrl = `${baseUrl}/addrs/${address}`; try { @@ -57,7 +57,7 @@ export default class BlockcypherCom implements Types.IBitcoinDetectionProvider { * @param eventName Indicates if it is an address for payment or refund * @returns Balance with events */ - public parse(addressInfo: any, eventName: Types.EVENTS_NAMES): Types.IBalanceWithEvents { + public parse(addressInfo: any, eventName: Types.EVENTS_NAMES): Types.BTCBalanceWithEvents { const balance = new bigNumber(addressInfo.total_received).toString(); // Retrieves all the transaction hash of the transactions having as input the current address @@ -65,20 +65,20 @@ export default class BlockcypherCom implements Types.IBitcoinDetectionProvider { .filter((tx: any) => tx.tx_output_n === -1) .map((tx: any) => tx.tx_hash); - const events: Types.IPaymentNetworkEvent[] = addressInfo.txrefs + const events: Types.BTCPaymentNetworkEvent[] = addressInfo.txrefs // keep only the transaction with this address as output .filter((tx: any) => tx.tx_input_n === -1) // exclude the transactions coming from the same address .filter((tx: any) => !inputTxHashes.includes(tx.tx_hash)) .map( - (tx: any): Types.IPaymentNetworkEvent => ({ + (tx: any): Types.BTCPaymentNetworkEvent => ({ + amount: tx.value.toString(), name: eventName, parameters: { - amount: tx.value.toString(), block: tx.block_height, - // timestamp - not given by this API txHash: tx.tx_hash, }, + // timestamp - not given by this API }), ); diff --git a/packages/request-client.js/src/api/payment-network/btc/default-providers/blockstream-info.ts b/packages/request-client.js/src/api/payment-network/btc/default-providers/blockstream-info.ts index 5cab6f864a..5fd82c17cb 100644 --- a/packages/request-client.js/src/api/payment-network/btc/default-providers/blockstream-info.ts +++ b/packages/request-client.js/src/api/payment-network/btc/default-providers/blockstream-info.ts @@ -30,7 +30,7 @@ export default class BlockstreamInfo implements Types.IBitcoinDetectionProvider bitcoinNetworkId: number, address: string, eventName: Types.EVENTS_NAMES, - ): Promise { + ): Promise { const baseUrl = this.getBaseUrl(bitcoinNetworkId); const queryUrl = `${baseUrl}/address/${address}/txs`; try { @@ -87,8 +87,8 @@ export default class BlockstreamInfo implements Types.IBitcoinDetectionProvider * @param eventName Indicates if it is an address for payment or refund * @returns Balance with events */ - public parse(addressInfo: any, eventName: Types.EVENTS_NAMES): Types.IBalanceWithEvents { - const events: Types.IPaymentNetworkEvent[] = addressInfo.txs + public parse(addressInfo: any, eventName: Types.EVENTS_NAMES): Types.BTCBalanceWithEvents { + const events: Types.BTCPaymentNetworkEvent[] = addressInfo.txs // exclude the transactions coming from the same address .filter((tx: any) => { const autoVin = tx.vin.filter( @@ -109,20 +109,20 @@ export default class BlockstreamInfo implements Types.IBitcoinDetectionProvider }, []) .filter((output: any) => output.output.scriptpubkey_address === addressInfo.address) .map( - (output: any): Types.IPaymentNetworkEvent => ({ + (output: any): Types.BTCPaymentNetworkEvent => ({ + amount: output.output.value.toString(), name: eventName, parameters: { - amount: output.output.value.toString(), block: output.blockHeight, - timestamp: output.timestamp, txHash: output.txHash, }, + timestamp: output.timestamp, }), ); const balance: string = events - .reduce((balanceAccumulator: any, event: Types.IPaymentNetworkEvent) => { - return balanceAccumulator.add(new bigNumber(event.parameters.amount)); + .reduce((balanceAccumulator: any, event: Types.BTCPaymentNetworkEvent) => { + return balanceAccumulator.add(new bigNumber(event.amount)); }, new bigNumber('0')) .toString(); diff --git a/packages/request-client.js/src/api/payment-network/btc/default-providers/chain-so.ts b/packages/request-client.js/src/api/payment-network/btc/default-providers/chain-so.ts index d646eb4336..da590e58f8 100644 --- a/packages/request-client.js/src/api/payment-network/btc/default-providers/chain-so.ts +++ b/packages/request-client.js/src/api/payment-network/btc/default-providers/chain-so.ts @@ -28,9 +28,9 @@ export default class ChainSo implements Types.IBitcoinDetectionProvider { bitcoinNetworkId: number, address: string, eventName: Types.EVENTS_NAMES, - ): Promise { + ): Promise { const baseUrl = this.getBaseUrl(bitcoinNetworkId); - const queryUrl = `${baseUrl}/${address}`; + const queryUrl = `${baseUrl}${address}`; try { const res = await Utils.retry(async () => fetch(queryUrl), { @@ -63,28 +63,28 @@ export default class ChainSo implements Types.IBitcoinDetectionProvider { * @param eventName Indicates if it is an address for payment or refund * @returns Balance with events */ - public parse(addressInfo: any, eventName: Types.EVENTS_NAMES): Types.IBalanceWithEvents { - const events: Types.IPaymentNetworkEvent[] = addressInfo.data.txs + public parse(addressInfo: any, eventName: Types.EVENTS_NAMES): Types.BTCBalanceWithEvents { + const events: Types.BTCPaymentNetworkEvent[] = addressInfo.data.txs // keep only the transaction with value incoming to the address .filter((tx: any) => tx.incoming !== undefined) // delete transactions that are from this address .filter((tx: any) => tx.outgoing === undefined) .map( - (tx: any): Types.IPaymentNetworkEvent => ({ + (tx: any): Types.BTCPaymentNetworkEvent => ({ + amount: converterBTC.toSatoshi(tx.incoming.value).toString(), name: eventName, parameters: { - amount: converterBTC.toSatoshi(tx.incoming.value).toString(), block: tx.block_no, - timestamp: tx.time, txHash: tx.txid, }, + timestamp: tx.time, }), ); // Compute the balance making the sum of all the transactions amount const balance: string = events - .reduce((balanceAccumulator: any, event: Types.IPaymentNetworkEvent) => { - return balanceAccumulator.add(new bigNumber(event.parameters.amount)); + .reduce((balanceAccumulator: any, event: Types.BTCPaymentNetworkEvent) => { + return balanceAccumulator.add(new bigNumber(event.amount)); }, new bigNumber('0')) .toString(); diff --git a/packages/request-client.js/src/api/payment-network/btc/mainnet-address-based.ts b/packages/request-client.js/src/api/payment-network/btc/mainnet-address-based.ts index f012cd2f27..d3e45a1e36 100644 --- a/packages/request-client.js/src/api/payment-network/btc/mainnet-address-based.ts +++ b/packages/request-client.js/src/api/payment-network/btc/mainnet-address-based.ts @@ -12,7 +12,8 @@ const MAINNET_BITCOIN_NETWORK_ID = 0; * * @class PaymentNetworkBTCAddressBased */ -export default class PaymentNetworkBTCAddressBased implements Types.IPaymentNetwork { +export default class PaymentNetworkBTCAddressBased + implements Types.IPaymentNetwork { private btcAddressBased: BTCAddressBased; /** @@ -76,7 +77,9 @@ export default class PaymentNetworkBTCAddressBased implements Types.IPaymentNetw * @param the request to check * @returns the balance and the payment/refund events */ - public async getBalance(request: RequestLogicTypes.IRequest): Promise { + public async getBalance( + request: RequestLogicTypes.IRequest, + ): Promise { return this.btcAddressBased.getBalance( request, PAYMENT_NETWORK_BITCOIN_ADDRESS_BASED, diff --git a/packages/request-client.js/src/api/payment-network/btc/testnet-address-based.ts b/packages/request-client.js/src/api/payment-network/btc/testnet-address-based.ts index c88290698a..17cfb99d79 100644 --- a/packages/request-client.js/src/api/payment-network/btc/testnet-address-based.ts +++ b/packages/request-client.js/src/api/payment-network/btc/testnet-address-based.ts @@ -12,7 +12,8 @@ const TESTNET_BITCOIN_NETWORK_ID = 3; * * @class PaymentNetworkBTCAddressBased */ -export default class PaymentNetworkBTCAddressBased implements Types.IPaymentNetwork { +export default class PaymentNetworkBTCAddressBased + implements Types.IPaymentNetwork { private btcAddressBased: BTCAddressBased; /** @@ -76,7 +77,9 @@ export default class PaymentNetworkBTCAddressBased implements Types.IPaymentNetw * @param the request to check * @returns the balance and the payment/refund events */ - public async getBalance(request: RequestLogicTypes.IRequest): Promise { + public async getBalance( + request: RequestLogicTypes.IRequest, + ): Promise { return this.btcAddressBased.getBalance( request, PAYMENT_NETWORK_TESTNET_BITCOIN_ADDRESS_BASED, diff --git a/packages/request-client.js/src/api/payment-network/declarative.ts b/packages/request-client.js/src/api/payment-network/declarative.ts index f06e5abe1b..a9d2f82569 100644 --- a/packages/request-client.js/src/api/payment-network/declarative.ts +++ b/packages/request-client.js/src/api/payment-network/declarative.ts @@ -7,7 +7,8 @@ const bigNumber: any = require('bn.js'); * * @class PaymentNetworkDeclarative */ -export default class PaymentNetworkDeclarative implements Types.IPaymentNetwork { +export default class PaymentNetworkDeclarative + implements Types.IPaymentNetwork { private extension: ExtensionTypes.PnAnyDeclarative.IAnyDeclarative; public constructor({ advancedLogic }: { advancedLogic: AdvancedLogicTypes.IAdvancedLogic }) { @@ -126,28 +127,41 @@ export default class PaymentNetworkDeclarative implements Types.IPaymentNetwork * @param request the request to check * @returns the balance and the payment/refund events */ - public async getBalance(request: RequestLogicTypes.IRequest): Promise { + public async getBalance( + request: RequestLogicTypes.IRequest, + ): Promise { let balance = new bigNumber(0); - const events: Types.IPaymentNetworkEvent[] = []; + const events: Types.DeclarativePaymentNetworkEvent[] = []; // For each extension data related to the declarative payment network, // we check if the data is a declared received payment or refund and we modify the balance // Received payment increase the balance and received refund decrease the balance request.extensions[Types.PAYMENT_NETWORK_ID.DECLARATIVE].events.forEach(data => { + const parameters = data.parameters; if (data.name === ExtensionTypes.PnAnyDeclarative.ACTION.DECLARE_RECEIVED_PAYMENT) { - const parameters = data.parameters; - parameters.timestamp = data.timestamp; - // Declared received payments from payee is added to the balance - balance = balance.add(new bigNumber(data.parameters.amount)); - events.push({ name: Types.EVENTS_NAMES.PAYMENT, parameters }); + balance = balance.add(new bigNumber(parameters.amount)); + events.push({ + amount: parameters.amount, + name: Types.EVENTS_NAMES.PAYMENT, + parameters: { + note: parameters.note, + }, + timestamp: data.timestamp, + }); } else if (data.name === ExtensionTypes.PnAnyDeclarative.ACTION.DECLARE_RECEIVED_REFUND) { - const parameters = data.parameters; parameters.timestamp = data.timestamp; // The balance is subtracted from declared received refunds from payer - balance = balance.sub(new bigNumber(data.parameters.amount)); - events.push({ name: Types.EVENTS_NAMES.REFUND, parameters }); + balance = balance.sub(new bigNumber(parameters.amount)); + events.push({ + amount: parameters.amount, + name: Types.EVENTS_NAMES.REFUND, + parameters: { + note: parameters.note, + }, + timestamp: data.timestamp, + }); } }); diff --git a/packages/request-client.js/src/api/payment-network/erc20/address-based-info-retriever.ts b/packages/request-client.js/src/api/payment-network/erc20/address-based-info-retriever.ts new file mode 100644 index 0000000000..6779d1555e --- /dev/null +++ b/packages/request-client.js/src/api/payment-network/erc20/address-based-info-retriever.ts @@ -0,0 +1,111 @@ +import { ethers } from 'ethers'; +import * as Types from '../../../types'; + +// The ERC20 smart contract ABI fragment containing decimals property and Transfer event +const erc20BalanceOfAbiFragment = [ + // decimals property + { + constant: true, + inputs: [], + name: 'decimals', + outputs: [ + { + name: '', + type: 'uint8', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + // Transfer events + { + anonymous: false, + inputs: [ + { + indexed: true, + name: 'from', + type: 'address', + }, + { + indexed: true, + name: 'to', + type: 'address', + }, + { + indexed: false, + name: 'value', + type: 'uint256', + }, + ], + name: 'Transfer', + type: 'event', + }, +]; + +/** + * Retrieves a list of transfer events for an address + */ +export default class ERC20InfoRetriever + implements Types.IPaymentNetworkInfoRetriever { + /** + * @param tokenContractAddress The address of the ERC20 contract + * @param address Address of the balance we want to check + * @param eventName Indicate if it is an address for payment or refund + * @param network The Ethereum network to use + */ + constructor( + private tokenContractAddress: string, + private toAddress: string, + private eventName: Types.EVENTS_NAMES, + private network: string, + ) {} + + /** + * Retrieves transfer events for the current contract, address and network. + */ + public async getTransferEvents(): Promise { + // Creates a local or default provider + const provider = + this.network === 'private' + ? new ethers.providers.JsonRpcProvider() + : ethers.getDefaultProvider(this.network); + + // Setup the ERC20 contract interface + const contract = new ethers.Contract( + this.tokenContractAddress, + erc20BalanceOfAbiFragment, + provider, + ); + + // Create a filter to find all the Transfer logs for the toAddress + const filter = contract.filters.Transfer(null, this.toAddress) as ethers.providers.Filter; + filter.fromBlock = 0; + filter.toBlock = 'latest'; + + // Get the event logs + const logs = await provider.getLogs(filter); + + // Clean up the Transfer logs data + const eventPromises = logs.map(async log => { + if (!log.blockNumber) { + throw new Error('Block number not found'); + } + const block = await provider.getBlock(log.blockNumber); + const parsedLog = contract.interface.parseLog(log); + return { + amount: parsedLog.values.value.toString(), + name: this.eventName, + parameters: { + block: block.number, + from: parsedLog.values.from, + to: parsedLog.values.to, + txHash: log.transactionHash, + }, + timestamp: block.timestamp, + }; + }); + + return Promise.all(eventPromises); + } +} diff --git a/packages/request-client.js/src/api/payment-network/erc20/address-based.ts b/packages/request-client.js/src/api/payment-network/erc20/address-based.ts index cc6a742d78..14ed91fb04 100644 --- a/packages/request-client.js/src/api/payment-network/erc20/address-based.ts +++ b/packages/request-client.js/src/api/payment-network/erc20/address-based.ts @@ -1,6 +1,6 @@ import { AdvancedLogicTypes, ExtensionTypes, RequestLogicTypes } from '@requestnetwork/types'; import * as Types from '../../../types'; -import erc20InfoRetriever from './info-retriever'; +import Erc20InfoRetriever from './address-based-info-retriever'; const bigNumber: any = require('bn.js'); const supportedNetworks = ['mainnet', 'rinkeby', 'private']; @@ -8,7 +8,8 @@ const supportedNetworks = ['mainnet', 'rinkeby', 'private']; /** * Handle payment networks with ERC20 based address extension */ -export default class PaymentNetworkERC20AddressBased implements Types.IPaymentNetwork { +export default class PaymentNetworkERC20AddressBased + implements Types.IPaymentNetwork { private extension: ExtensionTypes.PnAddressBased.IAddressBased; /** * @param extension The advanced logic payment network extensions @@ -66,7 +67,9 @@ export default class PaymentNetworkERC20AddressBased implements Types.IPaymentNe * @param request the request to check * @returns the balance and the payment/refund events */ - public async getBalance(request: RequestLogicTypes.IRequest): Promise { + public async getBalance( + request: RequestLogicTypes.IRequest, + ): Promise { if (!request.currency.network) { request.currency.network = 'mainnet'; } @@ -86,7 +89,7 @@ export default class PaymentNetworkERC20AddressBased implements Types.IPaymentNe request.extensions[ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED].values .refundAddress; - let payments: Types.IBalanceWithEvents = { balance: '0', events: [] }; + let payments: Types.ERC20BalanceWithEvents = { balance: '0', events: [] }; if (paymentAddress) { payments = await this.extractBalanceAndEvents( paymentAddress, @@ -96,7 +99,7 @@ export default class PaymentNetworkERC20AddressBased implements Types.IPaymentNe ); } - let refunds: Types.IBalanceWithEvents = { balance: '0', events: [] }; + let refunds: Types.ERC20BalanceWithEvents = { balance: '0', events: [] }; if (refundAddress) { refunds = await this.extractBalanceAndEvents( refundAddress, @@ -110,9 +113,8 @@ export default class PaymentNetworkERC20AddressBased implements Types.IPaymentNe .sub(new bigNumber(refunds.balance || 0)) .toString(); - const events: Types.IPaymentNetworkEvent[] = [...payments.events, ...refunds.events].sort( - (a: Types.IPaymentNetworkEvent, b: Types.IPaymentNetworkEvent) => - a.parameters.timestamp - b.parameters.timestamp, + const events: Types.ERC20PaymentNetworkEvent[] = [...payments.events, ...refunds.events].sort( + (a, b) => (a.timestamp || 0) - (b.timestamp || 0), ); return { @@ -136,13 +138,13 @@ export default class PaymentNetworkERC20AddressBased implements Types.IPaymentNe eventName: Types.EVENTS_NAMES, network: string, tokenContractAddress: string, - ): Promise { - const info = await erc20InfoRetriever(tokenContractAddress, address, network); + ): Promise { + const infoRetriever = new Erc20InfoRetriever(tokenContractAddress, address, eventName, network); + const events = await infoRetriever.getTransferEvents(); - const balance = info.tokenEvents - .reduce((acc, event) => acc.add(new bigNumber(event.value)), new bigNumber(0)) + const balance = events + .reduce((acc, event) => acc.add(new bigNumber(event.amount)), new bigNumber(0)) .toString(); - const events = info.tokenEvents.map(event => ({ name: eventName, parameters: event })); return { balance, diff --git a/packages/request-client.js/src/api/payment-network/erc20/info-retriever.ts b/packages/request-client.js/src/api/payment-network/erc20/info-retriever.ts deleted file mode 100644 index 1d97d5cf96..0000000000 --- a/packages/request-client.js/src/api/payment-network/erc20/info-retriever.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { ethers } from 'ethers'; - -const bigNumber: any = require('bn.js'); - -// The ERC20 smart contract ABI fragment containing decimals property and Transfer event -const erc20BalanceOfAbiFragment = [ - // decimals property - { - constant: true, - inputs: [], - name: 'decimals', - outputs: [ - { - name: '', - type: 'uint8', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - // Transfer events - { - anonymous: false, - inputs: [ - { - indexed: true, - name: 'from', - type: 'address', - }, - { - indexed: true, - name: 'to', - type: 'address', - }, - { - indexed: false, - name: 'value', - type: 'uint256', - }, - ], - name: 'Transfer', - type: 'event', - }, -]; - -/** - * Gets a list of transfer events for an address - * - * @param tokenContractAddress The address of the ERC20 contract - * @param address Address of the balance we want to check - * @param network The Ethereum network to use - */ -async function getTransferEvents( - tokenContractAddress: string, - toAddress: string, - network: string, -): Promise<{ - decimals: string; - tokenEvents: Array<{ from: string; to: string; value: string }>; -}> { - // Creates a local or default provider - const provider = - network === 'private' - ? new ethers.providers.JsonRpcProvider() - : ethers.getDefaultProvider(network); - - // Setup the ERC20 contract interface - const contract = new ethers.Contract(tokenContractAddress, erc20BalanceOfAbiFragment, provider); - - // Get the amount of decimals for the ERC20 - const decimals = new bigNumber(await contract.decimals()).toString(); - - // Create a filter to find all the Transfer logs for the toAddress - const filter = contract.filters.Transfer(null, toAddress) as ethers.providers.Filter; - filter.fromBlock = 0; - filter.toBlock = 'latest'; - - // Get the event logs - const logs = await provider.getLogs(filter); - - // Clean up the Transfer logs data - const tokenEvents = logs.map(log => { - const parsedLog = contract.interface.parseLog(log); - return { - from: parsedLog.values.from, - to: parsedLog.values.to, - value: parsedLog.values.value.toString(), - }; - }); - - return { - decimals, - tokenEvents, - }; -} - -export default getTransferEvents; - -/** - * Returns the amount of decimals for an ERC20 token - * - * @param tokenContractAddress The ERC20 contract address - * @param network The ERC20 contract network - * @returns The number of decimals - */ -export async function getDecimals(tokenContractAddress: string, network: string): Promise { - // Connect to the network - const provider = - network === 'private' - ? new ethers.providers.JsonRpcProvider() - : ethers.getDefaultProvider(network); - // Setup the ERC20 contract interface - const contract = new ethers.Contract(tokenContractAddress, erc20BalanceOfAbiFragment, provider); - // Returns the amount of decimals for the ERC20 - return new bigNumber(await contract.decimals()).toNumber(); -} diff --git a/packages/request-client.js/src/api/payment-network/erc20/proxy-contract.ts b/packages/request-client.js/src/api/payment-network/erc20/proxy-contract.ts new file mode 100644 index 0000000000..c99f83d393 --- /dev/null +++ b/packages/request-client.js/src/api/payment-network/erc20/proxy-contract.ts @@ -0,0 +1,214 @@ +import { AdvancedLogicTypes, ExtensionTypes, RequestLogicTypes } from '@requestnetwork/types'; +import Utils from '@requestnetwork/utils'; +import * as Types from '../../../types'; +import PaymentReferenceCalculator from '../payment-reference-calculator'; +import ProxyInfoRetriever from './proxy-info-retriever'; + +const bigNumber: any = require('bn.js'); + +interface IProxyContractByVersionByNetwork { + [version: string]: { + [network: string]: { address: string; creationBlockNumber: number }; + }; +} + +const PROXY_CONTRACT_ADDRESS_BY_VERSION_BY_NETWORK: IProxyContractByVersionByNetwork = { + ['0.1.0']: { + mainnet: { + address: '0x5f821c20947ff9be22e823edc5b3c709b33121b3', + creationBlockNumber: 9119380, + }, + private: { + address: '0x2c2b9c9a4a25e24b174f26114e8926a9f2128fe4', + creationBlockNumber: 0, + }, + rinkeby: { + address: '0x162edb802fae75b9ee4288345735008ba51a4ec9', + creationBlockNumber: 5628198, + }, + }, +}; + +/** + * Handle payment networks with ERC20 proxy contract extension + */ +export default class PaymentNetworkERC20ProxyContract implements Types.IPaymentNetwork { + private extension: ExtensionTypes.PnReferenceBased.IReferenceBased; + /** + * @param extension The advanced logic payment network extensions + */ + public constructor({ advancedLogic }: { advancedLogic: AdvancedLogicTypes.IAdvancedLogic }) { + this.extension = advancedLogic.extensions.proxyContractErc20; + } + + /** + * Creates the extensions data for the creation of this extension. + * Will set a salt if none is already given + * + * @param paymentNetworkCreationParameters Parameters to create the extension + * @returns The extensionData object + */ + public createExtensionsDataForCreation( + paymentNetworkCreationParameters: Types.IReferenceBasedCreationParameters, + ): ExtensionTypes.IAction { + // If no salt is given, generate one + const salt = paymentNetworkCreationParameters.salt || Utils.crypto.generate8randomBytes(); + + return this.extension.createCreationAction({ + paymentAddress: paymentNetworkCreationParameters.paymentAddress, + refundAddress: paymentNetworkCreationParameters.refundAddress, + salt, + }); + } + + /** + * Creates the extensions data to add payment address + * + * @param parameters to add payment information + * @returns The extensionData object + */ + public createExtensionsDataForAddPaymentInformation( + parameters: ExtensionTypes.PnReferenceBased.IAddPaymentAddressParameters, + ): ExtensionTypes.IAction { + return this.extension.createAddPaymentAddressAction({ + paymentAddress: parameters.paymentAddress, + }); + } + + /** + * Creates the extensions data to add refund address + * + * @param Parameters to add refund information + * @returns The extensionData object + */ + public createExtensionsDataForAddRefundInformation( + parameters: ExtensionTypes.PnReferenceBased.IAddRefundAddressParameters, + ): ExtensionTypes.IAction { + return this.extension.createAddRefundAddressAction({ + refundAddress: parameters.refundAddress, + }); + } + + /** + * Gets the balance and the payment/refund events + * + * @param request the request to check + * @param paymentNetworkId payment network id + * @param tokenContractAddress the address of the token contract + * @returns the balance and the payment/refund events + */ + public async getBalance(request: RequestLogicTypes.IRequest): Promise { + const paymentNetworkId = ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT; + const paymentNetwork = request.extensions[paymentNetworkId]; + + if (!paymentNetwork) { + throw new Error(`The request do not have the extension: ${paymentNetworkId}`); + } + + const paymentAddress = paymentNetwork.values.paymentAddress; + const refundAddress = paymentNetwork.values.refundAddress; + const salt = paymentNetwork.values.salt; + + let payments: Types.IBalanceWithEvents = { balance: '0', events: [] }; + if (paymentAddress) { + payments = await this.extractBalanceAndEvents( + request, + salt, + paymentAddress, + Types.EVENTS_NAMES.PAYMENT, + paymentNetwork.version, + ); + } + + let refunds: Types.IBalanceWithEvents = { balance: '0', events: [] }; + if (refundAddress) { + refunds = await this.extractBalanceAndEvents( + request, + salt, + refundAddress, + Types.EVENTS_NAMES.REFUND, + paymentNetwork.version, + ); + } + + const balance: string = new bigNumber(payments.balance || 0) + .sub(new bigNumber(refunds.balance || 0)) + .toString(); + + const events: Types.ERC20PaymentNetworkEvent[] = [...payments.events, ...refunds.events].sort( + (a, b) => (a.timestamp || 0) - (b.timestamp || 0), + ); + + return { + balance, + events, + }; + } + + /** + * Extracts the balance and events of an address + * + * @private + * @param address Address to check + * @param eventName Indicate if it is an address for payment or refund + * @param network The id of network we want to check + * @param tokenContractAddress the address of the token contract + * @returns The balance and events + */ + private async extractBalanceAndEvents( + request: RequestLogicTypes.IRequest, + salt: string, + toAddress: string, + eventName: Types.EVENTS_NAMES, + paymentNetworkVersion: string, + ): Promise { + const network = request.currency.network; + + if (!network) { + throw new Error(`Payment network not supported by ERC20 payment detection`); + } + + if (!PROXY_CONTRACT_ADDRESS_BY_VERSION_BY_NETWORK[paymentNetworkVersion]) { + throw new Error(`Payment network version not supported: ${paymentNetworkVersion}`); + } + + const proxyContractAddress: string | undefined = + PROXY_CONTRACT_ADDRESS_BY_VERSION_BY_NETWORK[paymentNetworkVersion][network].address; + const proxyCreationBlockNumber: number = + PROXY_CONTRACT_ADDRESS_BY_VERSION_BY_NETWORK[paymentNetworkVersion][network] + .creationBlockNumber; + + if (!proxyContractAddress) { + throw new Error( + `Network not supported for this payment network: ${request.currency.network}`, + ); + } + + const paymentReference = PaymentReferenceCalculator.calculate( + request.requestId, + salt, + toAddress, + ); + + const infoRetriever = new ProxyInfoRetriever( + paymentReference, + proxyContractAddress, + proxyCreationBlockNumber, + request.currency.value, + toAddress, + eventName, + network, + ); + + const events = await infoRetriever.getTransferEvents(); + + const balance = events + .reduce((acc, event) => acc.add(new bigNumber(event.amount)), new bigNumber(0)) + .toString(); + + return { + balance, + events, + }; + } +} diff --git a/packages/request-client.js/src/api/payment-network/erc20/proxy-info-retriever.ts b/packages/request-client.js/src/api/payment-network/erc20/proxy-info-retriever.ts new file mode 100644 index 0000000000..5aa16a6fa4 --- /dev/null +++ b/packages/request-client.js/src/api/payment-network/erc20/proxy-info-retriever.ts @@ -0,0 +1,94 @@ +import { ethers } from 'ethers'; +import * as Types from '../../../types'; + +// The ERC20 proxy smart contract ABI fragment containing TransferWithReference event +const erc20proxyContractAbiFragment = [ + 'event TransferWithReference(address tokenAddress,address to,uint256 amount,bytes indexed paymentReference)', +]; + +/** + * Retrieves a list of payment events from a payment reference, a destination address, a token address and a proxy contract + */ +export default class ProxyERC20InfoRetriever + implements Types.IPaymentNetworkInfoRetriever { + public contractProxy: ethers.Contract; + public provider: ethers.providers.Provider; + + /** + * @param paymentReference The reference to identify the payment + * @param proxyContractAddress The address of the proxy contract + * @param proxyCreationBlockNumber The block that created the proxy contract + * @param tokenContractAddress The address of the ERC20 contract + * @param toAddress Address of the balance we want to check + * @param eventName Indicate if it is an address for payment or refund + * @param network The Ethereum network to use + */ + constructor( + private paymentReference: string, + private proxyContractAddress: string, + private proxyCreationBlockNumber: number, + private tokenContractAddress: string, + private toAddress: string, + private eventName: Types.EVENTS_NAMES, + private network: string, + ) { + // Creates a local or default provider + this.provider = + this.network === 'private' + ? new ethers.providers.JsonRpcProvider() + : ethers.getDefaultProvider(this.network); + + // Setup the ERC20 proxy contract interface + this.contractProxy = new ethers.Contract( + this.proxyContractAddress, + erc20proxyContractAbiFragment, + this.provider, + ); + } + + /** + * Retrieves transfer events for the current contract, address and network. + */ + public async getTransferEvents(): Promise { + // Create a filter to find all the Transfer logs for the toAddress + const filter = this.contractProxy.filters.TransferWithReference( + null, + null, + null, + '0x' + this.paymentReference, + ) as ethers.providers.Filter; + filter.fromBlock = this.proxyCreationBlockNumber; + filter.toBlock = 'latest'; + + // Get the event logs + const logs = await this.provider.getLogs(filter); + + // Parses, filters and creates the events from the logs of the proxy contract + const eventPromises = logs + // Parses the logs + .map(log => { + const parsedLog = this.contractProxy.interface.parseLog(log); + return { parsedLog, log }; + }) + // Keeps only the log with the right token and the right destination address + .filter( + log => + log.parsedLog.values.tokenAddress.toLowerCase() === + this.tokenContractAddress.toLowerCase() && + log.parsedLog.values.to.toLowerCase() === this.toAddress.toLowerCase(), + ) + // Creates the balance events + .map(async t => ({ + amount: t.parsedLog.values.amount.toString(), + name: this.eventName, + parameters: { + block: t.log.blockNumber, + to: this.toAddress, + txHash: t.log.transactionHash, + }, + timestamp: (await this.provider.getBlock(t.log.blockNumber || 0)).timestamp, + })); + + return Promise.all(eventPromises); + } +} diff --git a/packages/request-client.js/src/api/payment-network/eth/info-retriever.ts b/packages/request-client.js/src/api/payment-network/eth/info-retriever.ts new file mode 100644 index 0000000000..c147cf79b7 --- /dev/null +++ b/packages/request-client.js/src/api/payment-network/eth/info-retriever.ts @@ -0,0 +1,57 @@ +import { ethers } from 'ethers'; +import * as Types from '../../../types'; + +/** + * Gets a list of transfer events for an address and payment reference + */ +export default class ETHInfoRetriever + implements Types.IPaymentNetworkInfoRetriever { + /** + * @param address Address to check + * @param eventName Indicate if it is an address for payment or refund + * @param network The id of network we want to check + * @param paymentReference The reference to identify the payment + * @param etherscanApiToken The etherscan API token + */ + constructor( + private toAddress: string, + private eventName: Types.EVENTS_NAMES, + private network: string, + private paymentReference: string, + private etherscanApiKey?: string, + ) {} + + public async getTransferEvents(): Promise { + if (this.network === 'private') { + throw new Error( + 'ETH input data info-retriever works with etherscan and cannot work on a local network', + ); + } + const provider = new ethers.providers.EtherscanProvider(this.network, this.etherscanApiKey); + const history = await provider.getHistory(this.toAddress); + + const events = history + // keep only when address is the destination + .filter( + transaction => + transaction.to && transaction.to.toLowerCase() === this.toAddress.toLowerCase(), + ) + // keep only if data contains the payment reference + .filter( + transaction => + transaction.data.toLowerCase() === '0x' + this.paymentReference.toLowerCase(), + ) + .map(transaction => ({ + amount: transaction.value.toString(), + name: this.eventName, + parameters: { + block: transaction.blockNumber, + confirmations: transaction.confirmations, + txHash: transaction.hash, + }, + timestamp: transaction.timestamp, + })); + + return events; + } +} diff --git a/packages/request-client.js/src/api/payment-network/eth/input-data.ts b/packages/request-client.js/src/api/payment-network/eth/input-data.ts new file mode 100644 index 0000000000..a0d363f04f --- /dev/null +++ b/packages/request-client.js/src/api/payment-network/eth/input-data.ts @@ -0,0 +1,178 @@ +import { AdvancedLogicTypes, ExtensionTypes, RequestLogicTypes } from '@requestnetwork/types'; +import Utils from '@requestnetwork/utils'; +import * as Types from '../../../types'; +import PaymentReferenceCalculator from '../payment-reference-calculator'; + +import EthInputDataInfoRetriever from './info-retriever'; + +const bigNumber: any = require('bn.js'); +const supportedNetworks = ['mainnet', 'rinkeby', 'private']; + +/** + * Handle payment networks with ETH input data extension + */ +export default class PaymentNetworkETHInputData + implements Types.IPaymentNetwork { + private extension: ExtensionTypes.PnReferenceBased.IReferenceBased; + /** + * @param extension The advanced logic payment network extensions + */ + public constructor({ advancedLogic }: { advancedLogic: AdvancedLogicTypes.IAdvancedLogic }) { + this.extension = advancedLogic.extensions.ethereumInputData; + } + + /** + * Creates the extensions data for the creation of this extension. + * Will set a salt if none is already given + * + * @param paymentNetworkCreationParameters Parameters to create the extension + * @returns The extensionData object + */ + public createExtensionsDataForCreation( + paymentNetworkCreationParameters: Types.IReferenceBasedCreationParameters, + ): ExtensionTypes.IAction { + // If no salt is given, generate one + const salt = paymentNetworkCreationParameters.salt || Utils.crypto.generate8randomBytes(); + + return this.extension.createCreationAction({ + paymentAddress: paymentNetworkCreationParameters.paymentAddress, + refundAddress: paymentNetworkCreationParameters.refundAddress, + salt, + }); + } + + /** + * Creates the extensions data to add payment address + * + * @param parameters to add payment information + * @returns The extensionData object + */ + public createExtensionsDataForAddPaymentInformation( + parameters: ExtensionTypes.PnReferenceBased.IAddPaymentAddressParameters, + ): ExtensionTypes.IAction { + return this.extension.createAddPaymentAddressAction({ + paymentAddress: parameters.paymentAddress, + }); + } + + /** + * Creates the extensions data to add refund address + * + * @param Parameters to add refund information + * @returns The extensionData object + */ + public createExtensionsDataForAddRefundInformation( + parameters: ExtensionTypes.PnReferenceBased.IAddRefundAddressParameters, + ): ExtensionTypes.IAction { + return this.extension.createAddRefundAddressAction({ + refundAddress: parameters.refundAddress, + }); + } + + /** + * Gets the balance and the payment/refund events + * + * @param request the request to check + * @returns the balance and the payment/refund events + */ + public async getBalance( + request: RequestLogicTypes.IRequest, + ): Promise { + if (!request.currency.network) { + request.currency.network = 'mainnet'; + } + if (!supportedNetworks.includes(request.currency.network)) { + throw new Error( + `Payment network ${ + request.currency.network + } not supported by ETH payment detection. Supported networks: ${supportedNetworks.join( + ', ', + )}`, + ); + } + const extensionValues: { paymentAddress: string; refundAddress: string; salt: string } = + request.extensions[ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA].values; + + const paymentAddress = extensionValues.paymentAddress; + const refundAddress = extensionValues.refundAddress; + + let payments: Types.ETHBalanceWithEvents = { balance: '0', events: [] }; + if (paymentAddress) { + const paymentReferencePayment = PaymentReferenceCalculator.calculate( + request.requestId, + extensionValues.salt, + paymentAddress, + ); + payments = await this.extractBalanceAndEvents( + paymentAddress, + Types.EVENTS_NAMES.PAYMENT, + request.currency.network, + paymentReferencePayment, + ); + } + + let refunds: Types.ETHBalanceWithEvents = { balance: '0', events: [] }; + if (refundAddress) { + const paymentReferenceRefund = PaymentReferenceCalculator.calculate( + request.requestId, + extensionValues.salt, + refundAddress, + ); + refunds = await this.extractBalanceAndEvents( + refundAddress, + Types.EVENTS_NAMES.REFUND, + request.currency.network, + paymentReferenceRefund, + ); + } + + const balance: string = new bigNumber(payments.balance || 0) + .sub(new bigNumber(refunds.balance || 0)) + .toString(); + + const events: Types.ETHPaymentNetworkEvent[] = [...payments.events, ...refunds.events].sort( + (a: Types.ETHPaymentNetworkEvent, b: Types.ETHPaymentNetworkEvent) => + (a.timestamp || 0) - (b.timestamp || 0), + ); + + return { + balance, + events, + }; + } + + /** + * Extracts the balance and events of an address + * + * @private + * @param address Address to check + * @param eventName Indicate if it is an address for payment or refund + * @param network The id of network we want to check + * @param paymentReference The reference to identify the payment + * @returns The balance + */ + private async extractBalanceAndEvents( + address: string, + eventName: Types.EVENTS_NAMES, + network: string, + paymentReference: string, + ): Promise { + const infoRetriever = new EthInputDataInfoRetriever( + address, + eventName, + network, + paymentReference, + ); + + const events = await infoRetriever.getTransferEvents(); + + const balance = events + .reduce((acc, event) => acc.add(new bigNumber(event.amount)), new bigNumber(0)) + .toString(); + + return { + balance, + events, + }; + } +} diff --git a/packages/request-client.js/src/api/payment-network/payment-network-factory.ts b/packages/request-client.js/src/api/payment-network/payment-network-factory.ts index 7e98051406..e941be30b3 100644 --- a/packages/request-client.js/src/api/payment-network/payment-network-factory.ts +++ b/packages/request-client.js/src/api/payment-network/payment-network-factory.ts @@ -4,9 +4,10 @@ import BTCAddressedBased from './btc/mainnet-address-based'; import TestnetBTCAddressedBased from './btc/testnet-address-based'; import Declarative from './declarative'; import ERC20AddressBased from './erc20/address-based'; +import ERC20ProxyContract from './erc20/proxy-contract'; +import EthInputData from './eth/input-data'; /** Register the payment network by currency and type */ -// TODO: take into account currency network and possibly value when finding supported network const supportedPaymentNetwork: Types.ISupportedPaymentNetworkByCurrency = { BTC: { mainnet: { @@ -20,12 +21,26 @@ const supportedPaymentNetwork: Types.ISupportedPaymentNetworkByCurrency = { ERC20: { mainnet: { [ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED as string]: ERC20AddressBased, + [ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT as string]: ERC20ProxyContract, }, private: { [ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED as string]: ERC20AddressBased, + [ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT as string]: ERC20ProxyContract, }, rinkeby: { [ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED as string]: ERC20AddressBased, + [ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT as string]: ERC20ProxyContract, + }, + }, + ETH: { + mainnet: { + [ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA as string]: EthInputData, + }, + private: { + [ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA as string]: EthInputData, + }, + rinkeby: { + [ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA as string]: EthInputData, }, }, }; diff --git a/packages/request-client.js/src/api/payment-network/payment-reference-calculator.ts b/packages/request-client.js/src/api/payment-network/payment-reference-calculator.ts new file mode 100644 index 0000000000..bbdda64989 --- /dev/null +++ b/packages/request-client.js/src/api/payment-network/payment-reference-calculator.ts @@ -0,0 +1,19 @@ +import Utils from '@requestnetwork/utils'; + +/** + * Compute the payment reference + * + * @param requestId The requestId + * @param salt The salt for the request + * @param address Payment or refund address + */ +function calculate(requestId: string, salt: string, address: string): string { + if (!requestId || !salt || !address) { + throw new Error('RequestId, salt and address are mandatory to calculate the payment reference'); + } + // "The value is the last 8 bytes of a salted hash of the requestId: `last8Bytes(hash(requestId + salt + address))`" + // tslint:disable:no-magic-numbers + return Utils.crypto.keccak256Hash((requestId + salt + address).toLowerCase()).slice(-16); +} + +export default { calculate }; diff --git a/packages/request-client.js/src/api/request-network.ts b/packages/request-client.js/src/api/request-network.ts index 463acf23a5..3343d94782 100644 --- a/packages/request-client.js/src/api/request-network.ts +++ b/packages/request-client.js/src/api/request-network.ts @@ -18,19 +18,20 @@ import { stringToCurrency } from './currency'; import { validERC20Address } from './currency/erc20'; import PaymentNetworkFactory from './payment-network/payment-network-factory'; import Request from './request'; +import localUtils from './utils'; /** * Entry point of the request-client.js library. Create requests, get requests, manipulate requests. */ export default class RequestNetwork { + public bitcoinDetectionProvider?: Types.IBitcoinDetectionProvider; + private requestLogic: RequestLogicTypes.IRequestLogic; private transaction: TransactionTypes.ITransactionManager; private advancedLogic: AdvancedLogicTypes.IAdvancedLogic; private contentData: ContentDataExtension; - private bitcoinDetectionProvider?: Types.IBitcoinDetectionProvider; - /** * @param dataAccess instance of data-access layer * @param signatureProvider module in charge of the signatures @@ -87,6 +88,7 @@ export default class RequestNetwork { const { requestParameters, topics, paymentNetwork } = await this.prepareRequestParameters( parameters, ); + const { result: { requestId }, } = await this.requestLogic.createEncryptedRequest( @@ -129,14 +131,18 @@ export default class RequestNetwork { requestId, ); - let paymentNetwork: Types.IPaymentNetwork | null = null; - if (requestAndMeta.result.request) { - paymentNetwork = PaymentNetworkFactory.getPaymentNetworkFromRequest({ + // if no request found, throw a human readable message: + if (!requestAndMeta.result.request) { + throw new Error(localUtils.formatGetRequestFromIdError(requestAndMeta)); + } + + const paymentNetwork: Types.IPaymentNetwork | null = PaymentNetworkFactory.getPaymentNetworkFromRequest( + { advancedLogic: this.advancedLogic, bitcoinDetectionProvider: this.bitcoinDetectionProvider, request: requestAndMeta.result.request, - }); - } + }, + ); // create the request object const request = new Request(this.requestLogic, requestId, paymentNetwork, this.contentData); diff --git a/packages/request-client.js/src/api/request.ts b/packages/request-client.js/src/api/request.ts index 88211b1ae3..d4f378bc14 100644 --- a/packages/request-client.js/src/api/request.ts +++ b/packages/request-client.js/src/api/request.ts @@ -4,6 +4,7 @@ import * as Types from '../types'; import ContentDataExtension from './content-data-extension'; import { currencyToString } from './currency'; import PaymentNetworkDeclarative from './payment-network/declarative'; +import localUtils from './utils'; /** * Class representing a request. @@ -458,7 +459,11 @@ export default class Request { ); if (!requestAndMeta.result.request) { - throw new Error(`No request found for the id: ${this.requestId}`); + throw new Error( + `No request found for the id: ${this.requestId} - ${localUtils.formatGetRequestFromIdError( + requestAndMeta, + )}`, + ); } if (this.paymentNetwork) { diff --git a/packages/request-client.js/src/api/utils.ts b/packages/request-client.js/src/api/utils.ts index 343ce79b55..a7daf9a4c2 100644 --- a/packages/request-client.js/src/api/utils.ts +++ b/packages/request-client.js/src/api/utils.ts @@ -1,9 +1,11 @@ +import { RequestLogicTypes } from '@requestnetwork/types'; import Utils from '@requestnetwork/utils'; import { getDecimalsForCurrency } from './currency'; /** * Collection of utils functions related to the library, meant to simplify its use. */ export default { + formatGetRequestFromIdError, getDecimalsForCurrency, /** @@ -13,3 +15,27 @@ export default { */ getCurrentTimestampInSecond: Utils.getCurrentTimestampInSecond, }; + +/** + * Formats a human readable message from ignored transactions + * + * @param requestAndMeta return from GetRequestFromId + * @returns human readable message + */ +function formatGetRequestFromIdError( + requestAndMeta: RequestLogicTypes.IReturnGetRequestFromId, +): string { + if ( + (requestAndMeta.meta.ignoredTransactions && + requestAndMeta.meta.ignoredTransactions.length !== 0) || + requestAndMeta.meta.transactionManagerMeta.ignoredTransactions.length !== 0 + ) { + return `Invalid transaction(s) found: ${JSON.stringify( + requestAndMeta.meta.transactionManagerMeta.ignoredTransactions + .concat(requestAndMeta.meta.ignoredTransactions || []) + .filter((tx: any) => tx !== null), + )}`; + } + + return 'No transaction found'; +} diff --git a/packages/request-client.js/src/index.ts b/packages/request-client.js/src/index.ts index aab55a5316..506c462bae 100644 --- a/packages/request-client.js/src/index.ts +++ b/packages/request-client.js/src/index.ts @@ -1,6 +1,8 @@ +import Currency from './api/currency'; +import PaymentReferenceCalculator from './api/payment-network/payment-reference-calculator'; import Request from './api/request'; import Utils from './api/utils'; import { default as RequestNetwork } from './http-request-network'; import * as Types from './types'; -export { Request, RequestNetwork, Types, Utils }; +export { Currency, PaymentReferenceCalculator, Request, RequestNetwork, Types, Utils }; diff --git a/packages/request-client.js/src/types.ts b/packages/request-client.js/src/types.ts index 74b587d79b..3333b7f981 100644 --- a/packages/request-client.js/src/types.ts +++ b/packages/request-client.js/src/types.ts @@ -23,12 +23,10 @@ export interface ITimestampBoundaries { } /** Interface request data */ -// TODO: when upgrading typescript to 3.5+ we should use Omit instead of Pick+Exclude -export interface IRequestData - extends Pick> { +export interface IRequestData extends Omit { currency: string; meta: RequestLogicTypes.IReturnMeta | null; - balance: IBalanceWithEvents | null; + balance: IBalanceWithEvents | null; contentData: any; currencyInfo: RequestLogicTypes.ICurrency; } @@ -74,12 +72,19 @@ export interface IPaymentNetworkCreateParameters { parameters: any; } +/** Parameters to create a request with reference based payment network */ +export interface IReferenceBasedCreationParameters { + paymentAddress?: string; + refundAddress?: string; + salt?: string; +} + /** Interface of the class to manage a payment network */ -export interface IPaymentNetwork { +export interface IPaymentNetwork { createExtensionsDataForCreation: (paymentNetworkCreationParameters: any) => any; createExtensionsDataForAddRefundInformation: (parameters: any) => any; createExtensionsDataForAddPaymentInformation: (parameters: any) => any; - getBalance(request: RequestLogicTypes.IRequest): Promise; + getBalance(request: RequestLogicTypes.IRequest): Promise>; } /** Interface of the class to manage the bitcoin provider API */ @@ -88,19 +93,21 @@ export interface IBitcoinDetectionProvider { bitcoinNetworkId: number, address: string, eventName: EVENTS_NAMES, - ) => Promise; + ) => Promise>; } /** Interface for balances and the events link to the payments and refund */ -export interface IBalanceWithEvents { +export interface IBalanceWithEvents { balance: string; - events: IPaymentNetworkEvent[]; + events: Array>; } /** payment network event */ -export interface IPaymentNetworkEvent { +export interface IPaymentNetworkEvent { + amount: string; name: EVENTS_NAMES; - parameters?: any; + parameters?: TEventParameters; + timestamp?: number; } /** payment network event names */ @@ -114,5 +121,59 @@ export enum PAYMENT_NETWORK_ID { BITCOIN_ADDRESS_BASED = ExtensionTypes.ID.PAYMENT_NETWORK_BITCOIN_ADDRESS_BASED, TESTNET_BITCOIN_ADDRESS_BASED = ExtensionTypes.ID.PAYMENT_NETWORK_TESTNET_BITCOIN_ADDRESS_BASED, ERC20_ADDRESS_BASED = ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED, + ERC20_PROXY_CONTRACT = ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_PROXY_CONTRACT, + ETH_INPUT_DATA = ExtensionTypes.ID.PAYMENT_NETWORK_ETH_INPUT_DATA, DECLARATIVE = ExtensionTypes.ID.PAYMENT_NETWORK_ANY_DECLARATIVE, } + +/** Generic info retriever interface */ +export interface IPaymentNetworkInfoRetriever< + TPaymentNetworkEvent extends IPaymentNetworkEvent<{}> +> { + getTransferEvents(): Promise; +} + +/** Parameters for events of ERC20 payments */ +export interface IERC20PaymentEventParameters { + from?: string; + to: string; + block?: number; + txHash?: string; +} + +/** ERC20 Payment Network Event */ +export type ERC20PaymentNetworkEvent = IPaymentNetworkEvent; +/** ERC20 BalanceWithEvents */ +export type ERC20BalanceWithEvents = IBalanceWithEvents; + +/** Parameters for events of ETH payments */ +export interface IETHPaymentEventParameters { + block?: number; + confirmations: number; + txHash?: string; +} +/** ETH Payment Network Event */ +export type ETHPaymentNetworkEvent = IPaymentNetworkEvent; +/** ETH BalanceWithEvents */ +export type ETHBalanceWithEvents = IBalanceWithEvents; + +/** Parameters for events of BTC payments */ +export interface IBTCPaymentEventParameters { + block?: number; + txHash?: string; +} +/** BTC Payment Network Event */ +export type BTCPaymentNetworkEvent = IPaymentNetworkEvent; +/** BTC BalanceWithEvents */ +export type BTCBalanceWithEvents = IBalanceWithEvents; + +/** Parameters for events of Declarative payments */ +export interface IDeclarativePaymentEventParameters { + note?: string; +} +/** Declarative Payment Network Event */ +export type DeclarativePaymentNetworkEvent = IPaymentNetworkEvent< + IDeclarativePaymentEventParameters +>; +/** Declarative BalanceWithEvents */ +export type DeclarativeBalanceWithEvents = IBalanceWithEvents; diff --git a/packages/request-client.js/test/api/currency.test.ts b/packages/request-client.js/test/api/currency.test.ts index 46b2ab115b..ecfcd9a52f 100644 --- a/packages/request-client.js/test/api/currency.test.ts +++ b/packages/request-client.js/test/api/currency.test.ts @@ -2,13 +2,65 @@ import { RequestLogicTypes } from '@requestnetwork/types'; import { assert } from 'chai'; import 'mocha'; -import { currencyToString, getDecimalsForCurrency, stringToCurrency } from '../../src/api/currency'; +import { + currencyToString, + getAllSupportedCurrencies, + getDecimalsForCurrency, + stringToCurrency, +} from '../../src/api/currency'; describe('api/currency', () => { + describe('getAllSupportedCurrencies', () => { + it('returns ETH', () => { + assert.deepEqual(getAllSupportedCurrencies().ETH[0], { + decimals: 18, + name: 'Ether', + symbol: 'ETH', + }); + }); + + it('returns BTC', () => { + assert.deepEqual(getAllSupportedCurrencies().BTC[0], { + decimals: 8, + name: 'Bitcoin', + symbol: 'BTC', + }); + }); + + it('returns SAI', () => { + assert.deepEqual(getAllSupportedCurrencies().ERC20.find(({ symbol }) => symbol === 'SAI'), { + address: '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359', + decimals: 18, + name: 'Sai Stablecoin v1.0', + symbol: 'SAI', + }); + }); + + it('returns CTBK', () => { + assert.deepEqual( + getAllSupportedCurrencies().ERC20.find(({ symbol }) => symbol === 'CTBK-rinkeby'), + { + address: '0x995d6a8c21f24be1dd04e105dd0d83758343e258', + decimals: 18, + name: 'Central Bank Token', + symbol: 'CTBK-rinkeby', + }, + ); + }); + + it('returns EUR', () => { + assert.deepEqual(getAllSupportedCurrencies().ISO4217.find(({ symbol }) => symbol === 'EUR'), { + decimals: 2, + name: 'Euro', + symbol: 'EUR', + }); + }); + }); + describe('getDecimalsForCurrency', () => { - it('returns the correct number of decimals', async () => { + it('returns the correct number of decimals', () => { assert.equal( - await getDecimalsForCurrency({ + getDecimalsForCurrency({ type: RequestLogicTypes.CURRENCY.ETH, value: 'ETH', }), @@ -16,19 +68,20 @@ describe('api/currency', () => { ); }); - it('throws for invalid currencies', async () => { - assert.isRejected( - getDecimalsForCurrency({ - type: 'BANANA' as RequestLogicTypes.CURRENCY, - value: 'SPLIT', - } as RequestLogicTypes.ICurrency), + it('throws for invalid currencies', () => { + assert.throws( + () => + getDecimalsForCurrency({ + type: 'BANANA' as RequestLogicTypes.CURRENCY, + value: 'SPLIT', + } as RequestLogicTypes.ICurrency), 'Currency BANANA not implemented', ); }); - it('returns the correct number of decimals for a supported ERC20', async () => { + it('returns the correct number of decimals for a supported ERC20', () => { assert.equal( - await getDecimalsForCurrency({ + getDecimalsForCurrency({ network: 'mainnet', type: RequestLogicTypes.CURRENCY.ERC20, value: '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359', // SAI @@ -37,14 +90,13 @@ describe('api/currency', () => { ); }); - it('returns the correct number of decimals for a non-supported ERC20', async () => { - assert.equal( - await getDecimalsForCurrency({ + it('throws for a non-supported ERC20', () => { + assert.throws(() => + getDecimalsForCurrency({ network: 'private', type: RequestLogicTypes.CURRENCY.ERC20, value: '0x9FBDa871d559710256a2502A2517b794B482Db40', // local ERC20 contract }), - 18, ); }); }); diff --git a/packages/request-client.js/test/api/payment-network/btc/default-bitcoin-detection-provider.test.ts b/packages/request-client.js/test/api/payment-network/btc/default-bitcoin-detection-provider.test.ts index 7088122074..b72fd2d432 100644 --- a/packages/request-client.js/test/api/payment-network/btc/default-bitcoin-detection-provider.test.ts +++ b/packages/request-client.js/test/api/payment-network/btc/default-bitcoin-detection-provider.test.ts @@ -12,28 +12,28 @@ import * as Types from '../../../../src/types'; import DefaultBitcoinDetectionProvider from '../../../../src/api/payment-network/btc/default-bitcoin-detection-provider'; const btcProviderMock0: Types.IBitcoinDetectionProvider = { - getAddressBalanceWithEvents: async (): Promise => ({ + getAddressBalanceWithEvents: async (): Promise => ({ balance: '0', events: [], }), }; const btcProviderMock1: Types.IBitcoinDetectionProvider = { - getAddressBalanceWithEvents: async (): Promise => ({ + getAddressBalanceWithEvents: async (): Promise => ({ balance: '1', events: [], }), }; const btcProviderMock2: Types.IBitcoinDetectionProvider = { - getAddressBalanceWithEvents: async (): Promise => ({ + getAddressBalanceWithEvents: async (): Promise => ({ balance: '2', events: [], }), }; const btcProviderMockMinus1: Types.IBitcoinDetectionProvider = { - getAddressBalanceWithEvents: async (): Promise => ({ + getAddressBalanceWithEvents: async (): Promise => ({ balance: '-1', events: [], }), diff --git a/packages/request-client.js/test/api/payment-network/btc/default-providers/blockchain-info.test.ts b/packages/request-client.js/test/api/payment-network/btc/default-providers/blockchain-info.test.ts index f5daeb0e5b..6d95854487 100644 --- a/packages/request-client.js/test/api/payment-network/btc/default-providers/blockchain-info.test.ts +++ b/packages/request-client.js/test/api/payment-network/btc/default-providers/blockchain-info.test.ts @@ -4,7 +4,12 @@ import BlockchainInfo from '../../../../../src/api/payment-network/btc/default-p import * as BlockchainInfoData from './blockchain-info-data'; -import { expect } from 'chai'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; + +chai.use(chaiAsPromised); +const expect = chai.expect; + import 'mocha'; // Most of the tests are done as integration tests in ../index.test.ts @@ -13,14 +18,11 @@ describe('api/btc/default-providers/blockchainInfo', () => { describe('getAddressInfo', () => { it('must throw if bitcoinNetworkId is not 0 or 3', async () => { const blockchainInfo = new BlockchainInfo(); - try { - await blockchainInfo.getAddressBalanceWithEvents(1, 'address', Types.EVENTS_NAMES.PAYMENT); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal( - 'Invalid network 0 (mainnet) or 3 (testnet) was expected but 1 was given', - ); - } + await expect( + blockchainInfo.getAddressBalanceWithEvents(1, 'address', Types.EVENTS_NAMES.PAYMENT), + ).to.eventually.be.rejectedWith( + 'Invalid network 0 (mainnet) or 3 (testnet) was expected but 1 was given', + ); }); }); @@ -35,22 +37,22 @@ describe('api/btc/default-providers/blockchainInfo', () => { expect(parsedData.balance, 'balance wrong').to.equal('50500000'); expect(parsedData.events, 'balance wrong').to.deep.equal([ { + amount: '500000', name: 'payment', parameters: { - amount: '500000', block: 1354204, - timestamp: 1531879904, txHash: '2a14f1ad2dfa4601bdc7a6be325241bbdc2ae99d05f096357fda76264b1c5c26', }, + timestamp: 1531879904, }, { + amount: '50000000', name: 'payment', parameters: { - amount: '50000000', block: 1354075, - timestamp: 1531817766, txHash: '7d84924c034798dedcc95f479c9cdb24fe014437f7ce0ee0c2f4bf3580e017d8', }, + timestamp: 1531817766, }, ]); }); diff --git a/packages/request-client.js/test/api/payment-network/btc/default-providers/blockcypher-com.test.ts b/packages/request-client.js/test/api/payment-network/btc/default-providers/blockcypher-com.test.ts index 5dd1728c75..ed041964ba 100644 --- a/packages/request-client.js/test/api/payment-network/btc/default-providers/blockcypher-com.test.ts +++ b/packages/request-client.js/test/api/payment-network/btc/default-providers/blockcypher-com.test.ts @@ -4,7 +4,12 @@ import BlockCypherCom from '../../../../../src/api/payment-network/btc/default-p import * as BlockCypherComData from './blockcypher-com-data'; -import { expect } from 'chai'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; + +chai.use(chaiAsPromised); +const expect = chai.expect; + import 'mocha'; // Most of the tests are done as integration tests in ../index.test.ts @@ -12,15 +17,12 @@ import 'mocha'; describe('api/btc/providers/blockCypherCom', () => { describe('getAddressInfo', () => { it('must throw if bitcoinNetworkId is not 0 or 3', async () => { - try { - const blockCypherCom = new BlockCypherCom(); - await blockCypherCom.getAddressBalanceWithEvents(1, 'address', Types.EVENTS_NAMES.PAYMENT); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal( - 'Invalid network 0 (mainnet) or 3 (testnet) was expected but 1 was given', - ); - } + const blockCypherCom = new BlockCypherCom(); + await expect( + blockCypherCom.getAddressBalanceWithEvents(1, 'address', Types.EVENTS_NAMES.PAYMENT), + ).to.eventually.be.rejectedWith( + 'Invalid network 0 (mainnet) or 3 (testnet) was expected but 1 was given', + ); }); }); @@ -34,20 +36,20 @@ describe('api/btc/providers/blockCypherCom', () => { expect(parsedData.balance, 'balance wrong').to.equal('50500000'); expect(parsedData.events, 'balance wrong').to.deep.equal([ { + amount: '500000', name: 'payment', + // timestamp: 1531879904, parameters: { - amount: '500000', block: 1354204, - // timestamp: 1531879904, txHash: '2a14f1ad2dfa4601bdc7a6be325241bbdc2ae99d05f096357fda76264b1c5c26', }, }, { + amount: '50000000', name: 'payment', + // timestamp: 1531817766, parameters: { - amount: '50000000', block: 1354075, - // timestamp: 1531817766, txHash: '7d84924c034798dedcc95f479c9cdb24fe014437f7ce0ee0c2f4bf3580e017d8', }, }, diff --git a/packages/request-client.js/test/api/payment-network/btc/default-providers/blockstream-info.test.ts b/packages/request-client.js/test/api/payment-network/btc/default-providers/blockstream-info.test.ts index 9d03d1f85e..32a45f1e2d 100644 --- a/packages/request-client.js/test/api/payment-network/btc/default-providers/blockstream-info.test.ts +++ b/packages/request-client.js/test/api/payment-network/btc/default-providers/blockstream-info.test.ts @@ -4,7 +4,12 @@ import Blockstream from '../../../../../src/api/payment-network/btc/default-prov import * as BlockstreamData from './blockstream-info-data'; -import { expect } from 'chai'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; + +chai.use(chaiAsPromised); +const expect = chai.expect; + import 'mocha'; // Most of the tests are done as integration tests in ../index.test.ts @@ -12,15 +17,12 @@ import 'mocha'; describe('api/btc/providers/blockstream', () => { describe('getAddressInfo', () => { it('must throw if bitcoinNetworkId is not 0 or 3', async () => { - try { - const blockstreamData = new Blockstream(); - await blockstreamData.getAddressBalanceWithEvents(1, 'address', Types.EVENTS_NAMES.PAYMENT); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal( - 'Invalid network 0 (mainnet) or 3 (testnet) was expected but 1 was given', - ); - } + const blockstreamData = new Blockstream(); + await expect( + blockstreamData.getAddressBalanceWithEvents(1, 'address', Types.EVENTS_NAMES.PAYMENT), + ).to.eventually.be.rejectedWith( + 'Invalid network 0 (mainnet) or 3 (testnet) was expected but 1 was given', + ); }); }); @@ -35,22 +37,22 @@ describe('api/btc/providers/blockstream', () => { expect(parsedData.events, 'events wrong').to.deep.equal([ { + amount: '500000', name: 'payment', parameters: { - amount: '500000', block: 1354204, - timestamp: 1531880048, txHash: '2a14f1ad2dfa4601bdc7a6be325241bbdc2ae99d05f096357fda76264b1c5c26', }, + timestamp: 1531880048, }, { + amount: '50000000', name: 'payment', parameters: { - amount: '50000000', block: 1354075, - timestamp: 1531818367, txHash: '7d84924c034798dedcc95f479c9cdb24fe014437f7ce0ee0c2f4bf3580e017d8', }, + timestamp: 1531818367, }, ]); }); diff --git a/packages/request-client.js/test/api/payment-network/btc/default-providers/chain-so.test.ts b/packages/request-client.js/test/api/payment-network/btc/default-providers/chain-so.test.ts index f0f633061e..712340e77d 100644 --- a/packages/request-client.js/test/api/payment-network/btc/default-providers/chain-so.test.ts +++ b/packages/request-client.js/test/api/payment-network/btc/default-providers/chain-so.test.ts @@ -4,7 +4,12 @@ import ChainSo from '../../../../../src/api/payment-network/btc/default-provider import * as ChainSoData from './chain-so-data'; -import { expect } from 'chai'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; + +chai.use(chaiAsPromised); +const expect = chai.expect; + import 'mocha'; // Most of the tests are done as integration tests in ../index.test.ts @@ -12,15 +17,12 @@ import 'mocha'; describe('api/btc/providers/chainSo', () => { describe('getAddressInfo', () => { it('must throw if bitcoinNetworkId is not 0 or 3', async () => { - try { - const chainSo = new ChainSo(); - await chainSo.getAddressBalanceWithEvents(1, 'address', Types.EVENTS_NAMES.PAYMENT); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal( - 'Invalid network 0 (mainnet) or 3 (testnet) was expected but 1 was given', - ); - } + const chainSo = new ChainSo(); + await expect( + chainSo.getAddressBalanceWithEvents(1, 'address', Types.EVENTS_NAMES.PAYMENT), + ).to.eventually.be.rejectedWith( + 'Invalid network 0 (mainnet) or 3 (testnet) was expected but 1 was given', + ); }); }); @@ -31,22 +33,22 @@ describe('api/btc/providers/chainSo', () => { expect(parsedData.balance, 'balance wrong').to.equal('50500000'); expect(parsedData.events, 'balance wrong').to.deep.equal([ { + amount: '500000', name: 'payment', parameters: { - amount: '500000', block: 1354204, - timestamp: 1531879904, txHash: '2a14f1ad2dfa4601bdc7a6be325241bbdc2ae99d05f096357fda76264b1c5c26', }, + timestamp: 1531879904, }, { + amount: '50000000', name: 'payment', parameters: { - amount: '50000000', block: 1354075, - timestamp: 1531817766, txHash: '7d84924c034798dedcc95f479c9cdb24fe014437f7ce0ee0c2f4bf3580e017d8', }, + timestamp: 1531817766, }, ]); }); diff --git a/packages/request-client.js/test/api/payment-network/declarative.test.ts b/packages/request-client.js/test/api/payment-network/declarative.test.ts index bded6776ba..f358d6d40a 100644 --- a/packages/request-client.js/test/api/payment-network/declarative.test.ts +++ b/packages/request-client.js/test/api/payment-network/declarative.test.ts @@ -214,36 +214,36 @@ describe('api/declarative', () => { balance: '1200', // 1000 + 500 - 100 - 200 events: [ { + amount: '1000', name: Types.EVENTS_NAMES.PAYMENT, parameters: { - amount: '1000', note: 'first payment', - timestamp: 10, }, + timestamp: 10, }, { + amount: '500', name: Types.EVENTS_NAMES.PAYMENT, parameters: { - amount: '500', note: 'second payment', - timestamp: 15, }, + timestamp: 15, }, { + amount: '100', name: Types.EVENTS_NAMES.REFUND, parameters: { - amount: '100', note: 'first refund', - timestamp: 20, }, + timestamp: 20, }, { + amount: '200', name: Types.EVENTS_NAMES.REFUND, parameters: { - amount: '200', note: 'second refund', - timestamp: 25, }, + timestamp: 25, }, ], }); diff --git a/packages/request-client.js/test/api/payment-network/erc20/info-retriever.test.ts b/packages/request-client.js/test/api/payment-network/erc20/address-based-info-retriever.test.ts similarity index 53% rename from packages/request-client.js/test/api/payment-network/erc20/info-retriever.test.ts rename to packages/request-client.js/test/api/payment-network/erc20/address-based-info-retriever.test.ts index 3fe63ace2f..b4a65847ce 100644 --- a/packages/request-client.js/test/api/payment-network/erc20/info-retriever.test.ts +++ b/packages/request-client.js/test/api/payment-network/erc20/address-based-info-retriever.test.ts @@ -1,9 +1,10 @@ // tslint:disable: no-invalid-this // tslint:disable: no-magic-numbers -import ERC20InfoRetriever from '../../../../src/api/payment-network/erc20/info-retriever'; +import ERC20InfoRetriever from '../../../../src/api/payment-network/erc20/address-based-info-retriever'; import 'chai'; import 'mocha'; +import { EVENTS_NAMES } from '../../../../src/types'; const chai = require('chai'); const expect = chai.expect; @@ -11,38 +12,42 @@ const expect = chai.expect; const erc20LocalhostContractAddress = '0x9FBDa871d559710256a2502A2517b794B482Db40'; /* tslint:disable:no-unused-expression */ -describe('api/erc20/info-retriever', () => { +describe('api/erc20/address-based-info-retriever', () => { describe('on localhost', () => { const paymentAddress = '0xf17f52151EbEF6C7334FAD080c5704D77216b732'; const payerAddress = '0x627306090abaB3A6e1400e9345bC60c78a8BEf57'; const emptyAddress = '0xC5fdf4076b8F3A5357c5E395ab970B5B54098Fef'; it('can get the localhost balance of an address', async () => { - const balanceObject = await ERC20InfoRetriever( + const infoRetriever = new ERC20InfoRetriever( erc20LocalhostContractAddress, paymentAddress, + EVENTS_NAMES.PAYMENT, 'private', ); + const events = await infoRetriever.getTransferEvents(); - expect(balanceObject.decimals).to.be.equal('18'); // if this assert fails it means this address received another transaction - expect(balanceObject.tokenEvents).to.have.lengthOf(1); - expect(balanceObject.tokenEvents[0]).to.deep.equal({ - from: payerAddress, - to: paymentAddress, - value: '10', - }); + expect(events).to.have.lengthOf(1); + expect(events[0].name).to.equal(EVENTS_NAMES.PAYMENT); + expect(events[0].amount).to.equal('10'); + expect(events[0].timestamp).to.be.a('number'); + expect(events[0].parameters!.from).to.equal(payerAddress); + expect(events[0].parameters!.to).to.equal(paymentAddress); + expect(events[0].parameters!.block).to.be.a('number'); + expect(events[0].parameters!.txHash).to.be.a('string'); }); it('gets an empty list of events for an address without ERC20 on localhost', async () => { - const balanceObject = await ERC20InfoRetriever( + const infoRetriever = new ERC20InfoRetriever( erc20LocalhostContractAddress, emptyAddress, + EVENTS_NAMES.PAYMENT, 'private', ); - expect(balanceObject.decimals).to.be.equal('18'); - expect(balanceObject.tokenEvents).to.be.empty; + const events = await infoRetriever.getTransferEvents(); + expect(events).to.be.empty; }); }); }); diff --git a/packages/request-client.js/test/api/payment-network/erc20/address-based.test.ts b/packages/request-client.js/test/api/payment-network/erc20/address-based.test.ts index 3cbce06a00..fcbaaaa933 100644 --- a/packages/request-client.js/test/api/payment-network/erc20/address-based.test.ts +++ b/packages/request-client.js/test/api/payment-network/erc20/address-based.test.ts @@ -107,12 +107,15 @@ describe('api/erc20/address-based', () => { expect(balance.balance).to.be.equal('10'); expect(balance.events).to.have.lengthOf(1); expect(balance.events[0].name).to.be.equal(Types.EVENTS_NAMES.PAYMENT); - expect(balance.events[0].parameters.to).to.be.equal( + expect(balance.events[0].amount).to.be.equal('10'); + expect(balance.events[0].timestamp).to.be.a('number'); + expect(balance.events[0].parameters!.to).to.be.equal( '0xf17f52151EbEF6C7334FAD080c5704D77216b732', ); - expect(balance.events[0].parameters.from).to.be.equal( + expect(balance.events[0].parameters!.from).to.be.equal( '0x627306090abaB3A6e1400e9345bC60c78a8BEf57', ); - expect(balance.events[0].parameters.value).to.be.equal('10'); + expect(balance.events[0].parameters!.block).to.be.a('number'); + expect(balance.events[0].parameters!.txHash).to.be.a('string'); }); }); diff --git a/packages/request-client.js/test/api/payment-network/erc20/proxy-contract.test.ts b/packages/request-client.js/test/api/payment-network/erc20/proxy-contract.test.ts new file mode 100644 index 0000000000..13ec714196 --- /dev/null +++ b/packages/request-client.js/test/api/payment-network/erc20/proxy-contract.test.ts @@ -0,0 +1,95 @@ +import { AdvancedLogicTypes } from '@requestnetwork/types'; +import ERC20ProxyContract from '../../../../src/api/payment-network/erc20/proxy-contract'; + +import * as chai from 'chai'; +import * as spies from 'chai-spies'; +import 'mocha'; + +const expect = chai.expect; +chai.use(spies); +const sandbox = chai.spy.sandbox(); + +let erc20ProxyContract: ERC20ProxyContract; + +const mockAdvancedLogic: AdvancedLogicTypes.IAdvancedLogic = { + applyActionToExtensions(): any { + return; + }, + extensions: { + proxyContractErc20: { + createAddPaymentAddressAction(): any { + return; + }, + createAddRefundAddressAction(): any { + return; + }, + createCreationAction(): any { + return; + }, + }, + }, +}; + +/* tslint:disable:no-unused-expression */ +describe('api/erc20/proxy-contract', () => { + beforeEach(() => { + sandbox.restore(); + erc20ProxyContract = new ERC20ProxyContract({ advancedLogic: mockAdvancedLogic }); + }); + + it('can createExtensionsDataForCreation', async () => { + const spy = sandbox.on(mockAdvancedLogic.extensions.proxyContractErc20, 'createCreationAction'); + + erc20ProxyContract.createExtensionsDataForCreation({ + paymentAddress: 'ethereum address', + salt: 'ea3bc7caf64110ca', + }); + + expect(spy).to.have.been.called.with({ + paymentAddress: 'ethereum address', + refundAddress: undefined, + salt: 'ea3bc7caf64110ca', + }); + }); + + it('can createExtensionsDataForCreation without salt', async () => { + const spy = sandbox.on(mockAdvancedLogic.extensions.proxyContractErc20, 'createCreationAction'); + + erc20ProxyContract.createExtensionsDataForCreation({ + paymentAddress: 'ethereum address', + }); + + // Can't check parameters since salt is generated in createExtensionsDataForCreation + expect(spy).to.have.been.called; + }); + + it('can createExtensionsDataForAddPaymentInformation', async () => { + const spy = sandbox.on( + mockAdvancedLogic.extensions.proxyContractErc20, + 'createAddPaymentAddressAction', + ); + + erc20ProxyContract.createExtensionsDataForAddPaymentInformation({ + paymentAddress: 'ethereum address', + }); + + expect(spy).to.have.been.called.with({ + paymentAddress: 'ethereum address', + }); + }); + + it('can createExtensionsDataForAddRefundInformation', async () => { + const spy = sandbox.on( + mockAdvancedLogic.extensions.proxyContractErc20, + 'createAddRefundAddressAction', + ); + + erc20ProxyContract.createExtensionsDataForAddRefundInformation({ + refundAddress: 'ethereum address', + }); + + expect(spy).to.have.been.called.with({ + refundAddress: 'ethereum address', + }); + }); +}); diff --git a/packages/request-client.js/test/api/payment-network/erc20/proxy-info-retriever.test.ts b/packages/request-client.js/test/api/payment-network/erc20/proxy-info-retriever.test.ts new file mode 100644 index 0000000000..647c9f47d4 --- /dev/null +++ b/packages/request-client.js/test/api/payment-network/erc20/proxy-info-retriever.test.ts @@ -0,0 +1,92 @@ +// tslint:disable: no-invalid-this +// tslint:disable: no-magic-numbers +import ProxyERC20InfoRetriever from '../../../../src/api/payment-network/erc20/proxy-info-retriever'; + +import 'chai'; +import 'mocha'; +import { EVENTS_NAMES } from '../../../../src/types'; + +const chai = require('chai'); +const expect = chai.expect; + +const erc20LocalhostContractAddress = '0x9FBDa871d559710256a2502A2517b794B482Db40'; +const proxyContractAddress = '0x2C2B9C9a4a25e24B174f26114e8926a9f2128FE4'; +const paymentReferenceMock = '0111111111111111111111111111111111111111111111111'; + +/* tslint:disable:no-unused-expression */ +describe('api/erc20/proxy-info-retriever', () => { + describe('on localhost', () => { + const paymentAddress = '0xf17f52151ebef6c7334fad080c5704d77216b732'; + + it('can get the localhost balance of an address', async () => { + const infoRetriever = new ProxyERC20InfoRetriever( + paymentReferenceMock, + proxyContractAddress, + 0, + erc20LocalhostContractAddress, + paymentAddress, + EVENTS_NAMES.PAYMENT, + 'private', + ); + + // inject mock provider.getLogs() + infoRetriever.provider.getLogs = (): any => { + return [ + { + address: proxyContractAddress, + blockHash: '0xe8693d0fb897eac7c350696834f4cf36be3b7d86f746d6764d9903a06dc5fe44', + blockNumber: 115, + data: `0x000000000000000000000000${erc20LocalhostContractAddress.slice( + 2, + )}000000000000000000000000f17f52151ebef6c7334fad080c5704d77216b7320000000000000000000000000000000000000000000000000000000000000001`, + logIndex: 2, + topics: [ + '0x4d4e9dbb7207a31cc25529ccb52e52ddba30ded7734e32691d13da66df7f81da', + '0x6330b989705733cc5c1f7285b8a5b892e08be86ed6fbe9d254713a4277bc5bd2', + ], + transactionHash: '0x66e20126e917ede3543c79357c71ddeda2af68e27d684fd5aa6a813bb6946ce4', + transactionIndex: 0, + }, + ]; + }; + + // inject mock provider.getBlock() + infoRetriever.provider.getBlock = (): any => { + return { + timestamp: 69, + }; + }; + + const events = await infoRetriever.getTransferEvents(); + + // if this assert fails it means this address received another transaction + expect(events).to.have.lengthOf(1); + expect(events[0].name).to.equal(EVENTS_NAMES.PAYMENT); + expect(events[0].amount).to.equal('1'); + expect(events[0].timestamp).to.be.a('number'); + expect(events[0].parameters!.to).to.equal(paymentAddress); + expect(events[0].parameters!.block).to.be.a('number'); + expect(events[0].parameters!.txHash).to.be.a('string'); + }); + + it('gets an empty list of events for an address without ERC20 on localhost', async () => { + const infoRetriever = new ProxyERC20InfoRetriever( + paymentReferenceMock, + proxyContractAddress, + 0, + erc20LocalhostContractAddress, + paymentAddress, + EVENTS_NAMES.PAYMENT, + 'private', + ); + + // inject mock provider.getLogs() + infoRetriever.provider.getLogs = (): any => { + return []; + }; + + const events = await infoRetriever.getTransferEvents(); + expect(events).to.be.empty; + }); + }); +}); diff --git a/packages/request-client.js/test/api/payment-network/eth/info-retriever.test.ts b/packages/request-client.js/test/api/payment-network/eth/info-retriever.test.ts new file mode 100644 index 0000000000..322798e0e6 --- /dev/null +++ b/packages/request-client.js/test/api/payment-network/eth/info-retriever.test.ts @@ -0,0 +1,50 @@ +import EthInfoRetriever from '../../../../src/api/payment-network/eth/info-retriever'; +import PaymentReferenceCalculator from '../../../../src/api/payment-network/payment-reference-calculator'; +import * as Types from '../../../../src/types'; + +import { expect } from 'chai'; +import 'mocha'; + +describe('api/eth/info-retriever', () => { + // In this test, we're looking this transaction: + // https://etherscan.io/tx/0x0de1759d8b246939e370e1d0509e3ed6f1d5f4f5b79735636c0283b64ff6f5ed + it('can get the balance of an address', async () => { + const paymentAddress = '0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB'; + const paymentReference = PaymentReferenceCalculator.calculate( + '01000', + '1234567890123456', + paymentAddress, + ); // 9649a1a4dd5854ed + + const infoRetriever = new EthInfoRetriever( + paymentAddress, + Types.EVENTS_NAMES.PAYMENT, + 'mainnet', + paymentReference, + ); + const events = await infoRetriever.getTransferEvents(); + + // If this assertion fails, another transaction with the data `9649a1a4dd5854ed` + // has been set to the address `0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB` + expect(events).to.have.lengthOf(1); + + expect(events[0].name).to.equal('payment'); + expect(events[0].amount).to.equal('33'); + expect(events[0].timestamp).to.be.a('number'); + expect(events[0].parameters!.txHash).to.equal( + '0x0b53c5296a7b286fef52336529f3934584fea116725d1fe4c59552e926229059', + ); + expect(events[0].parameters!.block).to.be.a('number'); + expect(events[0].parameters!.confirmations).to.be.a('number'); + }); + + it('throws when trying to use it in local', async () => { + const infoRetreiver = new EthInfoRetriever( + '0x01', + Types.EVENTS_NAMES.PAYMENT, + 'private', + '12345', + ); + expect(infoRetreiver.getTransferEvents()).to.be.rejectedWith(Error); + }); +}); diff --git a/packages/request-client.js/test/api/payment-network/eth/input-data.test.ts b/packages/request-client.js/test/api/payment-network/eth/input-data.test.ts new file mode 100644 index 0000000000..3d981fbff4 --- /dev/null +++ b/packages/request-client.js/test/api/payment-network/eth/input-data.test.ts @@ -0,0 +1,121 @@ +import { AdvancedLogicTypes, ExtensionTypes, RequestLogicTypes } from '@requestnetwork/types'; +import EthInputData from '../../../../src/api/payment-network/eth/input-data'; +import * as Types from '../../../../src/types'; + +import 'chai'; +import 'mocha'; + +const chai = require('chai'); +const spies = require('chai-spies'); +const expect = chai.expect; +chai.use(spies); +const sandbox = chai.spy.sandbox(); + +let ethInputData: EthInputData; + +const mockAdvancedLogic: AdvancedLogicTypes.IAdvancedLogic = { + applyActionToExtensions(): any { + return; + }, + extensions: { + ethereumInputData: { + createAddPaymentAddressAction(): any { + return; + }, + createAddRefundAddressAction(): any { + return; + }, + createCreationAction(): any { + return; + }, + }, + }, +}; + +// Most of the tests are done as integration tests in ../index.test.ts +/* tslint:disable:no-unused-expression */ +describe('api/eth/input-data', () => { + beforeEach(() => { + sandbox.restore(); + ethInputData = new EthInputData({ advancedLogic: mockAdvancedLogic }); + }); + + it('can createExtensionsDataForCreation', async () => { + const spy = sandbox.on(mockAdvancedLogic.extensions.ethereumInputData, 'createCreationAction'); + + ethInputData.createExtensionsDataForCreation({ paymentAddress: 'ethereum address' }); + + expect(spy).to.have.been.called.once; + }); + + it('can createExtensionsDataForAddPaymentInformation', async () => { + const spy = sandbox.on( + mockAdvancedLogic.extensions.ethereumInputData, + 'createAddPaymentAddressAction', + ); + + ethInputData.createExtensionsDataForAddPaymentInformation({ + paymentAddress: 'ethereum address', + }); + + expect(spy).to.have.been.called.once; + }); + + it('can createExtensionsDataForAddRefundInformation', async () => { + const spy = sandbox.on( + mockAdvancedLogic.extensions.ethereumInputData, + 'createAddRefundAddressAction', + ); + + ethInputData.createExtensionsDataForAddRefundInformation({ + refundAddress: 'ethereum address', + }); + + expect(spy).to.have.been.called.once; + }); + + //TODO: unskip + it.skip('can getBalance on a localhost request', async () => { + const mockRequest = { + creator: { type: '', value: '0x2' }, + currency: { + network: 'private', + type: RequestLogicTypes.CURRENCY.ETH, + value: 'ETH', + }, + events: [], + expectedAmount: '0', + extensions: { + [ExtensionTypes.ID.PAYMENT_NETWORK_ERC20_ADDRESS_BASED]: { + events: [], + id: '0', + type: 'none', + values: { + paymentAddress: '0xf17f52151EbEF6C7334FAD080c5704D77216b732', + }, + version: '0', + }, + }, + extensionsData: [], + requestId: '0x1', + state: 'Good', + timestamp: 0, + version: '0.2', + }; + + const balance = await ethInputData.getBalance(mockRequest as RequestLogicTypes.IRequest); + + expect(balance.balance).to.be.equal('10'); + expect(balance.events).to.have.lengthOf(1); + expect(balance.events[0].name).to.be.equal(Types.EVENTS_NAMES.PAYMENT); + // TODO: add to & from to parameters? + // expect(balance.events[0].parameters!.to).to.be.equal( + // '0xf17f52151EbEF6C7334FAD080c5704D77216b732', + // ); + // expect(balance.events[0].parameters!.from).to.be.equal( + // '0x627306090abaB3A6e1400e9345bC60c78a8BEf57', + // ); + expect(balance.events[0].amount).to.be.equal('10'); + expect(balance.events[0].timestamp).to.be.a('number'); + }); +}); diff --git a/packages/request-client.js/test/api/payment-network/payment-reference-calculator.test.ts b/packages/request-client.js/test/api/payment-network/payment-reference-calculator.test.ts new file mode 100644 index 0000000000..54ea1eb6dc --- /dev/null +++ b/packages/request-client.js/test/api/payment-network/payment-reference-calculator.test.ts @@ -0,0 +1,31 @@ +import PaymentReferenceCalculator from '../../../src/api/payment-network/payment-reference-calculator'; + +import 'chai'; +import { expect } from 'chai'; +import 'mocha'; + +/* tslint:disable:no-unused-expression */ +describe('api/eth/payment-reference-calculator', () => { + it('can calculate the payment reference', async () => { + const expected = 'a0098add01acc736'; + const actual = PaymentReferenceCalculator.calculate('01847474747474', '8d03ea7', '0x000001'); + + expect(actual).to.equal(expected); + }); + + it('should throw if a parameter is missing', async () => { + const expectedErrorMessage = + 'RequestId, salt and address are mandatory to calculate the payment reference'; + expect(() => PaymentReferenceCalculator.calculate('', '8d03ea7', '0x000001')).to.throw( + expectedErrorMessage, + ); + + expect(() => PaymentReferenceCalculator.calculate('01847474747474', '', '0x000001')).to.throw( + expectedErrorMessage, + ); + + expect(() => PaymentReferenceCalculator.calculate('01847474747474', '8d03ea7', '')).to.throw( + expectedErrorMessage, + ); + }); +}); diff --git a/packages/request-client.js/test/api/request-network.test.ts b/packages/request-client.js/test/api/request-network.test.ts index 60577a8d54..e0960f079c 100644 --- a/packages/request-client.js/test/api/request-network.test.ts +++ b/packages/request-client.js/test/api/request-network.test.ts @@ -1,8 +1,16 @@ -import { DataAccessTypes } from '@requestnetwork/types'; - -import { assert, expect } from 'chai'; +import MultiFormat from '@requestnetwork/multi-format'; +import { DataAccessTypes, SignatureTypes, TransactionTypes } from '@requestnetwork/types'; +import Utils from '@requestnetwork/utils'; import 'mocha'; + +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +const assert = chai.assert; + import RequestNetwork from '../../src/api/request-network'; import Request from '../../src/api/request'; @@ -59,18 +67,12 @@ describe('api/request-network', () => { const requestnetwork = new RequestNetwork(mockDataAccessWithTxs); - try { - await requestnetwork.createRequest({ + await expect( + requestnetwork.createRequest({ requestInfo: { extensionsData: ['not expected'] } as any, signer: {} as any, - }); - // tslint:disable-next-line:no-unused-expression - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message, 'exception wrong').to.equal( - 'extensionsData in request parameters must be empty', - ); - } + }), + ).to.eventually.be.rejectedWith('extensionsData in request parameters must be empty'); }); }); @@ -103,6 +105,54 @@ describe('api/request-network', () => { expect(request).to.instanceOf(Request); }); + + it('cannot get request fromRequestId with if transactions are ignored', async () => { + const txIgnoredByTransactionManager: TransactionTypes.IConfirmedTransaction = { + timestamp: 1549953337, + transaction: { data: 'broken transaction' }, + }; + const actionWrongSigner = Utils.signature.sign(TestData.data, { + method: SignatureTypes.METHOD.ECDSA, + privateKey: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + }); + + const txIgnoredByRequestLogic: TransactionTypes.IConfirmedTransaction = { + timestamp: 1549953338, + transaction: { + data: JSON.stringify(actionWrongSigner), + }, + }; + const requestId = MultiFormat.serialize( + Utils.crypto.normalizeKeccak256Hash(actionWrongSigner), + ); + + const mockDataAccessWithTxs: DataAccessTypes.IDataAccess = { + async getChannelsByTopic(): Promise { + return; + }, + async getTransactionsByChannelId(): Promise { + return { + result: { + transactions: [txIgnoredByTransactionManager, txIgnoredByRequestLogic], + }, + }; + }, + async initialize(): Promise { + return; + }, + async persistTransaction(): Promise { + return; + }, + async getChannelsByMultipleTopics(): Promise { + return; + }, + }; + + const requestnetwork = new RequestNetwork(mockDataAccessWithTxs); + await expect(requestnetwork.fromRequestId(requestId)).to.eventually.rejectedWith( + `Invalid transaction(s) found: [{"reason":"Impossible to JSON parse the transaction","transaction":{"timestamp":1549953337,"transaction":{"data":"broken transaction"}}},{"reason":"Signer must be the payee or the payer","transaction":{"action":{"data":{"name":"create","parameters":{"currency":{"network":"testnet","type":"BTC","value":"BTC"},"expectedAmount":"100000000000","extensionsData":[{"action":"create","id":"pn-testnet-bitcoin-address-based","parameters":{"paymentAddress":"mgPKDuVmuS9oeE2D9VPiCQriyU14wxWS1v"},"version":"0.1.0"}],"payee":{"type":"ethereumAddress","value":"0x627306090abab3a6e1400e9345bc60c78a8bef57"},"payer":{"type":"ethereumAddress","value":"0xf17f52151ebef6c7334fad080c5704d77216b732"},"timestamp":1549953337},"version":"2.0.2"},"signature":{"method":"ecdsa","value":"0xf3b62e61d8e0cb32bb2a85e8a4b4f7c6345a30e7328900551be0a5f8c2570a870ce984364fc4beb357ef5a181dbefb8dfd1da03bd6542ed9d77e2762a0c636271b"}},"timestamp":1549953338}}]`, + ); + }); }); describe('fromIdentity', () => { diff --git a/packages/request-client.js/test/api/request.test.ts b/packages/request-client.js/test/api/request.test.ts index 0ab8f4080f..fe7661d825 100644 --- a/packages/request-client.js/test/api/request.test.ts +++ b/packages/request-client.js/test/api/request.test.ts @@ -1,16 +1,18 @@ import { IdentityTypes, RequestLogicTypes } from '@requestnetwork/types'; -import { assert } from 'chai'; import 'mocha'; import Request from '../../src/api/request'; import * as Types from '../../src/types'; -const chaiAsPromised = require('chai-as-promised'); -const chai = require('chai'); -const spies = require('chai-spies'); -const expect = chai.expect; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; +import * as spies from 'chai-spies'; + chai.use(spies); chai.use(chaiAsPromised); +const expect = chai.expect; +const assert = chai.assert; + const sandbox = chai.spy.sandbox(); const mockRequestLogic: RequestLogicTypes.IRequestLogic = { @@ -151,12 +153,9 @@ describe('api/request', () => { it('cannot call accept and add refund address without payment network', async () => { const request = new Request(mockRequestLogic, '1'); - try { - await request.accept(signatureIdentity, { refundAddress: bitcoinAddress }); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal('Cannot add refund information without payment network'); - } + await expect( + request.accept(signatureIdentity, { refundAddress: bitcoinAddress }), + ).to.eventually.be.rejectedWith('Cannot add refund information without payment network'); }); }); @@ -185,12 +184,10 @@ describe('api/request', () => { }); it('cannot call cancel and add refund address without payment network', async () => { const request = new Request(mockRequestLogic, '1'); - try { - await request.cancel(signatureIdentity, { refundAddress: bitcoinAddress }); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal('Cannot add refund information without payment network'); - } + + await expect( + request.cancel(signatureIdentity, { refundAddress: bitcoinAddress }), + ).to.eventually.be.rejectedWith('Cannot add refund information without payment network'); }); }); @@ -222,14 +219,11 @@ describe('api/request', () => { it('cannot call increase and add refund address without payment network', async () => { const request = new Request(mockRequestLogic, '1'); - try { - await request.increaseExpectedAmountRequest(3, signatureIdentity, { + await expect( + request.increaseExpectedAmountRequest(3, signatureIdentity, { refundAddress: bitcoinAddress, - }); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal('Cannot add refund information without payment network'); - } + }), + ).to.eventually.be.rejectedWith('Cannot add refund information without payment network'); }); }); @@ -261,14 +255,11 @@ describe('api/request', () => { it('cannot call reduce and add payment address without payment network', async () => { const request = new Request(mockRequestLogic, '1'); - try { - await request.reduceExpectedAmountRequest('1', signatureIdentity, { + await expect( + request.reduceExpectedAmountRequest('1', signatureIdentity, { paymentInformation: bitcoinAddress, - }); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal('Cannot add payment information without payment network'); - } + }), + ).to.eventually.be.rejectedWith('Cannot add payment information without payment network'); }); }); @@ -289,12 +280,9 @@ describe('api/request', () => { it('cannot add payment address without payment network', async () => { const request = new Request(mockRequestLogic, '1'); - try { - await request.addPaymentInformation({ paymentAddress: bitcoinAddress }, signatureIdentity); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal('Cannot add payment information without payment network'); - } + await expect( + request.addPaymentInformation({ paymentAddress: bitcoinAddress }, signatureIdentity), + ).to.eventually.be.rejectedWith('Cannot add payment information without payment network'); }); }); @@ -315,12 +303,9 @@ describe('api/request', () => { it('cannot add payment address without payment network', async () => { const request = new Request(mockRequestLogic, '1'); - try { - await request.addRefundInformation({ refundAddress: bitcoinAddress }, signatureIdentity); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal('Cannot add refund information without payment network'); - } + await expect( + request.addRefundInformation({ refundAddress: bitcoinAddress }, signatureIdentity), + ).to.eventually.be.rejectedWith('Cannot add refund information without payment network'); }); }); @@ -341,24 +326,18 @@ describe('api/request', () => { it('cannot declare sent payment if no payment network', async () => { const request = new Request(mockRequestLogic, '1'); - try { - await request.declareSentPayment('1000', 'sent', signatureIdentity); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal('Cannot declare sent payment without payment network'); - } + await expect( + request.declareSentPayment('1000', 'sent', signatureIdentity), + ).to.eventually.be.rejectedWith('Cannot declare sent payment without payment network'); }); it('cannot declare sent payment if payment network is not declarative', async () => { const request = new Request(mockRequestLogic, '1', mockPaymentNetwork); - try { - await request.declareSentPayment('1000', 'sent', signatureIdentity); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal( - 'Cannot declare sent payment without declarative payment network', - ); - } + await expect( + request.declareSentPayment('1000', 'sent', signatureIdentity), + ).to.eventually.be.rejectedWith( + 'Cannot declare sent payment without declarative payment network', + ); }); }); @@ -379,24 +358,18 @@ describe('api/request', () => { it('cannot declare sent refund if no payment network', async () => { const request = new Request(mockRequestLogic, '1'); - try { - await request.declareSentRefund('1000', 'sent', signatureIdentity); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal('Cannot declare sent refund without payment network'); - } + await expect( + request.declareSentRefund('1000', 'sent', signatureIdentity), + ).to.eventually.be.rejectedWith('Cannot declare sent refund without payment network'); }); it('cannot declare sent refund if payment network is not declarative', async () => { const request = new Request(mockRequestLogic, '1', mockPaymentNetwork); - try { - await request.declareSentRefund('1000', 'sent', signatureIdentity); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal( - 'Cannot declare sent refund without declarative payment network', - ); - } + await expect( + request.declareSentRefund('1000', 'sent', signatureIdentity), + ).to.eventually.be.rejectedWith( + 'Cannot declare sent refund without declarative payment network', + ); }); }); @@ -417,24 +390,18 @@ describe('api/request', () => { it('cannot declare received payment if no payment network', async () => { const request = new Request(mockRequestLogic, '1'); - try { - await request.declareReceivedPayment('1000', 'received', signatureIdentity); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal('Cannot declare received payment without payment network'); - } + await expect( + request.declareReceivedPayment('1000', 'received', signatureIdentity), + ).to.eventually.be.rejectedWith('Cannot declare received payment without payment network'); }); it('cannot declare received payment if payment network is not declarative', async () => { const request = new Request(mockRequestLogic, '1', mockPaymentNetwork); - try { - await request.declareReceivedPayment('1000', 'received', signatureIdentity); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal( - 'Cannot declare received payment without declarative payment network', - ); - } + await expect( + request.declareReceivedPayment('1000', 'received', signatureIdentity), + ).to.eventually.be.rejectedWith( + 'Cannot declare received payment without declarative payment network', + ); }); }); @@ -455,24 +422,18 @@ describe('api/request', () => { it('cannot declare received refund if no payment network', async () => { const request = new Request(mockRequestLogic, '1'); - try { - await request.declareReceivedRefund('1000', 'received', signatureIdentity); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal('Cannot declare received refund without payment network'); - } + await expect( + request.declareReceivedRefund('1000', 'received', signatureIdentity), + ).to.eventually.be.rejectedWith('Cannot declare received refund without payment network'); }); it('cannot declare received refund if payment network is not declarative', async () => { const request = new Request(mockRequestLogic, '1', mockPaymentNetwork); - try { - await request.declareReceivedRefund('1000', 'received', signatureIdentity); - expect(false, 'should throw').to.be.true; - } catch (e) { - expect(e.message).to.equal( - 'Cannot declare received refund without declarative payment network', - ); - } + await expect( + request.declareReceivedRefund('1000', 'received', signatureIdentity), + ).to.eventually.be.rejectedWith( + 'Cannot declare received refund without declarative payment network', + ); }); }); diff --git a/packages/request-client.js/test/data-test.ts b/packages/request-client.js/test/data-test.ts index 6261745d4c..8f9eb832e8 100644 --- a/packages/request-client.js/test/data-test.ts +++ b/packages/request-client.js/test/data-test.ts @@ -43,7 +43,7 @@ export const parameters: RequestLogicTypes.ICreateParameters = { { action: 'create', id: 'pn-testnet-bitcoin-address-based', - parameters: {}, + parameters: { paymentAddress: 'mgPKDuVmuS9oeE2D9VPiCQriyU14wxWS1v' }, version: '0.1.0', }, ], @@ -150,7 +150,7 @@ const dataSecondRequest = { name: RequestLogicTypes.ACTION_NAME.CREATE, parameters: { currency: { - network: 'testnet', + network: 'rinkeby', type: RequestLogicTypes.CURRENCY.ETH, value: 'ETH', }, diff --git a/packages/request-client.js/test/index-encryption.html b/packages/request-client.js/test/index-encryption.html index f6ce2e4413..b381b51198 100644 --- a/packages/request-client.js/test/index-encryption.html +++ b/packages/request-client.js/test/index-encryption.html @@ -2,7 +2,7 @@ @requestnetwork/request-client.js Test Page - + @@ -88,6 +88,7 @@

Compatibility

currency: { type: RequestNetwork.Types.RequestLogic.CURRENCY.BTC, value: 'BTC', + network: 'testnet', }, expectedAmount: '100000000000', payee: { diff --git a/packages/request-client.js/test/index-metamask.html b/packages/request-client.js/test/index-metamask.html index d00f19b25c..722249a3ca 100644 --- a/packages/request-client.js/test/index-metamask.html +++ b/packages/request-client.js/test/index-metamask.html @@ -2,7 +2,7 @@ @requestnetwork/request-client.js Test Page - + @@ -49,6 +49,7 @@

Important

currency: { type: RequestNetwork.Types.RequestLogic.CURRENCY.BTC, value: 'BTC', + network: 'testnet', }, expectedAmount: '100000000000', payee: { diff --git a/packages/request-client.js/test/index.html b/packages/request-client.js/test/index.html index 197430e62c..65ff3d5d2a 100644 --- a/packages/request-client.js/test/index.html +++ b/packages/request-client.js/test/index.html @@ -2,7 +2,7 @@ @requestnetwork/request-client.js Test Page - + @@ -18,6 +18,7 @@ currency: { type: RequestNetwork.Types.RequestLogic.CURRENCY.BTC, value: 'BTC', + network: 'testnet', }, expectedAmount: '100000000000', payee: { diff --git a/packages/request-client.js/test/index.test.ts b/packages/request-client.js/test/index.test.ts index e8d03c160b..075fa5f0b1 100644 --- a/packages/request-client.js/test/index.test.ts +++ b/packages/request-client.js/test/index.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable spellcheck/spell-checker */ const axios = require('axios'); import { @@ -9,6 +10,7 @@ import { SignatureTypes, } from '@requestnetwork/types'; import Utils from '@requestnetwork/utils'; +import { ethers } from 'ethers'; import 'mocha'; import * as sinon from 'sinon'; const mockAdapter = require('axios-mock-adapter'); @@ -17,6 +19,8 @@ import * as Types from '../src/types'; import * as TestData from './data-test'; import * as TestDataRealBTC from './data-test-real-btc'; +import PaymentReferenceCalculator from '../src/api/payment-network/payment-reference-calculator'; + const chai = require('chai'); const spies = require('chai-spies'); const chaiAsPromised = require('chai-as-promised'); @@ -112,6 +116,24 @@ function mockAxios(): any { return mock; } +const mockBTCProvider = { + getAddressBalanceWithEvents: (): Promise> => { + return Promise.resolve({ + balance: '666743', + events: [ + { + amount: '666743', + name: Types.EVENTS_NAMES.PAYMENT, + parameters: { + block: 561874, + txHash: "4024936746a0994cf5cdf9c8b55e03b288a251ad172682e8e94b7806a4e3dace" + } + } + ] + }); + } +} + // Integration tests /* tslint:disable:no-unused-expression */ describe('index', () => { @@ -119,7 +141,7 @@ describe('index', () => { sandbox.restore(); }); - it.skip('uses http://localhost:3000 with signatureProvider and paymentNetwork', async () => { + it('uses http://localhost:3000 with signatureProvider and paymentNetwork', async () => { const mock = new mockAdapter(axios); const callback = (config: any): any => { @@ -134,6 +156,8 @@ describe('index', () => { const requestNetwork = new RequestNetwork({ signatureProvider: fakeSignatureProvider }); + requestNetwork.bitcoinDetectionProvider = mockBTCProvider; + const paymentNetwork: Types.IPaymentNetworkCreateParameters = { id: Types.PAYMENT_NETWORK_ID.TESTNET_BITCOIN_ADDRESS_BASED, parameters: { @@ -149,7 +173,7 @@ describe('index', () => { expect(spy).to.have.been.called.once; }); - it.skip('uses http://localhost:3000 with signatureProvider and paymentNetwork real btc', async () => { + it('uses http://localhost:3000 with signatureProvider and paymentNetwork real btc', async () => { const mock = new mockAdapter(axios); const callback = (config: any): any => { @@ -164,6 +188,8 @@ describe('index', () => { const requestNetwork = new RequestNetwork({ signatureProvider: fakeSignatureProvider }); + requestNetwork.bitcoinDetectionProvider = mockBTCProvider; + const paymentNetwork: Types.IPaymentNetworkCreateParameters = { id: Types.PAYMENT_NETWORK_ID.BITCOIN_ADDRESS_BASED, parameters: { @@ -352,12 +378,14 @@ describe('index', () => { expect(data.expectedAmount).to.equal(requestParameters.expectedAmount); }); - it('works with mocked storage and payment network', async () => { + it('works with mocked storage and mocked payment network', async () => { const requestNetwork = new RequestNetwork({ signatureProvider: fakeSignatureProvider, useMockStorage: true, }); + requestNetwork.bitcoinDetectionProvider = mockBTCProvider; + const paymentNetwork: Types.IPaymentNetworkCreateParameters = { id: Types.PAYMENT_NETWORK_ID.TESTNET_BITCOIN_ADDRESS_BASED, parameters: { @@ -615,41 +643,49 @@ describe('index', () => { expect(requestData.balance.balance).to.equal('990'); // @ts-ignore expect(requestData.balance.events[0]).to.deep.equal({ + amount: '10', name: 'refund', - parameters: { amount: '10', note: 'received refund', timestamp: 1 }, + parameters: { note: 'received refund' }, + timestamp: 1, }); // @ts-ignore expect(requestData.balance.events[1]).to.deep.equal({ + amount: '1000', name: 'payment', - parameters: { amount: '1000', note: 'received payment', timestamp: 1 }, + parameters: { note: 'received payment' }, + timestamp: 1, }); + sinon.restore(); }); it('cannot use declarative function if payment network is not declarative', async () => { - const mock = new mockAdapter(axios); - - const callback = (config: any): any => { - expect(config.baseURL).to.equal('http://localhost:3000'); - return [200, {}]; - }; - const spy = chai.spy(callback); - mock.onPost('/persistTransaction').reply(spy); - mock.onGet('/getTransactionsByChannelId').reply(200, { - result: { transactions: [TestDataRealBTC.transactionConfirmed] }, + const requestNetwork = new RequestNetwork({ + signatureProvider: fakeSignatureProvider, + useMockStorage: true, }); - const requestNetwork = new RequestNetwork({ signatureProvider: fakeSignatureProvider }); + const salt = 'ea3bc7caf64110ca'; const paymentNetwork: Types.IPaymentNetworkCreateParameters = { - id: Types.PAYMENT_NETWORK_ID.BITCOIN_ADDRESS_BASED, + id: Types.PAYMENT_NETWORK_ID.ETH_INPUT_DATA, parameters: { - paymentAddress: '1FersucwSqufU26w9GrGz9M3KcwuNmy6a9', + paymentAddress: '0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB', + refundAddress: '0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB', + salt, }, }; + const requestInfo = Object.assign({}, TestData.parametersWithoutExtensionsData, { + currency: { + network: 'rinkeby', + type: RequestLogicTypes.CURRENCY.ETH, + value: 'ETH', + }, + }); + const request = await requestNetwork.createRequest({ paymentNetwork, - requestInfo: requestParameters, + requestInfo, signer: payeeIdentity, }); @@ -967,4 +1003,337 @@ describe('index', () => { ); }); }); + + describe('ETH requests', () => { + it('can create ETH requests with given salt', async () => { + const requestNetwork = new RequestNetwork({ + signatureProvider: fakeSignatureProvider, + useMockStorage: true, + }); + + const salt = 'ea3bc7caf64110ca'; + + const paymentNetwork: Types.IPaymentNetworkCreateParameters = { + id: Types.PAYMENT_NETWORK_ID.ETH_INPUT_DATA, + parameters: { + paymentAddress: '0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB', + refundAddress: '0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB', + salt, + }, + }; + + const requestInfo = Object.assign({}, TestData.parametersWithoutExtensionsData, { + currency: { + network: 'rinkeby', + type: RequestLogicTypes.CURRENCY.ETH, + value: 'ETH', + }, + }); + + const request = await requestNetwork.createRequest({ + paymentNetwork, + requestInfo, + signer: payeeIdentity, + }); + + const data = request.getData(); + + expect(data).to.exist; + expect(data.balance).to.exist; + expect(data.meta).to.exist; + expect(data.currency).to.equal('ETH-rinkeby'); + expect(data.extensionsData[0].parameters.salt).to.equal(salt); + expect(data.expectedAmount).to.equal(requestParameters.expectedAmount); + }); + + it('can create ETH requests without given salt', async () => { + const requestNetwork = new RequestNetwork({ + signatureProvider: fakeSignatureProvider, + useMockStorage: true, + }); + + const paymentNetwork: Types.IPaymentNetworkCreateParameters = { + id: Types.PAYMENT_NETWORK_ID.ETH_INPUT_DATA, + parameters: { + paymentAddress: '0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB', + refundAddress: '0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB', + }, + }; + + const requestInfo = Object.assign({}, TestData.parametersWithoutExtensionsData, { + currency: { + network: 'rinkeby', + type: RequestLogicTypes.CURRENCY.ETH, + value: 'ETH', + }, + }); + + const request = await requestNetwork.createRequest({ + paymentNetwork, + requestInfo, + signer: payeeIdentity, + }); + + const data = request.getData(); + + expect(data.extensionsData[0].parameters.salt.length).to.equal(16); + }); + + it('can create ETH requests without refund address', async () => { + const requestNetwork = new RequestNetwork({ + signatureProvider: fakeSignatureProvider, + useMockStorage: true, + }); + + const paymentNetwork: Types.IPaymentNetworkCreateParameters = { + id: Types.PAYMENT_NETWORK_ID.ETH_INPUT_DATA, + parameters: { + paymentAddress: '0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB', + }, + }; + + const requestInfo = Object.assign({}, TestData.parametersWithoutExtensionsData, { + currency: { + network: 'rinkeby', + type: RequestLogicTypes.CURRENCY.ETH, + value: 'ETH', + }, + }); + + const request = await requestNetwork.createRequest({ + paymentNetwork, + requestInfo, + signer: payeeIdentity, + }); + + const data = request.getData(); + + expect(data.extensionsData[0].parameters.salt.length).to.equal(16); + }); + + // This test checks that 2 payments with reference `fb8cc0abeed87cb8` have reached 0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB + it('can get the balance of an ETH request', async function(): Promise { + // tslint:disable-next-line: no-invalid-this + this.timeout(10000); + const requestNetwork = new RequestNetwork({ + signatureProvider: fakeSignatureProvider, + useMockStorage: true, + }); + + const paymentNetwork: Types.IPaymentNetworkCreateParameters = { + id: Types.PAYMENT_NETWORK_ID.ETH_INPUT_DATA, + parameters: { + paymentAddress: '0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB', + refundAddress: '0x0000000000000000000000000000000000000002', + salt: 'a1a2a3a4a5a6a7a8', + }, + }; + + const requestInfo = Object.assign({}, TestData.parametersWithoutExtensionsData, { + currency: { + network: 'mainnet', + type: RequestLogicTypes.CURRENCY.ETH, + value: 'ETH', + }, + }); + + const request = await requestNetwork.createRequest({ + paymentNetwork, + requestInfo, + signer: payeeIdentity, + }); + + const data = request.getData(); + + // Payment reference should be fixed + expect( + PaymentReferenceCalculator.calculate( + data.requestId, + data.extensionsData[0].parameters.salt, + data.extensionsData[0].parameters.paymentAddress, + ), + ).to.equal('a93299ed2555d098'); + + await request.refresh(); + + const dataAfterRefresh = request.getData(); + + expect(dataAfterRefresh.balance?.balance).to.equal('138'); + expect(dataAfterRefresh.balance?.events.length).to.equal(2); + + expect(dataAfterRefresh.balance?.events[0].name).to.equal('payment'); + expect(dataAfterRefresh.balance?.events[0].amount).to.equal('133'); + expect(dataAfterRefresh.balance?.events[0].parameters!.txHash).to.equal('0x62264de4fbbe866df28e4fad7b4d44058f1b6ec74bf7c767a14eb67198c93a4d'); + + expect(dataAfterRefresh.balance?.events[1].name).to.equal('payment'); + expect(dataAfterRefresh.balance?.events[1].amount).to.equal('5'); + expect(dataAfterRefresh.balance?.events[1].parameters!.txHash).to.equal('0x74d5dafdfaa023583d8bb6993a873babd403a05b2286e556e2617801b130cb8e'); + }); + }); + + describe('ERC20 address based requests', () => { + it('can create ERC20 address based requests', async () => { + const testErc20TokenAddress = '0x9FBDa871d559710256a2502A2517b794B482Db40'; + + const requestNetwork = new RequestNetwork({ + signatureProvider: fakeSignatureProvider, + useMockStorage: true, + }); + // generate address randomly to avoid collisions + const paymentAddress = '0x' + (await Utils.crypto.CryptoWrapper.random32Bytes()).slice(12).toString('hex'); + const refundAddress = '0x' + (await Utils.crypto.CryptoWrapper.random32Bytes()).slice(12).toString('hex'); + + const paymentNetwork: Types.IPaymentNetworkCreateParameters = { + id: Types.PAYMENT_NETWORK_ID.ERC20_ADDRESS_BASED, + parameters: { + paymentAddress, + refundAddress, + }, + }; + + const requestInfo = Object.assign({}, TestData.parametersWithoutExtensionsData, { + currency: { + network: 'private', + type: RequestLogicTypes.CURRENCY.ERC20, + value: testErc20TokenAddress, + }, + }); + + const request = await requestNetwork.createRequest({ + paymentNetwork, + requestInfo, + signer: payeeIdentity, + }); + + let data = request.getData(); + + expect(data).to.exist; + expect(data.balance?.balance).to.equal('0'); + expect(data.balance?.events.length).to.equal(0); + expect(data.meta).to.exist; + expect(data.currency).to.equal('unknown'); + expect(data.extensions[Types.PAYMENT_NETWORK_ID.ERC20_ADDRESS_BASED].values.paymentAddress).to.equal(paymentAddress); + expect(data.extensions[Types.PAYMENT_NETWORK_ID.ERC20_ADDRESS_BASED].values.refundAddress).to.equal(refundAddress); + expect(data.expectedAmount).to.equal(requestParameters.expectedAmount); + + const provider = new ethers.providers.JsonRpcProvider('http://localhost:8545'); + const erc20abiFragment = ['function transfer(address _to, uint _value) returns (bool transfer)']; + + // Setup the ERC20 contract interface + const contract = new ethers.Contract( + testErc20TokenAddress, + erc20abiFragment, + provider.getSigner(0), + ); + + // check payment + await contract.transfer(paymentAddress, 2); + data = await request.refresh(); + expect(data.balance?.balance).to.equal('2'); + expect(data.balance?.events.length).to.equal(1); + expect(data.balance?.events[0].amount).to.equal('2'); + expect(data.balance?.events[0].name).to.equal('payment'); + expect(data.balance?.events[0].timestamp).to.exist; + expect(data.balance?.events[0].parameters.block).to.exist; + expect(data.balance?.events[0].parameters.from.length).to.equal(42); + expect(data.balance?.events[0].parameters.to.toLowerCase()).to.equal(paymentAddress); + expect(data.balance?.events[0].parameters.txHash.length).to.equal(66); + + // check refund + await contract.transfer(refundAddress, 1); + data = await request.refresh(); + expect(data.balance?.balance).to.equal('1'); + expect(data.balance?.events.length).to.equal(2); + expect(data.balance?.events[0].amount).to.equal('2'); + expect(data.balance?.events[0].name).to.equal('payment'); + expect(data.balance?.events[0].timestamp).to.exist; + expect(data.balance?.events[0].parameters.block).to.exist; + expect(data.balance?.events[0].parameters.from.length).to.equal(42); + expect(data.balance?.events[0].parameters.to.toLowerCase()).to.equal(paymentAddress); + expect(data.balance?.events[0].parameters.txHash.length).to.equal(66); + expect(data.balance?.events[1].amount).to.equal('1'); + expect(data.balance?.events[1].name).to.equal('refund'); + expect(data.balance?.events[1].timestamp).to.exist; + expect(data.balance?.events[1].parameters.block).to.exist; + expect(data.balance?.events[1].parameters.from.length).to.equal(42); + expect(data.balance?.events[1].parameters.to.toLowerCase()).to.equal(refundAddress); + expect(data.balance?.events[1].parameters.txHash.length).to.equal(66); + }); + }); + + describe('ERC20 proxy contract requests', () => { + it('can create ERC20 requests with given salt', async () => { + const requestNetwork = new RequestNetwork({ + signatureProvider: fakeSignatureProvider, + useMockStorage: true, + }); + const salt = 'ea3bc7caf64110ca'; + + const paymentNetwork: Types.IPaymentNetworkCreateParameters = { + id: Types.PAYMENT_NETWORK_ID.ERC20_PROXY_CONTRACT, + parameters: { + paymentAddress: '0x6330A553Fc93768F612722BB8c2eC78aC90B3bbc', + refundAddress: '0x5AEDA56215b167893e80B4fE645BA6d5Bab767DE', + salt, + }, + }; + + const requestInfo = Object.assign({}, TestData.parametersWithoutExtensionsData, { + currency: { + network: 'private', + type: RequestLogicTypes.CURRENCY.ERC20, + value: '0x9FBDa871d559710256a2502A2517b794B482Db40', // Test Erc20 + }, + }); + + const request = await requestNetwork.createRequest({ + paymentNetwork, + requestInfo, + signer: payeeIdentity, + }); + + const data = request.getData(); + + expect(data).to.exist; + expect(data.balance?.balance).to.equal('90'); + expect(data.balance?.events.length).to.equal(2); + expect(data.meta).to.exist; + expect(data.currency).to.equal('unknown'); + expect(data.extensionsData[0].parameters.salt).to.equal(salt); + expect(data.expectedAmount).to.equal(requestParameters.expectedAmount); + }); + + it('can create ERC20 requests without given salt', async () => { + const requestNetwork = new RequestNetwork({ + signatureProvider: fakeSignatureProvider, + useMockStorage: true, + }); + + const paymentNetwork: Types.IPaymentNetworkCreateParameters = { + id: Types.PAYMENT_NETWORK_ID.ERC20_PROXY_CONTRACT, + parameters: { + paymentAddress: '0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB', + refundAddress: '0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB', + }, + }; + + const requestInfo = Object.assign({}, TestData.parametersWithoutExtensionsData, { + currency: { + network: 'private', + type: RequestLogicTypes.CURRENCY.ERC20, + value: '0x9FBDa871d559710256a2502A2517b794B482Db40', + }, + }); + + const request = await requestNetwork.createRequest({ + paymentNetwork, + requestInfo, + signer: payeeIdentity, + }); + + const data = request.getData(); + + expect(data.extensionsData[0].parameters.salt.length).to.equal(16); + }); + }); }); diff --git a/packages/request-client.js/test/mock-storage.test.ts b/packages/request-client.js/test/mock-storage.test.ts index fee0e4b706..50992902b0 100644 --- a/packages/request-client.js/test/mock-storage.test.ts +++ b/packages/request-client.js/test/mock-storage.test.ts @@ -1,5 +1,12 @@ import { StorageTypes } from '@requestnetwork/types'; -import { assert } from 'chai'; + +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +const assert = chai.assert; + import 'mocha'; import MockStorage from '../src/mock-storage'; @@ -14,12 +21,9 @@ describe('mock-storage', () => { it('cannot append no data ', async () => { const storage = new MockStorage(); - try { - await storage.append(null as any); - assert.fail(); - } catch (e) { - assert.equal(e.message, 'Error: no content provided'); - } + await expect(storage.append(null as any)).to.eventually.be.rejectedWith( + 'Error: no content provided', + ); }); it('can read data', async () => { @@ -34,12 +38,7 @@ describe('mock-storage', () => { it('cannot read no data ', async () => { const storage = new MockStorage(); - try { - await storage.read(null as any); - assert.fail(); - } catch (e) { - assert.equal(e.message, 'No id provided'); - } + await expect(storage.read(null as any)).to.eventually.be.rejectedWith('No id provided'); }); it('can get all data', async () => { diff --git a/packages/request-logic/.vscode/settings.json b/packages/request-logic/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/request-logic/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/request-logic/CHANGELOG.md b/packages/request-logic/CHANGELOG.md index 528af5304a..6377f37c9c 100644 --- a/packages/request-logic/CHANGELOG.md +++ b/packages/request-logic/CHANGELOG.md @@ -3,6 +3,59 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.8.3](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/request-logic@0.8.0...@requestnetwork/request-logic@0.8.3) (2020-01-16) + + +### Bug Fixes + +* backward compatibility issue + removing test failing for external reason ([#93](https://github.com/RequestNetwork/requestNetwork/issues/93)) ([9a405dc](https://github.com/RequestNetwork/requestNetwork/commit/9a405dcc66b36a9a4a4b885dea2cd50abaad2725)) +* fix old version id mismatch issue ([#98](https://github.com/RequestNetwork/requestNetwork/issues/98)) ([c4d3f29](https://github.com/RequestNetwork/requestNetwork/commit/c4d3f291b7667f426a4a95cac7d65db90d13921b)) + + + +# 0.10.0 (2019-12-04) + + +### Bug Fixes + +* rollback legacy request currency renaming from DAI to SAI ([#622](https://github.com/RequestNetwork/requestNetwork/issues/622)) ([2882811](https://github.com/RequestNetwork/requestNetwork/commit/28828117f6490ada05180f2607098d3ebada681a)) + + + + + +## [0.8.2](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/request-logic@0.8.0...@requestnetwork/request-logic@0.8.2) (2019-12-18) + + +### Bug Fixes + +* backward compatibility issue + removing test failing for external reason ([#93](https://github.com/RequestNetwork/requestNetwork/issues/93)) ([9a405dc](https://github.com/RequestNetwork/requestNetwork/commit/9a405dcc66b36a9a4a4b885dea2cd50abaad2725)) +* fix old version id mismatch issue ([#98](https://github.com/RequestNetwork/requestNetwork/issues/98)) ([c4d3f29](https://github.com/RequestNetwork/requestNetwork/commit/c4d3f291b7667f426a4a95cac7d65db90d13921b)) + + + +# 0.10.0 (2019-12-04) + + +### Bug Fixes + +* rollback legacy request currency renaming from DAI to SAI ([#622](https://github.com/RequestNetwork/requestNetwork/issues/622)) ([2882811](https://github.com/RequestNetwork/requestNetwork/commit/28828117f6490ada05180f2607098d3ebada681a)) + + + + + +## [0.8.1](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/request-logic@0.8.0...@requestnetwork/request-logic@0.8.1) (2019-12-04) + + +### Bug Fixes + +* rollback legacy request currency renaming from DAI to SAI ([#622](https://github.com/RequestNetwork/requestNetwork/issues/622)) ([2882811](https://github.com/RequestNetwork/requestNetwork/commit/28828117f6490ada05180f2607098d3ebada681a)) + + + + + # [0.8.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/request-logic@0.7.1...@requestnetwork/request-logic@0.8.0) (2019-11-20) diff --git a/packages/request-logic/package.json b/packages/request-logic/package.json index fb9860ca72..b7d3ff2aed 100644 --- a/packages/request-logic/package.json +++ b/packages/request-logic/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/request-logic", - "version": "0.8.0", + "version": "0.8.3", "publishConfig": { "access": "public" }, @@ -32,30 +32,30 @@ ], "scripts": { "build": "tsc -b", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "example": "ts-node specs/example/example.ts", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", "stryker": "stryker run", - "test": "nyc mocha --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", - "test:watch": "nyc mocha --watch --watch-extensions ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"" + "test": "nyc mocha --extension ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", + "test:watch": "yarn test --watch" }, "dependencies": { - "@requestnetwork/advanced-logic": "0.6.0", - "@requestnetwork/multi-format": "0.2.1", - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0", + "@requestnetwork/advanced-logic": "0.9.0", + "@requestnetwork/multi-format": "0.2.4", + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0", "semver": "5.6.0" }, "devDependencies": { - "@stryker-mutator/core": "2.1.0", + "@stryker-mutator/core": "2.4.0", "@stryker-mutator/html-reporter": "2.1.0", "@stryker-mutator/mocha-framework": "2.1.0", "@stryker-mutator/mocha-runner": "2.1.0", - "@stryker-mutator/typescript": "2.1.0", + "@stryker-mutator/typescript": "2.3.0", "@types/chai": "4.1.7", "@types/chai-spies": "1.0.0", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", "@types/semver": "5.5.0", "@typescript-eslint/parser": "1.2.0", "chai": "4.2.0", @@ -65,12 +65,12 @@ "eslint-plugin-spellcheck": "0.0.11", "eslint-plugin-typescript": "0.14.0", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "nyc": "13.2.0", "prettier": "1.16.4", "shx": "0.3.2", "source-map-support": "0.5.13", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "tslint": "5.12.1", "typescript": "3.7.2" }, diff --git a/packages/request-logic/src/actions/create.ts b/packages/request-logic/src/actions/create.ts index 13e6c53be4..aa48a077d4 100644 --- a/packages/request-logic/src/actions/create.ts +++ b/packages/request-logic/src/actions/create.ts @@ -100,11 +100,6 @@ function createRequest( ); } - // If we're creating an older version of a request, we convert the string currency type to the new ICurrency one - if (Semver.lt(action.data.version, '2.0.2')) { - action.data.parameters.currency = legacyEnumToICurrencyConvert(action.data.parameters.currency); - } - const signer: IdentityTypes.IIdentity = Action.getSignerIdentityFromAction(action); // Copy to not modify the action itself @@ -114,6 +109,11 @@ function createRequest( request.version = Action.getVersionFromAction(action); request.events = [generateEvent(action, timestamp, signer)]; + // If we're creating an older version of a request, we convert the string currency type to the new ICurrency one + if (Semver.lt(action.data.version, '2.0.2')) { + request.currency = legacyEnumToICurrencyConvert(action.data.parameters.currency); + } + const signerRole = Action.getRoleInAction(signer, action); if (signerRole === RequestLogicTypes.ROLE.PAYEE) { request.state = RequestLogicTypes.STATE.CREATED; @@ -187,7 +187,7 @@ function legacyEnumToICurrencyConvert(currency: string): RequestLogicTypes.ICurr type: RequestLogicTypes.CURRENCY.ISO4217, value: 'USD', }; - case 'SAI': + case 'DAI': // DON'T RENAME: DAI was the name used by the legacy requests for SAI return { type: RequestLogicTypes.CURRENCY.ERC20, value: '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359', // SAI diff --git a/packages/request-logic/test/index.test.ts b/packages/request-logic/test/index.test.ts index cd6e7baa20..9015193f92 100644 --- a/packages/request-logic/test/index.test.ts +++ b/packages/request-logic/test/index.test.ts @@ -3,7 +3,6 @@ import 'mocha'; import MultiFormat from '@requestnetwork/multi-format'; import { AdvancedLogicTypes, RequestLogicTypes, TransactionTypes } from '@requestnetwork/types'; import Utils from '@requestnetwork/utils'; -import * as chaiAsPromised from 'chai-as-promised'; import { RequestLogic } from '../src/index'; import * as TestData from './unit/utils/test-data-generator'; @@ -12,12 +11,13 @@ import Version from '../src/version'; const CURRENT_VERSION = Version.currentVersion; -const chai = require('chai'); -const spies = require('chai-spies'); -const expect = chai.expect; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; +import * as spies from 'chai-spies'; -chai.use(spies); chai.use(chaiAsPromised); +chai.use(spies); +const expect = chai.expect; const createParams: RequestLogicTypes.ICreateParameters = { currency: { @@ -49,10 +49,10 @@ let fakeTransactionManager: TransactionTypes.ITransactionManager; describe('index', () => { beforeEach(() => { fakeTransactionManager = { - getChannelsByMultipleTopics: chai.spy(), - getChannelsByTopic: chai.spy(), - getTransactionsByChannelId: chai.spy(), - persistTransaction: chai.spy.returns(fakeMetaTransactionManager), + getChannelsByMultipleTopics: chai.spy() as any, + getChannelsByTopic: chai.spy() as any, + getTransactionsByChannelId: chai.spy() as any, + persistTransaction: chai.spy.returns(fakeMetaTransactionManager) as any, }; }); @@ -60,14 +60,9 @@ describe('index', () => { it('cannot createRequest without signature provider', async () => { const requestLogic = new RequestLogic(fakeTransactionManager); - try { - await requestLogic.createRequest(createParams, TestData.payeeRaw.identity); - expect(false, 'must have thrown').to.be.true; - } catch (e) { - expect(e.message, 'wrong exception').to.equal( - 'You must give a signature provider to create actions', - ); - } + await expect( + requestLogic.createRequest(createParams, TestData.payeeRaw.identity), + ).to.eventually.be.rejectedWith('You must give a signature provider to create actions'); }); it('cannot createRequest if apply fails in the advanced request logic', async () => { @@ -348,8 +343,8 @@ describe('index', () => { TestData.payeeRaw.signatureParams, ); const transactionManager: TransactionTypes.ITransactionManager = { - getChannelsByMultipleTopics: chai.spy(), - getChannelsByTopic: chai.spy(), + getChannelsByMultipleTopics: chai.spy() as any, + getChannelsByTopic: chai.spy() as any, getTransactionsByChannelId: chai.spy.returns( Promise.resolve({ meta: { ignoredTransactions: [] }, @@ -363,7 +358,7 @@ describe('index', () => { }, }), ), - persistTransaction: chai.spy(), + persistTransaction: chai.spy() as any, }; const acceptParams = { requestId, @@ -430,8 +425,8 @@ describe('index', () => { TestData.payeeRaw.signatureParams, ); const transactionManager: TransactionTypes.ITransactionManager = { - getChannelsByMultipleTopics: chai.spy(), - getChannelsByTopic: chai.spy(), + getChannelsByMultipleTopics: chai.spy() as any, + getChannelsByTopic: chai.spy() as any, getTransactionsByChannelId: chai.spy.returns( Promise.resolve({ meta: { ignoredTransactions: [] }, @@ -445,7 +440,7 @@ describe('index', () => { }, }), ), - persistTransaction: chai.spy(), + persistTransaction: chai.spy() as any, }; const cancelParams = { requestId, @@ -517,8 +512,8 @@ describe('index', () => { TestData.payeeRaw.signatureParams, ); const transactionManager: TransactionTypes.ITransactionManager = { - getChannelsByMultipleTopics: chai.spy(), - getChannelsByTopic: chai.spy(), + getChannelsByMultipleTopics: chai.spy() as any, + getChannelsByTopic: chai.spy() as any, getTransactionsByChannelId: chai.spy.returns( Promise.resolve({ meta: { ignoredTransactions: [] }, @@ -532,7 +527,7 @@ describe('index', () => { }, }), ), - persistTransaction: chai.spy(), + persistTransaction: chai.spy() as any, }; const increaseRequest = { deltaAmount: '1000', @@ -609,8 +604,8 @@ describe('index', () => { TestData.payeeRaw.signatureParams, ); const transactionManager: TransactionTypes.ITransactionManager = { - getChannelsByMultipleTopics: chai.spy(), - getChannelsByTopic: chai.spy(), + getChannelsByMultipleTopics: chai.spy() as any, + getChannelsByTopic: chai.spy() as any, getTransactionsByChannelId: chai.spy.returns( Promise.resolve({ meta: { ignoredTransactions: [] }, @@ -624,7 +619,7 @@ describe('index', () => { }, }), ), - persistTransaction: chai.spy(), + persistTransaction: chai.spy() as any, }; const increaseRequest = { deltaAmount: '1000', @@ -704,8 +699,8 @@ describe('index', () => { TestData.payeeRaw.signatureParams, ); const transactionManager: TransactionTypes.ITransactionManager = { - getChannelsByMultipleTopics: chai.spy(), - getChannelsByTopic: chai.spy(), + getChannelsByMultipleTopics: chai.spy() as any, + getChannelsByTopic: chai.spy() as any, getTransactionsByChannelId: chai.spy.returns( Promise.resolve({ meta: { ignoredTransactions: [] }, @@ -719,7 +714,7 @@ describe('index', () => { }, }), ), - persistTransaction: chai.spy(), + persistTransaction: chai.spy() as any, }; const addExtensionParams = { extensionsData: ['whatever'], @@ -802,11 +797,11 @@ describe('index', () => { }); const fakeTransactionManagerGet: TransactionTypes.ITransactionManager = { - getChannelsByMultipleTopics: chai.spy(), - getChannelsByTopic: chai.spy(), + getChannelsByMultipleTopics: chai.spy() as any, + getChannelsByTopic: chai.spy() as any, getTransactionsByChannelId: (): Promise => listActions, - persistTransaction: chai.spy(), + persistTransaction: chai.spy() as any, }; const requestLogic = new RequestLogic( fakeTransactionManagerGet, @@ -949,11 +944,11 @@ describe('index', () => { }); const fakeTransactionManagerGet: TransactionTypes.ITransactionManager = { - getChannelsByMultipleTopics: chai.spy(), - getChannelsByTopic: chai.spy(), + getChannelsByMultipleTopics: chai.spy() as any, + getChannelsByTopic: chai.spy() as any, getTransactionsByChannelId: (): Promise => listActions, - persistTransaction: chai.spy(), + persistTransaction: chai.spy() as any, }; const requestLogic = new RequestLogic( fakeTransactionManagerGet, @@ -1102,11 +1097,11 @@ describe('index', () => { }); const fakeTransactionManagerGet: TransactionTypes.ITransactionManager = { - getChannelsByMultipleTopics: chai.spy(), - getChannelsByTopic: chai.spy(), + getChannelsByMultipleTopics: chai.spy() as any, + getChannelsByTopic: chai.spy() as any, getTransactionsByChannelId: (): Promise => listActions, - persistTransaction: chai.spy(), + persistTransaction: chai.spy() as any, }; const requestLogic = new RequestLogic( fakeTransactionManagerGet, @@ -1191,11 +1186,11 @@ describe('index', () => { }); const fakeTransactionManagerGet: TransactionTypes.ITransactionManager = { - getChannelsByMultipleTopics: chai.spy(), - getChannelsByTopic: chai.spy(), + getChannelsByMultipleTopics: chai.spy() as any, + getChannelsByTopic: chai.spy() as any, getTransactionsByChannelId: (): Promise => listActions, - persistTransaction: chai.spy(), + persistTransaction: chai.spy() as any, }; const requestLogic = new RequestLogic( fakeTransactionManagerGet, @@ -1247,11 +1242,11 @@ describe('index', () => { }); const fakeTransactionManagerGet: TransactionTypes.ITransactionManager = { - getChannelsByMultipleTopics: chai.spy(), - getChannelsByTopic: chai.spy(), + getChannelsByMultipleTopics: chai.spy() as any, + getChannelsByTopic: chai.spy() as any, getTransactionsByChannelId: (): Promise => listActions, - persistTransaction: chai.spy(), + persistTransaction: chai.spy() as any, }; const requestLogic = new RequestLogic( fakeTransactionManagerGet, @@ -1423,12 +1418,12 @@ describe('index', () => { }); const fakeTransactionManagerGet: TransactionTypes.ITransactionManager = { - getChannelsByMultipleTopics: chai.spy(), + getChannelsByMultipleTopics: chai.spy() as any, getChannelsByTopic: (): Promise => { return listAllActions; }, - getTransactionsByChannelId: chai.spy(), - persistTransaction: chai.spy(), + getTransactionsByChannelId: chai.spy() as any, + persistTransaction: chai.spy() as any, }; const requestLogic = new RequestLogic( fakeTransactionManagerGet, @@ -1499,12 +1494,12 @@ describe('index', () => { }); const fakeTransactionManagerGet: TransactionTypes.ITransactionManager = { - getChannelsByMultipleTopics: chai.spy(), + getChannelsByMultipleTopics: chai.spy() as any, getChannelsByTopic: (): Promise => { return listActions; }, - getTransactionsByChannelId: chai.spy(), - persistTransaction: chai.spy(), + getTransactionsByChannelId: chai.spy() as any, + persistTransaction: chai.spy() as any, }; const requestLogic = new RequestLogic( fakeTransactionManagerGet, @@ -1669,9 +1664,9 @@ describe('index', () => { > => { return listAllActions; }, - getChannelsByTopic: chai.spy(), - getTransactionsByChannelId: chai.spy(), - persistTransaction: chai.spy(), + getChannelsByTopic: chai.spy() as any, + getTransactionsByChannelId: chai.spy() as any, + persistTransaction: chai.spy() as any, }; const requestLogic = new RequestLogic( fakeTransactionManagerGet, diff --git a/packages/request-logic/test/unit/action.test.ts b/packages/request-logic/test/unit/action.test.ts index bf4408397a..68b198808e 100644 --- a/packages/request-logic/test/unit/action.test.ts +++ b/packages/request-logic/test/unit/action.test.ts @@ -11,7 +11,7 @@ import { import Utils from '@requestnetwork/utils'; import Action from '../../src/action'; - +import CreateAction from '../../src/actions/create'; import Version from '../../src/version'; const CURRENT_VERSION = Version.currentVersion; @@ -141,3 +141,28 @@ describe('Action', () => { ); }); }); + +describe('actions retrocompatibility', () => { + it('old format requestId match', async () => { + const actionData = { + name: RequestLogicTypes.ACTION_NAME.CREATE, + parameters: { + currency: 'ETH', + expectedAmount: '123400000000000000', + payee: TestData.payeeRaw.identity, + timestamp: 1, + }, + version: '2.0.1', + }; + + const action = await Action.createAction( + actionData, + TestData.payeeRaw.identity, + TestData.fakeSignatureProvider, + ); + + const request = CreateAction.createRequest(action, 2); + + expect(Action.getRequestId(action)).equals(request.requestId); + }); +}); diff --git a/packages/request-node/.vscode/settings.json b/packages/request-node/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/request-node/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/request-node/CHANGELOG.md b/packages/request-node/CHANGELOG.md index a7ec2686f2..7fc08591d5 100644 --- a/packages/request-node/CHANGELOG.md +++ b/packages/request-node/CHANGELOG.md @@ -3,6 +3,38 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.5.7](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/request-node@0.5.4...@requestnetwork/request-node@0.5.7) (2020-01-16) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/request-node + + + + + +## [0.5.6](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/request-node@0.5.4...@requestnetwork/request-node@0.5.6) (2019-12-18) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/request-node + + + + + +## [0.5.5](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/request-node@0.5.4...@requestnetwork/request-node@0.5.5) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/request-node + + + + + ## [0.5.4](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/request-node@0.5.3...@requestnetwork/request-node@0.5.4) (2019-11-20) **Note:** Version bump only for package @requestnetwork/request-node diff --git a/packages/request-node/package.json b/packages/request-node/package.json index bf0c993800..8825a99eed 100644 --- a/packages/request-node/package.json +++ b/packages/request-node/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/request-node", - "version": "0.5.4", + "version": "0.5.7", "publishConfig": { "access": "public" }, @@ -31,20 +31,20 @@ "scripts": { "build": "tsc -b", "build:watch": "tsc -b --watch", - "test": "nyc mocha --timeout=10000 --exit --require ts-node/register --require source-map-support/register test/**/*.ts", - "test:watch": "nyc mocha --watch --watch-extensions ts --timeout=10000 --exit --require ts-node/register --require source-map-support/register test/**/*.ts", + "test": "nyc mocha --timeout=10000 --exit --extension ts --require ts-node/register --require source-map-support/register test/**/*.ts", + "test:watch": "yarn test --watch", "start": "ts-node src/server.ts", "start:watch": "ts-node-dev src/server.ts", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint-staged": "lint-staged", "lint": "tslint --project .", "init-ipfs": "node init-ipfs.js" }, "dependencies": { - "@requestnetwork/data-access": "0.5.2", - "@requestnetwork/ethereum-storage": "0.4.5", - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0", + "@requestnetwork/data-access": "0.5.5", + "@requestnetwork/ethereum-storage": "0.4.8", + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0", "@truffle/hdwallet-provider": "1.0.18", "chalk": "2.4.2", "cors": "2.8.5", @@ -63,12 +63,12 @@ "chai": "4.2.0", "chai-as-promised": "7.1.1", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "prettier": "1.16.4", "shx": "0.3.2", "source-map-support": "0.5.13", "supertest": "3.4.2", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "ts-node-dev": "1.0.0-pre.39", "tslint": "5.12.1", "typescript": "3.7.2" diff --git a/packages/ethereum-storage/.gitignore b/packages/smart-contracts/.gitignore similarity index 100% rename from packages/ethereum-storage/.gitignore rename to packages/smart-contracts/.gitignore diff --git a/packages/ethereum-storage/.soliumrc.json b/packages/smart-contracts/.soliumrc.json similarity index 100% rename from packages/ethereum-storage/.soliumrc.json rename to packages/smart-contracts/.soliumrc.json diff --git a/packages/smart-contracts/CHANGELOG.md b/packages/smart-contracts/CHANGELOG.md new file mode 100644 index 0000000000..ebda6c2b9a --- /dev/null +++ b/packages/smart-contracts/CHANGELOG.md @@ -0,0 +1,39 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# 0.3.0 (2020-01-16) + + +### Bug Fixes + +* add payable to the ERC20 proxy contract fallback ([#96](https://github.com/RequestNetwork/requestNetwork/issues/96)) ([1237b64](https://github.com/RequestNetwork/requestNetwork/commit/1237b6431f3d6e141e3bae1690ac59c553ed49f2)) +* **smart-contracts:** fix json require to work with webpack ([#105](https://github.com/RequestNetwork/requestNetwork/issues/105)) ([a465e83](https://github.com/RequestNetwork/requestNetwork/commit/a465e83a739a7648e71d8ebb4a3a4eb389e00f13)) + + +### Features + +* deploy ERC20 proxy smart contract to mainnet ([#97](https://github.com/RequestNetwork/requestNetwork/issues/97)) ([84a7d2a](https://github.com/RequestNetwork/requestNetwork/commit/84a7d2ae9c06a3c6e457c8583e44e8df01676b2a)) +* deploy ERC20 proxy smart contract to Rinkeby ([#95](https://github.com/RequestNetwork/requestNetwork/issues/95)) ([39e6a6a](https://github.com/RequestNetwork/requestNetwork/commit/39e6a6a0ea62fd4ee9e6343d03770711638b698b)) +* **request-client.js:** get balance from request ERC20 with proxy contract ([#94](https://github.com/RequestNetwork/requestNetwork/issues/94)) ([08758ae](https://github.com/RequestNetwork/requestNetwork/commit/08758ae83e3834db06c0f1441e51bc6c2b897669)) +* **smart-contracts:** add the erc20 proxy contract PN's smart contract ([#92](https://github.com/RequestNetwork/requestNetwork/issues/92)) ([30f7937](https://github.com/RequestNetwork/requestNetwork/commit/30f79374a78f1a060a91bc7e53e6dc44c2fbad2c)) + + + + + +# 0.2.0 (2019-12-18) + + +### Bug Fixes + +* add payable to the ERC20 proxy contract fallback ([#96](https://github.com/RequestNetwork/requestNetwork/issues/96)) ([1237b64](https://github.com/RequestNetwork/requestNetwork/commit/1237b6431f3d6e141e3bae1690ac59c553ed49f2)) + + +### Features + +* deploy ERC20 proxy smart contract to mainnet ([#97](https://github.com/RequestNetwork/requestNetwork/issues/97)) ([84a7d2a](https://github.com/RequestNetwork/requestNetwork/commit/84a7d2ae9c06a3c6e457c8583e44e8df01676b2a)) +* deploy ERC20 proxy smart contract to Rinkeby ([#95](https://github.com/RequestNetwork/requestNetwork/issues/95)) ([39e6a6a](https://github.com/RequestNetwork/requestNetwork/commit/39e6a6a0ea62fd4ee9e6343d03770711638b698b)) +* **request-client.js:** get balance from request ERC20 with proxy contract ([#94](https://github.com/RequestNetwork/requestNetwork/issues/94)) ([08758ae](https://github.com/RequestNetwork/requestNetwork/commit/08758ae83e3834db06c0f1441e51bc6c2b897669)) +* **smart-contracts:** add the erc20 proxy contract PN's smart contract ([#92](https://github.com/RequestNetwork/requestNetwork/issues/92)) ([30f7937](https://github.com/RequestNetwork/requestNetwork/commit/30f79374a78f1a060a91bc7e53e6dc44c2fbad2c)) diff --git a/packages/smart-contracts/README.md b/packages/smart-contracts/README.md new file mode 100644 index 0000000000..b4e997c8ff --- /dev/null +++ b/packages/smart-contracts/README.md @@ -0,0 +1,77 @@ +# @requestnetwork/smart-contracs + +`@requestnetwork/smart-contracts` is a package part of the [Request Network protocol](https://github.com/RequestNetwork/requestNetwork). +The package stores the sources and artifacts of the smart contracts deployed on Ethereum. It also exposes a library to get information about the artifacts. + +## Installation + +```bash +npm install @requestnetwork/smart-contracts +``` + +## Usage + +Library usage: + +```js +import * as SmartContracts from '@requestnetwork/smart-contracts'; + +const requestHashStorageMainnetAddress = SmartContracts.requestHashStorageArtifact.getAddress( + 'mainnet', +); + +const requestHashSubmitterRinkebyAddress = SmartContracts.requestHashSubmitterArtifact.getAddress( + 'rinkeby', +); + +const requestHashStorageABI = SmartContracts.requestHashStorageArtifact.getContractAbi() +``` + +## Smart Contract + +The package stores the following smart contracts: + + +**Smart contracts for ethereum-storage package** +- `RequestHashStorage` allows to declare a hash `NewHash(hash, submitter, feesParameters)`. Only a whitelisted contract can declare hashes. +- `RequestOpenHashSubmitter` entry point to add hashes in `RequestHashStorage`. It gives the rules to get the right to submit hashes and collect the fees. This contract must be whitelisted in `RequestHashStorage`. The only condition for adding hash is to pay the fees. +- `StorageFeeCollector` parent contract (not deployed) of `RequestOpenHashSubmitter`, computes the fees and send them to the burner. + +**Smart contracts for advanced-logic package** +- `TestERC20` minimal erc20 token used for tests. +- `ERC20Proxy` smart contract used by the erc20 proxy contract payment network to store payment references of erc20 transfers + +#### Smart contracts local deployment + +The smart contracts can be deployed locally with the following commands: + +```bash +git clone https://github.com/RequestNetwork/requestNetwork.git +cd requestNetwork/packages/smart-contracts +yarn install +yarn run build +yarn run ganache +``` + +And in another terminal: + +```bash +yarn run deploy +``` + +#### Configuring the provider using Truffle and the development network + +When deploying the smart contracts for development you can manually set the provider host and port via env variables: + +```bash +TRUFFLE_GANACHE_HOST="host" TRUFFLE_GANACHE_PORT=1010 yarn run deploy +``` + +## Contributing + +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. +[Read the contributing guide](/CONTRIBUTING.md) + +## License + +[MIT](/LICENSE) diff --git a/packages/smart-contracts/artifacts/ERC20Proxy/0.1.0.json b/packages/smart-contracts/artifacts/ERC20Proxy/0.1.0.json new file mode 100644 index 0000000000..8bb69de611 --- /dev/null +++ b/packages/smart-contracts/artifacts/ERC20Proxy/0.1.0.json @@ -0,0 +1,70 @@ +{ + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes", + "name": "paymentReference", + "type": "bytes" + } + ], + "name": "TransferWithReference", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_paymentReference", + "type": "bytes" + } + ], + "name": "transferFromWithReference", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] +} diff --git a/packages/smart-contracts/artifacts/ERC20Proxy/artifacts.json b/packages/smart-contracts/artifacts/ERC20Proxy/artifacts.json new file mode 100644 index 0000000000..545d85ab1b --- /dev/null +++ b/packages/smart-contracts/artifacts/ERC20Proxy/artifacts.json @@ -0,0 +1,20 @@ +{ + "lastVersion": "0.1.0", + "0.1.0": { + "artifact": "0.1.0.json", + "deployment": { + "private": { + "address": "0x2c2b9c9a4a25e24b174f26114e8926a9f2128fe4", + "creationBlockNumber": 0 + }, + "mainnet": { + "address": "0x5f821c20947ff9be22e823edc5b3c709b33121b3", + "creationBlockNumber": 9119380 + }, + "rinkeby": { + "address": "0x162edb802fae75b9ee4288345735008ba51a4ec9", + "creationBlockNumber": 5628198 + } + } + } +} diff --git a/packages/ethereum-storage/artifacts/RequestHashStorage/0.1.0.json b/packages/smart-contracts/artifacts/RequestHashStorage/0.1.0.json similarity index 100% rename from packages/ethereum-storage/artifacts/RequestHashStorage/0.1.0.json rename to packages/smart-contracts/artifacts/RequestHashStorage/0.1.0.json diff --git a/packages/ethereum-storage/artifacts/RequestHashStorage/artifacts.json b/packages/smart-contracts/artifacts/RequestHashStorage/artifacts.json similarity index 100% rename from packages/ethereum-storage/artifacts/RequestHashStorage/artifacts.json rename to packages/smart-contracts/artifacts/RequestHashStorage/artifacts.json diff --git a/packages/ethereum-storage/artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/0.1.0.json b/packages/smart-contracts/artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/0.1.0.json similarity index 100% rename from packages/ethereum-storage/artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/0.1.0.json rename to packages/smart-contracts/artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/0.1.0.json diff --git a/packages/ethereum-storage/artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/artifacts.json b/packages/smart-contracts/artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/artifacts.json similarity index 100% rename from packages/ethereum-storage/artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/artifacts.json rename to packages/smart-contracts/artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/artifacts.json diff --git a/packages/ethereum-storage/migrations/1_initial_migration.js b/packages/smart-contracts/migrations/1_initial_migration.js similarity index 100% rename from packages/ethereum-storage/migrations/1_initial_migration.js rename to packages/smart-contracts/migrations/1_initial_migration.js diff --git a/packages/ethereum-storage/migrations/2_deploy_contracts.js b/packages/smart-contracts/migrations/2_deploy_contracts.js similarity index 57% rename from packages/ethereum-storage/migrations/2_deploy_contracts.js rename to packages/smart-contracts/migrations/2_deploy_contracts.js index e77b61406c..361aa05015 100644 --- a/packages/ethereum-storage/migrations/2_deploy_contracts.js +++ b/packages/smart-contracts/migrations/2_deploy_contracts.js @@ -1,6 +1,7 @@ const RequestHashStorage = artifacts.require('./RequestHashStorage.sol'); const RequestOpenHashSubmitter = artifacts.require('./RequestOpenHashSubmitter.sol'); const erc20 = artifacts.require('./TestERC20.sol'); +const ERC20Proxy = artifacts.require('./ERC20Proxy.sol'); const addressContractBurner = '0xfCb4393e7fAef06fAb01c00d67c1895545AfF3b8'; @@ -21,11 +22,30 @@ module.exports = async function(deployer) { // Whitelist the requestSubmitter in requestHashDeclaration const instanceRequestHashStorage = await RequestHashStorage.deployed(); - instanceRequestHashStorage.addWhitelisted(RequestOpenHashSubmitter.address); + await instanceRequestHashStorage.addWhitelisted(RequestOpenHashSubmitter.address); console.log('requestSubmitter Whitelisted in requestHashDeclaration'); // Deploy the ERC20 contract - await deployer.deploy(erc20, 1000); // 1000 initial supply + const instanceTestERC20 = await deployer.deploy(erc20, 1000); // 1000 initial supply + + // Deploy ERC20 proxy contract + const instanceRequestERC20Proxy = await deployer.deploy(ERC20Proxy); + + // create some events for test purpose + await instanceTestERC20.approve(ERC20Proxy.address, 110); + await instanceRequestERC20Proxy.transferFromWithReference( + instanceTestERC20.address, + '0x6330A553Fc93768F612722BB8c2eC78aC90B3bbc', + 100, + '0x152191b6ec81c20c', + ); + await instanceRequestERC20Proxy.transferFromWithReference( + instanceTestERC20.address, + '0x5AEDA56215b167893e80B4fE645BA6d5Bab767DE', + 10, + '0x0690ebf9d9f17132', + ); + // ---------------------------------- console.log('Contracts initialized'); } catch (e) { diff --git a/packages/smart-contracts/package.json b/packages/smart-contracts/package.json new file mode 100644 index 0000000000..9ac9ecf408 --- /dev/null +++ b/packages/smart-contracts/package.json @@ -0,0 +1,55 @@ +{ + "name": "@requestnetwork/smart-contracts", + "version": "0.3.0", + "publishConfig": { + "access": "public" + }, + "description": "Smart contracts for the Request protocol.", + "keywords": [ + "requestnetwork", + "smart-contracts" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/RequestNetwork/requestNetwork.git" + }, + "homepage": "https://github.com/RequestNetwork/requestNetwork/tree/master/packages/smart-contract#readme", + "bugs": { + "url": "https://github.com/RequestNetwork/requestNetwork/issues" + }, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + }, + "main": "dist/src/lib/index.js", + "types": "dist/src/lib/index.d.ts", + "directories": { + "lib": "src/lib", + "test": "test/lib" + }, + "files": [ + "dist" + ], + "scripts": { + "build:lib": "tsc -b", + "build:sol": "truffle compile --contracts_directory=./src", + "build": "yarn run build:lib && yarn run build:sol", + "clean:lib": "shx rm -rf dist", + "clean:sol": "shx rm -rf build", + "clean": "yarn run clean:lib && yarn run clean:sol", + "lint:lib": "tslint --project . && eslint \"src/lib/**/*.ts\"", + "lint:sol": "solium --dir src/contracts", + "lint": "yarn run lint:lib && yarn run lint:sol", + "ganache": "ganache-cli -l 90000000 -p 8545 -m \"candy maple cake sugar pudding cream honey rich smooth crumble sweet treat\"", + "deploy": "truffle --contracts_directory=./src deploy", + "test": "truffle test --contracts_directory=./src test/contracts/*.js" + }, + "devDependencies": { + "@openzeppelin/contracts": "2.4.0", + "ethers": "4.0.38", + "ganache-cli": "6.7.0", + "lint-staged": "9.5.0", + "shx": "0.3.2", + "truffle": "5.1.2" + } +} diff --git a/packages/ethereum-storage/src/contracts/Bytes.sol b/packages/smart-contracts/src/contracts/Bytes.sol similarity index 100% rename from packages/ethereum-storage/src/contracts/Bytes.sol rename to packages/smart-contracts/src/contracts/Bytes.sol diff --git a/packages/smart-contracts/src/contracts/ERC20Proxy.sol b/packages/smart-contracts/src/contracts/ERC20Proxy.sol new file mode 100644 index 0000000000..c981114c04 --- /dev/null +++ b/packages/smart-contracts/src/contracts/ERC20Proxy.sol @@ -0,0 +1,51 @@ +pragma solidity ^0.5.0; + +import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; + + +/** + * @title ERC20Proxy + * @notice This contract performs an ERC20 token transfer and stores a reference + */ +contract ERC20Proxy { + // Event to declare a transfer with a reference + event TransferWithReference( + address tokenAddress, + address to, + uint256 amount, + bytes indexed paymentReference + ); + + // Fallback function returns funds to the sender + function() + external + payable + { + revert("not payable fallback"); + } + + /** + * @notice Performs a ERC20 token transfer with a reference + * @param _tokenAddress Address of the ERC20 token smart contract + * @param _to Transfer recipient + * @param _amount Amount to transfer + * @param _paymentReference Reference of the payment related + */ + function transferFromWithReference( + address _tokenAddress, + address _to, + uint256 _amount, + bytes calldata _paymentReference + ) + external + { + ERC20 erc20 = ERC20(_tokenAddress); + require(erc20.transferFrom(msg.sender, _to, _amount), "transferFrom() failed"); + emit TransferWithReference( + _tokenAddress, + _to, + _amount, + _paymentReference + ); + } +} diff --git a/packages/ethereum-storage/src/contracts/Migrations.sol b/packages/smart-contracts/src/contracts/Migrations.sol similarity index 100% rename from packages/ethereum-storage/src/contracts/Migrations.sol rename to packages/smart-contracts/src/contracts/Migrations.sol diff --git a/packages/ethereum-storage/src/contracts/RequestHashStorage.sol b/packages/smart-contracts/src/contracts/RequestHashStorage.sol similarity index 100% rename from packages/ethereum-storage/src/contracts/RequestHashStorage.sol rename to packages/smart-contracts/src/contracts/RequestHashStorage.sol diff --git a/packages/ethereum-storage/src/contracts/RequestOpenHashSubmitter.sol b/packages/smart-contracts/src/contracts/RequestOpenHashSubmitter.sol similarity index 100% rename from packages/ethereum-storage/src/contracts/RequestOpenHashSubmitter.sol rename to packages/smart-contracts/src/contracts/RequestOpenHashSubmitter.sol diff --git a/packages/ethereum-storage/src/contracts/StorageFeeCollector.sol b/packages/smart-contracts/src/contracts/StorageFeeCollector.sol similarity index 100% rename from packages/ethereum-storage/src/contracts/StorageFeeCollector.sol rename to packages/smart-contracts/src/contracts/StorageFeeCollector.sol diff --git a/packages/ethereum-storage/src/contracts/testERC20.sol b/packages/smart-contracts/src/contracts/TestERC20.sol similarity index 99% rename from packages/ethereum-storage/src/contracts/testERC20.sol rename to packages/smart-contracts/src/contracts/TestERC20.sol index 5f82132592..97d227d247 100644 --- a/packages/ethereum-storage/src/contracts/testERC20.sol +++ b/packages/smart-contracts/src/contracts/TestERC20.sol @@ -3,11 +3,12 @@ pragma solidity ^0.5.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol"; + /** * @title TestERC20 * * @notice TestERC20 is a contract to test ERC20 detection - */ +*/ contract TestERC20 is ERC20, ERC20Detailed { constructor(uint256 initialSupply) ERC20Detailed("ERC 20", "ERC20", 18) public { _mint(msg.sender, initialSupply); diff --git a/packages/ethereum-storage/src/contracts/test/BytesUtilsMock.sol b/packages/smart-contracts/src/contracts/test/BytesUtilsMock.sol similarity index 100% rename from packages/ethereum-storage/src/contracts/test/BytesUtilsMock.sol rename to packages/smart-contracts/src/contracts/test/BytesUtilsMock.sol diff --git a/packages/smart-contracts/src/lib/erc20ProxyArtifact.ts b/packages/smart-contracts/src/lib/erc20ProxyArtifact.ts new file mode 100644 index 0000000000..475d682609 --- /dev/null +++ b/packages/smart-contracts/src/lib/erc20ProxyArtifact.ts @@ -0,0 +1,61 @@ +const artifactsERC20Proxy = require('../../artifacts/ERC20Proxy/artifacts.json'); +const ARTIFACTS_VERSION: string = artifactsERC20Proxy.lastVersion; + +/** + * Retrieve the abi from the artifact of the used version + * @returns the abi of the artifact as a json object + */ +export function getContractAbi(): any { + const artifactFilename: string = artifactsERC20Proxy[ARTIFACTS_VERSION].artifact; + + const artifact = require(`../../artifacts/ERC20Proxy/${artifactFilename.replace( + /\.[^/.]+$/, + '', + )}.json`); + + // Check the abi exists inside the artifact file + if (!artifact.abi) { + throw Error(`No abi in artifact ${artifactFilename}`); + } + + return artifact.abi; +} + +/** + * Retrieve the address from the artifact of the used version + * deployed into the specified network + * @param networkName the name of the network where the contract is deployed + * @returns the address of the deployed contract + */ +export function getAddress(networkName: string): string { + return getDeploymentInformation(networkName).address; +} + +/** + * Retrieve the block creation number from the artifact of the used version + * deployed into the specified network + * @param networkName the name of the network where the contract is deployed + * @returns the number of the block where the contract was deployed + */ +export function getCreationBlockNumber(networkName: string): number { + return getDeploymentInformation(networkName).creationBlockNumber; +} + +/** + * Retrieve the deployment information from the artifact of the used version + * deployed into the specified network + * @param networkName the name of the network where the contract is deployed + * @returns the deployment information of the contract as a json object containing address and the number of the creation block + */ +function getDeploymentInformation( + networkName: string, +): { address: string; creationBlockNumber: number } { + const deploymentInformation = artifactsERC20Proxy[ARTIFACTS_VERSION].deployment[networkName]; + + // Check the artifact has been deployed into the specified network + if (!deploymentInformation) { + throw Error(`No deployment for network: ${networkName}`); + } + + return deploymentInformation; +} diff --git a/packages/smart-contracts/src/lib/index.ts b/packages/smart-contracts/src/lib/index.ts new file mode 100644 index 0000000000..89554eefa1 --- /dev/null +++ b/packages/smart-contracts/src/lib/index.ts @@ -0,0 +1,9 @@ +import * as erc20ProxyArtifact from './erc20ProxyArtifact'; +import * as requestHashStorageArtifact from './requestHashStorageArtifact'; +import * as requestHashSubmitterArtifact from './requestHashSubmitterArtifact'; + +export { + erc20ProxyArtifact, + requestHashStorageArtifact, + requestHashSubmitterArtifact, +}; diff --git a/packages/ethereum-storage/src/lib/artifacts-request-hash-storage-utils.ts b/packages/smart-contracts/src/lib/requestHashStorageArtifact.ts similarity index 93% rename from packages/ethereum-storage/src/lib/artifacts-request-hash-storage-utils.ts rename to packages/smart-contracts/src/lib/requestHashStorageArtifact.ts index f3a0d242f1..027a24c486 100644 --- a/packages/ethereum-storage/src/lib/artifacts-request-hash-storage-utils.ts +++ b/packages/smart-contracts/src/lib/requestHashStorageArtifact.ts @@ -1,4 +1,3 @@ -import * as path from 'path'; const artifacts = require('../../artifacts/RequestHashStorage/artifacts.json'); const ARTIFACTS_VERSION: string = artifacts.lastVersion; @@ -8,7 +7,11 @@ const ARTIFACTS_VERSION: string = artifacts.lastVersion; */ export function getContractAbi(): any { const artifactFilename: string = artifacts[ARTIFACTS_VERSION].artifact; - const artifact = require(path.join('../../artifacts/RequestHashStorage/', artifactFilename)); + + const artifact = require(`../../artifacts/RequestHashStorage/${artifactFilename.replace( + /\.[^/.]+$/, + '', + )}.json`); // Check the abi exists inside the artifact file if (!artifact.abi) { diff --git a/packages/ethereum-storage/src/lib/artifacts-request-hash-submitter-utils.ts b/packages/smart-contracts/src/lib/requestHashSubmitterArtifact.ts similarity index 92% rename from packages/ethereum-storage/src/lib/artifacts-request-hash-submitter-utils.ts rename to packages/smart-contracts/src/lib/requestHashSubmitterArtifact.ts index 9c503102c1..b19ba884f5 100644 --- a/packages/ethereum-storage/src/lib/artifacts-request-hash-submitter-utils.ts +++ b/packages/smart-contracts/src/lib/requestHashSubmitterArtifact.ts @@ -1,5 +1,3 @@ -import * as path from 'path'; - const artifactsRequestOpenHashSubmitter = require('../../artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/artifacts.json'); const ARTIFACTS_OPEN_STORAGE_LAST_VERSION: string = artifactsRequestOpenHashSubmitter.lastVersion; @@ -11,10 +9,10 @@ export function getContractAbi(): any { const artifactFilename: string = artifactsRequestOpenHashSubmitter[ARTIFACTS_OPEN_STORAGE_LAST_VERSION].artifact; - const artifact = require(path.join( - '../../artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/', - artifactFilename, - )); + const artifact = require(`../../artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/${artifactFilename.replace( + /\.[^/.]+$/, + '', + )}.json`); // Check the abi exists inside the artifact file if (!artifact.abi) { diff --git a/packages/smart-contracts/test/contracts/ERC20Proxy.js b/packages/smart-contracts/test/contracts/ERC20Proxy.js new file mode 100644 index 0000000000..b7c8fdd51e --- /dev/null +++ b/packages/smart-contracts/test/contracts/ERC20Proxy.js @@ -0,0 +1,69 @@ +const ethers = require('ethers'); + +const { expectEvent, shouldFail } = require('openzeppelin-test-helpers'); +const ERC20Proxy = artifacts.require('./ERC20Proxy.sol'); +const TestERC20 = artifacts.require('./TestERC20.sol'); + +contract('ERC20Proxy', function(accounts) { + const from = accounts[0]; + const to = accounts[1]; + const otherGuy = accounts[2]; + let erc20Proxy; + let testERC20; + const referenceExample = '0xaaaa'; + + beforeEach(async () => { + testERC20 = await TestERC20.new(1000, { + from, + }); + erc20Proxy = await ERC20Proxy.new({ + from, + }); + }); + + it('allows to store a reference', async function() { + await testERC20.approve(erc20Proxy.address, '100', { from }); + + let { logs } = await erc20Proxy.transferFromWithReference( + testERC20.address, + to, + '100', + referenceExample, + { from }, + ); + + // transferReference indexes the event log, therefore the keccak256 is stored + expectEvent.inLogs(logs, 'TransferWithReference', { + tokenAddress: testERC20.address, + to, + amount: '100', + paymentReference: ethers.utils.keccak256(referenceExample), + }); + }); + + it('allows to transfer tokens', async function() { + await testERC20.approve(erc20Proxy.address, '100', { from }); + + const fromOldBalance = await testERC20.balanceOf(from); + const toOldBalance = await testERC20.balanceOf(to); + + await erc20Proxy.transferFromWithReference(testERC20.address, to, '100', referenceExample, { + from, + }); + + const fromNewBalance = await testERC20.balanceOf(from); + const toNewBalance = await testERC20.balanceOf(to); + + // Check balance changes + expect(fromNewBalance.toNumber()).to.equals(fromOldBalance.toNumber() - 100); + expect(toNewBalance.toNumber()).to.equals(toOldBalance.toNumber() + 100); + }); + + it('should revert if no fund', async function() { + await shouldFail.reverting( + erc20Proxy.transferFromWithReference(testERC20.address, to, '100', referenceExample, { + from: otherGuy, + }), + ); + }); +}); diff --git a/packages/ethereum-storage/test/contracts/RequestHashStorage.js b/packages/smart-contracts/test/contracts/RequestHashStorage.js similarity index 98% rename from packages/ethereum-storage/test/contracts/RequestHashStorage.js rename to packages/smart-contracts/test/contracts/RequestHashStorage.js index 39bccec8c1..2784c0a09a 100644 --- a/packages/ethereum-storage/test/contracts/RequestHashStorage.js +++ b/packages/smart-contracts/test/contracts/RequestHashStorage.js @@ -1,4 +1,3 @@ -const BigNumber = require('bn.js'); const { expectEvent, shouldFail } = require('openzeppelin-test-helpers'); const RequestHashStorage = artifacts.require('./RequestHashStorage.sol'); diff --git a/packages/ethereum-storage/test/contracts/RequestOpenHashSubmitter.js b/packages/smart-contracts/test/contracts/RequestOpenHashSubmitter.js similarity index 100% rename from packages/ethereum-storage/test/contracts/RequestOpenHashSubmitter.js rename to packages/smart-contracts/test/contracts/RequestOpenHashSubmitter.js diff --git a/packages/ethereum-storage/test/contracts/StorageFeeCollector.js b/packages/smart-contracts/test/contracts/StorageFeeCollector.js similarity index 100% rename from packages/ethereum-storage/test/contracts/StorageFeeCollector.js rename to packages/smart-contracts/test/contracts/StorageFeeCollector.js diff --git a/packages/ethereum-storage/test/contracts/bytes-test.js b/packages/smart-contracts/test/contracts/bytes-test.js similarity index 100% rename from packages/ethereum-storage/test/contracts/bytes-test.js rename to packages/smart-contracts/test/contracts/bytes-test.js diff --git a/packages/ethereum-storage/test/contracts/utils.js b/packages/smart-contracts/test/contracts/utils.js similarity index 100% rename from packages/ethereum-storage/test/contracts/utils.js rename to packages/smart-contracts/test/contracts/utils.js diff --git a/packages/ethereum-storage/truffle-config.js b/packages/smart-contracts/truffle-config.js similarity index 100% rename from packages/ethereum-storage/truffle-config.js rename to packages/smart-contracts/truffle-config.js diff --git a/packages/smart-contracts/tsconfig.json b/packages/smart-contracts/tsconfig.json new file mode 100644 index 0000000000..23ab398da0 --- /dev/null +++ b/packages/smart-contracts/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "outDir": "dist", + "rootDir": ".", + "resolveJsonModule": true + }, + "include": ["./src/**/*", "./artifacts/**/*"], + "files": [ + "./artifacts/ERC20Proxy/artifacts.json", + "./artifacts/ERC20Proxy/0.1.0.json", + "./artifacts/RequestHashStorage/artifacts.json", + "./artifacts/RequestHashStorage/0.1.0.json", + "./artifacts/RequestHashStorage/artifacts.json", + "./artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/0.1.0.json", + "./artifacts/RequestHashSubmitter/RequestOpenHashSubmitter/artifacts.json" + ] +} diff --git a/packages/smart-contracts/tslint.json b/packages/smart-contracts/tslint.json new file mode 100644 index 0000000000..86908345b4 --- /dev/null +++ b/packages/smart-contracts/tslint.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tslint.json", + "linterOptions": { + "exclude": ["artifacts/**/*"] + } +} diff --git a/packages/toolbox/.vscode/settings.json b/packages/toolbox/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/toolbox/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/toolbox/CHANGELOG.md b/packages/toolbox/CHANGELOG.md index 67edc88ab7..773c7b410b 100644 --- a/packages/toolbox/CHANGELOG.md +++ b/packages/toolbox/CHANGELOG.md @@ -3,6 +3,38 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.6](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/toolbox@0.1.3...@requestnetwork/toolbox@0.1.6) (2020-01-16) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/toolbox + + + + + +## [0.1.5](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/toolbox@0.1.3...@requestnetwork/toolbox@0.1.5) (2019-12-18) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/toolbox + + + + + +## [0.1.4](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/toolbox@0.1.3...@requestnetwork/toolbox@0.1.4) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/toolbox + + + + + ## [0.1.3](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/toolbox@0.1.2...@requestnetwork/toolbox@0.1.3) (2019-11-20) **Note:** Version bump only for package @requestnetwork/toolbox diff --git a/packages/toolbox/package.json b/packages/toolbox/package.json index 09dd8c9385..f9242a6dd2 100644 --- a/packages/toolbox/package.json +++ b/packages/toolbox/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/toolbox", - "version": "0.1.3", + "version": "0.1.6", "private": true, "description": "Toolbox for Request Network.", "keywords": [ @@ -32,17 +32,17 @@ }, "scripts": { "build": "tsc -b", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", "prepare": "yarn run build", "cli": "cross-env NODE_ENV=development ts-node src/cli.ts" }, "dependencies": { - "@requestnetwork/epk-signature": "0.5.4", - "@requestnetwork/request-client.js": "0.9.0", - "@requestnetwork/types": "0.9.0", - "axios": "0.18.1", + "@requestnetwork/epk-signature": "0.5.7", + "@requestnetwork/request-client.js": "0.12.0", + "@requestnetwork/types": "0.11.0", + "axios": "0.19.0", "yargs": "14.0.0" }, "devDependencies": { diff --git a/packages/transaction-manager/.vscode/settings.json b/packages/transaction-manager/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/transaction-manager/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/transaction-manager/CHANGELOG.md b/packages/transaction-manager/CHANGELOG.md index b59b4ea3a8..240fe61da5 100644 --- a/packages/transaction-manager/CHANGELOG.md +++ b/packages/transaction-manager/CHANGELOG.md @@ -3,6 +3,38 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.8.4](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/transaction-manager@0.8.1...@requestnetwork/transaction-manager@0.8.4) (2020-01-16) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/transaction-manager + + + + + +## [0.8.3](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/transaction-manager@0.8.1...@requestnetwork/transaction-manager@0.8.3) (2019-12-18) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/transaction-manager + + + + + +## [0.8.2](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/transaction-manager@0.8.1...@requestnetwork/transaction-manager@0.8.2) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/transaction-manager + + + + + ## [0.8.1](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/transaction-manager@0.8.0...@requestnetwork/transaction-manager@0.8.1) (2019-11-20) **Note:** Version bump only for package @requestnetwork/transaction-manager diff --git a/packages/transaction-manager/package.json b/packages/transaction-manager/package.json index 5c8500fbe6..4ee0b967ac 100644 --- a/packages/transaction-manager/package.json +++ b/packages/transaction-manager/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/transaction-manager", - "version": "0.8.1", + "version": "0.8.4", "publishConfig": { "access": "public" }, @@ -32,21 +32,21 @@ ], "scripts": { "build": "tsc -b", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", - "test": "nyc mocha --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", - "test:watch": "nyc mocha --watch --watch-extensions ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"" + "test": "nyc mocha --extension ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", + "test:watch": "yarn test --watch" }, "dependencies": { - "@requestnetwork/multi-format": "0.2.1", - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0" + "@requestnetwork/multi-format": "0.2.4", + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0" }, "devDependencies": { "@types/chai": "4.1.7", "@types/chai-spies": "1.0.0", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", "@typescript-eslint/parser": "1.2.0", "chai": "4.2.0", "chai-as-promised": "7.1.1", @@ -55,12 +55,12 @@ "eslint-plugin-spellcheck": "0.0.11", "eslint-plugin-typescript": "0.14.0", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "nyc": "13.2.0", "prettier": "1.16.4", "shx": "0.3.2", "source-map-support": "0.5.13", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "tslint": "5.12.1", "typescript": "3.7.2" }, diff --git a/packages/transaction-manager/specs/encryption.md b/packages/transaction-manager/specs/encryption.md index 7d72147534..4640bc901f 100644 --- a/packages/transaction-manager/specs/encryption.md +++ b/packages/transaction-manager/specs/encryption.md @@ -50,7 +50,7 @@ The encrypted data, the encrypted keys and a hash of the data are pushed on chai | Property | Type | Description | | -------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------- | -| **data** | String | First encrypted data of the channel in base64 | +| **encryptedData** | String | First encrypted data of the channel in base64 | | **hash** | String | Normalized Keccak256 hash of the message before encryption | | **keys** | Object | AES-256 key encrypted with ECIES from the parties public keys, encoded in base64 and indexed by their multi-formatted identities | | **encryptionMethod** | String | Encryption method use for the channel _('ECIES-AES256' here)_ | @@ -63,7 +63,7 @@ Example: ```JSON { - "data": "JOz9aOV1aYatMSAx+3CD9EyjNI/FwLp6DeA+AYk5ERnTDwwaETY7zz2NemubnGW7GGDATjSVsnCVWXuM58cihq1Bhkon2aiPHhQdpteEugkrM2Zx/kWrVlvRY8kyseB30hU7NhyiDUSLGOJ/Pmq3PjANbBi2svgADLFZ6SdYgwFkjxaO1XkvW/qvjuraFqW55/4wCd53yjWcjMcLzMgLYcTLmSns642xAjx0hAvwVPQmTVI5xOFf6PjbEN9qfRPfdQkaOuuGG2AYsVhOkSK73BULdIvx6PArfqICCtL23xmt4kCeFgd6HYQvSzSFqszqAWT1kJdiRj3sZXRtf6xcpeXDelBacHN+xD2mzdZlroVhlsjZi5s0mhemBd+C", + "encryptedData": "JOz9aOV1aYatMSAx+3CD9EyjNI/FwLp6DeA+AYk5ERnTDwwaETY7zz2NemubnGW7GGDATjSVsnCVWXuM58cihq1Bhkon2aiPHhQdpteEugkrM2Zx/kWrVlvRY8kyseB30hU7NhyiDUSLGOJ/Pmq3PjANbBi2svgADLFZ6SdYgwFkjxaO1XkvW/qvjuraFqW55/4wCd53yjWcjMcLzMgLYcTLmSns642xAjx0hAvwVPQmTVI5xOFf6PjbEN9qfRPfdQkaOuuGG2AYsVhOkSK73BULdIvx6PArfqICCtL23xmt4kCeFgd6HYQvSzSFqszqAWT1kJdiRj3sZXRtf6xcpeXDelBacHN+xD2mzdZlroVhlsjZi5s0mhemBd+C", "hash": "01865ea95812388a93162b560e01c5680f12966492dfbad8a9a104e1e79f6665fc", "keys": { @@ -78,14 +78,14 @@ Example: | Property | Type | Description | | -------- | ------ | ---------------------------------------------------------- | -| **data** | String | Encrypted data in base64 | +| **encryptedData** | String | Encrypted data in base64 | | **hash** | String | Normalized Keccak256 hash of the message before encryption | Example: ```JSON { - "data": "mBVy2ENb0Edkego5c9QXcFxszKxe7iQVE22wUPHMbrC7bBm99S238BAyACa1TBDlI4SajbrWM+/MG8CkBoph4FLTvh4PsUjhnfazFI9BnMtIMhdqDAoxXUSHsvnwbEFhllqwhFCWn6pslLNu7X7UJSDgj7nQ0t1IHegBSV7ZRqdOYw3UoxAEAyVOoUwMhr/sitF2AlgMSvKas5YCD47YIm6rDNmzyBn9Ed/fAxNojMXcg386khrPs37P6Q==", + "encryptedData": "mBVy2ENb0Edkego5c9QXcFxszKxe7iQVE22wUPHMbrC7bBm99S238BAyACa1TBDlI4SajbrWM+/MG8CkBoph4FLTvh4PsUjhnfazFI9BnMtIMhdqDAoxXUSHsvnwbEFhllqwhFCWn6pslLNu7X7UJSDgj7nQ0t1IHegBSV7ZRqdOYw3UoxAEAyVOoUwMhr/sitF2AlgMSvKas5YCD47YIm6rDNmzyBn9Ed/fAxNojMXcg386khrPs37P6Q==", "hash": "018f94ee7e96fa65a761e8df9792af3f72fcf936f186fbb86881630f7d5333c8bb", } ``` diff --git a/packages/types/.vscode/settings.json b/packages/types/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/types/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index f809869249..caf87d9164 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -3,6 +3,44 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.11.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/types@0.9.0...@requestnetwork/types@0.11.0) (2020-01-16) + + +### Features + +* **advanced-logic:** add ERC20 proxy contract payment network ([#74](https://github.com/RequestNetwork/requestNetwork/issues/74)) ([031a374](https://github.com/RequestNetwork/requestNetwork/commit/031a3742d2dddc0324e75b7853287d252bf43c6c)) + + + +# 0.10.0 (2019-12-04) + + + + + +# [0.10.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/types@0.9.0...@requestnetwork/types@0.10.0) (2019-12-18) + + +### Features + +* **advanced-logic:** add ERC20 proxy contract payment network ([#74](https://github.com/RequestNetwork/requestNetwork/issues/74)) ([031a374](https://github.com/RequestNetwork/requestNetwork/commit/031a3742d2dddc0324e75b7853287d252bf43c6c)) + + + +# 0.10.0 (2019-12-04) + + + + + +## [0.9.1](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/types@0.9.0...@requestnetwork/types@0.9.1) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/types + + + + + # [0.9.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/types@0.8.0...@requestnetwork/types@0.9.0) (2019-11-20) diff --git a/packages/types/package.json b/packages/types/package.json index e79fe51f69..0881005c57 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/types", - "version": "0.9.0", + "version": "0.11.0", "publishConfig": { "access": "public" }, @@ -32,7 +32,7 @@ ], "scripts": { "build": "tsc -b", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", "prepare": "yarn run build" diff --git a/packages/types/src/extension-types.ts b/packages/types/src/extension-types.ts index 6c47941c93..ae29b09d15 100644 --- a/packages/types/src/extension-types.ts +++ b/packages/types/src/extension-types.ts @@ -1,11 +1,11 @@ import * as ContentData from './extensions/content-data-types'; import * as PnAddressBased from './extensions/pn-any-address-based-types'; import * as PnAnyDeclarative from './extensions/pn-any-declarative-types'; -import * as PnEthInputData from './extensions/pn-eth-input-data-types'; +import * as PnReferenceBased from './extensions/pn-any-reference-based-types'; import * as Identity from './identity-types'; import * as RequestLogic from './request-logic-types'; -export { ContentData, PnAnyDeclarative, PnAddressBased, PnEthInputData }; +export { ContentData, PnAnyDeclarative, PnAddressBased, PnReferenceBased }; /** Extension interface is extended by the extensions implementation */ export interface IExtension { @@ -48,6 +48,7 @@ export enum ID { PAYMENT_NETWORK_BITCOIN_ADDRESS_BASED = 'pn-bitcoin-address-based', PAYMENT_NETWORK_TESTNET_BITCOIN_ADDRESS_BASED = 'pn-testnet-bitcoin-address-based', PAYMENT_NETWORK_ERC20_ADDRESS_BASED = 'pn-erc20-address-based', + PAYMENT_NETWORK_ERC20_PROXY_CONTRACT = 'pn-erc20-proxy-contract', PAYMENT_NETWORK_ETH_INPUT_DATA = 'pn-eth-input-data', PAYMENT_NETWORK_ANY_DECLARATIVE = 'pn-any-declarative', } diff --git a/packages/types/src/extensions/pn-eth-input-data-types.ts b/packages/types/src/extensions/pn-any-reference-based-types.ts similarity index 94% rename from packages/types/src/extensions/pn-eth-input-data-types.ts rename to packages/types/src/extensions/pn-any-reference-based-types.ts index e667765909..a88cf996cc 100644 --- a/packages/types/src/extensions/pn-eth-input-data-types.ts +++ b/packages/types/src/extensions/pn-any-reference-based-types.ts @@ -1,7 +1,7 @@ import * as Extension from '../extension-types'; /** Manager of the extension */ -export interface IEthInputData extends Extension.IExtension { +export interface IReferenceBased extends Extension.IExtension { createAddPaymentAddressAction: ( creationParameters: IAddPaymentAddressParameters, ) => Extension.IAction; diff --git a/packages/usage-examples/.vscode/settings.json b/packages/usage-examples/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/usage-examples/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/usage-examples/CHANGELOG.md b/packages/usage-examples/CHANGELOG.md index 7defa7afe4..9ac023123a 100644 --- a/packages/usage-examples/CHANGELOG.md +++ b/packages/usage-examples/CHANGELOG.md @@ -3,6 +3,44 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.5.3](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/usage-examples@0.5.0...@requestnetwork/usage-examples@0.5.3) (2020-01-16) + + +### Bug Fixes + +* backward compatibility issue + removing test failing for external reason ([#93](https://github.com/RequestNetwork/requestNetwork/issues/93)) ([9a405dc](https://github.com/RequestNetwork/requestNetwork/commit/9a405dcc66b36a9a4a4b885dea2cd50abaad2725)) + + + +# 0.10.0 (2019-12-04) + + + + + +## [0.5.2](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/usage-examples@0.5.0...@requestnetwork/usage-examples@0.5.2) (2019-12-18) + + +### Bug Fixes + +* backward compatibility issue + removing test failing for external reason ([#93](https://github.com/RequestNetwork/requestNetwork/issues/93)) ([9a405dc](https://github.com/RequestNetwork/requestNetwork/commit/9a405dcc66b36a9a4a4b885dea2cd50abaad2725)) + + + +# 0.10.0 (2019-12-04) + + + + + +## [0.5.1](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/usage-examples@0.5.0...@requestnetwork/usage-examples@0.5.1) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/usage-examples + + + + + # [0.5.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/usage-examples@0.4.4...@requestnetwork/usage-examples@0.5.0) (2019-11-20) diff --git a/packages/usage-examples/package.json b/packages/usage-examples/package.json index 8c355a8587..f69d591b28 100644 --- a/packages/usage-examples/package.json +++ b/packages/usage-examples/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/usage-examples", - "version": "0.5.0", + "version": "0.5.3", "private": true, "description": "Usage examples of Request Network.", "keywords": [ @@ -21,22 +21,22 @@ }, "scripts": { "build": "tsc -b", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", - "start": "ts-node src/request-client-js.ts && ts-node src/request-client-js-declarative-request.ts && ts-node src/request-client-js-erc20-request.ts && ts-node src/request-logic-clear-request.ts && ts-node src/request-logic-encrypted-request.ts", + "start": "ts-node src/request-client-js-declarative-request.ts && ts-node src/request-client-js-erc20-request.ts && ts-node src/request-logic-clear-request.ts && ts-node src/request-logic-encrypted-request.ts", "prepare": "yarn run build" }, "dependencies": { - "@requestnetwork/data-access": "0.5.2", - "@requestnetwork/epk-decryption": "0.3.3", - "@requestnetwork/epk-signature": "0.5.4", - "@requestnetwork/multi-format": "0.2.1", - "@requestnetwork/request-client.js": "0.9.0", - "@requestnetwork/request-logic": "0.8.0", - "@requestnetwork/transaction-manager": "0.8.1", - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0" + "@requestnetwork/data-access": "0.5.5", + "@requestnetwork/epk-decryption": "0.3.6", + "@requestnetwork/epk-signature": "0.5.7", + "@requestnetwork/multi-format": "0.2.4", + "@requestnetwork/request-client.js": "0.12.0", + "@requestnetwork/request-logic": "0.8.3", + "@requestnetwork/transaction-manager": "0.8.4", + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0" }, "devDependencies": { "@typescript-eslint/parser": "1.2.0", @@ -45,7 +45,7 @@ "eslint-plugin-typescript": "0.14.0", "lint-staged": "8.1.3", "prettier": "1.16.4", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "tslint": "5.12.1", "typescript": "3.7.2" } diff --git a/packages/utils/.vscode/settings.json b/packages/utils/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/utils/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index 88eb0a56ec..aa911a4a8f 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -3,6 +3,47 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.10.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/utils@0.7.0...@requestnetwork/utils@0.10.0) (2020-01-16) + + + +# 0.10.0 (2019-12-04) + + +### Features + +* add ETH paymentNetwork to request-client ([#617](https://github.com/RequestNetwork/requestNetwork/issues/617)) ([84ed64e](https://github.com/RequestNetwork/requestNetwork/commit/84ed64ebf96a296155dc2d4d5e6c538344fb881b)) + + + + + +# [0.9.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/utils@0.7.0...@requestnetwork/utils@0.9.0) (2019-12-18) + + + +# 0.10.0 (2019-12-04) + + +### Features + +* add ETH paymentNetwork to request-client ([#617](https://github.com/RequestNetwork/requestNetwork/issues/617)) ([84ed64e](https://github.com/RequestNetwork/requestNetwork/commit/84ed64ebf96a296155dc2d4d5e6c538344fb881b)) + + + + + +# [0.8.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/utils@0.7.0...@requestnetwork/utils@0.8.0) (2019-12-04) + + +### Features + +* add ETH paymentNetwork to request-client ([#617](https://github.com/RequestNetwork/requestNetwork/issues/617)) ([84ed64e](https://github.com/RequestNetwork/requestNetwork/commit/84ed64ebf96a296155dc2d4d5e6c538344fb881b)) + + + + + # [0.7.0](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/utils@0.6.2...@requestnetwork/utils@0.7.0) (2019-11-20) diff --git a/packages/utils/package.json b/packages/utils/package.json index d448623659..e066c82133 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/utils", - "version": "0.7.0", + "version": "0.10.0", "publishConfig": { "access": "public" }, @@ -32,22 +32,23 @@ ], "scripts": { "build": "tsc -b", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", "prepare": "yarn run build", - "test": "nyc mocha --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", - "test:watch": "nyc mocha --watch --watch-extensions ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"" + "test": "nyc mocha --extension ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", + "test:watch": "yarn test --watch" }, "dependencies": { - "@requestnetwork/types": "0.9.0", + "@requestnetwork/types": "0.11.0", "bn.js": "4.11.8", "eth-crypto": "1.5.0" }, "devDependencies": { "@types/bn.js": "4.11.5", "@types/chai": "4.1.7", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", + "@types/sinon": "7.5.0", "@typescript-eslint/parser": "1.2.0", "chai": "4.2.0", "chai-as-promised": "7.1.1", @@ -56,11 +57,11 @@ "eslint-plugin-spellcheck": "0.0.11", "eslint-plugin-typescript": "0.14.0", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "nyc": "13.2.0", "prettier": "1.16.4", "shx": "0.3.2", - "sinon": "7.3.2", + "sinon": "7.5.0", "source-map-support": "0.5.13", "tslint": "5.12.1", "typescript": "3.7.2" diff --git a/packages/utils/src/crypto.ts b/packages/utils/src/crypto.ts index 4de61cddae..b352382d1b 100644 --- a/packages/utils/src/crypto.ts +++ b/packages/utils/src/crypto.ts @@ -11,6 +11,7 @@ export default { CryptoWrapper, EcUtils, generate32BufferKey, + generate8randomBytes, keccak256Hash, normalize, normalizeKeccak256Hash, @@ -67,3 +68,28 @@ function keccak256Hash(data: string): string { async function generate32BufferKey(): Promise { return (await CryptoWrapper.random32Bytes()).toString('base64'); } + +// eslint-disable-next-line spellcheck/spell-checker +/** + * Generate 8 random bytes and return as a hexadecimal string. + * Used for salt in ETH input data. + * Example: 'ea3bc7caf64110ca' + * + * @returns a string of 8 random bytes + */ +function generate8randomBytes(): string { + const base16 = 16; + + const generate4randomBytes = (): string => { + // A 4 byte random integer + const randomInteger = Math.floor(Math.random() * Math.pow(2, 4 * 8)); + + // Convert to hexadecimal and padded with 0 + return randomInteger.toString(base16).padStart(8, '0'); + }; + + // Do it in 2 passes because an integer doesn't have enough bits + const high = generate4randomBytes(); + const low = generate4randomBytes(); + return high + low; +} diff --git a/packages/utils/src/random.ts b/packages/utils/src/random.ts deleted file mode 100644 index 0f038f3700..0000000000 --- a/packages/utils/src/random.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * A collection of functions about randomness generation - */ -export default { - generate8randomBytes, -}; - -// eslint-disable-next-line spellcheck/spell-checker -/** - * Generate 8 random bytes and return as a hexadecimal string. - * Used for salt in ETH input data. - * Example: 'ea3bc7caf64110ca' - * - * @returns a string of 8 random bytes - */ -function generate8randomBytes(): string { - const base16 = 16; - - const generate4randomBytes = (): string => { - // A 4 byte random integer - const randomInteger = Math.floor(Math.random() * Math.pow(2, 4 * 8)); - - // Convert to hexadecimal and padded with 0 - return randomInteger.toString(base16).padStart(8, '0'); - }; - - // Do it in 2 passes because an integer doesn't have enough bits - const high = generate4randomBytes(); - const low = generate4randomBytes(); - return high + low; -} diff --git a/packages/utils/test/crypto.test.ts b/packages/utils/test/crypto.test.ts index 8f8308fdbd..5a17a3db23 100644 --- a/packages/utils/test/crypto.test.ts +++ b/packages/utils/test/crypto.test.ts @@ -107,4 +107,31 @@ describe('Utils.crypto', () => { const randomKey = await crypto.generate32BufferKey(); expect(Buffer.from(randomKey, 'base64').length, 'random32Bytes() error').to.be.equal(32); }); + + /* tslint:disable:no-unused-expression */ + /* tslint:disable:no-magic-numbers */ + describe('generate8randomBytes', () => { + it('generates a 16 charaters long string', () => { + // Do it 20 times because it's random. It's ok, it takes a few milliseconds + for (let i = 0; i < 100; i++) { + expect(crypto.generate8randomBytes().length).to.be.equal(16); + } + }); + + it('generates a 16 charater of hexademical number', () => { + // Regex for "at least 16 hexadecimal numbers". Used to validate the salt + const eightHexRegex = /[0-9a-f]{16}/; + + // Do it 20 times because it's random. It's ok, it takes a few milliseconds + for (let i = 0; i < 100; i++) { + expect(eightHexRegex.test(crypto.generate8randomBytes())).to.be.true; + } + }); + + it('generates unique strings', () => { + const first = crypto.generate8randomBytes(); + const second = crypto.generate8randomBytes(); + expect(first).to.not.equal(second); + }); + }); }); diff --git a/packages/utils/test/encryption.test.ts b/packages/utils/test/encryption.test.ts index d2b330f683..fc469660a5 100644 --- a/packages/utils/test/encryption.test.ts +++ b/packages/utils/test/encryption.test.ts @@ -1,8 +1,11 @@ -import * as chai from 'chai'; import 'mocha'; -const chaiAsPromised = require('chai-as-promised'); +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; +import * as spies from 'chai-as-promised'; + chai.use(chaiAsPromised); +chai.use(spies); const expect = chai.expect; import { EncryptionTypes, IdentityTypes } from '@requestnetwork/types'; @@ -48,17 +51,14 @@ describe('Encryption', () => { ); }); - it('cannot getIdentityFromEncryptionParams with encryption method not supported', () => { - try { - const params: any = { - method: 'notECIES', - publicKey: otherIdRaw.publicKey, - }; - Encryption.getIdentityFromEncryptionParams(params); - expect(false, 'exception not thrown').to.be.true; - } catch (e) { - expect(e.message, 'exception not right').to.equal('encryptionParams.method not supported'); - } + it('cannot getIdentityFromEncryptionParams with encryption method not supported', async () => { + const params: any = { + method: 'notECIES', + publicKey: otherIdRaw.publicKey, + }; + expect(() => Encryption.getIdentityFromEncryptionParams(params)).to.be.throw( + 'encryptionParams.method not supported', + ); }); }); diff --git a/packages/utils/test/random.ts b/packages/utils/test/random.ts deleted file mode 100644 index e711a257ef..0000000000 --- a/packages/utils/test/random.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { expect } from 'chai'; -import 'mocha'; - -import Random from '../src/random'; - -// Regex for "at least 16 hexadecimal numbers". Used to validate the salt -const eightHexRegex = /[0-9a-f]{16}/; - -/* tslint:disable:no-unused-expression */ -/* tslint:disable:no-magic-numbers */ -describe('random/generate8randomBytes', () => { - it('generates a 16 charaters long string', () => { - // Do it 20 times because it's random. It's ok, it takes a few milliseconds - for (let i = 0; i < 100; i++) { - expect(Random.generate8randomBytes().length).to.be.equal(16); - } - }); - - it('generates a 16 charater of hexademical number', () => { - // Do it 20 times because it's random. It's ok, it takes a few milliseconds - for (let i = 0; i < 100; i++) { - expect(eightHexRegex.test(Random.generate8randomBytes())).to.be.true; - } - }); - - it('generates unique strings', () => { - const first = Random.generate8randomBytes(); - const second = Random.generate8randomBytes(); - expect(first).to.not.equal(second); - }); -}); diff --git a/packages/utils/test/signature.test.ts b/packages/utils/test/signature.test.ts index e9802d759f..96bb4efa28 100644 --- a/packages/utils/test/signature.test.ts +++ b/packages/utils/test/signature.test.ts @@ -44,21 +44,18 @@ describe('Signature', () => { }); it('cannot getIdentityFromSignatureParams with signature method not supported', () => { - try { - const params: any = { - method: 'notECDSA', - privateKey: otherIdRaw.privateKey, - }; - Signature.getIdentityFromSignatureParams(params); - expect(false, 'exception not thrown').to.be.true; - } catch (e) { - expect(e.message, 'exception not right').to.equal('signatureParams.method not supported'); - } + const params: any = { + method: 'notECDSA', + privateKey: otherIdRaw.privateKey, + }; + expect(() => Signature.getIdentityFromSignatureParams(params)).to.throw( + 'signatureParams.method not supported', + ); }); }); describe('sign', () => { - it('can sign()', () => { + it('can sign() with ECDSA', () => { const signature = Signature.sign(data, { method: SignatureTypes.METHOD.ECDSA, privateKey: otherIdRaw.privateKey, @@ -73,6 +70,21 @@ describe('Signature', () => { }); }); + it('can sign() with ECDSA_ETHEREUM', () => { + const signature = Signature.sign(data, { + method: SignatureTypes.METHOD.ECDSA_ETHEREUM, + privateKey: otherIdRaw.privateKey, + }); + expect(signature, 'sign() error').to.be.deep.equal({ + data, + signature: { + method: SignatureTypes.METHOD.ECDSA_ETHEREUM, + value: + '0x3fbc7ed9dfa003067f646749d4223def2a69df70371d4f15ec001bc1491cdee40558de1f31fdc7cc5d805a5c4080b54cda3430b29ab14f04e17a5b23fcd39b391b', + }, + }); + }); + it('can sign() with different case', () => { const signature = Signature.sign(dataDiffCase, { method: SignatureTypes.METHOD.ECDSA, @@ -89,21 +101,18 @@ describe('Signature', () => { }); it('cannot sign with signature method not supported', () => { - try { - const params: any = { - method: 'notECDSA', - privateKey: otherIdRaw.privateKey, - }; - Signature.sign(Crypto.normalizeKeccak256Hash(data), params); - expect(false, 'exception not thrown').to.be.true; - } catch (e) { - expect(e.message, 'exception not right').to.equal('signatureParams.method not supported'); - } + const params: any = { + method: 'notECDSA', + privateKey: otherIdRaw.privateKey, + }; + expect(() => Signature.sign(Crypto.normalizeKeccak256Hash(data), params)).to.throw( + 'signatureParams.method not supported', + ); }); }); describe('recover', () => { - it('can recover()', () => { + it('can recover() ECDSA signature', () => { const id = Signature.recover({ data, signature: { @@ -115,6 +124,19 @@ describe('Signature', () => { expect(id, 'recover() error').to.be.deep.equal(otherIdRaw.identity); }); + it('can recover() ECDSA_ETHEREUM signature', () => { + const id = Signature.recover({ + data, + signature: { + method: SignatureTypes.METHOD.ECDSA_ETHEREUM, + value: + '0x3fbc7ed9dfa003067f646749d4223def2a69df70371d4f15ec001bc1491cdee40558de1f31fdc7cc5d805a5c4080b54cda3430b29ab14f04e17a5b23fcd39b391b', + }, + }); + expect(id.value, 'recover() error').to.be.deep.equal(otherIdRaw.identity.value.toLowerCase()); + expect(id.type, 'recover() error').to.be.deep.equal(otherIdRaw.identity.type); + }); + it('can recover() with different case', () => { const id = Signature.recover({ data: dataDiffCase, @@ -128,16 +150,13 @@ describe('Signature', () => { }); it('cannot recover with signature method not supported', () => { - try { - const params: any = { - method: 'notECDSA', - value: '0x00000000000000000000', - }; - Signature.recover({ data, signature: params }); - expect(false, 'exception not thrown').to.be.true; - } catch (e) { - expect(e.message, 'exception not right').to.equal('signatureParams.method not supported'); - } + const params: any = { + method: 'notECDSA', + value: '0x00000000000000000000', + }; + expect(() => Signature.recover({ data, signature: params })).to.throw( + 'signatureParams.method not supported', + ); }); }); }); diff --git a/packages/utils/test/utils.test.ts b/packages/utils/test/utils.test.ts index 19e404bdd2..b8be2be982 100644 --- a/packages/utils/test/utils.test.ts +++ b/packages/utils/test/utils.test.ts @@ -87,10 +87,15 @@ describe('Utils', () => { }); it('getCurrentTimestampInSecond()', () => { + sinon.useFakeTimers(Date.now()); + const time = Math.floor(Date.now() / 1000); expect(Utils.getCurrentTimestampInSecond(), 'getCurrentTimestampInSecond() error').to.be.equal( time, ); + + // Cleanup + sinon.restore(); }); describe('unique', () => { diff --git a/packages/web3-signature/.vscode/settings.json b/packages/web3-signature/.vscode/settings.json new file mode 100644 index 0000000000..1a7d6049b8 --- /dev/null +++ b/packages/web3-signature/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "mochaExplorer.files": "**/test/**/*.ts", + "mochaExplorer.require": "ts-node/register", + "mochaExplorer.cwd": "../.." +} \ No newline at end of file diff --git a/packages/web3-signature/CHANGELOG.md b/packages/web3-signature/CHANGELOG.md index c839db3ba9..9537a458b5 100644 --- a/packages/web3-signature/CHANGELOG.md +++ b/packages/web3-signature/CHANGELOG.md @@ -3,6 +3,38 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.4.8](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/web3-signature@0.4.5...@requestnetwork/web3-signature@0.4.8) (2020-01-16) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/web3-signature + + + + + +## [0.4.7](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/web3-signature@0.4.5...@requestnetwork/web3-signature@0.4.7) (2019-12-18) + + + +# 0.10.0 (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/web3-signature + + + + + +## [0.4.6](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/web3-signature@0.4.5...@requestnetwork/web3-signature@0.4.6) (2019-12-04) + +**Note:** Version bump only for package @requestnetwork/web3-signature + + + + + ## [0.4.5](https://github.com/RequestNetwork/requestNetwork/compare/@requestnetwork/web3-signature@0.4.4...@requestnetwork/web3-signature@0.4.5) (2019-11-20) **Note:** Version bump only for package @requestnetwork/web3-signature diff --git a/packages/web3-signature/package.json b/packages/web3-signature/package.json index bb8d5a66e5..88c28ae021 100644 --- a/packages/web3-signature/package.json +++ b/packages/web3-signature/package.json @@ -1,6 +1,6 @@ { "name": "@requestnetwork/web3-signature", - "version": "0.4.5", + "version": "0.4.8", "publishConfig": { "access": "public" }, @@ -34,21 +34,21 @@ "build": "run-s build:commonjs build:umd", "build:commonjs": "tsc -b", "build:umd": "webpack", - "clean": "shx rm -rf dist", + "clean": "shx rm -rf dist tsconfig.tsbuildinfo", "lint": "tslint --project . && eslint \"src/**/*.ts\"", "lint-staged": "lint-staged", - "test": "nyc mocha --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", - "test:watch": "nyc mocha --watch --watch-extensions ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"" + "test": "nyc mocha --extension ts --require ts-node/register --require source-map-support/register \"test/**/*.ts\"", + "test:watch": "yarn test --watch" }, "dependencies": { - "@requestnetwork/types": "0.9.0", - "@requestnetwork/utils": "0.7.0", + "@requestnetwork/types": "0.11.0", + "@requestnetwork/utils": "0.10.0", "web3-eth": "1.0.0-beta.37" }, "devDependencies": { "@types/chai": "4.1.7", "@types/chai-spies": "1.0.0", - "@types/mocha": "5.2.6", + "@types/mocha": "5.2.7", "@typescript-eslint/parser": "1.2.0", "amd-loader": "0.0.8", "awesome-typescript-loader": "5.2.1", @@ -60,18 +60,18 @@ "eslint-plugin-spellcheck": "0.0.11", "eslint-plugin-typescript": "0.14.0", "lint-staged": "8.1.3", - "mocha": "5.2.0", + "mocha": "6.2.2", "npm-run-all": "4.1.5", "nyc": "13.2.0", "prettier": "1.16.4", "shx": "0.3.2", "source-map-support": "0.5.13", "terser-webpack-plugin": "1.3.0", - "ts-node": "8.5.2", + "ts-node": "8.5.4", "tslint": "5.12.1", "typescript": "3.7.2", "webpack": "4.38.0", "webpack-bundle-analyzer": "3.3.2", - "webpack-cli": "3.3.6" + "webpack-cli": "3.3.10" } } diff --git a/yarn.lock b/yarn.lock index effa8c0330..c613c954df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,38 +9,38 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/generator@^7.4.0", "@babel/generator@^7.7.2": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.2.tgz#2f4852d04131a5e17ea4f6645488b5da66ebf3af" - integrity sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ== +"@babel/generator@^7.4.0", "@babel/generator@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369" + integrity sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg== dependencies: - "@babel/types" "^7.7.2" + "@babel/types" "^7.7.4" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" -"@babel/helper-function-name@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz#44a5ad151cfff8ed2599c91682dda2ec2c8430a3" - integrity sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q== +"@babel/helper-function-name@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" + integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ== dependencies: - "@babel/helper-get-function-arity" "^7.7.0" - "@babel/template" "^7.7.0" - "@babel/types" "^7.7.0" + "@babel/helper-get-function-arity" "^7.7.4" + "@babel/template" "^7.7.4" + "@babel/types" "^7.7.4" -"@babel/helper-get-function-arity@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz#c604886bc97287a1d1398092bc666bc3d7d7aa2d" - integrity sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw== +"@babel/helper-get-function-arity@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" + integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA== dependencies: - "@babel/types" "^7.7.0" + "@babel/types" "^7.7.4" -"@babel/helper-split-export-declaration@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz#1365e74ea6c614deeb56ebffabd71006a0eb2300" - integrity sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA== +"@babel/helper-split-export-declaration@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" + integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug== dependencies: - "@babel/types" "^7.7.0" + "@babel/types" "^7.7.4" "@babel/highlight@^7.0.0": version "7.5.0" @@ -51,10 +51,10 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.7.2": - version "7.7.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.3.tgz#5fad457c2529de476a248f75b0f090b3060af043" - integrity sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A== +"@babel/parser@^7.4.3", "@babel/parser@^7.7.4": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71" + integrity sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig== "@babel/runtime@7.0.0": version "7.0.0" @@ -64,40 +64,40 @@ regenerator-runtime "^0.12.0" "@babel/runtime@^7.3.1": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.2.tgz#111a78002a5c25fc8e3361bedc9529c696b85a6a" - integrity sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw== + version "7.7.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.6.tgz#d18c511121aff1b4f2cd1d452f1bac9601dd830f" + integrity sha512-BWAJxpNVa0QlE5gZdWjSxXtemZyZ9RmrmVozxt3NUXeZhVIJ5ANyqmMc0JDrivBZyxUuQvFxlvH4OWWOogGfUw== dependencies: regenerator-runtime "^0.13.2" -"@babel/template@^7.4.0", "@babel/template@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.0.tgz#4fadc1b8e734d97f56de39c77de76f2562e597d0" - integrity sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ== +"@babel/template@^7.4.0", "@babel/template@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" + integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.0" - "@babel/types" "^7.7.0" + "@babel/parser" "^7.7.4" + "@babel/types" "^7.7.4" "@babel/traverse@^7.4.3": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.2.tgz#ef0a65e07a2f3c550967366b3d9b62a2dcbeae09" - integrity sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw== + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" + integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.2" - "@babel/helper-function-name" "^7.7.0" - "@babel/helper-split-export-declaration" "^7.7.0" - "@babel/parser" "^7.7.2" - "@babel/types" "^7.7.2" + "@babel/generator" "^7.7.4" + "@babel/helper-function-name" "^7.7.4" + "@babel/helper-split-export-declaration" "^7.7.4" + "@babel/parser" "^7.7.4" + "@babel/types" "^7.7.4" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.4.0", "@babel/types@^7.7.0", "@babel/types@^7.7.2": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7" - integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA== +"@babel/types@^7.4.0", "@babel/types@^7.7.4": + version "7.7.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" + integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA== dependencies: esutils "^2.0.2" lodash "^4.17.13" @@ -1002,9 +1002,9 @@ universal-user-agent "^4.0.0" "@octokit/rest@^16.28.4": - version "16.35.0" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.35.0.tgz#7ccc1f802f407d5b8eb21768c6deca44e7b4c0d8" - integrity sha512-9ShFqYWo0CLoGYhA1FdtdykJuMzS/9H6vSbbQWDX4pWr4p9v+15MsH/wpd/3fIU+tSxylaNO48+PIHqOkBRx3w== + version "16.35.2" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.35.2.tgz#0098c9e2a895d4afb0fa6578479283553543143c" + integrity sha512-iijaNZpn9hBpUdh8YdXqNiWazmq4R1vCUsmxpBB0kCQ0asHZpCx+HNs22eiHuwYKRhO31ZSAGBJLi0c+3XHaKQ== dependencies: "@octokit/request" "^5.2.0" "@octokit/request-error" "^1.0.2" @@ -1020,9 +1020,9 @@ universal-user-agent "^4.0.0" "@octokit/types@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.0.1.tgz#0caf0364e010296265621593ac9a37f40ef75dad" - integrity sha512-YDYgV6nCzdGdOm7wy43Ce8SQ3M5DMKegB8E5sTB/1xrxOdo2yS/KgUgML2N2ZGD621mkbdrAglwTyA4NDOlFFA== + version "2.0.2" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.0.2.tgz#0888497f5a664e28b0449731d5e88e19b2a74f90" + integrity sha512-StASIL2lgT3TRjxv17z9pAqbnI7HGu9DrJlg3sEBFfCLaMEqp+O3IQPUF6EZtQ4xkAu2ml6kMBBCtGxjvmtmuQ== dependencies: "@types/node" ">= 8" @@ -1050,7 +1050,7 @@ dependencies: type-detect "4.0.8" -"@sinonjs/formatio@^3.1.0", "@sinonjs/formatio@^3.2.1": +"@sinonjs/formatio@^3.2.1": version "3.2.2" resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.2.2.tgz#771c60dfa75ea7f2d68e3b94c7e888a78781372c" integrity sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ== @@ -1058,7 +1058,7 @@ "@sinonjs/commons" "^1" "@sinonjs/samsam" "^3.1.0" -"@sinonjs/samsam@^3.0.2", "@sinonjs/samsam@^3.1.0", "@sinonjs/samsam@^3.3.1", "@sinonjs/samsam@^3.3.3": +"@sinonjs/samsam@^3.1.0", "@sinonjs/samsam@^3.3.3": version "3.3.3" resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.3.tgz#46682efd9967b259b81136b9f120fd54585feb4a" integrity sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ== @@ -1072,29 +1072,30 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== -"@stryker-mutator/api@^2.1.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@stryker-mutator/api/-/api-2.3.0.tgz#8f4010471f8cd22ceec8efe78429d39e7af12ccc" - integrity sha512-N+XlEZAxMq4GKWt8OOn7R+124ieCiicLG3heiX2JQXNjn7uTVDfI5rSGn0oPvpwYtgeV9x6F//vzniRGhsOWIQ== +"@stryker-mutator/api@^2.1.0", "@stryker-mutator/api@^2.3.0", "@stryker-mutator/api@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@stryker-mutator/api/-/api-2.4.0.tgz#9e710b6dde7f889d5c6d573f349bb622c57b9a57" + integrity sha512-VV12SWtoHKM8G2CSUHD7b8O6zJSygHjAju+e9qOjmrTaEgy8KUVO7OWuUNcRLpcRDVAlB2osuo3qndMstpPExg== dependencies: - mutation-testing-report-schema "^1.0.0" + mutation-testing-report-schema "^1.1.0" tslib "~1.10.0" -"@stryker-mutator/core@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@stryker-mutator/core/-/core-2.1.0.tgz#38b4a1fc4319d2d6f9e955688415d6c7a3c8da98" - integrity sha512-CucANfEfYKuc3gDPJlrMw0UElr8YD3LrrC/dGN9/GyGgPFdgb4zX9XHw0Q/deGQTk51h9BieuSMLqleVxP5UqQ== +"@stryker-mutator/core@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@stryker-mutator/core/-/core-2.4.0.tgz#533a2e42a2a6c9ada820a6ceb91b08285e7ccfaa" + integrity sha512-Z/PsUC/X2BOMJsbno9zWeNqx5sYeBYExtUQW2JL0niYNbs0xkhcU7S7UC2npjwGFOCrjjWzek5TQVGQtrlDhbw== dependencies: - "@stryker-mutator/api" "^2.1.0" - "@stryker-mutator/util" "^2.1.0" - chalk "~2.4.1" - commander "~3.0.1" + "@stryker-mutator/api" "^2.4.0" + "@stryker-mutator/util" "^2.4.0" + chalk "~3.0.0" + commander "~4.0.0" get-port "~5.0.0" glob "~7.1.2" inquirer "~7.0.0" istanbul-lib-instrument "~3.3.0" - lodash "~4.17.4" - log4js "~5.1.0" + lodash.flatmap "^4.5.0" + lodash.groupby "^4.6.0" + log4js "~6.1.0" mkdirp "~0.5.1" mutation-testing-metrics "^1.1.1" progress "~2.0.0" @@ -1104,7 +1105,7 @@ surrial "~1.0.0" tree-kill "~1.2.0" tslib "~1.10.0" - typed-inject "~2.0.0" + typed-inject "~2.1.1" typed-rest-client "~1.5.0" "@stryker-mutator/html-reporter@2.1.0": @@ -1135,21 +1136,21 @@ multimatch "~4.0.0" tslib "~1.10.0" -"@stryker-mutator/typescript@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@stryker-mutator/typescript/-/typescript-2.1.0.tgz#7ef27eaa01bf58648d1cfa37f2f09e486b3df281" - integrity sha512-ReD59cKIiWoKeh7ZdSD6dngs8i4OzUsjn2x1T+mSWK3rn9smc4FZ3X6wm3abweGOhABATzPBVrdTU/j7VWMyZw== +"@stryker-mutator/typescript@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@stryker-mutator/typescript/-/typescript-2.3.0.tgz#1f13fb63f5dc68a29ca0d1815dc8dafc36dca4b1" + integrity sha512-rDF005coMvCaCWHt3pxgXf5iySPvvR7NRpY5WtqVYWEoOpbX0nhxBm4+hHbbotbdd7sUsYySa9qAkhKeDtGW/A== dependencies: - "@stryker-mutator/api" "^2.1.0" - "@stryker-mutator/util" "^2.1.0" + "@stryker-mutator/api" "^2.3.0" + "@stryker-mutator/util" "^2.3.0" lodash.flatmap "~4.5.0" semver "~6.3.0" tslib "~1.10.0" -"@stryker-mutator/util@^2.1.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@stryker-mutator/util/-/util-2.3.0.tgz#854bba4444bdb49471ae5dd33ad6aa271bb46b6b" - integrity sha512-mQLkbHy6HmN+/qb1aR02TUProbhcYASDLrthHILZriwZshCnxgfwrEOOssXlOQR/QAPXjZCnSA+fKjJwpngQQA== +"@stryker-mutator/util@^2.1.0", "@stryker-mutator/util@^2.3.0", "@stryker-mutator/util@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@stryker-mutator/util/-/util-2.4.0.tgz#20e1e2f2388ae4e91f67f442224d479a539edf27" + integrity sha512-+pKsudzHy7r51S39bpo/2N4lmdnFb9qhF34My3Y5BtXWZEcKm+FELWkCAC4H8CmO/j0RgTLyfnQDoaw4MjdLgg== "@szmarczak/http-timer@^1.1.2": version "1.1.2" @@ -1203,15 +1204,20 @@ "@types/chai" "*" "@types/chai@*": - version "4.2.5" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.5.tgz#f8da153ebbe30babb0adc9a528b9ad32be3175a2" - integrity sha512-YvbLiIc0DbbhiANrfVObdkLEHJksQZVq0Uvfg550SRAKVYaEJy+V70j65BVe2WNp6E3HtKsUczeijHFCjba3og== + version "4.2.7" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.7.tgz#1c8c25cbf6e59ffa7d6b9652c78e547d9a41692d" + integrity sha512-luq8meHGYwvky0O7u0eQZdA7B4Wd9owUCqvbw2m3XCrCU8mplYOujMBbvyS547AxJkC+pGnd0Cm15eNxEUNU8g== "@types/chai@4.1.7": version "4.1.7" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.7.tgz#1b8e33b61a8c09cbe1f85133071baa0dbf9fa71a" integrity sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA== +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + "@types/connect@*": version "3.4.32" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28" @@ -1305,10 +1311,10 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/mocha@5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.6.tgz#b8622d50557dd155e9f2f634b7d68fd38de5e94b" - integrity sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw== +"@types/mocha@5.2.7": + version "5.2.7" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" + integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== "@types/node-fetch@2.1.4": version "2.1.4" @@ -1318,9 +1324,9 @@ "@types/node" "*" "@types/node@*", "@types/node@>= 8": - version "12.12.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.8.tgz#dab418655af39ce2fa99286a0bed21ef8072ac9d" - integrity sha512-XLla8N+iyfjvsa0KKV+BP/iGSoTmwxsu5Ci5sM33z9TjohF72DEz95iNvD6pPmemvbQgxAv/909G73gUn8QR7w== + version "12.12.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.18.tgz#8d16634797d63c2af5bc647ce879f8de20b56469" + integrity sha512-DBkZuIMFuAfjJHiunyRc+aNvmXYNwV1IPMgGKGlwCp6zh6MKrVtmvjSWK/axWcD25KJffkXgkfvFra8ndenXAw== "@types/node@10.12.21": version "10.12.21" @@ -1338,9 +1344,9 @@ integrity sha512-zkOxCS/fA+3SsdA+9Yun0iANxzhQRiNwTvJSr6N95JhuJ/x27z9G2URx1Jpt3zYFfCGUXZGL5UDxt5eyLE7wgw== "@types/node@^10.3.2": - version "10.17.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.5.tgz#c1920150f7b90708a7d0f3add12a06bc9123c055" - integrity sha512-RElZIr/7JreF1eY6oD5RF3kpmdcreuQPjg5ri4oQ5g9sq7YWU8HkfB3eH8GwAwxf5OaCh0VPi7r4N/yoTGelrA== + version "10.17.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.9.tgz#4f251a1ed77ac7ef09d456247d67fc8173f6b9da" + integrity sha512-+6VygF9LbG7Gaqeog2G7u1+RUcmo0q1rI+2ZxdIg2fAUngk5Vz9fOCHXdloNUOHEPd1EuuOpL5O0CdgN9Fx5UQ== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -1365,10 +1371,10 @@ "@types/express-serve-static-core" "*" "@types/mime" "*" -"@types/sinon@7.0.5": - version "7.0.5" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-7.0.5.tgz#f7dea19400c193a3b36a804a7f1f4b26dacf452b" - integrity sha512-4DShbH857bZVOY4tPi1RQJNrLcf89hEtU0klZ9aYTMbtt95Ok4XdPqqcbtGOHIbAHMLSzQP8Uw/6qtBBqyloww== +"@types/sinon@7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-7.5.0.tgz#f5a10c27175465a0b001b68d8b9f761582967cc6" + integrity sha512-NyzhuSBy97B/zE58cDw4NyGvByQbAHNP9069KVSgnXt/sc0T6MFRh0InKAeBVHJWdSXG1S3+PxgVIgKo9mTHbw== "@types/strip-bom@^3.0.0": version "3.0.0" @@ -1643,9 +1649,9 @@ acorn@^5.0.0: integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== acorn@^6.0.7, acorn@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" - integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== + version "6.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" + integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== aes-js@3.0.0: version "3.0.0" @@ -1673,6 +1679,14 @@ agentkeepalive@^3.4.1: dependencies: humanize-ms "^1.2.1" +aggregate-error@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" + integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv-errors@^1.0.0, ajv-errors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" @@ -1723,6 +1737,11 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + ansi-colors@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" @@ -1781,6 +1800,14 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.0.tgz#5681f0dcf7ae5880a7841d8831c4724ed9cc0172" + integrity sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + ansi-wrap@0.1.0, ansi-wrap@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" @@ -1868,9 +1895,9 @@ are-we-there-yet@~1.1.2: readable-stream "^2.0.6" arg@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.1.tgz#485f8e7c390ce4c5f78257dbea80d4be11feda4c" - integrity sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw== + version "4.1.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.2.tgz#e70c90579e02c63d80e3ad4e31d8bfdb8bd50064" + integrity sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg== argparse@^1.0.7: version "1.0.10" @@ -2086,9 +2113,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" + integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== axios-mock-adapter@1.16.0: version "1.16.0" @@ -2097,10 +2124,10 @@ axios-mock-adapter@1.16.0: dependencies: deep-equal "^1.0.1" -axios@0.18.1: - version "0.18.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3" - integrity sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g== +axios@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8" + integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ== dependencies: follow-redirects "1.5.10" is-buffer "^2.0.2" @@ -2266,9 +2293,9 @@ bluebird@3.5.5: integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== bluebird@^3.5.0, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5: - version "3.7.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" - integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg== + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== bn.js@4.11.6: version "4.11.6" @@ -2341,7 +2368,7 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" -brfs@^1.3.0, brfs@^1.4.0: +brfs@^1.4.0: version "1.6.1" resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.6.1.tgz#b78ce2336d818e25eea04a0947cba6d4fb8849c3" integrity sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ== @@ -2740,7 +2767,7 @@ chai@4.2.0, chai@^4.2.0: pathval "^1.1.0" type-detect "^4.0.5" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2, chalk@~2.4.1: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1, 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== @@ -2760,6 +2787,14 @@ chalk@^1.0.0, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -2823,9 +2858,9 @@ chokidar@^2.0.2, chokidar@^2.0.4: fsevents "^1.2.7" chokidar@^3.0.2: - version "3.3.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" - integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== + version "3.3.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450" + integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -2833,9 +2868,9 @@ chokidar@^3.0.2: is-binary-path "~2.1.0" is-glob "~4.0.1" normalize-path "~3.0.0" - readdirp "~3.2.0" + readdirp "~3.3.0" optionalDependencies: - fsevents "~2.1.1" + fsevents "~2.1.2" chownr@^1.1.1, chownr@^1.1.2: version "1.1.3" @@ -2877,6 +2912,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + cli-cursor@^2.0.0, cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -2964,11 +3004,23 @@ color-convert@^1.9.0: dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + color-support@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" @@ -3016,10 +3068,10 @@ commander@~2.8.1: dependencies: graceful-readlink ">= 1.0.0" -commander@~3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" - integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== +commander@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.0.1.tgz#b67622721785993182e807f4883633e6401ba53c" + integrity sha512-IPF4ouhCP+qdlcmCedhxX4xiGBPyigb8v5NeUp+0LyhwLgxMqyp3S0vl7TAPfS/hiP7FC3caI/PB9lTmP8r1NA== commondir@^1.0.1: version "1.0.1" @@ -3232,9 +3284,9 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^2.4.0, core-js@^2.5.0: - version "2.6.10" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f" - integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA== + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -3348,6 +3400,15 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" + integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypto-browserify@3.12.0, crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -3437,6 +3498,11 @@ date-format@^2.1.0: resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.1.0.tgz#31d5b5ea211cf5fd764cd38baf9d033df7e125cf" integrity sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA== +date-format@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/date-format/-/date-format-3.0.0.tgz#eb8780365c7d2b1511078fb491e6479780f3ad95" + integrity sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w== + dateformat@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" @@ -3469,7 +3535,7 @@ debug@3.1.0, debug@=3.1.0: dependencies: ms "2.0.0" -debug@^3.1.0, debug@^3.2.6: +debug@3.2.6, debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -3590,11 +3656,6 @@ deep-equal@^1.0.0, deep-equal@^1.0.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -3615,9 +3676,9 @@ defaults@^1.0.3: clone "^1.0.2" defer-to-connect@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.0.tgz#b41bd7efa8508cef13f8456975f7a278c72833fd" - integrity sha512-WE2sZoctWm/v4smfCAdjYbrfS55JiMRdlY9ZubFhsYbteCK9+BvAx4YV7nPjYM6ZnX5BcoVKwfmyx9sIFTgQMQ== + version "1.1.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.1.tgz#88ae694b93f67b81815a2c8c769aef6574ac8f2f" + integrity sha512-J7thop4u3mRTkYRQ+Vpfwy2G5Ehoy82I14+14W4YMDLKdWloI9gSzRbV30s/NckQGVJtPkWNcW4oMAUigTdqiQ== define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" @@ -3660,6 +3721,20 @@ del@^3.0.0: pify "^3.0.0" rimraf "^2.2.8" +del@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/del/-/del-5.1.0.tgz#d9487c94e367410e6eff2925ee58c0c84a75b3a7" + integrity sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA== + dependencies: + globby "^10.0.1" + graceful-fs "^4.2.2" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.1" + p-map "^3.0.0" + rimraf "^3.0.0" + slash "^3.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -3703,11 +3778,6 @@ detect-indent@^5.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -3853,9 +3923,9 @@ dot-prop@^4.2.0: is-obj "^1.0.0" dot@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/dot/-/dot-1.1.2.tgz#c7377019fc4e550798928b2b9afeb66abfa1f2f9" - integrity sha1-xzdwGfxOVQeYkosrmv62ar+h8vk= + version "1.1.3" + resolved "https://registry.yarnpkg.com/dot/-/dot-1.1.3.tgz#351360e00a748bce9a1f8f27c00c394a7e4e1e9f" + integrity sha512-/nt74Rm+PcfnirXGEdhZleTwGC2LMnuKTeeTIlI82xb5loBBoXNYzr2ezCroPSMtilK8EZIfcNZwOcHN+ib1Lg== dotenv@8.0.0: version "8.0.0" @@ -3941,9 +4011,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= ejs@^2.6.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.2.tgz#749037c4c09bd57626a6140afbe6b7e650661614" - integrity sha512-rHGwtpl67oih3xAHbZlpw5rQAt+YV1mSCu2fUZ9XNrfaGEhom7E+AUiMci+ByP4aSfuAWx7hE0BPuJLMrpXwOw== + version "2.7.4" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" + integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== elegant-spinner@^1.0.1: version "1.0.1" @@ -3960,7 +4030,7 @@ elliptic@6.3.3: hash.js "^1.0.0" inherits "^2.0.1" -elliptic@6.5.1, elliptic@^6.0.0, elliptic@^6.4.0, elliptic@^6.4.1: +elliptic@6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.1.tgz#c380f5f909bf1b9b4428d028cd18d3b0efd6b52b" integrity sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg== @@ -3973,6 +4043,19 @@ elliptic@6.5.1, elliptic@^6.0.0, elliptic@^6.4.0, elliptic@^6.4.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +elliptic@^6.0.0, elliptic@^6.4.0, elliptic@^6.4.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" + integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw== + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -4035,10 +4118,10 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== -env-paths@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" - integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA= +env-paths@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" + integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== eol@^0.9.1: version "0.9.1" @@ -4064,23 +4147,24 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.4.3, es-abstract@^1.5.1: - version "1.16.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" - integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== +es-abstract@^1.17.0-next.1: + version "1.17.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0-next.1.tgz#94acc93e20b05a6e96dacb5ab2f1cb3a81fc2172" + integrity sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw== dependencies: - es-to-primitive "^1.2.0" + es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.0" + has-symbols "^1.0.1" is-callable "^1.1.4" is-regex "^1.0.4" - object-inspect "^1.6.0" + object-inspect "^1.7.0" object-keys "^1.1.1" + object.assign "^4.1.0" string.prototype.trimleft "^2.1.0" string.prototype.trimright "^2.1.0" -es-to-primitive@^1.2.0: +es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== @@ -4090,12 +4174,12 @@ es-to-primitive@^1.2.0: is-symbol "^1.0.2" es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@~0.10.14: - version "0.10.52" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.52.tgz#bb21777e919a04263736ded120a9d665f10ea63f" - integrity sha512-bWCbE9fbpYQY4CU6hJbJ1vSz70EClMlDgJ7BmwI+zEJhxrwjesZRPglGJlsZhu0334U3hI+gaspwksH9IGD6ag== + version "0.10.53" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== dependencies: es6-iterator "~2.0.3" - es6-symbol "~3.1.2" + es6-symbol "~3.1.3" next-tick "~1.0.0" es6-error@^4.0.1: @@ -4160,7 +4244,7 @@ es6-symbol@3.1.1: d "1" es5-ext "~0.10.14" -es6-symbol@^3.1.1, es6-symbol@~3.1.1, es6-symbol@~3.1.2: +es6-symbol@^3.1.1, es6-symbol@~3.1.1, es6-symbol@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== @@ -4190,7 +4274,7 @@ escodegen@1.8.x: optionalDependencies: source-map "~0.2.0" -escodegen@^1.8.1: +escodegen@^1.11.1: version "1.12.0" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541" integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg== @@ -4408,7 +4492,7 @@ eth-ens-namehash@2.0.8: idna-uts46-hx "^2.3.1" js-sha3 "^0.5.7" -eth-lib@0.1.27, eth-lib@^0.1.26: +eth-lib@0.1.27: version "0.1.27" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" integrity sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA== @@ -4439,10 +4523,22 @@ eth-lib@0.2.8: elliptic "^6.4.0" xhr-request-promise "^0.1.2" +eth-lib@^0.1.26: + version "0.1.29" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" + integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + nano-json-stream-parser "^0.1.2" + servify "^0.1.12" + ws "^3.0.0" + xhr-request-promise "^0.1.2" + ethereumjs-common@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.4.0.tgz#a940685f88f3c2587e4061630fe720b089c965b8" - integrity sha512-ser2SAplX/YI5W2AnzU8wmSjKRy4KQd4uxInJ36BzjS3m18E/B9QedPUIresZN1CSEQb/RgNQ2gN7C/XbpTafA== + version "1.5.0" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd" + integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== ethereumjs-tx@2.1.1: version "2.1.1" @@ -4637,6 +4733,21 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-2.1.0.tgz#e5d3ecd837d2a60ec50f3da78fd39767747bbe99" + integrity sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^3.0.0" + onetime "^5.1.0" + p-finally "^2.0.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" @@ -4708,9 +4819,9 @@ express@4.17.1, express@^4.14.0, express@^4.16.3: vary "~1.1.2" ext@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.2.0.tgz#8dd8d2dd21bcced3045be09621fa0cbf73908ba4" - integrity sha512-0ccUQK/9e3NreLFg6K6np8aPyRgwycx+oFGtfx1dSp7Wj00Ozw9r05FgBRlzjf2XBM7LAzwgLyDscRrtSU91hA== + version "1.4.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" + integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== dependencies: type "^2.0.0" @@ -4817,9 +4928,9 @@ fast-glob@^2.0.2, fast-glob@^2.2.6: micromatch "^3.1.10" fast-glob@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.0.tgz#77375a7e3e6f6fc9b18f061cddd28b8d1eec75ae" - integrity sha512-TrUz3THiq2Vy3bjfQUB2wNyPdGBeGmdjbzzBLhfHN4YFurYptCKwGq/TfiRavbGywFRzY6U2CdmQ1zmsY5yYaw== + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.1.tgz#87ee30e9e9f3eb40d6f254a7997655da753d7c82" + integrity sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -4828,9 +4939,9 @@ fast-glob@^3.0.3: micromatch "^4.0.2" fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + 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: version "2.0.6" @@ -5005,6 +5116,13 @@ find-root@^1.0.0: resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -5020,13 +5138,6 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - find-up@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -5065,6 +5176,13 @@ flat-cache@^1.2.1: rimraf "~2.6.2" write "^0.2.1" +flat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== + dependencies: + is-buffer "~2.0.3" + flatted@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" @@ -5090,7 +5208,7 @@ follow-redirects@1.5.10: dependencies: debug "=3.1.0" -fontkit@^1.0.0: +fontkit@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/fontkit/-/fontkit-1.8.0.tgz#deb9351619e90ddc91707b6156a9f14c8ab11554" integrity sha512-EFDRCca7khfQWYu1iFhsqeABpi87f03MBdkT93ZE6YhqCdMzb5Eojb6c4dlJikGv5liuhByyzA7ikpIPTSBWbQ== @@ -5195,17 +5313,6 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== -fs-extra@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" - path-is-absolute "^1.0.0" - rimraf "^2.2.8" - fs-extra@^4.0.1, fs-extra@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" @@ -5256,19 +5363,19 @@ fs.realpath@^1.0.0: integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.0.0, fsevents@^1.2.7: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== + version "1.2.11" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.11.tgz#67bf57f4758f02ede88fb2a1712fef4d15358be3" + integrity sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw== dependencies: + bindings "^1.5.0" nan "^2.12.1" - node-pre-gyp "^0.12.0" -fsevents@~2.1.1: +fsevents@~2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== -function-bind@^1.0.2, function-bind@^1.1.1: +function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== @@ -5287,14 +5394,14 @@ g-status@^2.0.2: matcher "^1.0.0" simple-git "^1.85.0" -ganache-cli@6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.3.0.tgz#574f9d35aaec8da6e01c2be49db8fe73129eb561" - integrity sha512-8SyzfX2ipRVBx1fBZLg3j8I3E334U3Vazk5mEpYcWqnIjC2ace6jtOXHG4aTuAvSz3+HzQ8p8pRjOJxdDZ2pnQ== +ganache-cli@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.7.0.tgz#b59845578221bdf686cf124d007c5ee62e85a62f" + integrity sha512-9CZsClo9hl5MxGL7hkk14mie89Q94P0idh92jcV7LmppTYTCG7SHatuwcfqN7emFHArMt3fneN4QbH2do2N6Ow== dependencies: - bn.js "4.11.8" - source-map-support "0.5.9" - yargs "11.1.0" + ethereumjs-util "6.1.0" + source-map-support "0.5.12" + yargs "13.2.4" gauge@~2.7.3: version "2.7.4" @@ -5336,9 +5443,9 @@ get-func-name@^2.0.0: integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= get-own-enumerable-property-symbols@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.1.tgz#6f7764f88ea11e0b514bd9bd860a132259992ca4" - integrity sha512-09/VS4iek66Dh2bctjRkowueRJbY1JDGR1L/zRxO1Qk8Uxs6PnqaNSqalpizPT+CDjre3hnEsuzvhgomz9qYrA== + version "3.0.2" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" + integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== get-pkg-repo@^1.0.0: version "1.4.0" @@ -5393,7 +5500,7 @@ get-stream@^4.0.0, get-stream@^4.1.0: dependencies: pump "^3.0.0" -get-stream@^5.1.0: +get-stream@^5.0.0, get-stream@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== @@ -5513,6 +5620,18 @@ glob@7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" @@ -5674,7 +5793,7 @@ got@^7.1.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" -graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: +graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2: version "4.2.3" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== @@ -5753,12 +5872,17 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-symbol-support-x@^1.4.1: version "1.4.2" resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== -has-symbols@^1.0.0: +has-symbols@^1.0.0, has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== @@ -5849,6 +5973,11 @@ he@1.1.1: resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -6041,7 +6170,7 @@ i18next@^17.0.3: dependencies: "@babel/runtime" "^7.3.1" -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -6135,6 +6264,11 @@ indent-string@^3.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + infer-owner@^1.0.3, infer-owner@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" @@ -6148,7 +6282,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -6163,7 +6297,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.2, ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: +ini@^1.3.2, ini@^1.3.4, ini@^1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== @@ -6202,9 +6336,9 @@ inquirer@^6.1.0, inquirer@^6.2.0: through "^2.3.6" inquirer@~7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.0.tgz#9e2b032dde77da1db5db804758b8fea3a970519a" - integrity sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ== + version "7.0.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.1.tgz#13f7980eedc73c689feff3994b109c4e799c6ebb" + integrity sha512-V1FFQ3TIO15det8PijPLFR9M9baSlnRs9nL7zWu1MNVA2T9YVl9ZbrHJhYs7e9X8jeMZ3lr2JH/rdHFgNCBdYw== dependencies: ansi-escapes "^4.2.1" chalk "^2.4.2" @@ -6215,7 +6349,7 @@ inquirer@~7.0.0: lodash "^4.17.15" mute-stream "0.0.8" run-async "^2.2.0" - rxjs "^6.4.0" + rxjs "^6.5.3" string-width "^4.1.0" strip-ansi "^5.1.0" through "^2.3.6" @@ -6313,7 +6447,7 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-buffer@^2.0.2: +is-buffer@^2.0.2, is-buffer@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== @@ -6517,6 +6651,11 @@ is-path-cwd@^1.0.0: resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= +is-path-cwd@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + is-path-in-cwd@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" @@ -6531,6 +6670,11 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-path-inside@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" + integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== + is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -6571,11 +6715,11 @@ is-promise@^2.1.0: integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== dependencies: - has "^1.0.1" + has "^1.0.3" is-regexp@^1.0.0: version "1.0.0" @@ -6606,12 +6750,17 @@ is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== dependencies: - has-symbols "^1.0.0" + has-symbols "^1.0.1" is-text-path@^1.0.1: version "1.0.1" @@ -6794,7 +6943,7 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.12.0, js-yaml@^3.13.1, js-yaml@^3.7.0: +js-yaml@3.13.1, js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.12.0, js-yaml@^3.13.1, js-yaml@^3.7.0: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -6861,13 +7010,6 @@ json5@^2.1.0: dependencies: minimist "^1.2.0" -jsonfile@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= - optionalDependencies: - graceful-fs "^4.1.6" - jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -6911,14 +7053,14 @@ keccak@^1.0.2: safe-buffer "^5.1.0" keccak@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-2.0.0.tgz#7456ea5023284271e6f362b4397e8df4d2bb994c" - integrity sha512-rKe/lRr0KGhjoz97cwg+oeT1Rj/Y4cjae6glArioUC8JBF9ROGZctwIaaruM7d7naovME4Q8WcQSO908A8qcyQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-2.1.0.tgz#734ea53f2edcfd0f42cdb8d5f4c358fef052752b" + integrity sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q== dependencies: - bindings "^1.2.1" - inherits "^2.0.3" - nan "^2.2.1" - safe-buffer "^5.1.0" + bindings "^1.5.0" + inherits "^2.0.4" + nan "^2.14.0" + safe-buffer "^5.2.0" keccakjs@^0.2.1: version "0.2.3" @@ -6968,13 +7110,6 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== -klaw@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= - optionalDependencies: - graceful-fs "^4.1.9" - lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" @@ -7025,15 +7160,6 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -linebreak@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/linebreak/-/linebreak-0.3.0.tgz#0526480a62c05bd679f3e9d99830e09c6a7d0ed6" - integrity sha1-BSZICmLAW9Z58+nZmDDgnGp9DtY= - dependencies: - base64-js "0.0.8" - brfs "^1.3.0" - unicode-trie "^0.3.0" - linebreak@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/linebreak/-/linebreak-1.0.2.tgz#4b5781733e9a9eb2849dba2f963e47c887f8aa06" @@ -7079,6 +7205,26 @@ lint-staged@8.1.3: stringify-object "^3.2.2" yup "^0.26.10" +lint-staged@9.5.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-9.5.0.tgz#290ec605252af646d9b74d73a0fa118362b05a33" + integrity sha512-nawMob9cb/G1J98nb8v3VC/E8rcX1rryUYXVZ69aT9kde6YWX+uvNOEHY5yf2gcWcTJGiD0kqXmCnS3oD75GIA== + dependencies: + chalk "^2.4.2" + commander "^2.20.0" + cosmiconfig "^5.2.1" + debug "^4.1.1" + dedent "^0.7.0" + del "^5.0.0" + execa "^2.0.3" + listr "^0.14.3" + log-symbols "^3.0.0" + micromatch "^4.0.2" + normalize-path "^3.0.0" + please-upgrade-node "^3.1.1" + string-argv "^0.3.0" + stringify-object "^3.3.0" + listr-silent-renderer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" @@ -7108,7 +7254,7 @@ listr-verbose-renderer@^0.5.0: date-fns "^1.27.2" figures "^2.0.0" -listr@^0.14.2: +listr@^0.14.2, listr@^0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== @@ -7221,7 +7367,7 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= -lodash.flatmap@~4.5.0: +lodash.flatmap@^4.5.0, lodash.flatmap@~4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" integrity sha1-74y/QI9uSCaGYzRTBcaswLd4cC4= @@ -7286,7 +7432,7 @@ lodash@4.17.13: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.13.tgz#0bdc3a6adc873d2f4e0c4bac285df91b64fc7b93" integrity sha512-vm3/XWXfWtRua0FkUyEHBZy8kCPjErNBT9fJx8Zvs+U6zjqPbTUOpkaoum3O5uiA8sm+yNMHXfYkTUHFoMxFNA== -lodash@^4.14.2, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@~4.17.4: +lodash@^4.14.2, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -7296,6 +7442,13 @@ log-driver@^1.2.7: resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== +log-symbols@2.2.0, log-symbols@^2.1.0, log-symbols@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + log-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" @@ -7303,13 +7456,6 @@ log-symbols@^1.0.2: dependencies: chalk "^1.0.0" -log-symbols@^2.1.0, log-symbols@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - log-symbols@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" @@ -7326,16 +7472,16 @@ log-update@^2.3.0: cli-cursor "^2.0.0" wrap-ansi "^3.0.1" -log4js@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-5.1.0.tgz#3fa5372055a4c2611ab92d80496bffc100841508" - integrity sha512-QtXrBGZiIwfwBrH9zF2uQarvBuJ5+Icqx9fW+nQL4pnmPITJw8n6kh3bck5IkcTDBQatDeKqUMXXX41fp0TIqw== +log4js@~6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.1.0.tgz#51268154adb2eb5d8a594b2c77f024a77f047265" + integrity sha512-fSCHMYsMJbHwfNTuMlopVVcfkKwIRLh5mpNZGB2oBbnSmr3yUTo4tL4xGBA0/q29xowlu96eTXGghJFNhPXMnA== dependencies: - date-format "^2.1.0" + date-format "^3.0.0" debug "^4.1.1" flatted "^2.0.1" rfdc "^1.1.4" - streamroller "^2.1.0" + streamroller "^2.2.3" loglevelnext@^1.0.1: version "1.0.5" @@ -7345,12 +7491,7 @@ loglevelnext@^1.0.1: es6-symbol "^3.1.1" object.assign "^4.1.0" -lolex@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-3.1.0.tgz#1a7feb2fefd75b3e3a7f79f0e110d9476e294434" - integrity sha512-zFo5MgCJ0rZ7gQg69S4pqBsLURbFw11X68C18OcJjJQbqaXm2NoTrGl1IMM3TIz0/BnN1tIs2tzmmqvCsOMMjw== - -lolex@^4.0.1, lolex@^4.1.0, lolex@^4.2.0: +lolex@^4.1.0, lolex@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lolex/-/lolex-4.2.0.tgz#ddbd7f6213ca1ea5826901ab1222b65d714b3cd7" integrity sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg== @@ -7614,6 +7755,11 @@ merge-source-map@^1.1.0: dependencies: source-map "^0.6.1" +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.2.3, merge2@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" @@ -7827,7 +7973,36 @@ mocha@5.2.0: mkdirp "0.5.1" supports-color "5.4.0" -mocha@^4.0.1, mocha@^4.1.0: +mocha@6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" + integrity sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A== + dependencies: + ansi-colors "3.2.3" + browser-stdout "1.3.1" + debug "3.2.6" + diff "3.5.0" + escape-string-regexp "1.0.5" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" + minimatch "3.0.4" + mkdirp "0.5.1" + ms "2.1.1" + node-environment-flags "1.0.5" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" + +mocha@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== @@ -7844,9 +8019,9 @@ mocha@^4.0.1, mocha@^4.1.0: supports-color "4.4.0" mock-fs@^4.1.0: - version "4.10.3" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.10.3.tgz#d0550663dd2b5d33a7c1b8713c6925aab07a04ae" - integrity sha512-bcukePBvuA3qovmq0Qtqu9+1APCIGkFHnsozrPIVromt5XFGGgkQSfaN0H6RI8gStHkO/hRgimvS3tooNes4pQ== + version "4.10.4" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.10.4.tgz#4eaa3d6f7da2f44e1f3dd6b462cbbcb7b082e3d4" + integrity sha512-gDfZDLaPIvtOusbusLinfx6YSe2YpQsDT8qdP41P47dQ/NQggtkHukz7hwqgt8QvMBmAv+Z6DGmXPyb5BWX2nQ== modify-values@^1.0.0: version "1.0.1" @@ -7923,19 +8098,19 @@ multimatch@~4.0.0: minimatch "^3.0.4" mutation-testing-elements@^1.0.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mutation-testing-elements/-/mutation-testing-elements-1.2.0.tgz#986ce17ed17385fb62d3e7cfcf6ce5d63df1a2d1" - integrity sha512-yE+sg3BAh3nsijMbSsej4ZJQnnJlbb8QtmtXaXx+DRgRvmDs95SGQkOYc+9poXIQkKZxrAynzk6vSFsZibT/lw== + version "1.2.3" + resolved "https://registry.yarnpkg.com/mutation-testing-elements/-/mutation-testing-elements-1.2.3.tgz#1a8e77d34f97c9223e896c771ee8c3ea952efc57" + integrity sha512-ht3H+MDnSTcWXbiS66TC6t0XrastDA6KtwQemKKB6KcSf4ppisQ3xQwTXR0fQVG9AdY/7Bk/NbGQ01eKBDttYA== mutation-testing-metrics@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mutation-testing-metrics/-/mutation-testing-metrics-1.2.0.tgz#1fe748aa1fb6bd7968a8cca6bafe88d22b5325a4" - integrity sha512-agtR/XMhIaZMdfp7ovDoXRb/Jme+YaVDDCFX/nCboCkZBPP12QZOiRCgDHt8DcmTSyDKt4HwiUrOUzj1A0H5Zw== + version "1.2.2" + resolved "https://registry.yarnpkg.com/mutation-testing-metrics/-/mutation-testing-metrics-1.2.2.tgz#08b465c55132a44b398a7dfe04405da16add830d" + integrity sha512-8qhRVdhezomBx3pzc2TYjZHM6rQ068Xlug+WttnjfHlAFPr9M6dWc9syAOSzYemJrsSHYYLXr0cD0eG7oPcG4A== dependencies: lodash.groupby "^4.6.0" mutation-testing-report-schema "^1.2.0" -mutation-testing-report-schema@^1.0.0, mutation-testing-report-schema@^1.2.0: +mutation-testing-report-schema@^1.1.0, mutation-testing-report-schema@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mutation-testing-report-schema/-/mutation-testing-report-schema-1.2.0.tgz#ed89cde7302833108b75703d4ef62085b1bb490e" integrity sha512-4LdCuO33sH8R2YJ1idP+GUTjPR/VeSEml1tboQX0+5dSwH2YccUrw73rzAEOzkbeD+IyzBDHLzQKmanScV4smA== @@ -7996,15 +8171,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -8030,7 +8196,7 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -nise@^1.4.10, nise@^1.4.8, nise@^1.5.2: +nise@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/nise/-/nise-1.5.2.tgz#b6d29af10e48b321b307e10e065199338eeb2652" integrity sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA== @@ -8041,6 +8207,14 @@ nise@^1.4.10, nise@^1.4.8, nise@^1.5.2: lolex "^4.1.0" path-to-regexp "^1.7.0" +node-environment-flags@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + node-fetch-npm@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" @@ -8061,21 +8235,21 @@ node-fetch@2.6.0, node-fetch@^2.3.0, node-fetch@^2.5.0: integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== node-gyp@^5.0.2: - version "5.0.5" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.0.5.tgz#f6cf1da246eb8c42b097d7cd4d6c3ce23a4163af" - integrity sha512-WABl9s4/mqQdZneZHVWVG4TVr6QQJZUC6PAx47ITSk9lreZ1n+7Z9mMAIbA3vnO4J9W20P7LhCxtzfWsAD/KDw== + version "5.0.7" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.0.7.tgz#dd4225e735e840cf2870e4037c2ed9c28a31719e" + integrity sha512-K8aByl8OJD51V0VbUURTKsmdswkQQusIvlvmTyhHlIT1hBvaSxzdxpSle857XuXa7uc02UEZx9OR5aDxSWS5Qw== dependencies: - env-paths "^1.0.0" - glob "^7.0.3" - graceful-fs "^4.1.2" - mkdirp "^0.5.0" - nopt "2 || 3" - npmlog "0 || 1 || 2 || 3 || 4" - request "^2.87.0" - rimraf "2" - semver "~5.3.0" + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.2" + mkdirp "^0.5.1" + nopt "^4.0.1" + npmlog "^4.1.2" + request "^2.88.0" + rimraf "^2.6.3" + semver "^5.7.1" tar "^4.4.12" - which "1" + which "^1.3.1" node-libs-browser@^2.0.0: version "2.2.1" @@ -8117,23 +8291,7 @@ node-notifier@^5.4.0: shellwords "^0.1.1" which "^1.3.0" -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -"nopt@2 || 3", nopt@3.x: +nopt@3.x: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= @@ -8181,9 +8339,11 @@ normalize-url@^4.1.0: integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + version "1.1.1" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" + integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== + dependencies: + npm-normalize-package-bin "^1.0.1" npm-lifecycle@^3.1.2: version "3.1.4" @@ -8199,6 +8359,11 @@ npm-lifecycle@^3.1.2: umask "^1.1.0" which "^1.3.1" +npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + "npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: version "6.1.1" resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.1.tgz#02168cb0a49a2b75bf988a28698de7b529df5cb7" @@ -8228,10 +8393,10 @@ npm-package-json-lint@4.0.3: semver "^6.3.0" strip-json-comments "^3.0.1" -npm-packlist@^1.1.6, npm-packlist@^1.4.4: - version "1.4.6" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.6.tgz#53ba3ed11f8523079f1457376dd379ee4ea42ff4" - integrity sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg== +npm-packlist@^1.4.4: + version "1.4.7" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.7.tgz#9e954365a06b80b18111ea900945af4f88ed4848" + integrity sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -8274,6 +8439,13 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" +npm-run-path@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-3.1.0.tgz#7f91be317f6a466efed3c9f2980ad8a4ee8b0fa5" + integrity sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg== + dependencies: + path-key "^3.0.0" + npm-which@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa" @@ -8283,7 +8455,7 @@ npm-which@^3.0.1: npm-path "^2.0.2" which "^1.2.10" -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.2, npmlog@^4.1.2: +npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -8398,7 +8570,7 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.6.0: +object-inspect@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== @@ -8409,9 +8581,9 @@ object-inspect@~1.4.0: integrity sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw== object-is@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" - integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY= + version "1.0.2" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4" + integrity sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ== object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.1.1: version "1.1.1" @@ -8425,7 +8597,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.1.0: +object.assign@4.1.0, object.assign@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== @@ -8436,12 +8608,12 @@ object.assign@^4.1.0: object-keys "^1.0.11" object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" object.omit@^2.0.0: version "2.0.1" @@ -8636,6 +8808,11 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= +p-finally@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" + integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== + p-is-promise@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" @@ -8693,6 +8870,13 @@ p-map@^2.0.0, p-map@^2.1.0: resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + p-pipe@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-1.2.0.tgz#4b1a11399a11520a67790ee5a0c1d5881d6befe9" @@ -8914,6 +9098,11 @@ path-key@^2.0.0, path-key@^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" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -8980,25 +9169,25 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -pdfkit@>=0.8.1, pdfkit@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/pdfkit/-/pdfkit-0.10.0.tgz#88f2aa8e3cf9e1cc2caff6447b68dd4e435cb284" - integrity sha512-mRJ6iuDzpIQ4ftKp5GvijLXNVRK86xjnyIPBraYSPrUPubNqWM5/oYmc7FZKUWz3wusRTj3PLR9HJ1X5ooqfsg== +pdfkit@>=0.8.1, pdfkit@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/pdfkit/-/pdfkit-0.11.0.tgz#9cdb2fc42bd2913587fe3ddf48cc5bbb3c36f7de" + integrity sha512-1s9gaumXkYxcVF1iRtSmLiISF2r4nHtsTgpwXiK8Swe+xwk/1pm8FJjYqN7L3x13NsWnGyUFntWcO8vfqq+wwA== dependencies: crypto-js "^3.1.9-1" - fontkit "^1.0.0" - linebreak "^0.3.0" - png-js ">=0.1.0" + fontkit "^1.8.0" + linebreak "^1.0.2" + png-js "^1.0.0" pdfmake@^0.1.57: - version "0.1.62" - resolved "https://registry.yarnpkg.com/pdfmake/-/pdfmake-0.1.62.tgz#62f2400eba066cc271736b95c7d0cdf9c8e06983" - integrity sha512-2QIzijdkwFBChTFu5nVmMe+fLBQTAYTPTxi4jGbUTyGxZBq7YR1I17FBk1Cs+3nrYufNKNukT6OR1RNxbovsTA== + version "0.1.63" + resolved "https://registry.yarnpkg.com/pdfmake/-/pdfmake-0.1.63.tgz#0001ecffe4ab30843485ce08744393315721e3f1" + integrity sha512-TjchyLVDzaEmtaDNUrceNrm0QvNIFERYOeDwHwMUQ1twGy68Uhjd1MKsb9DGAh8SuB8MCWQXB7m4k7cUevLjoA== dependencies: iconv-lite "^0.5.0" linebreak "^1.0.2" - pdfkit "^0.10.0" - svg-to-pdfkit "^0.1.7" + pdfkit "^0.11.0" + svg-to-pdfkit "^0.1.8" pegjs@^0.10.0: version "0.10.0" @@ -9015,7 +9204,7 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picomatch@^2.0.4, picomatch@^2.0.5: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7: version "2.1.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5" integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA== @@ -9095,7 +9284,7 @@ plur@^3.1.1: dependencies: irregular-plurals "^2.0.0" -png-js@>=0.1.0: +png-js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/png-js/-/png-js-1.0.0.tgz#e5484f1e8156996e383aceebb3789fd75df1874d" integrity sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g== @@ -9231,9 +9420,9 @@ pseudomap@^1.0.2: integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24: - version "1.4.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" - integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== + version "1.6.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110" + integrity sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA== public-encrypt@^4.0.0: version "4.0.3" @@ -9389,16 +9578,6 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - read-cmd-shim@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16" @@ -9407,14 +9586,14 @@ read-cmd-shim@^1.0.1: graceful-fs "^4.1.2" "read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13: - version "2.1.0" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.0.tgz#e3d42e6c35ea5ae820d9a03ab0c7291217fc51d5" - integrity sha512-KLhu8M1ZZNkMcrq1+0UJbR8Dii8KZUqB0Sha4mOx/bknfKI/fyrQVrG/YIt2UOtG667sD8+ee4EXMM91W9dC+A== + version "2.1.1" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.1.tgz#16aa66c59e7d4dad6288f179dd9295fd59bb98f1" + integrity sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A== dependencies: glob "^7.1.1" json-parse-better-errors "^1.0.1" normalize-package-data "^2.0.0" - slash "^1.0.0" + npm-normalize-package-bin "^1.0.0" optionalDependencies: graceful-fs "^4.1.2" @@ -9527,12 +9706,12 @@ readdirp@^2.0.0, readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" -readdirp@~3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" - integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== +readdirp@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17" + integrity sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ== dependencies: - picomatch "^2.0.4" + picomatch "^2.0.7" rechoir@^0.6.2: version "0.6.2" @@ -9593,11 +9772,12 @@ regex-not@^1.0.0, regex-not@^1.0.2: safe-regex "^1.1.0" regexp.prototype.flags@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c" - integrity sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA== + version "1.3.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" + integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== dependencies: - define-properties "^1.1.2" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" regexpp@^2.0.1: version "2.0.1" @@ -9644,7 +9824,7 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@^2.79.0, request@^2.86.0, request@^2.87.0: +request@^2.79.0, request@^2.86.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -9675,11 +9855,6 @@ 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.0: - 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@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" @@ -9731,9 +9906,9 @@ resolve@1.1.7, resolve@1.1.x: integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= resolve@^1.0.0, resolve@^1.1.5, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2: - version "1.12.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" - integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== + version "1.13.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16" + integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w== dependencies: path-parse "^1.0.6" @@ -9787,13 +9962,6 @@ rfdc@^1.1.4: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2" integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug== -rimraf@2, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rimraf@2.6.3, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -9801,7 +9969,14 @@ rimraf@2.6.3, rimraf@~2.6.2: dependencies: glob "^7.1.3" -rimraf@~3.0.0: +rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.0, rimraf@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.0.tgz#614176d4b3010b75e5c390eb0ee96f6dc0cebb9b" integrity sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg== @@ -9847,7 +10022,7 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@^6.3.3, rxjs@^6.4.0, rxjs@~6.5.1: +rxjs@^6.3.3, rxjs@^6.4.0, rxjs@^6.5.3, rxjs@~6.5.1: version "6.5.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== @@ -9883,11 +10058,6 @@ satoshi-bitcoin@1.0.4: dependencies: big.js "^3.1.3" -sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" @@ -9972,7 +10142,7 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= -"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -9997,11 +10167,6 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.2.0, semver@^6.3.0, semver@~6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= - send@0.17.1, send@latest: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -10026,6 +10191,11 @@ serialize-javascript@^1.7.0: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A== +serialize-javascript@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" + integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== + serve-index@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" @@ -10104,9 +10274,9 @@ sha.js@^2.4.0, sha.js@^2.4.8: safe-buffer "^5.0.1" sha3@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.3.tgz#ed5958fa8331df1b1b8529ca9fdf225a340c5418" - integrity sha512-sOWDZi8cDBRkLfWOw18wvJyNblXDHzwMGnRWut8zNNeIeLnmMRO17bjpLc7OzMuj1ASUgx2IyohzUCAl+Kx5vA== + version "1.2.6" + resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.6.tgz#102aa3e47dc793e2357902c3cce8760822f9e905" + integrity sha512-KgLGmJGrmNB4JWVsAV11Yk6KbvsAiygWJc7t5IebWva/0NukNrjJqhtKhzy3Eiv2AKuGvhZZt7dt1mDo7HkoiQ== dependencies: nan "2.13.2" @@ -10122,11 +10292,23 @@ shebang-command@^1.2.0: 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" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + 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" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + shell-quote@^1.6.1: version "1.7.2" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" @@ -10182,9 +10364,9 @@ simple-get@^2.7.0: simple-concat "^1.0.0" simple-git@^1.85.0: - version "1.126.0" - resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.126.0.tgz#0c345372275139c8433b8277f4b3e155092aa434" - integrity sha512-47mqHxgZnN8XRa9HbpWprzUv3Ooqz9RY/LSZgvA7jCkW8jcwLahMz7LKugY91KZehfG0sCVPtgXiU72hd6b1Bw== + version "1.129.0" + resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.129.0.tgz#eddd2611d2bf41c77e1d08cd70c0b7f3af785040" + integrity sha512-XbzNmugMTeV2crZnPl+b1ZJn+nqXCUNyrZxDXpLM0kHL3B85sbPlpd8q9I4qtAHI9D2FxTB6w4BuiAGKYtyzKw== dependencies: debug "^4.0.1" @@ -10193,32 +10375,6 @@ simple-statistics@7.0.2: resolved "https://registry.yarnpkg.com/simple-statistics/-/simple-statistics-7.0.2.tgz#46671f45cb6f9b68207dccd6a3c4f7e745e6e638" integrity sha512-wqTjlmbiaL6Fqaw28tSjQrthjxVV17MMfi/H/qvE0jAvtLspB2S7gEtcR27uvhSRAa64LhjhoO169rX8sFW3pg== -sinon@7.2.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.2.3.tgz#f8bfd956df32ddf592f8c102fd46982366412d8e" - integrity sha512-i6j7sqcLEqTYqUcMV327waI745VASvYuSuQMCjbAwlpAeuCgKZ3LtrjDxAbu+GjNQR0FEDpywtwGCIh8GicNyg== - dependencies: - "@sinonjs/commons" "^1.3.0" - "@sinonjs/formatio" "^3.1.0" - "@sinonjs/samsam" "^3.0.2" - diff "^3.5.0" - lolex "^3.0.0" - nise "^1.4.8" - supports-color "^5.5.0" - -sinon@7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.3.2.tgz#82dba3a6d85f6d2181e1eca2c10d8657c2161f28" - integrity sha512-thErC1z64BeyGiPvF8aoSg0LEnptSaWE7YhdWWbWXgelOyThent7uKOnnEh9zBxDbKixtr5dEko+ws1sZMuFMA== - dependencies: - "@sinonjs/commons" "^1.4.0" - "@sinonjs/formatio" "^3.2.1" - "@sinonjs/samsam" "^3.3.1" - diff "^3.5.0" - lolex "^4.0.1" - nise "^1.4.10" - supports-color "^5.5.0" - sinon@7.5.0: version "7.5.0" resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.5.0.tgz#e9488ea466070ea908fd44a3d6478fd4923c67ec" @@ -10327,18 +10483,6 @@ sol-explore@1.6.1: resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.1.tgz#b59f073c69fe332560d5a10c32ba8ca7f2986cfb" integrity sha1-tZ8HPGn+MyVg1aEMMrqMp/KYbPs= -solc@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.0.tgz#2deb2ae992acac3afb909f85c38d00f01dcb335e" - integrity sha512-mdLHDl9WeYrN+FIKcMc9PlPfnA9DG9ur5QpCDKcv6VC4RINAsTF4EMuXMZMKoQTvZhtLyJIVH/BZ+KU830Z8Xg== - dependencies: - fs-extra "^0.30.0" - keccak "^1.0.2" - memorystream "^0.3.1" - require-from-string "^2.0.0" - semver "^5.5.0" - yargs "^11.0.0" - solium-plugin-security@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/solium-plugin-security/-/solium-plugin-security-0.1.1.tgz#2a87bcf8f8c3abf7d198e292e4ac080284e3f3f6" @@ -10395,18 +10539,18 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== +source-map-support@0.5.12: + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@0.5.9: - version "0.5.9" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" - integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -10552,11 +10696,11 @@ staged-git-files@1.1.2: integrity sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA== static-eval@^2.0.0, static-eval@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.2.tgz#2d1759306b1befa688938454c546b7871f806a42" - integrity sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg== + version "2.0.3" + resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.3.tgz#cb62fc79946bd4d5f623a45ad428233adace4d72" + integrity sha512-zsxDGucfAh8T339sSKgpFbvg15Fms2IVaJGC+jqp0bVsxhcpM+iMeAI8weNo8dmf4OblgifTBUoyk1vGVtYw2w== dependencies: - escodegen "^1.8.1" + escodegen "^1.11.1" static-extend@^0.1.1: version "0.1.2" @@ -10646,11 +10790,11 @@ stream-http@^2.7.2: xtend "^4.0.0" stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== -streamroller@^2.1.0: +streamroller@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-2.2.3.tgz#b95c9fad44e2e89005d242141486b3b4962c2d28" integrity sha512-AegmvQsscTRhHVO46PhCDerjIpxi7E+d2GxgUDu+nzw/HuLnUdxHWr6WQ+mVn/4iJgMKKFFdiUwFcFRDvcjCtw== @@ -10669,6 +10813,11 @@ string-argv@^0.0.2: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.0.2.tgz#dac30408690c21f3c3630a3ff3a05877bdcbd736" integrity sha1-2sMECGkMIfPDYwo/86BYd73L1zY= +string-argv@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" + integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -10705,13 +10854,12 @@ string-width@^4.1.0: strip-ansi "^6.0.0" string.prototype.padend@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz#f3aaef7c1719f170c5eab1c32bf780d96e21f2f0" - integrity sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA= + version "3.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz#dc08f57a8010dc5c153550318f67e13adbb72ac3" + integrity sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA== dependencies: - define-properties "^1.1.2" - es-abstract "^1.4.3" - function-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" string.prototype.trimleft@^2.1.0: version "2.1.0" @@ -10743,7 +10891,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -stringify-object@^3.2.2: +stringify-object@^3.2.2, stringify-object@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== @@ -10804,6 +10952,11 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" @@ -10823,7 +10976,7 @@ strip-indent@^2.0.0: resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= -strip-json-comments@^2.0.0, strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: +strip-json-comments@2.0.1, strip-json-comments@^2.0.0, strip-json-comments@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -10880,6 +11033,13 @@ supports-color@5.4.0: dependencies: has-flag "^3.0.0" +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== + dependencies: + has-flag "^3.0.0" + supports-color@6.1.0, supports-color@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" @@ -10906,15 +11066,22 @@ supports-color@^5.3.0, supports-color@^5.5.0: dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + surrial@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/surrial/-/surrial-1.0.0.tgz#3ac560cc7038a8ff446920a4f7c3495e1f03a578" integrity sha512-dkvhz3QvgraMeFWI9V+BinpNCNoaSNxKcxb0umRpkWeFlZ0WSbIfeTm9YtLA6a4kv/Q2pOMQOtMlcv/b5h6qpg== -svg-to-pdfkit@^0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/svg-to-pdfkit/-/svg-to-pdfkit-0.1.7.tgz#7db6d47e47b3888dce18060751a8de2417f85775" - integrity sha1-fbbUfkeziI3OGAYHUajeJBf4V3U= +svg-to-pdfkit@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/svg-to-pdfkit/-/svg-to-pdfkit-0.1.8.tgz#5921765922044843f0c1a5b25ec1ef8a4a33b8af" + integrity sha512-QItiGZBy5TstGy+q8mjQTMGRlDDOARXLxH+sgVm1n/LYeo0zFcQlcCh8m4zi8QxctrxB9Kue/lStc/RD5iLadQ== dependencies: pdfkit ">=0.8.1" @@ -10974,7 +11141,7 @@ tar-stream@^1.5.2: to-buffer "^1.1.1" xtend "^4.0.0" -tar@^4, tar@^4.0.2, tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: +tar@^4.0.2, tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== @@ -11021,24 +11188,24 @@ terser-webpack-plugin@1.3.0: worker-farm "^1.7.0" terser-webpack-plugin@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4" - integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg== + version "1.4.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" + integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== dependencies: cacache "^12.0.2" find-cache-dir "^2.1.0" is-wsl "^1.1.0" schema-utils "^1.0.0" - serialize-javascript "^1.7.0" + serialize-javascript "^2.1.2" source-map "^0.6.1" terser "^4.1.2" webpack-sources "^1.4.0" worker-farm "^1.7.0" terser@^4.0.0, terser@^4.1.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.0.tgz#22c46b4817cf4c9565434bfe6ad47336af259ac3" - integrity sha512-oDG16n2WKm27JO8h4y/w3iqBGAOSCtq7k8dRmrn4Wf9NouL0b2WpMHGChFGZq4nFAQy1FsNJrVQHfurXOSTmOA== + version "4.4.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.3.tgz#401abc52b88869cf904412503b1eb7da093ae2f0" + integrity sha512-0ikKraVtRDKGzHrzkCv5rUNDzqlhmhowOBqC0XqUHFpW+vJ45+20/IFBcebwKfiS2Z9fJin6Eo+F1zLZsxi8RA== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -11218,9 +11385,9 @@ traverse@^0.6.6: integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= tree-kill@^1.2.1, tree-kill@~1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.1.tgz#5398f374e2f292b9dcc7b2e71e30a5c3bb6c743a" - integrity sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q== + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== trim-newlines@^1.0.0: version "1.0.0" @@ -11237,15 +11404,14 @@ trim-off-newlines@^1.0.0: resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= -truffle@5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.3.tgz#ff54abdd3dba7ff0850356c0aae7c390d013e40b" - integrity sha512-XTR1SwWoxNGCBa8zWrv/4J8RNfclL6qhyAp+bfnv4AD3L7GEWziDQvcq5ufSKIPKnoK0a4y1O+EZOW5izyEaKg== +truffle@5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.1.2.tgz#516f28126fdb623bd5eff20c665b2f2bfbaa4eba" + integrity sha512-VfNdtk/dh8zj9onE/q8A7SSrFyqPqz61W+sx5FrUK++BbSE7N09/6z2F/VORuDykPmFaujtYKt8iNoD3Htfeww== dependencies: app-module-path "^2.2.0" - mocha "^4.1.0" + mocha "5.2.0" original-require "1.0.1" - solc "0.5.0" tryer@^1.0.1: version "1.0.1" @@ -11269,10 +11435,10 @@ ts-node-dev@1.0.0-pre.39: ts-node "*" tsconfig "^7.0.0" -ts-node@*, ts-node@8.5.2: - version "8.5.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.5.2.tgz#434f6c893bafe501a30b32ac94ee36809ba2adce" - integrity sha512-W1DK/a6BGoV/D4x/SXXm6TSQx6q3blECUzd5TN+j56YEMX3yPVMpHsICLedUw3DvGF3aTQ8hfdR9AKMaHjIi+A== +ts-node@*, ts-node@8.5.4: + version "8.5.4" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.5.4.tgz#a152add11fa19c221d0b48962c210cf467262ab2" + integrity sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw== dependencies: arg "^4.1.0" diff "^4.0.1" @@ -11306,12 +11472,7 @@ tsconfig@^7.0.0: strip-bom "^3.0.0" strip-json-comments "^2.0.0" -tslib@1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== - -tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3, tslib@~1.10.0: +tslib@1.10.0, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3, tslib@~1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== @@ -11408,10 +11569,12 @@ type@^2.0.0: resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== -typed-inject@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/typed-inject/-/typed-inject-2.0.0.tgz#78fc8b3e27104fb2945c3242d7eff9bc1e5e6320" - integrity sha512-x4gVaWZzGBZMR15rTMWdijKlMg/rBc7YkjTx9koW7Lp+9UYr+GQZLRMtpQm7MJv4J6r1AVhclwouZ0z+G6tYAw== +typed-inject@~2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/typed-inject/-/typed-inject-2.1.1.tgz#5e16c5d46961fd77f475295f0170627ac81ffd19" + integrity sha512-TaQrNsYjGTMmgfEwKtjP9+qyZu//H1RJ0RYNvvQ/rcAnpQGZLxHajb+O6TnyFZGfLaK/9319VYaG4PFXGjImug== + dependencies: + typescript "^3.6.3" typed-rest-client@~1.5.0: version "1.5.0" @@ -11448,10 +11611,15 @@ typescript@^2.4.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w== +typescript@^3.6.3: + version "3.7.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69" + integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw== + uglify-js@^3.1.4: - version "3.6.9" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.9.tgz#85d353edb6ddfb62a9d798f36e91792249320611" - integrity sha512-pcnnhaoG6RtrvHJ1dFncAe8Od6Nuy30oaJ82ts6//sGSXOP5UjBMEthiProjXmMNHOfd93sqlkztifFMcb+4yw== + version "3.7.2" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.2.tgz#cb1a601e67536e9ed094a92dd1e333459643d3f9" + integrity sha512-uhRwZcANNWVLrxLfNFEdltoPNhECUR3lc+UdJoG9CBpMcSnKyWA94tc3eAujB1GcMY5Uwq8ZMp4qWpxWYDQmaA== dependencies: commander "~2.20.3" source-map "~0.6.1" @@ -12219,10 +12387,10 @@ webpack-bundle-analyzer@3.3.2: opener "^1.5.1" ws "^6.0.0" -webpack-cli@3.3.6: - version "3.3.6" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.6.tgz#2c8c399a2642133f8d736a359007a052e060032c" - integrity sha512-0vEa83M7kJtxK/jUhlpZ27WHIOndz5mghWL2O53kiDoA9DIxSKnfqB92LoqEn77cT4f3H2cZm1BMEat/6AZz3A== +webpack-cli@3.3.10: + version "3.3.10" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.10.tgz#17b279267e9b4fb549023fae170da8e6e766da13" + integrity sha512-u1dgND9+MXaEt74sJR4PR7qkPxXUSQ0RXYq8x1L6Jg1MYVEmGPrH6Ah6C4arD4r0J1P5HKjRqpab36k0eIzPqg== dependencies: chalk "2.4.2" cross-spawn "6.0.5" @@ -12298,11 +12466,12 @@ websocket-extensions@>=0.1.1: integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== websocket@^1.0.28: - version "1.0.30" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.30.tgz#91d3bd00c3d43e916f0cf962f8f8c451bb0b2373" - integrity sha512-aO6klgaTdSMkhfl5VVJzD5fm+Srhh5jLYbS15+OiI1sN6h/RU/XW6WN9J1uVIpUKNmsTvT3Hs35XAFjn9NMfOw== + version "1.0.31" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.31.tgz#e5d0f16c3340ed87670e489ecae6144c79358730" + integrity sha512-VAouplvGKPiKFDTeCCO65vYHsyay8DqoBSlzIO3fayrfOgU94lQN5a1uWVnFrMLceTJw/+fQXR5PGbUVRaHshQ== dependencies: debug "^2.2.0" + es5-ext "^0.10.50" nan "^2.14.0" typedarray-to-buffer "^3.1.5" yaeti "^0.0.6" @@ -12349,14 +12518,21 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1, which@^1.1.1, which@^1.2.10, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: +which@1.3.1, which@^1.1.1, which@^1.2.10, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: 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.0: +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3, wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== @@ -12558,6 +12734,14 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yargs-parser@13.1.1, yargs-parser@^13.0.0, yargs-parser@^13.1.0, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" @@ -12573,14 +12757,6 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^13.0.0, yargs-parser@^13.1.0, yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" @@ -12588,30 +12764,14 @@ yargs-parser@^8.1.0: dependencies: camelcase "^4.1.0" -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= - dependencies: - camelcase "^4.1.0" - -yargs@11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" yargs@12.0.5, yargs@^12.0.1, yargs@^12.0.5: version "12.0.5" @@ -12648,6 +12808,22 @@ yargs@13.2.4: y18n "^4.0.0" yargs-parser "^13.1.0" +yargs@13.3.0, yargs@^13.2.2, yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" + yargs@14.0.0: version "14.0.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.0.0.tgz#ba4cacc802b3c0b3e36a9e791723763d57a85066" @@ -12683,40 +12859,6 @@ yargs@^10.0.3: y18n "^3.2.1" yargs-parser "^8.1.0" -yargs@^11.0.0: - version "11.1.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.1.tgz#5052efe3446a4df5ed669c995886cc0f13702766" - integrity sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw== - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^3.1.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" - -yargs@^13.2.2: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.1" - yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"