diff --git a/.babel.config.js b/.babel.config.js index 422df09ab..5716478ee 100644 --- a/.babel.config.js +++ b/.babel.config.js @@ -24,7 +24,7 @@ module.exports = { plugins: [ "add-module-exports", ['@babel/plugin-transform-runtime', { - corejs: false, + corejs: 3, helpers: true, regenerator: false }], diff --git a/.eslintignore b/.eslintignore index 86f9d8952..20d5177ca 100644 --- a/.eslintignore +++ b/.eslintignore @@ -6,3 +6,5 @@ test/legacy/** src/shim/** test/unit/StubbedStreamrClient.js streamr-docker-dev/** +vendor/** +test/exports/** diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 13104dfd5..4176bd4cf 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -48,8 +48,6 @@ jobs: run: npm ci - name: npm run eslint run: npm run eslint - - name: test-types - run: npm run test-types test: name: Test Unit using Node ${{ matrix.node-version }} @@ -107,7 +105,7 @@ jobs: - name: npm ci run: npm ci - name: Start Streamr Docker Stack - uses: streamr-dev/streamr-docker-dev-action@v1.0.0-alpha.2 + uses: streamr-dev/streamr-docker-dev-action@v1.0.0-alpha.3 with: services-to-start: "mysql redis engine-and-editor cassandra parity-node0 parity-sidechain-node0 bridge broker-node-storage-1 nginx smtp" - name: Run Test @@ -129,7 +127,7 @@ jobs: - name: npm ci run: npm ci - name: Start Streamr Docker Stack - uses: streamr-dev/streamr-docker-dev-action@v1.0.0-alpha.2 + uses: streamr-dev/streamr-docker-dev-action@v1.0.0-alpha.3 with: services-to-start: "mysql redis engine-and-editor cassandra parity-node0 parity-sidechain-node0 bridge broker-node-storage-1 nginx smtp" - uses: nick-invision/retry@v2 @@ -140,6 +138,26 @@ jobs: retry_on: error command: npm run test-flakey || echo "::warning::Flakey Tests Failed" + test-exports: + name: Test Exports using Node 14.x + runs-on: ubuntu-latest + needs: build + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: "14.x" + - uses: actions/download-artifact@v2 + with: + name: build + path: dist + - name: npm ci + run: npm ci + - name: test-types + run: npm run test-types + - name: npm run test-exports + run: npm run test-exports + browser: name: Test Browser using Node 14.x runs-on: ubuntu-latest @@ -156,7 +174,7 @@ jobs: - name: npm ci run: npm ci - name: Start Streamr Docker Stack - uses: streamr-dev/streamr-docker-dev-action@v1.0.0-alpha.2 + uses: streamr-dev/streamr-docker-dev-action@v1.0.0-alpha.3 with: services-to-start: "mysql redis engine-and-editor cassandra parity-node0 parity-sidechain-node0 bridge broker-node-storage-1 nginx smtp" @@ -186,7 +204,7 @@ jobs: name: build path: dist - name: Start Streamr Docker Stack - uses: streamr-dev/streamr-docker-dev-action@v1.0.0-alpha.2 + uses: streamr-dev/streamr-docker-dev-action@v1.0.0-alpha.3 with: services-to-start: "mysql redis engine-and-editor cassandra parity-node0 parity-sidechain-node0 bridge broker-node-storage-1 nginx smtp" - name: npm ci @@ -233,17 +251,20 @@ jobs: name: build path: dist - name: Start Streamr Docker Stack - uses: streamr-dev/streamr-docker-dev-action@v1.0.0-alpha.2 + uses: streamr-dev/streamr-docker-dev-action@v1.0.0-alpha.3 with: services-to-start: "mysql redis engine-and-editor cassandra parity-node0 parity-sidechain-node0 bridge broker-node-storage-1 nginx smtp" - name: npm ci run: npm ci - name: npm link - run: npm link + run: cd dist && npm link - uses: actions/checkout@v2 with: repository: streamr-dev/streamr-client-testing path: streamr-client-testing + - uses: actions/setup-java@v1 + with: + java-version: '8' - name: setup-client-testing working-directory: streamr-client-testing run: | diff --git a/.gitignore b/.gitignore index 409d3b4a3..c55ede7b5 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,6 @@ examples/webpack/dist/* reports tests_outputbenchmarks.txt tests_output +test/exports/dist +test/exports/package-lock.json +vendor diff --git a/README.md b/README.md index f2a088ead..b91bff58e 100644 --- a/README.md +++ b/README.md @@ -43,10 +43,10 @@ const client = new StreamrClient({ }) ``` -When using Node.js remember to require the library with: +When using Node.js remember to import the library with: ```js -const StreamrClient = require('streamr-client') +import { StreamrClient } from 'streamr-client'; ``` ### Subscribing to real-time events in a stream @@ -329,11 +329,15 @@ This library provides functions for working with Data Unions. To get a DataUnion TODO: All `options`-parameters should be documented (see TypeScript interfaces for the definitions) These DataUnion-specific options are used from `StreamrClient` options: -| Property | Default | Description | -| :----------------------- | :----------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------- | -| tokenAddress | 0x0Cf0Ee637
88A0849fE52
97F3407f701
E122cC023 | Token used by the DU | -| factoryMainnetAddress | TODO | Data Union factory that creates a new Data Union | -| minimumWithdrawTokenWei | 1000000 | Threshold value set in AMB configs, smallest token amount that can pass over the bridge | +| Property | Default | Description | +| :---------------------------------- | :----------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------- | +| tokenAddress | 0x0Cf0Ee637
88A0849fE52
97F3407f701
E122cC023 | Token used by the DU | +| dataUnion.minimumWithdrawTokenWei | 1000000 | Threshold value set in AMB configs, smallest token amount that can pass over the bridge | +| dataUnion.freeWithdraw | false | true = someone else pays for the gas when transporting the withdraw tx to mainnet; false = client does the transport as self-service and pays the mainnet gas costs | +| dataUnion.factoryMainnetAddress | TODO | Data Union factory that creates a new Data Union | +| dataUnion.factorySidechainAddress | TODO | | +| dataUnion.templateMainnetAddress | TODO | | +| dataUnion.templateSidechainAddress | TODO | | ### Admin Functions diff --git a/copy-package.js b/copy-package.js new file mode 100644 index 000000000..43b27d153 --- /dev/null +++ b/copy-package.js @@ -0,0 +1,15 @@ +const fs = require('fs') +// eslint-disable-next-line +const pkg = Object.assign({}, require('./package.json')) + +delete pkg.scripts + +try { + fs.mkdirSync('./dist/') +} catch (err) { + if (err.code !== 'EEXIST') { + throw err + } +} + +fs.writeFileSync('./dist/package.json', JSON.stringify(pkg, null, 2)) diff --git a/examples/node/node-example-produce.js b/examples/node/node-example-produce.js index 25a6bb95f..310711fe8 100644 --- a/examples/node/node-example-produce.js +++ b/examples/node/node-example-produce.js @@ -1,4 +1,4 @@ -const StreamrClient = require('streamr-client') +import { StreamrClient } from 'streamr-client'; // Create the client and supply either an API key or an Ethereum private key to authenticate const client = new StreamrClient({ diff --git a/examples/node/node-example-subscribe.js b/examples/node/node-example-subscribe.js index a38d06ff2..05f0ce2a7 100644 --- a/examples/node/node-example-subscribe.js +++ b/examples/node/node-example-subscribe.js @@ -1,4 +1,4 @@ -const StreamrClient = require('streamr-client') +import { StreamrClient } from 'streamr-client'; // Create the client and supply either an API key or an Ethereum private key to authenticate const client = new StreamrClient({ diff --git a/package-lock.json b/package-lock.json index aa1c75f20..d93fdbc59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2636,13 +2636,13 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.2.tgz", - "integrity": "sha512-uiQQeu9tWl3f1+oK0yoAv9lt/KXO24iafxgQTkIYO/kitruILGx3uH+QtIAHqxFV+yIsdnJH+alel9KuE3J15Q==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.17.0.tgz", + "integrity": "sha512-/fKFDcoHg8oNan39IKFOb5WmV7oWhQe1K6CDaAVfJaNWEhmfqlA24g+u1lqU5bMH7zuNasfMId4LaYWC5ijRLw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.15.2", - "@typescript-eslint/scope-manager": "4.15.2", + "@typescript-eslint/experimental-utils": "4.17.0", + "@typescript-eslint/scope-manager": "4.17.0", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "lodash": "^4.17.15", @@ -2663,55 +2663,55 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.2.tgz", - "integrity": "sha512-Fxoshw8+R5X3/Vmqwsjc8nRO/7iTysRtDqx6rlfLZ7HbT8TZhPeQqbPjTyk2RheH3L8afumecTQnUc9EeXxohQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.17.0.tgz", + "integrity": "sha512-ZR2NIUbnIBj+LGqCFGQ9yk2EBQrpVVFOh9/Kd0Lm6gLpSAcCuLLe5lUCibKGCqyH9HPwYC0GIJce2O1i8VYmWA==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.15.2", - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/typescript-estree": "4.15.2", + "@typescript-eslint/scope-manager": "4.17.0", + "@typescript-eslint/types": "4.17.0", + "@typescript-eslint/typescript-estree": "4.17.0", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" } }, "@typescript-eslint/parser": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.2.tgz", - "integrity": "sha512-SHeF8xbsC6z2FKXsaTb1tBCf0QZsjJ94H6Bo51Y1aVEZ4XAefaw5ZAilMoDPlGghe+qtq7XdTiDlGfVTOmvA+Q==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.17.0.tgz", + "integrity": "sha512-KYdksiZQ0N1t+6qpnl6JeK9ycCFprS9xBAiIrw4gSphqONt8wydBw4BXJi3C11ywZmyHulvMaLjWsxDjUSDwAw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.15.2", - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/typescript-estree": "4.15.2", + "@typescript-eslint/scope-manager": "4.17.0", + "@typescript-eslint/types": "4.17.0", + "@typescript-eslint/typescript-estree": "4.17.0", "debug": "^4.1.1" } }, "@typescript-eslint/scope-manager": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.2.tgz", - "integrity": "sha512-Zm0tf/MSKuX6aeJmuXexgdVyxT9/oJJhaCkijv0DvJVT3ui4zY6XYd6iwIo/8GEZGy43cd7w1rFMiCLHbRzAPQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.17.0.tgz", + "integrity": "sha512-OJ+CeTliuW+UZ9qgULrnGpPQ1bhrZNFpfT/Bc0pzNeyZwMik7/ykJ0JHnQ7krHanFN9wcnPK89pwn84cRUmYjw==", "dev": true, "requires": { - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/visitor-keys": "4.15.2" + "@typescript-eslint/types": "4.17.0", + "@typescript-eslint/visitor-keys": "4.17.0" } }, "@typescript-eslint/types": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.2.tgz", - "integrity": "sha512-r7lW7HFkAarfUylJ2tKndyO9njwSyoy6cpfDKWPX6/ctZA+QyaYscAHXVAfJqtnY6aaTwDYrOhp+ginlbc7HfQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.17.0.tgz", + "integrity": "sha512-RN5z8qYpJ+kXwnLlyzZkiJwfW2AY458Bf8WqllkondQIcN2ZxQowAToGSd9BlAUZDB5Ea8I6mqL2quGYCLT+2g==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.2.tgz", - "integrity": "sha512-cGR8C2g5SPtHTQvAymEODeqx90pJHadWsgTtx6GbnTWKqsg7yp6Eaya9nFzUd4KrKhxdYTTFBiYeTPQaz/l8bw==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.17.0.tgz", + "integrity": "sha512-lRhSFIZKUEPPWpWfwuZBH9trYIEJSI0vYsrxbvVvNyIUDoKWaklOAelsSkeh3E2VBSZiNe9BZ4E5tYBZbUczVQ==", "dev": true, "requires": { - "@typescript-eslint/types": "4.15.2", - "@typescript-eslint/visitor-keys": "4.15.2", + "@typescript-eslint/types": "4.17.0", + "@typescript-eslint/visitor-keys": "4.17.0", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", @@ -2731,12 +2731,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.2.tgz", - "integrity": "sha512-TME1VgSb7wTwgENN5KVj4Nqg25hP8DisXxNBojM4Nn31rYaNDIocNm5cmjOFfh42n7NVERxWrDFoETO/76ePyg==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.17.0.tgz", + "integrity": "sha512-WfuMN8mm5SSqXuAr9NM+fItJ0SVVphobWYkWOwQ1odsfC014Vdxk/92t4JwS1Q6fCA/ABfCKpa3AVtpUKTNKGQ==", "dev": true, "requires": { - "@typescript-eslint/types": "4.15.2", + "@typescript-eslint/types": "4.17.0", "eslint-visitor-keys": "^2.0.0" } }, @@ -13088,9 +13088,9 @@ "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" }, "tsutils": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.20.0.tgz", - "integrity": "sha512-RYbuQuvkhuqVeXweWT3tJLKOEJ/UUw9GjNEZGWdrLLlM+611o1gwLHBpxoFJKKl25fLprp2eVthtKs5JOrNeXg==", + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "requires": { "tslib": "^1.8.1" @@ -13160,9 +13160,9 @@ } }, "typescript": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.5.tgz", - "integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", + "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", "dev": true }, "unicode-canonical-property-names-ecmascript": { diff --git a/package.json b/package.json index c1a03e99f..c3a37e03f 100644 --- a/package.json +++ b/package.json @@ -6,18 +6,29 @@ "type": "git", "url": "git://github.com/streamr-dev/streamr-client.git" }, - "types": "dist/types/src/StreamrClient.d.ts", - "main": "dist/node/src/StreamrClient.js", - "browser": "dist/streamr-client.web.min.js", - "directories": { - "example": "examples", - "test": "test" + "types": "./types/src/index.d.ts", + "main": "./src/index-commonjs.js", + "browser": "./streamr-client.web.js", + "exports": { + "browser": "./streamr-client.web.js", + "default": { + "import": "./src/index-esm.mjs", + "require": "./src/index-commonjs.js" + } }, "scripts": { - "build": "rm -rf dist; NODE_ENV=production webpack --mode=production --progress && npm run build-node && npm run build:types", - "build-node": "tsc --incremental --project ./tsconfig.node.json", - "watch-node": "tsc --incremental --watch --project ./tsconfig.node.json", - "build:types": "tsc --incremental --emitDeclarationOnly", + "build": "rm -rf dist; rm -rf vendor; npm run bootstrap-dist && npm run build-browser && npm run build-node && npm run build:types", + "postinstall": "npm run vendor", + "build-node": "npm run bootstrap-dist && tsc --incremental --project ./tsconfig.node.json", + "postbuild-node": "npm run copy-package", + "build-browser": "npm run bootstrap-dist && NODE_ENV=production webpack --mode=production --progress ", + "watch-browser": "npm run bootstrap-dist && webpack --progress --watch", + "watch-node": "npm run bootstrap-dist && tsc --incremental --watch --project ./tsconfig.node.json", + "bootstrap-dist": "npm run vendor && npm run copy-package && npm run fix-esm", + "fix-esm": "mkdir -p dist/src/; cp -Rf src/index-esm.mjs dist/src/index-esm.mjs", + "vendor": "mkdir -p vendor/quick-lru; cp -n node_modules/quick-lru/index.d.ts vendor/quick-lru; cp -n node_modules/quick-lru/index.js vendor/quick-lru; true", + "copy-package": "mkdir -p dist/; node copy-package.js; cp -f package-lock.json dist; true", + "build:types": "tsc --incremental --emitDeclarationOnly --stripInternal", "benchmarks": "node test/benchmarks/publish.js && node test/benchmarks/subscribe.js", "prebuild-benchmark": "npm run build -- --config-name=node-lib", "build-benchmark": "npm run benchmarks", @@ -29,9 +40,10 @@ "eslint": "eslint --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'", "test": "jest --detectOpenHandles", "test-unit": "jest test/unit --detectOpenHandles", - "test-types": "tsc --noEmit --incremental --project ./tsconfig.test.json", + "test-types": "(cd test/exports && npm run link) && tsc --noEmit --incremental --project ./tsconfig.test.json", "coverage": "jest --coverage", "test-integration": "jest --forceExit test/integration", + "test-exports": "cd test/exports && npm run link && npm test", "test-integration-no-resend": "jest --forceExit --testTimeout=10000 --testPathIgnorePatterns='resend|Resend' --testNamePattern='^((?!(resend|Resend|resent|Resent|gap|Gap)).)*$' test/integration/*.test.js", "test-integration-resend": "jest --forceExit --testTimeout=15000 --testNamePattern='(resend|Resend|resent|Resent)' test/integration/*.test.js", "test-integration-dataunions": "jest --forceExit --testTimeout=15000 --runInBand test/integration/dataunion", @@ -39,7 +51,7 @@ "test-browser": "node ./test/browser/server.js & node node_modules/nightwatch/bin/nightwatch ./test/browser/browser.js && pkill -f server.js", "install-example": "cd examples/webpack && npm ci", "build-example": "cd examples/webpack && npm run build-with-parent", - "clear-cache": "rm -rf node_modules/.cache; rm -rf .cache; rm -rf dist; jest --clearCache;" + "clear-cache": "rm -rf node_modules/.cache; rm -rf .cache; rm -rf dist; rm -rf vendor; jest --clearCache;" }, "engines": { "node": ">= 12" @@ -67,8 +79,8 @@ "@types/sinon": "^9.0.10", "@types/uuid": "^8.3.0", "@types/ws": "^7.4.0", - "@typescript-eslint/eslint-plugin": "^4.15.1", - "@typescript-eslint/parser": "^4.15.1", + "@typescript-eslint/eslint-plugin": "^4.17.0", + "@typescript-eslint/parser": "^4.17.0", "babel-loader": "^8.2.2", "babel-plugin-add-module-exports": "^1.0.4", "babel-plugin-transform-class-properties": "^6.24.1", @@ -96,7 +108,7 @@ "terser-webpack-plugin": "^5.1.1", "ts-jest": "^26.5.1", "ts-loader": "^8.0.17", - "typescript": "^4.1.5", + "typescript": "^4.2.3", "util": "^0.12.3", "webpack": "^5.23.0", "webpack-bundle-analyzer": "^4.4.0", diff --git a/src/Config.ts b/src/Config.ts index 54d903dc9..03bd9c89d 100644 --- a/src/Config.ts +++ b/src/Config.ts @@ -4,13 +4,13 @@ import { ExternalProvider, JsonRpcFetchFunc } from '@ethersproject/providers' import { BigNumber } from '@ethersproject/bignumber' import { getVersionString } from './utils' import { ConnectionInfo } from '@ethersproject/web' -import { Todo } from './types' +import { EthereumAddress, Todo } from './types' export type EthereumConfig = ExternalProvider|JsonRpcFetchFunc -export type StreamrClientOptions = { +export type StrictStreamrClientOptions = { auth: { - privateKey?: string + privateKey?: EthereumAddress ethereum?: EthereumConfig apiKey?: string username?: string @@ -18,7 +18,7 @@ export type StreamrClientOptions = { } url: string restUrl: string - streamrNodeAddress: string + streamrNodeAddress: EthereumAddress autoConnect: boolean autoDisconnect: boolean orderMessages: boolean @@ -33,23 +33,29 @@ export type StreamrClientOptions = { keyExchange: Todo mainnet?: ConnectionInfo|string sidechain?: ConnectionInfo|string - dataUnion?: string - tokenAddress: string, - minimumWithdrawTokenWei?: BigNumber|number|string - factoryMainnetAddress: string - factorySidechainAddress: string - payForSignatureTransport: boolean + tokenAddress: EthereumAddress, + dataUnion: { + minimumWithdrawTokenWei: BigNumber|number|string + freeWithdraw: boolean + factoryMainnetAddress: EthereumAddress + factorySidechainAddress: EthereumAddress + templateMainnetAddress: EthereumAddress + templateSidechainAddress: EthereumAddress + }, cache: { maxSize: number, maxAge: number } } +export type StreamrClientOptions = Partial & { dataUnion: Partial}> + const { ControlMessage } = ControlLayer const { StreamMessage } = MessageLayer -export default function ClientConfig(opts: Partial = {}) { - const defaults: StreamrClientOptions = { +/** @internal */ +export default function ClientConfig(opts: StreamrClientOptions = {}) { + const defaults: StrictStreamrClientOptions = { // Authentication: identity used by this StreamrClient instance auth: {}, // can contain member privateKey or (window.)ethereum @@ -77,21 +83,29 @@ export default function ClientConfig(opts: Partial = {}) { // Ethereum and Data Union related options // For ethers.js provider params, see https://docs.ethers.io/ethers.js/v5-beta/api-providers.html#provider mainnet: undefined, // Default to ethers.js default provider settings - sidechain: undefined, // TODO: add our default public service sidechain node, also find good PoA params below + sidechain: 'https://rpc.xdaichain.com/', tokenAddress: '0x0Cf0Ee63788A0849fE5297F3407f701E122cC023', - minimumWithdrawTokenWei: '1000000', // Threshold value set in AMB configs, smallest token amount to pass over the bridge - factoryMainnetAddress: 'TODO', // TODO // Data Union factory that creates a new Data Union - factorySidechainAddress: 'TODO', - payForSignatureTransport: true, // someone must pay for transporting the withdraw tx to mainnet, either us or bridge operator + dataUnion: { + minimumWithdrawTokenWei: '1000000', // Threshold value set in AMB configs, smallest token amount to pass over the bridge + freeWithdraw: false, // if someone else pays for the gas when transporting the withdraw tx to mainnet; otherwise the client does the transport as self-service and pays the mainnet gas costs + factoryMainnetAddress: '0x7d55f9981d4E10A193314E001b96f72FCc901e40', + factorySidechainAddress: '0x1b55587Beea0b5Bc96Bb2ADa56bD692870522e9f', + templateMainnetAddress: '0x5FE790E3751dd775Cb92e9086Acd34a2adeB8C7b', + templateSidechainAddress: '0xf1E9d6E254BeA3f0129018AcA1A50AEcb7D528be', + }, cache: { maxSize: 10000, maxAge: 30 * 60 * 1000, // 30 minutes } } - const options: StreamrClientOptions = { + const options: StrictStreamrClientOptions = { ...defaults, ...opts, + dataUnion: { + ...defaults.dataUnion, + ...opts.dataUnion + }, cache: { ...opts.cache, ...defaults.cache, diff --git a/src/Session.ts b/src/Session.ts index c3cd2397f..ef349071b 100644 --- a/src/Session.ts +++ b/src/Session.ts @@ -1,7 +1,8 @@ import EventEmitter from 'eventemitter3' import { Wallet } from '@ethersproject/wallet' import { ExternalProvider, JsonRpcFetchFunc, Web3Provider } from '@ethersproject/providers' -import StreamrClient from './StreamrClient' +import { StreamrClient } from './StreamrClient' +import { EthereumAddress } from './types' enum State { LOGGING_OUT = 'logging out', @@ -11,7 +12,7 @@ enum State { } export interface SessionOptions { - privateKey?: string + privateKey?: EthereumAddress ethereum?: ExternalProvider|JsonRpcFetchFunc apiKey?: string username?: string @@ -20,10 +21,11 @@ export interface SessionOptions { unauthenticated?: boolean } -export interface TokenObject { +interface TokenObject { token: string } +/** @internal */ export default class Session extends EventEmitter { _client: StreamrClient diff --git a/src/StreamrClient.ts b/src/StreamrClient.ts index 74f368769..bcd105fcf 100644 --- a/src/StreamrClient.ts +++ b/src/StreamrClient.ts @@ -4,14 +4,14 @@ import Debug from 'debug' import { counterId, uuid, CacheAsyncFn } from './utils' import { validateOptions } from './stream/utils' -import Config, { StreamrClientOptions } from './Config' +import Config, { StreamrClientOptions, StrictStreamrClientOptions } from './Config' import StreamrEthereum from './Ethereum' import Session from './Session' import Connection, { ConnectionError } from './Connection' import Publisher from './publish' -import Subscriber from './subscribe' +import { Subscriber } from './subscribe' import { getUserId } from './user' -import { Todo, MaybeAsync } from './types' +import { Todo, MaybeAsync, EthereumAddress } from './types' import { StreamEndpoints } from './rest/StreamEndpoints' import { LoginEndpoints } from './rest/LoginEndpoints' import { DataUnion, DataUnionDeployOptions } from './dataunion/DataUnion' @@ -26,8 +26,6 @@ interface MessageEvent { data: any } -export { StreamrClientOptions } - /** * Wrap connection message events with message parsing. */ @@ -139,13 +137,14 @@ function Plugin(targetInstance: any, srcInstance: any) { } // these are mixed in via Plugin function above -interface StreamrClient extends StreamEndpoints, LoginEndpoints {} +export interface StreamrClient extends StreamEndpoints, LoginEndpoints {} // eslint-disable-next-line no-redeclare -class StreamrClient extends EventEmitter { +export class StreamrClient extends EventEmitter { id: string debug: Debug.Debugger - options: StreamrClientOptions + options: StrictStreamrClientOptions + /** @internal */ session: Session connection: StreamrConnection publisher: Todo @@ -155,7 +154,7 @@ class StreamrClient extends EventEmitter { streamEndpoints: StreamEndpoints loginEndpoints: LoginEndpoints - constructor(options: Partial = {}, connection?: StreamrConnection) { + constructor(options: StreamrClientOptions = {}, connection?: StreamrConnection) { super() this.id = counterId(`${this.constructor.name}:${uid}`) this.debug = Debug(this.id) @@ -379,7 +378,7 @@ class StreamrClient extends EventEmitter { /** * Get token balance in "wei" (10^-18 parts) for given address */ - async getTokenBalance(address: string): Promise { + async getTokenBalance(address: EthereumAddress): Promise { const { tokenAddress } = this.options if (!tokenAddress) { throw new Error('StreamrClient has no tokenAddress configuration.') @@ -399,7 +398,7 @@ class StreamrClient extends EventEmitter { return token.balanceOf(addr) } - getDataUnion(contractAddress: string) { + getDataUnion(contractAddress: EthereumAddress) { return DataUnion._fromContractAddress(contractAddress, this) // eslint-disable-line no-underscore-dangle } @@ -407,7 +406,7 @@ class StreamrClient extends EventEmitter { return DataUnion._deploy(options, this) // eslint-disable-line no-underscore-dangle } - _getDataUnionFromName({ dataUnionName, deployerAddress }: { dataUnionName: string, deployerAddress: string}) { + _getDataUnionFromName({ dataUnionName, deployerAddress }: { dataUnionName: string, deployerAddress: EthereumAddress}) { return DataUnion._fromName({ // eslint-disable-line no-underscore-dangle dataUnionName, deployerAddress @@ -418,7 +417,3 @@ class StreamrClient extends EventEmitter { return StreamrEthereum.generateEthereumAccount() } } - -export default StreamrClient - -module.exports = StreamrClient diff --git a/src/dataunion/Contracts.ts b/src/dataunion/Contracts.ts index dcb7bdd80..f4f65f3c6 100644 --- a/src/dataunion/Contracts.ts +++ b/src/dataunion/Contracts.ts @@ -10,21 +10,25 @@ import { dataUnionMainnetABI, dataUnionSidechainABI, factoryMainnetABI, mainnetA import { until } from '../utils' import { BigNumber } from '@ethersproject/bignumber' import StreamrEthereum from '../Ethereum' -import StreamrClient from '../StreamrClient' +import { StreamrClient } from '../StreamrClient' const log = debug('StreamrClient::DataUnion') export class Contracts { ethereum: StreamrEthereum - factoryMainnetAddress: string - factorySidechainAddress: string + factoryMainnetAddress: EthereumAddress + factorySidechainAddress: EthereumAddress + templateMainnetAddress: EthereumAddress + templateSidechainAddress: EthereumAddress cachedSidechainAmb?: Todo constructor(client: StreamrClient) { this.ethereum = client.ethereum - this.factoryMainnetAddress = client.options.factoryMainnetAddress - this.factorySidechainAddress = client.options.factorySidechainAddress + this.factoryMainnetAddress = client.options.dataUnion.factoryMainnetAddress + this.factorySidechainAddress = client.options.dataUnion.factorySidechainAddress + this.templateMainnetAddress = client.options.dataUnion.templateMainnetAddress + this.templateSidechainAddress = client.options.dataUnion.templateSidechainAddress } async fetchDataUnionMainnetAddress( @@ -37,11 +41,15 @@ export class Contracts { } getDataUnionMainnetAddress(dataUnionName: string, deployerAddress: EthereumAddress) { - if (!this.factoryMainnetAddress) { - throw new Error('StreamrClient has no factoryMainnetAddress configuration.') + if (!isAddress(this.factoryMainnetAddress)) { + throw new Error('StreamrClient factoryMainnetAddress configuration is ' + (this.factoryMainnetAddress ? 'not a valid Ethereum address' : 'missing')) + } + + if (!isAddress(this.templateMainnetAddress)) { + throw new Error('StreamrClient templateMainnetAddress configuration is ' + (this.templateMainnetAddress ? 'not a valid Ethereum address' : 'missing')) } - // NOTE! this must be updated when DU sidechain smartcontract changes: keccak256(CloneLib.cloneBytecode(data_union_mainnet_template)); - const codeHash = '0x50a78bac973bdccfc8415d7d9cfd62898b8f7cf6e9b3a15e7d75c0cb820529eb' + // This magic hex comes from https://github.com/streamr-dev/data-union-solidity/blob/master/contracts/CloneLib.sol#L19 + const codeHash = keccak256(`0x3d602d80600a3d3981f3363d3d373d3d3d363d73${this.templateMainnetAddress.slice(2)}5af43d82803e903d91602b57fd5bf3`) const salt = keccak256(defaultAbiCoder.encode(['string', 'address'], [dataUnionName, deployerAddress])) return getCreate2Address(this.factoryMainnetAddress, salt, codeHash) } @@ -53,11 +61,15 @@ export class Contracts { } getDataUnionSidechainAddress(mainnetAddress: EthereumAddress) { - if (!this.factorySidechainAddress) { - throw new Error('StreamrClient has no factorySidechainAddress configuration.') + if (!isAddress(this.factorySidechainAddress)) { + throw new Error('StreamrClient factorySidechainAddress configuration is ' + (this.factorySidechainAddress ? 'not a valid Ethereum address' : 'missing')) } - // NOTE! this must be updated when DU sidechain smartcontract changes: keccak256(CloneLib.cloneBytecode(data_union_sidechain_template)) - const codeHash = '0x040cf686e25c97f74a23a4bf01c29dd77e260c4b694f5611017ce9713f58de83' + + if (!isAddress(this.templateSidechainAddress)) { + throw new Error('StreamrClient templateSidechainAddress configuration is ' + (this.templateSidechainAddress ? 'not a valid Ethereum address' : 'missing')) + } + // This magic hex comes from https://github.com/streamr-dev/data-union-solidity/blob/master/contracts/CloneLib.sol#L19 + const codeHash = keccak256(`0x3d602d80600a3d3981f3363d3d373d3d3d363d73${this.templateSidechainAddress.slice(2)}5af43d82803e903d91602b57fd5bf3`) return getCreate2Address(this.factorySidechainAddress, hexZeroPad(mainnetAddress, 32), codeHash) } @@ -95,11 +107,8 @@ export class Contracts { async getSidechainAmb() { if (!this.cachedSidechainAmb) { const getAmbPromise = async () => { - const mainnetProvider = this.ethereum.getMainnetProvider() - const factoryMainnet = new Contract(this.factoryMainnetAddress, factoryMainnetABI, mainnetProvider) const sidechainProvider = this.ethereum.getSidechainProvider() - const factorySidechainAddress = await factoryMainnet.data_union_sidechain_factory() // TODO use getDataUnionSidechainAddress() - const factorySidechain = new Contract(factorySidechainAddress, [{ + const factorySidechain = new Contract(this.factorySidechainAddress, [{ name: 'amb', inputs: [], outputs: [{ type: 'address' }], @@ -137,7 +146,7 @@ export class Contracts { } // move signatures from sidechain to mainnet - async transportSignatures(messageHash: string) { + async transportSignaturesForMessage(messageHash: string) { const sidechainAmb = await this.getSidechainAmb() const message = await sidechainAmb.message(messageHash) const messageId = '0x' + message.substr(2, 64) @@ -171,7 +180,7 @@ export class Contracts { const alreadyProcessed = await mainnetAmb.relayedMessages(messageId) if (alreadyProcessed) { log(`WARNING: Tried to transport signatures but they have already been transported (Message ${messageId} has already been processed)`) - log('This could happen if payForSignatureTransport=true, but bridge operator also pays for signatures, and got there before your client') + log('This could happen if freeWithdraw=false (attempt self-service), but bridge actually paid before your client') return null } @@ -218,7 +227,7 @@ export class Contracts { return trAMB } - async payForSignatureTransport(tr: ContractReceipt, options: { pollingIntervalMs?: number, retryTimeoutMs?: number } = {}) { + async transportSignaturesForTransaction(tr: ContractReceipt, options: { pollingIntervalMs?: number, retryTimeoutMs?: number } = {}) { const { pollingIntervalMs = 1000, retryTimeoutMs = 60000, @@ -229,6 +238,7 @@ export class Contracts { if (sigEventArgsArray.length < 1) { throw new Error("No UserRequestForSignature events emitted from withdraw transaction, can't transport withdraw to mainnet") } + /* eslint-disable no-await-in-loop */ // eslint-disable-next-line no-restricted-syntax for (const eventArgs of sigEventArgsArray) { @@ -242,17 +252,16 @@ export class Contracts { const mainnetAmb = await this.getMainnetAmb() const alreadySent = await mainnetAmb.messageCallStatus(messageId) const failAddress = await mainnetAmb.failedMessageSender(messageId) - if (alreadySent || failAddress !== '0x0000000000000000000000000000000000000000') { // zero address means no failed messages + + // zero address means no failed messages + if (alreadySent || failAddress !== '0x0000000000000000000000000000000000000000') { log(`WARNING: Mainnet bridge has already processed withdraw messageId=${messageId}`) - log([ - 'This could happen if payForSignatureTransport=true, but bridge operator also pays for', - 'signatures, and got there before your client', - ].join(' ')) + log('This could happen if freeWithdraw=false (attempt self-service), but bridge actually paid before your client') continue } log(`Transporting signatures for hash=${messageHash}`) - await this.transportSignatures(messageHash) + await this.transportSignaturesForMessage(messageHash) } /* eslint-enable no-await-in-loop */ } @@ -294,7 +303,7 @@ export class Contracts { } if (await mainnetProvider.getCode(this.factoryMainnetAddress) === '0x') { - throw new Error(`Data union factory contract not found at ${this.factoryMainnetAddress}, check StreamrClient.options.factoryMainnetAddress!`) + throw new Error(`Data union factory contract not found at ${this.factoryMainnetAddress}, check StreamrClient.options.dataUnion.factoryMainnetAddress!`) } const factoryMainnet = new Contract(this.factoryMainnetAddress!, factoryMainnetABI, mainnetWallet) diff --git a/src/dataunion/DataUnion.ts b/src/dataunion/DataUnion.ts index 3fe0e304e..2c92d2b77 100644 --- a/src/dataunion/DataUnion.ts +++ b/src/dataunion/DataUnion.ts @@ -5,7 +5,7 @@ import { Contract } from '@ethersproject/contracts' import { TransactionReceipt, TransactionResponse } from '@ethersproject/providers' import debug from 'debug' import { Contracts } from './Contracts' -import StreamrClient from '../StreamrClient' +import { StreamrClient } from '../StreamrClient' import { EthereumAddress } from '../types' import { until, getEndpointUrl } from '../utils' import authFetch from '../rest/authFetch' @@ -35,7 +35,7 @@ export interface JoinResponse { export interface DataUnionWithdrawOptions { pollingIntervalMs?: number retryTimeoutMs?: number - payForSignatureTransport?: boolean + freeWithdraw?: boolean } export interface DataUnionMemberListModificationOptions { @@ -153,9 +153,9 @@ export class DataUnion { throw new Error(`${address} has nothing to withdraw in (sidechain) data union ${duSidechain.address}`) } - if (this.client.options.minimumWithdrawTokenWei && withdrawable.lt(this.client.options.minimumWithdrawTokenWei)) { + if (this.client.options.dataUnion.minimumWithdrawTokenWei && withdrawable.lt(this.client.options.dataUnion.minimumWithdrawTokenWei)) { throw new Error(`${address} has only ${withdrawable} to withdraw in ` - + `(sidechain) data union ${duSidechain.address} (min: ${this.client.options.minimumWithdrawTokenWei})`) + + `(sidechain) data union ${duSidechain.address} (min: ${this.client.options.dataUnion.minimumWithdrawTokenWei})`) } return duSidechain.withdrawAll(address, true) // sendToMainnet=true } @@ -546,14 +546,14 @@ export class DataUnion { const { pollingIntervalMs = 1000, retryTimeoutMs = 60000, - payForSignatureTransport = this.client.options.payForSignatureTransport + freeWithdraw = this.client.options.dataUnion.freeWithdraw }: any = options const getBalanceFunc = () => this.client.getTokenBalance(recipientAddress) const balanceBefore = await getBalanceFunc() const tx = await getWithdrawTxFunc() const tr = await tx.wait() - if (payForSignatureTransport) { - await this.getContracts().payForSignatureTransport(tr, options) + if (!freeWithdraw) { + await this.getContracts().transportSignaturesForTransaction(tr, options) } log(`Waiting for balance ${balanceBefore.toString()} to change`) await until(async () => !(await getBalanceFunc()).eq(balanceBefore), retryTimeoutMs, pollingIntervalMs) diff --git a/src/index-commonjs.js b/src/index-commonjs.js new file mode 100644 index 000000000..50b0515ef --- /dev/null +++ b/src/index-commonjs.js @@ -0,0 +1,5 @@ +const Client = require('./index') + +// required to get require('streamr-client') instead of require('streamr-client').default +module.exports = Client.default +Object.assign(Client.default, Client) diff --git a/src/index-esm.mjs b/src/index-esm.mjs new file mode 100644 index 000000000..35e094d45 --- /dev/null +++ b/src/index-esm.mjs @@ -0,0 +1,6 @@ +import StreamrClient from './index.js' +// required to get import { DataUnion } from 'streamr-client' to work +export * from './index.js' +// required to get import StreamrClient from 'streamr-client' to work +export default StreamrClient.default +// note this file is manually copied as-is into dist/src since we don't want tsc to compile it to commonjs diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 000000000..bb4b4c70d --- /dev/null +++ b/src/index.ts @@ -0,0 +1,24 @@ +import { StreamrClient } from './StreamrClient' + +export * from './StreamrClient' +export * from './Config' +export * from './stream' +export * from './stream/Encryption' +export * from './stream/StreamPart' +export * from './stream/StorageNode' +export * from './subscribe' +export * from './rest/LoginEndpoints' +export * from './rest/StreamEndpoints' +export * from './dataunion/DataUnion' +export * from './rest/authFetch' +export * from './types' + +// TODO should export these to support StreamMessageAsObject: export { StreamMessageType, ContentType, EncryptionType, SignatureType } from 'streamr-client-protocol/dist/src/protocol/message_layer/StreamMessage' +export { BigNumber } from '@ethersproject/bignumber' +export { ConnectionInfo } from '@ethersproject/web' +export { Contract } from '@ethersproject/contracts' +export { TransactionReceipt, TransactionResponse } from '@ethersproject/providers' + +export default StreamrClient + +// Note awful export wrappers in index-commonjs.js & index-esm.mjs diff --git a/src/publish/Encrypt.ts b/src/publish/Encrypt.ts index 0dbde22d4..b35e265b4 100644 --- a/src/publish/Encrypt.ts +++ b/src/publish/Encrypt.ts @@ -1,8 +1,8 @@ import { MessageLayer } from 'streamr-client-protocol' import EncryptionUtil from '../stream/Encryption' -import type Stream from '../stream' -import type StreamrClient from '../StreamrClient' +import { Stream } from '../stream' +import { StreamrClient } from '../StreamrClient' import { PublisherKeyExhange } from '../stream/KeyExchange' const { StreamMessage } = MessageLayer diff --git a/src/rest/ErrorCode.ts b/src/rest/ErrorCode.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/rest/LoginEndpoints.ts b/src/rest/LoginEndpoints.ts index 4a70bf49c..56e38f89d 100644 --- a/src/rest/LoginEndpoints.ts +++ b/src/rest/LoginEndpoints.ts @@ -1,4 +1,4 @@ -import StreamrClient from '../StreamrClient' +import { StreamrClient } from '../StreamrClient' import { getEndpointUrl } from '../utils' import authFetch, { AuthFetchError } from './authFetch' @@ -25,6 +25,7 @@ async function getSessionToken(url: string, props: any) { ) } +/** TODO the class should be annotated with at-internal, but adding the annotation hides the methods */ export class LoginEndpoints { client: StreamrClient diff --git a/src/rest/StreamEndpoints.ts b/src/rest/StreamEndpoints.ts index 3e4c1d3b3..a1b9426f3 100644 --- a/src/rest/StreamEndpoints.ts +++ b/src/rest/StreamEndpoints.ts @@ -6,13 +6,13 @@ import debugFactory from 'debug' import { getEndpointUrl } from '../utils' import { validateOptions } from '../stream/utils' -import Stream, { StreamOperation, StreamProperties } from '../stream' +import { Stream, StreamOperation, StreamProperties } from '../stream' import StreamPart from '../stream/StreamPart' import { isKeyExchangeStream } from '../stream/KeyExchange' import authFetch, { ErrorCode, NotFoundError } from './authFetch' -import { Todo } from '../types' -import StreamrClient from '../StreamrClient' +import { EthereumAddress, Todo } from '../types' +import { StreamrClient } from '../StreamrClient' // TODO change this import when streamr-client-protocol exports StreamMessage type or the enums types directly import { ContentType, EncryptionType, SignatureType, StreamMessageType } from 'streamr-client-protocol/dist/src/protocol/message_layer/StreamMessage' @@ -76,6 +76,7 @@ function getKeepAliveAgentForUrl(url: string) { throw new Error(`Unknown protocol in URL: ${url}`) } +/** TODO the class should be annotated with at-internal, but adding the annotation hides the methods */ export class StreamEndpoints { client: StreamrClient @@ -122,7 +123,7 @@ export class StreamEndpoints { return json[0] ? new Stream(this.client, json[0]) : Promise.reject(new NotFoundError('Stream: name=' + name)) } - async createStream(props?: StreamProperties) { + async createStream(props?: Partial) { this.client.debug('createStream %o', { props, }) @@ -236,11 +237,11 @@ export class StreamEndpoints { + `?${qs.stringify({ count })}` ) - const json = await authFetch(url, this.client.session) + const json = await authFetch(url, this.client.session) return json } - async getStreamPartsByStorageNode(address: string) { + async getStreamPartsByStorageNode(address: EthereumAddress) { type ItemType = { id: string, partitions: number} const json = await authFetch(getEndpointUrl(this.client.options.restUrl, 'storageNodes', address, 'streams'), this.client.session) let result: StreamPart[] = [] diff --git a/src/rest/authFetch.ts b/src/rest/authFetch.ts index 62f9f99f0..f38acb6a2 100644 --- a/src/rest/authFetch.ts +++ b/src/rest/authFetch.ts @@ -66,6 +66,7 @@ const debug = Debug('StreamrClient:utils:authfetch') // TODO: could use the debu let ID = 0 +/** @internal */ export default async function authFetch(url: string, session?: Session, opts?: any, requireNewToken = false): Promise { ID += 1 const timeStart = Date.now() diff --git a/src/stream/Encryption.js b/src/stream/Encryption.js index f682f0c58..d3b2771f1 100644 --- a/src/stream/Encryption.js +++ b/src/stream/Encryption.js @@ -246,6 +246,7 @@ class EncryptionUtilBase { } } +/** @internal */ export default class EncryptionUtil extends EncryptionUtilBase { /** * Creates a new instance + waits for ready. diff --git a/src/stream/StorageNode.ts b/src/stream/StorageNode.ts index 83d223561..2e18d5767 100644 --- a/src/stream/StorageNode.ts +++ b/src/stream/StorageNode.ts @@ -1,6 +1,8 @@ +import { EthereumAddress } from '../types' + export default class StorageNode { - _address: string - constructor(address: string) { + _address: EthereumAddress + constructor(address: EthereumAddress) { this._address = address } diff --git a/src/stream/index.ts b/src/stream/index.ts index 3be723063..9a7496a6c 100644 --- a/src/stream/index.ts +++ b/src/stream/index.ts @@ -2,7 +2,7 @@ import { getEndpointUrl } from '../utils' import authFetch from '../rest/authFetch' import StorageNode from './StorageNode' -import StreamrClient from '../StreamrClient' +import { StreamrClient } from '../StreamrClient' import { Todo } from '../types' interface StreamPermisionBase { @@ -45,7 +45,7 @@ export interface StreamProperties { const VALID_FIELD_TYPES = ['number', 'string', 'boolean', 'list', 'map'] as const -type Field = { +export type Field = { name: string; type: typeof VALID_FIELD_TYPES[number]; } @@ -69,7 +69,7 @@ function getFieldType(value: any): (Field['type'] | undefined) { } } -export default class Stream { +export class Stream { // TODO add field definitions for all fields // @ts-expect-error id: string diff --git a/src/subscribe/index.js b/src/subscribe/index.js index 93cab50e5..591e51c32 100644 --- a/src/subscribe/index.js +++ b/src/subscribe/index.js @@ -464,8 +464,7 @@ class Subscriptions { /** * Top-level user-facing interface for creating/destroying subscriptions. */ - -export default class Subscriber { +export class Subscriber { constructor(client) { this.client = client this.subscriptions = new Subscriptions(client) diff --git a/src/utils/index.ts b/src/utils/index.ts index 9d4e06c46..a0788f679 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,13 +3,13 @@ import EventEmitter from 'events' import { v4 as uuidv4 } from 'uuid' import uniqueId from 'lodash.uniqueid' -import LRU from 'quick-lru' import pMemoize from 'p-memoize' import pLimit from 'p-limit' import mem from 'mem' import { L, F } from 'ts-toolbelt' import pkg from '../../package.json' +import LRU from '../../vendor/quick-lru' import { MaybeAsync } from '../types' import AggregatedError from './AggregatedError' diff --git a/test/benchmarks/publish.js b/test/benchmarks/publish.js index 95b5c3906..a98a158da 100644 --- a/test/benchmarks/publish.js +++ b/test/benchmarks/publish.js @@ -3,9 +3,11 @@ const { format } = require('util') const { Benchmark } = require('benchmark') // eslint-disable-next-line import/no-unresolved -const StreamrClient = require('../..') +const StreamrClient = require('../../dist') const config = require('../integration/config') +console.log('StreamrClient', { StreamrClient }) + /* eslint-disable no-console */ let count = 100000 // pedantic: use large initial number so payload size is similar diff --git a/test/benchmarks/subscribe.js b/test/benchmarks/subscribe.js index 171380169..77c8a658a 100644 --- a/test/benchmarks/subscribe.js +++ b/test/benchmarks/subscribe.js @@ -3,7 +3,7 @@ const { format } = require('util') const { Benchmark } = require('benchmark') // eslint-disable-next-line import/no-unresolved -const StreamrClient = require('../..') +const StreamrClient = require('../../dist') const config = require('../integration/config') /* eslint-disable no-console */ diff --git a/test/exports/package.json b/test/exports/package.json new file mode 100644 index 000000000..fa3878cd1 --- /dev/null +++ b/test/exports/package.json @@ -0,0 +1,22 @@ +{ + "name": "test-streamr-exports", + "version": "1.0.0", + "description": "", + "main": "commonjs.js", + "private": true, + "scripts": { + "pretest": "rm -Rf dist", + "test": "npm run test-commonjs && npm run test-esm && npm run test-ts && npm run webpack", + "build-ts": "tsc --project ./tsconfig.json", + "pretest-ts": "npm run build-ts", + "test-ts": "node dist/typescript.js", + "test-esm": "node tests/esm.mjs", + "test-commonjs": "node tests/commonjs.js", + "webpack": "../../node_modules/.bin/webpack --progress", + "link": "mkdir -p node_modules && ln -fs ../../../dist/ node_modules/streamr-client" + }, + "author": "Tim Oxley ", + "license": "ISC", + "dependencies": { + } +} diff --git a/test/exports/tests/commonjs.js b/test/exports/tests/commonjs.js new file mode 100644 index 000000000..fe77b792e --- /dev/null +++ b/test/exports/tests/commonjs.js @@ -0,0 +1,14 @@ +// checks that require works +const StreamrClient = require('streamr-client') + +console.info('const StreamrClient = require(\'streamr-client\'):', { StreamrClient }) + +const auth = StreamrClient.generateEthereumAccount() +const client = new StreamrClient({ + auth, +}) + +client.connect().then(() => { + console.info('success') + return client.disconnect() +}) diff --git a/test/exports/tests/esm.mjs b/test/exports/tests/esm.mjs new file mode 100644 index 000000000..45c39ab54 --- /dev/null +++ b/test/exports/tests/esm.mjs @@ -0,0 +1,16 @@ +// check esm works, as native and via webpack + babel. Also see typescript.ts +import DefaultExport, * as NamedExports from 'streamr-client' + +console.info('import DefaultExport, * as NamedExports from \'streamr-client\':', { DefaultExport, NamedExports }) + +const StreamrClient = DefaultExport + +const auth = StreamrClient.generateEthereumAccount() +const client = new StreamrClient({ + auth, +}) +console.assert(!!NamedExports.DataUnion, 'NamedExports should have DataUnion') +client.connect().then(() => { + console.info('success') + return client.disconnect() +}) diff --git a/test/exports/tests/typescript.ts b/test/exports/tests/typescript.ts new file mode 100644 index 000000000..7a68f57ee --- /dev/null +++ b/test/exports/tests/typescript.ts @@ -0,0 +1,19 @@ +// check ts esm works via tsc + +import DefaultExport, * as NamedExports from 'streamr-client' + +console.info('import DefaultExport, * as NamedExports from \'streamr-client\':', { DefaultExport, NamedExports }) + +const StreamrClient = DefaultExport + +const auth = StreamrClient.generateEthereumAccount() +const client = new StreamrClient({ + auth, +}) + +console.assert(!!NamedExports.DataUnion, 'NamedExports should have DataUnion') + +client.connect().then(() => { + console.info('success') + return client.disconnect() +}) diff --git a/test/exports/tsconfig.json b/test/exports/tsconfig.json new file mode 100644 index 000000000..7b216a526 --- /dev/null +++ b/test/exports/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "@tsconfig/node14/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "declaration": true, + "outDir": "dist", + "strict": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "module": "commonjs" + }, + "include": [ + "tests/typescript.ts" + ] +} diff --git a/test/exports/webpack.config.js b/test/exports/webpack.config.js new file mode 100644 index 000000000..3a89ee501 --- /dev/null +++ b/test/exports/webpack.config.js @@ -0,0 +1,47 @@ +/* eslint-disable prefer-template */ +/* eslint-disable prefer-destructuring */ + +process.env.NODE_ENV = process.env.NODE_ENV || 'development' // set a default NODE_ENV + +const path = require('path') + +module.exports = (env, argv) => { + const isProduction = argv.mode === 'production' || process.env.NODE_ENV === 'production' + + return { + mode: isProduction ? 'production' : 'development', + target: 'web', + entry: { + commonjs: path.join(__dirname, 'tests/commonjs.js'), + typescript: path.join(__dirname, 'tests/typescript.ts'), + esm: path.join(__dirname, 'tests/esm.mjs'), + }, + devtool: false, + output: { + filename: '[name].webpacked.js', + }, + optimization: { + minimize: false, + }, + module: { + rules: [ + { + test: /(\.jsx|\.js|\.ts)$/, + exclude: /(node_modules|bower_components)/, + use: { + loader: 'babel-loader', + options: { + configFile: path.resolve(__dirname, '../../.babel.config.js'), + babelrc: false, + cacheDirectory: true, + } + } + }, + ], + }, + resolve: { + modules: [path.resolve('./node_modules'), path.resolve('./tests/'), path.resolve('../../node_modules')], + extensions: ['.json', '.js', '.ts', '.mjs'], + }, + } +} diff --git a/test/flakey/EnvStressTest.test.js b/test/flakey/EnvStressTest.test.js index d1da5f4d9..60ceb263e 100644 --- a/test/flakey/EnvStressTest.test.js +++ b/test/flakey/EnvStressTest.test.js @@ -1,5 +1,5 @@ import { pTimeout } from '../../src/utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { fakePrivateKey, uid } from '../utils' import config from '../integration/config' diff --git a/test/integration/Encryption.test.js b/test/integration/Encryption.test.js index 7f5d05a49..8b4475760 100644 --- a/test/integration/Encryption.test.js +++ b/test/integration/Encryption.test.js @@ -3,7 +3,7 @@ import { MessageLayer } from 'streamr-client-protocol' import { fakePrivateKey, uid, Msg, getPublishTestMessages } from '../utils' import { Defer } from '../../src/utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { GroupKey } from '../../src/stream/Encryption' import Connection from '../../src/Connection' diff --git a/test/integration/GapFill.test.js b/test/integration/GapFill.test.js index 4271b30c8..7eb7dc8fa 100644 --- a/test/integration/GapFill.test.js +++ b/test/integration/GapFill.test.js @@ -1,7 +1,7 @@ import { wait } from 'streamr-test-utils' import { uid, fakePrivateKey, describeRepeats, getPublishTestMessages } from '../utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import Connection from '../../src/Connection' import config from './config' diff --git a/test/integration/LoginEndpoints.test.js b/test/integration/LoginEndpoints.test.js index a544a483b..5c1b35c93 100644 --- a/test/integration/LoginEndpoints.test.js +++ b/test/integration/LoginEndpoints.test.js @@ -2,7 +2,7 @@ import assert from 'assert' import { ethers } from 'ethers' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import config from './config' diff --git a/test/integration/MultipleClients.test.js b/test/integration/MultipleClients.test.js index 68d32f682..2869b92d5 100644 --- a/test/integration/MultipleClients.test.js +++ b/test/integration/MultipleClients.test.js @@ -2,7 +2,7 @@ import { wait } from 'streamr-test-utils' import { ControlLayer } from 'streamr-client-protocol' import { describeRepeats, uid, fakePrivateKey, getWaitForStorage, getPublishTestMessages, addAfterFn } from '../utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { counterId, Defer, pLimitFn } from '../../src/utils' import Connection from '../../src/Connection' diff --git a/test/integration/ResendReconnect.test.js b/test/integration/ResendReconnect.test.js index dc650c20e..a777acc22 100644 --- a/test/integration/ResendReconnect.test.js +++ b/test/integration/ResendReconnect.test.js @@ -1,7 +1,7 @@ import { wait, waitForCondition } from 'streamr-test-utils' import { uid, fakePrivateKey, getPublishTestMessages } from '../utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { Defer } from '../../src/utils' import config from './config' diff --git a/test/integration/Resends.test.js b/test/integration/Resends.test.js index 611dbcf25..836632117 100644 --- a/test/integration/Resends.test.js +++ b/test/integration/Resends.test.js @@ -1,7 +1,7 @@ import { wait, waitForCondition, waitForEvent } from 'streamr-test-utils' import { uid, describeRepeats, fakePrivateKey, getPublishTestMessages } from '../utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { Defer, pTimeout } from '../../src/utils' import Connection from '../../src/Connection' diff --git a/test/integration/Sequencing.test.js b/test/integration/Sequencing.test.js index b75720d34..f9ee621bd 100644 --- a/test/integration/Sequencing.test.js +++ b/test/integration/Sequencing.test.js @@ -1,7 +1,7 @@ import { wait, waitForCondition, waitForEvent } from 'streamr-test-utils' import { uid, fakePrivateKey, getWaitForStorage } from '../utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import Connection from '../../src/Connection' import config from './config' diff --git a/test/integration/Session.test.js b/test/integration/Session.test.js index 90c9b0bf7..bccd20182 100644 --- a/test/integration/Session.test.js +++ b/test/integration/Session.test.js @@ -1,4 +1,4 @@ -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { fakePrivateKey } from '../utils' import config from './config' diff --git a/test/integration/Stream.test.js b/test/integration/Stream.test.js index 56f112f1b..19df708a3 100644 --- a/test/integration/Stream.test.js +++ b/test/integration/Stream.test.js @@ -1,4 +1,4 @@ -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { uid, fakePrivateKey, getPublishTestMessages } from '../utils' import config from './config' diff --git a/test/integration/StreamConnectionState.test.js b/test/integration/StreamConnectionState.test.js index 4c137da74..d8fcd8c4e 100644 --- a/test/integration/StreamConnectionState.test.js +++ b/test/integration/StreamConnectionState.test.js @@ -2,7 +2,7 @@ import { wait } from 'streamr-test-utils' import { ControlLayer } from 'streamr-client-protocol' import { uid, fakePrivateKey, describeRepeats, getPublishTestMessages } from '../utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { Defer, pLimitFn } from '../../src/utils' import Connection from '../../src/Connection' diff --git a/test/integration/StreamEndpoints.test.ts b/test/integration/StreamEndpoints.test.ts index ccd617f6f..ea4e2672a 100644 --- a/test/integration/StreamEndpoints.test.ts +++ b/test/integration/StreamEndpoints.test.ts @@ -1,8 +1,8 @@ import { ethers, Wallet } from 'ethers' import { NotFoundError, ValidationError } from '../../src/rest/authFetch' -import Stream, { StreamOperation } from '../../src/stream' +import { Stream, StreamOperation } from '../../src/stream' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { uid } from '../utils' import config from './config' diff --git a/test/integration/StreamrClient.test.js b/test/integration/StreamrClient.test.js index 77e3017ee..3f22997b8 100644 --- a/test/integration/StreamrClient.test.js +++ b/test/integration/StreamrClient.test.js @@ -6,7 +6,7 @@ import { ControlLayer, MessageLayer } from 'streamr-client-protocol' import { wait, waitForEvent } from 'streamr-test-utils' import { describeRepeats, uid, fakePrivateKey, getWaitForStorage, getPublishTestMessages, Msg } from '../utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { Defer, pLimitFn } from '../../src/utils' import Connection from '../../src/Connection' diff --git a/test/integration/Subscriber.test.js b/test/integration/Subscriber.test.js index 379390e51..55800d3eb 100644 --- a/test/integration/Subscriber.test.js +++ b/test/integration/Subscriber.test.js @@ -2,7 +2,7 @@ import { ControlLayer } from 'streamr-client-protocol' import { wait } from 'streamr-test-utils' import { uid, fakePrivateKey, describeRepeats, getPublishTestMessages, collect } from '../utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { Defer } from '../../src/utils' import Connection from '../../src/Connection' diff --git a/test/integration/SubscriberResends.test.js b/test/integration/SubscriberResends.test.js index 806ba8058..5193dcfe9 100644 --- a/test/integration/SubscriberResends.test.js +++ b/test/integration/SubscriberResends.test.js @@ -2,7 +2,7 @@ import { ControlLayer } from 'streamr-client-protocol' import { wait } from 'streamr-test-utils' import { Msg, uid, collect, describeRepeats, fakePrivateKey, getWaitForStorage, getPublishTestMessages } from '../utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import Connection from '../../src/Connection' import { Defer } from '../../src/utils' diff --git a/test/integration/Subscription.test.js b/test/integration/Subscription.test.js index b15dfadca..bdcd8dd17 100644 --- a/test/integration/Subscription.test.js +++ b/test/integration/Subscription.test.js @@ -1,7 +1,7 @@ import { wait, waitForEvent } from 'streamr-test-utils' import { uid, fakePrivateKey } from '../utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import config from './config' diff --git a/test/integration/Validation.test.js b/test/integration/Validation.test.js index 9951fb4c2..bcefc8b0f 100644 --- a/test/integration/Validation.test.js +++ b/test/integration/Validation.test.js @@ -1,7 +1,7 @@ import { wait } from 'streamr-test-utils' import { uid, fakePrivateKey, describeRepeats, getPublishTestMessages } from '../utils' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import Connection from '../../src/Connection' import config from './config' diff --git a/test/integration/authFetch.test.js b/test/integration/authFetch.test.js index bfef4d431..bb699a7c2 100644 --- a/test/integration/authFetch.test.js +++ b/test/integration/authFetch.test.js @@ -2,7 +2,7 @@ jest.mock('node-fetch') import fetch from 'node-fetch' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { fakePrivateKey } from '../utils' import config from './config' diff --git a/test/integration/config.js b/test/integration/config.js index f103ad654..72a4d7f86 100644 --- a/test/integration/config.js +++ b/test/integration/config.js @@ -9,8 +9,12 @@ module.exports = { streamrNodeAddress: '0xFCAd0B19bB29D4674531d6f115237E16AfCE377c', tokenAddress: process.env.TOKEN_ADDRESS || '0xbAA81A0179015bE47Ad439566374F2Bae098686F', tokenAddressSidechain: process.env.TOKEN_ADDRESS_SIDECHAIN || '0x73Be21733CC5D08e1a14Ea9a399fb27DB3BEf8fF', - factoryMainnetAddress: process.env.DU_FACTORY_MAINNET || '0x5E959e5d5F3813bE5c6CeA996a286F734cc9593b', - factorySidechainAddress: process.env.DU_FACTORY_SIDECHAIN || '0x4081B7e107E59af8E82756F96C751174590989FE', + dataUnion: { + factoryMainnetAddress: process.env.DU_FACTORY_MAINNET || '0x4bbcBeFBEC587f6C4AF9AF9B48847caEa1Fe81dA', + factorySidechainAddress: process.env.DU_FACTORY_SIDECHAIN || '0x4A4c4759eb3b7ABee079f832850cD3D0dC48D927', + templateMainnetAddress: process.env.DU_TEMPLATE_MAINNET || '0x7bFBAe10AE5b5eF45e2aC396E0E605F6658eF3Bc', + templateSidechainAddress: process.env.DU_TEMPLATE_SIDECHAIN || '0x36afc8c9283CC866b8EB6a61C6e6862a83cd6ee8', + }, sidechain: { url: process.env.SIDECHAIN_URL || 'http://10.200.10.1:8546', timeout: process.env.TEST_TIMEOUT, diff --git a/test/integration/dataunion/adminFee.test.ts b/test/integration/dataunion/adminFee.test.ts index 18a2bd48e..0e25f2d1c 100644 --- a/test/integration/dataunion/adminFee.test.ts +++ b/test/integration/dataunion/adminFee.test.ts @@ -2,7 +2,7 @@ import { Contract, providers, Wallet } from 'ethers' import { parseEther, formatEther } from 'ethers/lib/utils' import debug from 'debug' -import StreamrClient from '../../../src/StreamrClient' +import { StreamrClient } from '../../../src/StreamrClient' import * as Token from '../../../contracts/TestToken.json' import config from '../config' diff --git a/test/integration/dataunion/calculate.test.ts b/test/integration/dataunion/calculate.test.ts index 57d7002d6..cba46a0e4 100644 --- a/test/integration/dataunion/calculate.test.ts +++ b/test/integration/dataunion/calculate.test.ts @@ -1,7 +1,7 @@ import { providers, Wallet } from 'ethers' import debug from 'debug' -import StreamrClient from '../../../src/StreamrClient' +import { StreamrClient } from '../../../src/StreamrClient' import config from '../config' import { createClient, expectInvalidAddress } from '../../utils' diff --git a/test/integration/dataunion/deploy.test.ts b/test/integration/dataunion/deploy.test.ts index 6caca2e77..c76d86aed 100644 --- a/test/integration/dataunion/deploy.test.ts +++ b/test/integration/dataunion/deploy.test.ts @@ -1,7 +1,7 @@ import { providers } from 'ethers' import debug from 'debug' -import StreamrClient from '../../../src/StreamrClient' +import { StreamrClient } from '../../../src/StreamrClient' import config from '../config' import { createMockAddress } from '../../utils' diff --git a/test/integration/dataunion/member.test.ts b/test/integration/dataunion/member.test.ts index 68adf9a51..53c445e4e 100644 --- a/test/integration/dataunion/member.test.ts +++ b/test/integration/dataunion/member.test.ts @@ -1,7 +1,7 @@ import { providers, Wallet } from 'ethers' import debug from 'debug' -import StreamrClient from '../../../src/StreamrClient' +import { StreamrClient } from '../../../src/StreamrClient' import config from '../config' import { DataUnion, JoinRequestState } from '../../../src/dataunion/DataUnion' import { createMockAddress, expectInvalidAddress, fakePrivateKey } from '../../utils' diff --git a/test/integration/dataunion/signature.test.ts b/test/integration/dataunion/signature.test.ts index d90a24fda..65281fc0b 100644 --- a/test/integration/dataunion/signature.test.ts +++ b/test/integration/dataunion/signature.test.ts @@ -3,7 +3,7 @@ import { parseEther } from 'ethers/lib/utils' import debug from 'debug' import { getEndpointUrl } from '../../../src/utils' -import StreamrClient from '../../../src/StreamrClient' +import { StreamrClient } from '../../../src/StreamrClient' import * as Token from '../../../contracts/TestToken.json' import * as DataUnionSidechain from '../../../contracts/DataUnionSidechain.json' import config from '../config' diff --git a/test/integration/dataunion/stats.test.ts b/test/integration/dataunion/stats.test.ts index 7ea3a36ae..d9bcfe911 100644 --- a/test/integration/dataunion/stats.test.ts +++ b/test/integration/dataunion/stats.test.ts @@ -1,7 +1,7 @@ import { providers } from 'ethers' import debug from 'debug' -import StreamrClient from '../../../src/StreamrClient' +import { StreamrClient } from '../../../src/StreamrClient' import config from '../config' import { DataUnion, MemberStatus } from '../../../src/dataunion/DataUnion' import { createClient, createMockAddress, expectInvalidAddress } from '../../utils' diff --git a/test/integration/dataunion/withdraw.test.ts b/test/integration/dataunion/withdraw.test.ts index cba025574..2b5cf0278 100644 --- a/test/integration/dataunion/withdraw.test.ts +++ b/test/integration/dataunion/withdraw.test.ts @@ -4,7 +4,7 @@ import { TransactionReceipt } from '@ethersproject/providers' import debug from 'debug' import { getEndpointUrl, until } from '../../../src/utils' -import StreamrClient from '../../../src/StreamrClient' +import { StreamrClient } from '../../../src/StreamrClient' import * as Token from '../../../contracts/TestToken.json' import * as DataUnionSidechain from '../../../contracts/DataUnionSidechain.json' import config from '../config' diff --git a/test/legacy/MessageCreationUtil.test.js b/test/legacy/MessageCreationUtil.test.js index 41189c460..66c77bb8e 100644 --- a/test/legacy/MessageCreationUtil.test.js +++ b/test/legacy/MessageCreationUtil.test.js @@ -4,7 +4,7 @@ import { wait } from 'streamr-test-utils' import { MessageLayer } from 'streamr-client-protocol' import { MessageCreationUtil, StreamPartitioner } from '../../src/Publisher' -import Stream from '../../src/stream' +import { Stream } from '../../src/stream' // eslint-disable-next-line import/no-named-as-default-member import StubbedStreamrClient from './StubbedStreamrClient' diff --git a/test/unit/Session.test.js b/test/unit/Session.test.js index 08046b45d..b273b79ec 100644 --- a/test/unit/Session.test.js +++ b/test/unit/Session.test.js @@ -1,6 +1,6 @@ import sinon from 'sinon' -import StreamrClient from '../../src/StreamrClient' +import { StreamrClient } from '../../src/StreamrClient' import { Defer } from '../../src/utils' import Session from '../../src/Session' import config from '../integration/config' diff --git a/test/unit/Stream.test.js b/test/unit/Stream.test.js index a0c1e0848..15f68dab6 100644 --- a/test/unit/Stream.test.js +++ b/test/unit/Stream.test.js @@ -1,4 +1,4 @@ -import Stream from '../../src/stream' +import { Stream } from '../../src/stream' describe('Stream', () => { let stream diff --git a/test/unit/StubbedStreamrClient.js b/test/unit/StubbedStreamrClient.js index 3eb8943e8..d1086d26f 100644 --- a/test/unit/StubbedStreamrClient.js +++ b/test/unit/StubbedStreamrClient.js @@ -1,5 +1,5 @@ -import StreamrClient from '../../src/' -import Stream from '../../src/stream' +import { StreamrClient } from '../../src/' +import { Stream } from '../../src/stream' export default class StubbedStreamrClient extends StreamrClient { getUserInfo() { diff --git a/test/utils.ts b/test/utils.ts index 3c068aba9..b691ff5ac 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -3,7 +3,7 @@ import { wait } from 'streamr-test-utils' import { providers, Wallet } from 'ethers' import { pTimeout, counterId, AggregatedError } from '../src/utils' import { validateOptions } from '../src/stream/utils' -import StreamrClient from '../src/StreamrClient' +import { StreamrClient } from '../src/StreamrClient' const crypto = require('crypto') const config = require('./integration/config') diff --git a/tsconfig.json b/tsconfig.json index 1daeea6fc..c9699f3c2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,30 +1,34 @@ { - "compilerOptions": { - "target": "ES2015", - "module": "commonjs", - "allowJs": true, - "declaration": true, - "declarationDir": "dist/types", - "outDir": "dist", - "lib": [ - "ES5", - "ES2015", - "ES2016", - "ES2017", - "ES2018", - "ES2019", - "ES2020", - "ESNext", - "DOM" + "compilerOptions": { + "target": "ES2015", + "module": "commonjs", + "allowJs": true, + "declaration": true, + "declarationDir": "dist/types", + "outDir": "dist", + "lib": [ + "ES5", + "ES2015", + "ES2016", + "ES2017", + "ES2018", + "ES2019", + "ES2020", + "ESNext", + "DOM" + ], + "strict": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "moduleResolution": "node" + }, + "globals": { + "ts-jest": {} + }, + "include": [ + "src/**/*", + "vendor/**/*", + "contracts/**/*" ], - "strict": true, - "esModuleInterop": true, - "resolveJsonModule": true, - "moduleResolution": "node" - }, - "globals": { - "ts-jest": {} - }, - "include": ["src/**/*", "contracts/*"], - "exclude": ["node_modules", "dist"] + "exclude": ["node_modules", "dist"] } diff --git a/tsconfig.node.json b/tsconfig.node.json index 0b2d144c9..06a4b2762 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -4,7 +4,7 @@ "allowJs": true, "declaration": true, "declarationDir": "dist/types", - "outDir": "dist/node", + "outDir": "dist", "lib": [ "ES5", "ES2015", @@ -18,15 +18,15 @@ ], "strict": true, "moduleResolution": "node", - "resolveJsonModule": true + "resolveJsonModule": true, + "module": "commonjs" }, "globals": { "ts-jest": {} }, "include": [ "src/**/*", - "contracts/**/*", - // quick-lru is esm, need to transpile :/ - "node_modules/quick-lru/index.js" + "vendor/**/*", + "contracts/**/*" ] } diff --git a/webpack.config.js b/webpack.config.js index dd8dd3c43..c4952a461 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -54,7 +54,7 @@ module.exports = (env, argv) => { ], }, resolve: { - modules: [path.resolve('./node_modules'), path.resolve('./src')], + modules: [path.resolve('./node_modules'), path.resolve('./vendor'), path.resolve('./src')], extensions: ['.json', '.js', '.ts'], }, plugins: [ @@ -76,6 +76,19 @@ module.exports = (env, argv) => { libraryTarget: 'umd2', filename: libraryName + '.web.js', library: 'StreamrClient', + // NOTE: + // exporting the class directly + // `export default class StreamrClient {}` + // becomes: + // `window.StreamrClient === StreamrClient` + // which is correct, but if we define the class and export separately, + // which is required if we do interface StreamrClient extends …: + // `class StreamrClient {}; export default StreamrClient;` + // becomes: + // `window.StreamrClient = { default: StreamrClient, … }` + // which is wrong for browser builds. + // see: https://github.com/webpack/webpack/issues/706#issuecomment-438007763 + libraryExport: 'StreamrClient', // This fixes the above. }, resolve: { alias: {