diff --git a/.babel.config.js b/.babel.config.js new file mode 100644 index 000000000..5716478ee --- /dev/null +++ b/.babel.config.js @@ -0,0 +1,36 @@ +module.exports = { + presets: [ + ['@babel/preset-env', { + useBuiltIns: 'usage', + corejs: 3, + loose: false, + bugfixes: true, + shippedProposals: true, + targets: { + browsers: [ + 'supports async-functions', + 'supports cryptography', + 'supports es6', + 'supports async-iterations-and-generators', + 'not dead', + 'not ie <= 11', + 'not ie_mob <= 11' + ] + }, + exclude: ['transform-regenerator', '@babel/plugin-transform-regenerator'] + }], + ['@babel/preset-typescript'] + ], + plugins: [ + "add-module-exports", + ['@babel/plugin-transform-runtime', { + corejs: 3, + helpers: true, + regenerator: false + }], + "@babel/plugin-transform-modules-commonjs", + ['@babel/plugin-proposal-class-properties', { + loose: false + }] + ] +} diff --git a/.babel.node.config.js b/.babel.node.config.js new file mode 100644 index 000000000..245b492cd --- /dev/null +++ b/.babel.node.config.js @@ -0,0 +1,29 @@ +module.exports = { + presets: [ + ['@babel/preset-env', { + useBuiltIns: 'usage', + modules: false, + corejs: 3, + loose: false, + bugfixes: true, + shippedProposals: true, + targets: { + node: true + } + }], + ['@babel/preset-typescript'] + ], + plugins: [ + 'add-module-exports', + ['@babel/plugin-transform-runtime', { + useESModules: false, + corejs: 3, + helpers: true, + regenerator: false + }], + '@babel/plugin-transform-modules-commonjs', + ['@babel/plugin-proposal-class-properties', { + loose: false + }] + ] +} diff --git a/.babelrc b/.babelrc deleted file mode 100644 index a08d9c6c0..000000000 --- a/.babelrc +++ /dev/null @@ -1,34 +0,0 @@ -{ - "presets": [ - ["@babel/preset-env", { - "useBuiltIns": "usage", - "modules": false, - "corejs": 3, - "loose": false, - "targets": { - "browsers": [ - "> 1.5%", - "Opera >= 58", - "Safari >= 12", - "Edge >= 75", - "Firefox ESR", - "not dead", - "not ie <= 11", - "not ie_mob <= 11" - ] - } - }] - ], - "plugins": [ - "add-module-exports", - ["@babel/plugin-transform-runtime", { - "corejs": false, - "helpers": true, - "regenerator": true - }], - "@babel/plugin-transform-modules-commonjs", - ["@babel/plugin-proposal-class-properties", { - "loose": false - }] - ] -} diff --git a/.eslintignore b/.eslintignore index b381af368..20d5177ca 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,5 +2,9 @@ node_modules/** examples/** coverage/** dist/** +test/legacy/** src/shim/** test/unit/StubbedStreamrClient.js +streamr-docker-dev/** +vendor/** +test/exports/** diff --git a/.eslintrc.js b/.eslintrc.js index 338d5fe40..7a82d59ec 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,21 @@ module.exports = { + parser: '@typescript-eslint/parser', + plugins: [ + '@typescript-eslint' + ], extends: [ 'streamr-nodejs' ], + parserOptions: { + ecmaVersion: 2020, + ecmaFeatures: { + modules: true + } + }, + env: { + browser: true, + es6: true + }, rules: { 'max-len': ['warn', { code: 150 @@ -19,11 +33,32 @@ module.exports = { } ], 'prefer-destructuring': 'warn', - + 'object-curly-newline': 'off', + 'no-continue': 'off', + 'max-classes-per-file': 'off', // javascript is not java // TODO check all errors/warnings and create separate PR 'promise/always-return': 'warn', 'promise/catch-or-return': 'warn', 'require-atomic-updates': 'warn', - 'promise/param-names': 'warn' + 'promise/param-names': 'warn', + 'no-restricted-syntax': [ + 'error', 'ForInStatement', 'LabeledStatement', 'WithStatement' + ], + 'import/extensions': ['error', 'never', { json: 'always' }], + 'lines-between-class-members': 'off', + 'padded-blocks': 'off', + 'no-use-before-define': 'off', + 'import/order': 'off', + 'no-shadow': 'off', + '@typescript-eslint/no-shadow': 'error', + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': ['error'], + }, + settings: { + 'import/resolver': { + node: { + extensions: ['.js', '.ts'] + } + } } } diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 48e7ebbdc..4176bd4cf 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -1,167 +1,278 @@ -name: Test, lint & Publish - +name: Lint, Unit, Integration Tests +env: + CI: true + DEBUG_COLORS: true + DEBUG: "Streamr*" on: push: tags: - - '*' + - "*" branches: - master pull_request: branches: - - '*' + - "*" schedule: # run every day at 00:00 - - cron: '0 0 * * *' + - cron: "0 0 * * *" jobs: - lint: - name: Run linter using Node 12 + build: + name: Run build using Node 14.x runs-on: ubuntu-latest - + env: + BUNDLE_ANALYSIS: true steps: - - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 with: - node-version: 12 - + node-version: "14.x" - name: npm ci run: npm ci + - name: npm run build + run: npm run build + - uses: actions/upload-artifact@v2 + with: + name: build + path: dist + lint: + name: Run linter using Node 14.x + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: "14.x" + - name: npm ci + run: npm ci - name: npm run eslint run: npm run eslint test: - name: Test Unit/Build/Benchmark using Node ${{ matrix.node-version }} + name: Test Unit using Node ${{ matrix.node-version }} runs-on: ubuntu-latest - strategy: matrix: node-version: [12.x, 14.x] - + env: + TEST_REPEATS: 5 steps: - - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} - - name: npm ci run: npm ci - - name: test-unit + timeout-minutes: 7 run: npm run test-unit - - name: build - run: npm run build - - - name: benchmarks - run: npm run benchmarks - integration: - name: Test Integration using Node ${{ matrix.node-version }} + name: ${{ matrix.test-name }} ${{ matrix.websocket-url.name }} using Node ${{ matrix.node-version }} runs-on: ubuntu-latest - strategy: + fail-fast: false matrix: node-version: [12.x, 14.x] + test-name: [ + "test-integration-no-resend", + "test-integration-resend", + "test-integration-dataunions", + ] + websocket-url: + - name: "default" + url: "" + - name: "storage-node-only" + url: "ws://localhost:8890/api/v1/ws" + + exclude: + # no need to test different ws urls for dataunion tests + - test-name: "test-integration-dataunions" + websocket-url: + - name: "storage-node-only" + - url: "ws://localhost:8890/api/v1/ws" env: - WEBSOCKET_URL: ws://localhost:8890/api/v1/ws + TEST_NAME: ${{ matrix.test-name }} + WEBSOCKET_URL: ${{ matrix.websocket-url.url}} + TEST_REPEATS: 2 steps: - - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} - - - name: setup streamr-docker-dev - run: | - sudo service mysql stop - git clone https://github.com/streamr-dev/streamr-docker-dev.git - sudo ifconfig docker0 10.200.10.1/24 - ${GITHUB_WORKSPACE}/streamr-docker-dev/streamr-docker-dev/bin.sh start --wait - - name: npm ci run: npm ci + - name: Start Streamr Docker Stack + 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 + run: npm run $TEST_NAME - - name: build - run: npm run build - - - name: test-browser - run: npm run test-browser - - - name: test-integration - run: npm run test-integration + flakey: + name: Flakey Tests using Node ${{ matrix.node-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node-version: [12.x, 14.x] - - name: test-integration-flakey - continue-on-error: true - run: npm run test-integration-flakey + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + - name: npm ci + run: npm ci + - name: Start Streamr Docker Stack + 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 + name: Run Test + with: + max_attempts: 2 + timeout_minutes: 15 + retry_on: error + command: npm run test-flakey || echo "::warning::Flakey Tests Failed" - streamr-client-testing-tool: - needs: [test, lint] + test-exports: + name: Test Exports using Node 14.x runs-on: ubuntu-latest + needs: build steps: - - name: Use Node.js 12 - uses: actions/setup-node@v1 + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 with: - node-version: '12.x' - - uses: actions/checkout@v1 - - name: streamr-client tool test - continue-on-error: true - run: | - sudo service mysql stop - if [ ! -d streamr-docker-dev ]; then # Skip clone on subsequent attemps. - git clone https://github.com/streamr-dev/streamr-docker-dev.git - fi - sudo ifconfig docker0 10.200.10.1/24 - ${GITHUB_WORKSPACE}/streamr-docker-dev/streamr-docker-dev/bin.sh start smart-contracts-init nginx engine-and-editor --wait - echo "Testing Tool setup" - git clone https://github.com/streamr-dev/streamr-client-testing.git - cd ${GITHUB_WORKSPACE}/streamr-client-testing - echo "Setup package.json to use PR JS client" - sed -i "s/com.streamr:client:1.3.0/com.streamr:client:+/g" build.gradle - sed -i "s/\"streamr-client\": \"\^3.1.2\"/\"streamr-client\":\"PATH\"/g" package.json - ## fix for escaping / of workspace path - sed -i "s|"PATH"|"${GITHUB_WORKSPACE}"|g" package.json - echo "Prepare for test" - ## npm install is used because package-lock.json could be form a previous client version. - npm install - ./gradlew fatjar - echo "Run streamr-client test" - java -jar build/libs/client_testing-1.0-SNAPSHOT.jar -s stream-encrypted-shared-rotating-signed -m test + 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 - publish: - needs: [test, lint, integration, streamr-client-testing-tool] - name: Publishing master using Node 12 + browser: + name: Test Browser using Node 14.x runs-on: ubuntu-latest - - # run job only for tags and skip for cron - if: startsWith(github.ref, 'refs/tags/') && github.event_name != 'schedule' + needs: build steps: - - name: Get the release version - id: get_version - run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} - - - uses: actions/checkout@master - - uses: actions/setup-node@v1 + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 with: - node-version: 12 - registry-url: https://registry.npmjs.org/ - + node-version: "14.x" + - uses: actions/download-artifact@v2 + with: + name: build + path: dist - name: npm ci run: npm ci + - name: Start Streamr Docker Stack + 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: build - run: npm run build --if-present + - uses: nick-invision/retry@v2 + name: Run Test + with: + max_attempts: 3 + timeout_minutes: 3 + retry_on: error + command: npm run test-browser + + benchmarks: + name: Test Benchmark using Node ${{ matrix.node-version }} + runs-on: ubuntu-latest + needs: build - - name: Publish beta ${{ steps.get_version.outputs.VERSION }} - # if tag includes beta keyword - if: contains(steps.get_version.outputs.VERSION, 'beta') == true - run: npm publish --tag beta - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + strategy: + matrix: + node-version: [12.x, 14.x] + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + - uses: actions/download-artifact@v2 + with: + name: build + path: dist + - name: Start Streamr Docker Stack + 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: benchmarks + run: npm run benchmarks > benchmarks.txt + - uses: actions/upload-artifact@v2 + with: + name: benchmarks + path: benchmarks.txt - - name: Publish latest ${{ steps.get_version.outputs.VERSION }} - # if tag doesn't include beta keyword - if: contains(steps.get_version.outputs.VERSION, 'beta') == false - run: npm publish - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + streamr-client-testing-tool: + name: ${{ matrix.config-name }} ${{ matrix.test-name }} + needs: build + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + test-name: + - stream-cleartext-unsigned + - stream-cleartext-signed + - stream-encrypted-shared-signed + - stream-encrypted-shared-rotating-signed + - stream-encrypted-exchanged-rotating-signed + config-name: + - default + - js-only + - java-only + - realtime-only + - js-realtime-only + - java-realtime-only + env: + NUM_MESSAGES: 20 + TEST_NAME: ${{ matrix.test-name }} + CONFIG_NAME: ${{ matrix.config-name }} + steps: + - uses: actions/checkout@v2 + - name: Use Node.js 14 + uses: actions/setup-node@v2 + with: + node-version: "14.x" + - uses: actions/download-artifact@v2 + with: + name: build + path: dist + - name: Start Streamr Docker Stack + 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: 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: | + ## npm install is used because package-lock.json could be from a previous client version. + npm install + npm link streamr-client + ./gradlew fatjar + - name: run-client-testing + timeout-minutes: 10 + working-directory: streamr-client-testing + run: java -jar build/libs/client_testing-1.0-SNAPSHOT.jar -s $TEST_NAME -c config/$CONFIG_NAME.conf -n $NUM_MESSAGES diff --git a/.gitignore b/.gitignore index fb5e7ca28..c55ede7b5 100644 --- a/.gitignore +++ b/.gitignore @@ -38,4 +38,8 @@ examples/webpack/dist/* .idea/dataSources* reports -tests_output \ No newline at end of file +tests_outputbenchmarks.txt +tests_output +test/exports/dist +test/exports/package-lock.json +vendor diff --git a/.npmignore b/.npmignore index 6e306d4b2..3aa10a184 100644 --- a/.npmignore +++ b/.npmignore @@ -29,4 +29,6 @@ node_modules .idea *.iml .DS_Store + # dist/* we want the dist folder on npm! +dist/*.html diff --git a/README.md b/README.md index 065995bb8..b91bff58e 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ Streamr JavaScript Client - By using this client, you can easily interact with the [Streamr](https://streamr.network) API from JavaScript-based environments, such as browsers and [node.js](https://nodejs.org). You can, for example, subscribe to real-time data in streams, produce new data to streams, and create new streams. The client uses websockets for producing and consuming messages to/from streams. It should work in all modern browsers. @@ -15,7 +14,8 @@ The client uses websockets for producing and consuming messages to/from streams. [![Build Status](https://travis-ci.com/streamr-dev/streamr-client-javascript.svg?branch=master)](https://travis-ci.com/streamr-dev/streamr-client-javascript) ## Breaking changes notice -- Date TBD: Support for unsigned data will be dropped. + +* Date TBD: Support for unsigned data will be dropped. [Installation](#installation) · [Usage](#usage) · [Client options](#client-options) · [Authentication options](#authentication-options) · [Message handler callback](#message-handler-callback) · [StreamrClient object](#streamrclient-object) · [Stream object](#stream-object) · [Subscription options](#subscription-options) · [Data Unions](#data-unions) · [Utility functions](#utility-functions) · [Events](#binding-to-events) · [Partitioning](#partitioning) · [Logging](#logging) · [NPM Publishing](#publishing-latest) @@ -33,9 +33,9 @@ Here are some quick examples. More detailed examples for the browser and node.js If you don't have an Ethereum account you can use the utility function `StreamrClient.generateEthereumAccount()`, which returns the address and private key of a fresh Ethereum account. -#### Creating a StreamrClient instance +### Creating a StreamrClient instance -```javascript +```js const client = new StreamrClient({ auth: { privateKey: 'your-private-key' @@ -43,62 +43,54 @@ const client = new StreamrClient({ }) ``` -When using Node.js remember to require the library with: +When using Node.js remember to import the library with: -```javascript -const StreamrClient = require('streamr-client') +```js +import { StreamrClient } from 'streamr-client'; ``` -#### Subscribing to real-time events in a stream +### Subscribing to real-time events in a stream -```javascript -const sub = client.subscribe( - { - stream: 'streamId', - partition: 0, // Optional, defaults to zero. Use for partitioned streams to select partition. - // optional resend options here - }, - (message, metadata) => { - // This is the message handler which gets called for every incoming message in the stream. - // Do something with the message here! - } -) +```js +const sub = await client.subscribe({ + stream: 'streamId', + partition: 0, // Optional, defaults to zero. Use for partitioned streams to select partition. + // optional resend options here +}, (message, metadata) => { + // This is the message handler which gets called for every incoming message in the stream. + // Do something with the message here! +}) ``` -#### Resending historical data +### Resending historical data -```javascript -const sub = await client.resend( - { - stream: 'streamId', - resend: { - last: 5, - }, +```js +const sub = await client.resend({ + stream: 'streamId', + resend: { + last: 5, }, - (message) => { - // This is the message handler which gets called for every received message in the stream. - // Do something with the message here! - } -) +}, (message) => { + // This is the message handler which gets called for every received message in the stream. + // Do something with the message here! +}) ``` See "Subscription options" for resend options -#### Programmatically creating a stream +### Programmatically creating a stream -```javascript -client.getOrCreateStream({ +```js +const stream = await client.getOrCreateStream({ name: 'My awesome stream created via the API', }) - .then((stream) => { - console.log(`Stream ${stream.id} has been created!`) - // Do something with the stream, for example call stream.publish(message) - }) +console.log(`Stream ${stream.id} has been created!`) +// Do something with the stream, for example call stream.publish(message) ``` -#### Publishing data points to a stream +### Publishing data points to a stream -```javascript +```js // Here's our example data point const msg = { temperature: 25.4, @@ -107,57 +99,57 @@ const msg = { } // Publish using the stream id only -client.publish('my-stream-id', msg) +await client.publish('my-stream-id', msg) // The first argument can also be the stream object -client.publish(stream, msg) +await client.publish(stream, msg) // Publish with a specific timestamp as a Date object (default is now) -client.publish('my-stream-id', msg, new Date(54365472)) +await client.publish('my-stream-id', msg, new Date(54365472)) // Publish with a specific timestamp in ms -client.publish('my-stream-id', msg, 54365472) +await client.publish('my-stream-id', msg, 54365472) // Publish with a specific timestamp as a ISO8601 string -client.publish('my-stream-id', msg, '2019-01-01T00:00:00.123Z') +await client.publish('my-stream-id', msg, '2019-01-01T00:00:00.123Z') // Publish with a specific partition key (read more about partitioning further down this readme) -client.publish('my-stream-id', msg, Date.now(), 'my-partition-key') +await client.publish('my-stream-id', msg, Date.now(), 'my-partition-key') // For convenience, stream.publish(...) equals client.publish(stream, ...) -stream.publish(msg) +await stream.publish(msg) ``` ## Client options -| Option | Default value | Description | -| :------------------------ | :------------------------------- | :------------------------------------------------------------ | -| url | wss://streamr.network/api/v1/ws | Address of the Streamr websocket endpoint to connect to. | -| restUrl | https://streamr.network/api/v1 | Base URL of the Streamr REST API. | -| auth | {} | Object that can contain different information to authenticate. More details below. | -| publishWithSignature | 'auto' | Determines if data points published to streams are signed or not. Possible values are: 'auto', 'always' and 'never'. Signing requires `auth.privateKey` or `auth.provider`. 'auto' will sign only if one of them is set. 'always' will throw an exception if none of them is set. | -| verifySignatures | 'auto' | Determines under which conditions signed and unsigned data points are accepted or rejected. 'always' accepts only signed and verified data points. 'never' accepts all data points. 'auto' verifies all signed data points before accepting them and accepts unsigned data points only for streams not supposed to contain signed data. | -| autoConnect | true | If set to `true`, the client connects automatically on the first call to `subscribe()`. Otherwise an explicit call to `connect()` is required. | -| autoDisconnect | true | If set to `true`, the client automatically disconnects when the last stream is unsubscribed. Otherwise the connection is left open and can be disconnected explicitly by calling `disconnect()`. | -| orderMessages | true | If set to `true`, the subscriber handles messages in the correct order, requests missing messages and drops duplicates. Otherwise, the subscriber processes messages as they arrive without any check. | -| maxPublishQueueSize | 10000 | Only in effect when `autoConnect = true`. Controls the maximum number of messages to retain in internal queue when client has disconnected and is reconnecting to Streamr. | -| publisherGroupKeys | {} | Object defining the group key as a hex string used to encrypt for each stream id. | -| publisherStoreKeyHistory | true | If `true`, the client will locally store every key used to encrypt messages at some point. If set to `false`, the client will not be able to answer subscribers asking for historical keys during resend requests. | -| subscriberGroupKeys | {} | Object defining, for each stream id, an object containing the group key used to decrypt for each publisher id. Not needed if `keyExchange` is defined. | -| keyExchange | {} | Defines RSA key pair to use for group key exchange. Can define `publicKey` and `privateKey` fields as strings in the PEM format, or stay empty to generate a key pair automatically. Can be set to `null` if no key exchange is required. | +| Option | Default value | Description | +| :----------------------- | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| url | wss://streamr.network/api/v1/ws | Address of the Streamr websocket endpoint to connect to. | +| restUrl | | Base URL of the Streamr REST API. | +| auth | {} | Object that can contain different information to authenticate. More details below. | +| publishWithSignature | 'auto' | Determines if data points published to streams are signed or not. Possible values are: 'auto', 'always' and 'never'. Signing requires `auth.privateKey` or `auth.ethereum`. 'auto' will sign only if one of them is set. 'always' will throw an exception if none of them is set. | +| verifySignatures | 'auto' | Determines under which conditions signed and unsigned data points are accepted or rejected. 'always' accepts only signed and verified data points. 'never' accepts all data points. 'auto' verifies all signed data points before accepting them and accepts unsigned data points only for streams not supposed to contain signed data. | +| autoConnect | true | If set to `true`, the client connects automatically on the first call to `subscribe()`. Otherwise an explicit call to `connect()` is required. | +| autoDisconnect | true | If set to `true`, the client automatically disconnects when the last stream is unsubscribed. Otherwise the connection is left open and can be disconnected explicitly by calling `disconnect()`. | +| orderMessages | true | If set to `true`, the subscriber handles messages in the correct order, requests missing messages and drops duplicates. Otherwise, the subscriber processes messages as they arrive without any check. | +| maxPublishQueueSize | 10000 | Only in effect when `autoConnect = true`. Controls the maximum number of messages to retain in internal queue when client has disconnected and is reconnecting to Streamr. | +| publisherGroupKeys | {} | Object defining the group key as a hex string used to encrypt for each stream id. | +| publisherStoreKeyHistory | true | If `true`, the client will locally store every key used to encrypt messages at some point. If set to `false`, the client will not be able to answer subscribers asking for historical keys during resend requests. | +| subscriberGroupKeys | {} | Object defining, for each stream id, an object containing the group key used to decrypt for each publisher id. Not needed if `keyExchange` is defined. | +| keyExchange | {} | Defines RSA key pair to use for group key exchange. Can define `publicKey` and `privateKey` fields as strings in the PEM format, or stay empty to generate a key pair automatically. Can be set to `null` if no key exchange is required. | ## Authentication options -**Authenticating with an API key has been deprecated.** +Note: **Authenticating with an API key has been deprecated.** -**Support for email/password authentication will be dropped in the future and cryptographic keys/wallets will be the only supported method.** +Note: **Support for email/password authentication will be dropped in the future and cryptographic keys/wallets will be the only supported method.** If you don't have an Ethereum account you can use the utility function `StreamrClient.generateEthereumAccount()`, which returns the address and private key of a fresh Ethereum account. Authenticating with Ethereum also automatically creates an associated Streamr user, even if it doesn't already exist. Under the hood, the client will cryptographically sign a challenge to authenticate you as a Streamr user: -```javascript -new StreamrClient({ +```js +const client = new StreamrClient({ auth: { privateKey: 'your-private-key' } @@ -166,297 +158,355 @@ new StreamrClient({ Authenticating with an Ethereum private key contained in an Ethereum (web3) provider: -```javascript -new StreamrClient({ +```js +const client = new StreamrClient({ auth: { - provider: window.ethereum, + ethereum: window.ethereum, } }) ``` (Authenticating with a pre-existing session token, for internal use by the Streamr app): -```javascript -new StreamrClient({ +```js +const client = new StreamrClient({ auth: { sessionToken: 'session-token' } }) ``` -## Message handler callback - -The second argument to `client.subscribe(options, callback)` is the callback function that will be called for each message as they arrive. Its arguments are as follows: - -| Argument | Description | -| :------------- | :------------------------------------------------------------ | -| payload | A JS object containing the message payload itself | -| streamMessage | The whole [StreamMessage](https://github.com/streamr-dev/streamr-client-protocol-js/blob/master/src/protocol/message_layer/StreamMessage.js) object containing various metadata, for example `streamMessage.getTimestamp()` etc. | - -## StreamrClient object +## Connecting -#### Connecting +By default the client will automatically connect and disconnect as needed, ideally you should not need to manage connection state explicitly. +Specifically, it will automatically connect when you publish or subscribe, and automatically disconnect once all subscriptions are removed and no +messages were recently published. This behaviour can be disabled using the `autoConnect` & `autoDisconnect` options when creating a `new +StreamrClient`. Explicit calls to either `connect()` or `disconnect()` will disable all `autoConnect` & `autoDisconnect` functionality, but they can +be re-enabled by calling `enableAutoConnect()` or `enableAutoDisconnect()`. -| Name | Description | -| :-------------------- | :------------------------------------------------------------ | -| connect() | Connects to the server, and also subscribes to any streams for which `subscribe()` has been called before calling `connect()`. Returns a Promise. Rejects if already connected or connecting. | -| disconnect() | Disconnects from the server, clearing all subscriptions. Returns a Promise. Rejects if already disconnected or disconnecting. | -| pause() | Disconnects from the server without clearing subscriptions. | -| ensureConnected() | Safely connects if not connected. Returns a promise. Resolves immediately if already connected. Only rejects if an error occurs during connection. | -| ensureDisconnected() | Safely disconnects if not disconnected. Returns a promise. Resolves immediately if already disconnected. Only rejects if an error occurs during disconnection. | +Calls that need a connection, such as `publish` or `subscribe` will fail with an error if you are disconnected and autoConnect is disabled. -#### Managing subscriptions +| Name | Description | +| :---------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| connect() | Safely connects if not connected. Returns a promise. Resolves immediately if already connected. Only rejects if an error occurs during connection. | +| disconnect() | Safely disconnects if not already disconnected, clearing all subscriptions. Returns a Promise. Resolves immediately if already disconnected. Only rejects if an error occurs during disconnection. | +| enableAutoConnect(enable = true) | Enables autoConnect if it wasn't already enabled. Does not connect immediately. Use `enableAutoConnect(false)` to disable autoConnect. | +| enableAutoDisconnect(enable = true) | Enables autoDisconnect if it wasn't already enabled. Does not disconnect immediately. Use `enableAutoConnect(false)` to disable autoDisconnect. | -| Name | Description | -| :---------------------------- | :------------------------------------------------------------ | -| subscribe(options, callback) | Subscribes to a stream. Messages in this stream are passed to the `callback` function. See below for subscription options. Returns a `Subscription` object. | -| unsubscribe(Subscription) | Unsubscribes the given `Subscription`. | -| unsubscribeAll(`streamId`) | Unsubscribes all `Subscriptions` for `streamId`. | -| getSubscriptions(`streamId`) | Returns a list of `Subscriptions` for `streamId`. | +```js +const client = new StreamrClient({ + auth: { + privateKey: 'your-private-key' + }, + autoConnect: false, + autoDisconnect: false, +}) -#### Stream API +await client.connect() +``` -All the below functions return a Promise which gets resolved with the result. +## Managing subscriptions -| Name | Description | -| :--------------------------------------------------- | :------------------------------------------------------------ | -| getStream(streamId) | Fetches a stream object from the API. | -| listStreams(query) | Fetches an array of stream objects from the API. For the query params, consult the [API docs](https://api-explorer.streamr.com). | -| getStreamByName(name) | Fetches a stream which exactly matches the given name. | -| createStream(properties) | Creates a stream with the given properties. For more information on the stream properties, consult the [API docs](https://api-explorer.streamr.com). | -| getOrCreateStream(properties) | Gets a stream with the id or name given in `properties`, or creates it if one is not found. | -| publish(streamId, message, timestamp, partitionKey) | Publishes a new message to the given stream. | +| Name | Description | +| :--------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| subscribe(options, callback) | Subscribes to a stream. Messages in this stream are passed to the `callback` function. See below for subscription options. Returns a Promise resolving a `Subscription` object. | +| unsubscribe(Subscription) | Unsubscribes the given `Subscription`. Returns a promise. | +| unsubscribeAll(`streamId`) | Unsubscribes all `Subscriptions` for `streamId`. Returns a promise. | +| getSubscriptions(`streamId`) | Returns a list of `Subscriptions` for `streamId`. Returns a promise. | -#### Listening to state changes of the client +### Message handler callback -on(eventName, function) | Binds a `function` to an event called `eventName` -once(eventName, function) | Binds a `function` to an event called `eventName`. It gets called once and then removed. -removeListener(eventName, function) | Unbinds the `function` from events called `eventName` +The second argument to `client.subscribe(options, callback)` is the callback function that will be called for each message as they arrive. Its arguments are as follows: -## Stream object +| Argument | Description | +| :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| payload | A JS object containing the message payload itself | +| streamMessage | The whole [StreamMessage](https://github.com/streamr-dev/streamr-client-protocol-js/blob/master/src/protocol/message_layer/StreamMessage.js) object containing various metadata, for example `streamMessage.getTimestamp()` etc. | -All the below functions return a Promise which gets resolved with the result. +```js +const sub = await client.subscribe({ + streamId: 'my-stream-id', +}, (payload, streamMessage) => { + console.log({ + payload, streamMessage + }) +}) -| Name | Description | -| :----------------------------------------- | :------------------------------------------------------------ | -| update() | Updates the properties of this stream object by sending them to the API. | -| delete() | Deletes this stream. | -| getPermissions() | Returns the list of permissions for this stream. | -| hasPermission(operation, user) | Returns a permission object, or null if no such permission was found. Valid `operation` values for streams are: stream_get, stream_edit, stream_delete, stream_publish, stream_subscribe, and stream_share. `user` is the username of a user, or null for public permissions. | -| grantPermission(operation, user) | Grants the permission to do `operation` to `user`, which are defined as above. | -| revokePermission(permissionId) | Revokes a permission identified by its `id`. | -| detectFields() | Updates the stream field config (schema) to match the latest data point in the stream. | -| publish(message, timestamp, partitionKey) | Publishes a new message to this stream. | +``` -## Subscription options +### Subscription Options Note that only one of the resend options can be used for a particular subscription. The default functionality is to resend nothing, only subscribe to messages from the subscription moment onwards. -| Name | Description | -| :--------- | :------------------------------------------------------------ | -| stream | Stream id to subscribe to | -| partition | Partition number to subscribe to. Defaults to partition 0. | -| resend | Object defining the resend options. Below are examples of its contents. | +| Name | Description | +| :-------- | :--------------------------------------------------------------------------------- | +| stream | Stream id to subscribe to | +| partition | Partition number to subscribe to. Defaults to partition 0. | +| resend | Object defining the resend options. Below are examples of its contents. | | groupKeys | Object defining the group key as a hex string for each publisher id of the stream. | -```javascript +```js // Resend N most recent messages -resend: { - last: 10, -} +const sub1 = await client.subscribe({ + streamId: 'my-stream-id', + resend: { + last: 10, + } +}, onMessage) // Resend from a specific message reference up to the newest message -resend: { - from: { - timestamp: 12345, - sequenceNumber: 0, // optional +const sub2 = await client.subscribe({ + streamId: 'my-stream-id', + resend: { + from: { + timestamp: 12345, + sequenceNumber: 0, // optional + }, + publisher: 'publisherId', // optional + msgChainId: 'msgChainId', // optional } - publisher: 'publisherId', // optional - msgChainId: 'msgChainId', // optional -} +}, onMessage) // Resend a limited range of messages -resend: { - from: { - timestamp: 12345, - sequenceNumber: 0, // optional - }, - to: { - timestamp: 54321, - sequenceNumber: 0, // optional - }, - publisher: 'publisherId', // optional - msgChainId: 'msgChainId', // optional -} +const sub3 = await client.subscribe({ + streamId: 'my-stream-id', + resend: { + from: { + timestamp: 12345, + sequenceNumber: 0, // optional + }, + to: { + timestamp: 54321, + sequenceNumber: 0, // optional + }, + publisher: 'publisherId', // optional + msgChainId: 'msgChainId', // optional + } +}, onMessage) ``` If you choose one of the above resend options when subscribing, you can listen on the completion of this resend by doing the following: -```javascript -const sub = client.subscribe(...) -sub.on('initial_resend_done', () => { +```js +const sub = await client.subscribe(options) +sub.on('resent', () => { console.log('All caught up and received all requested historical messages! Now switching to real time!') }) ``` +## Stream API + +All the below functions return a Promise which gets resolved with the result. + +| Name | Description | +| :-------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | +| getStream(streamId) | Fetches a stream object from the API. | +| listStreams(query) | Fetches an array of stream objects from the API. For the query params, consult the [API docs](https://api-explorer.streamr.com). | +| getStreamByName(name) | Fetches a stream which exactly matches the given name. | +| createStream(\[properties]) | Creates a stream with the given properties. For more information on the stream properties, consult the [API docs](https://api-explorer.streamr.com). | +| getOrCreateStream(properties) | Gets a stream with the id or name given in `properties`, or creates it if one is not found. | +| publish(streamId, message, timestamp, partitionKey) | Publishes a new message to the given stream. | + +### Stream object + +All the below functions return a Promise which gets resolved with the result. + +| Name | Description | +| :---------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| update() | Updates the properties of this stream object by sending them to the API. | +| delete() | Deletes this stream. | +| getPermissions() | Returns the list of permissions for this stream. | +| hasPermission(operation, user) | Returns a permission object, or null if no such permission was found. Valid `operation` values for streams are: stream_get, stream_edit, stream_delete, stream_publish, stream_subscribe, and stream_share. `user` is the username of a user, or null for public permissions. | +| grantPermission(operation, user) | Grants the permission to do `operation` to `user`, which are defined as above. | +| revokePermission(permissionId) | Revokes a permission identified by its `id`. | +| detectFields() | Updates the stream field config (schema) to match the latest data point in the stream. | +| publish(message, timestamp, partitionKey) | Publishes a new message to this stream. | + ## Data Unions -This library provides functions for working with Data Unions. All of the below methods return a Promise. +This library provides functions for working with Data Unions. To get a DataUnion instance, call `client.getDataUnion(address)`. To deploy a new DataUnion, call `deployDataUnion(options)` + +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 | +| 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 -#### Admin functions +| Name | Returns | Description | +| :-------------------------------------------------------------------------- | :------------------ | :------------------------------------------------------------- | +| createSecret(\[name]) | string | Create a secret for a Data Union | +| addMembers(memberAddressList, \[options]) | Transaction receipt | Add members | +| removeMembers(memberAddressList, \[options]) | Transaction receipt | Remove members from Data Union | +| withdrawAllToMember(memberAddress, \[options]) | | | +| withdrawAllToSigned(memberAddress, recipientAddress, signature, \[options]) | | | +| setAdminFee(newFeeFraction) | Transaction receipt | `newFeeFraction` is a `Number` between 0.0 and 1.0 (inclusive) | -| Name | Returns | Description | -| :------------------------------------------------------- | :----------- | :---------------------------------------------------------- | -| deployDataUnion() | Transaction | Deploy a new Data Union | -| createSecret(dataUnionContractAddress, secret[, name]) | | Create a secret for a Data Union | -| dataUnionIsReady(address) | | Wait until a new Data Union is initialized by its Operator | -| addMembers(dataUnionContractAddress, memberAddressList) | | Add members | -| kick(dataUnionContractAddress, memberAddressList) | | Kick members out from Data Union | +Here's an example how to deploy a data union contract and set the admin fee: + +```js +const client = new StreamrClient({ + auth: { privateKey }, +}) -```javascript const dataUnion = await client.deployDataUnion() -dataUnion.address // already available before deployment -await dataUnion.deployed() // waits until contract is deployed -await dataUnion.isReady() // waits until data union is operated +await client.setAdminFee(0.3, { dataUnion }) ``` -#### Member functions +### Member functions -| Name | Returns | Description | -| :------------------------------------------------------------ | :----------- | :------------------------------------------------------------ | -| joinDataUnion(dataUnionContractAddress[, secret]) | JoinRequest | Join a Data Union | -| hasJoined(dataUnionContractAddress[, memberAddress]) | | Wait until member has been accepted | -| validateProof(dataUnionContractAddress, options) | true/false | Check that server is giving a proof that allows withdrawing | -| withdraw(dataUnionContractAddress, options) | Receipt | Withdraw funds from Data Union | -| withdrawFor(memberAddress, dataUnionContractAddress, options) | Receipt | Pay for withdraw transaction on behalf of a Data Union member | -| withdrawTo(recipientAddress, dataUnionContractAddress, options) | Receipt | Donate/move your earnings to recipientAddress instead of your memberAddress | +| Name | Returns | Description | +| :-------------------------------------------------------------- | :------------------ | :-------------------------------------------------------------------------- | +| join(\[secret]) | JoinRequest | Join the Data Union (if a valid secret is given, the promise waits until the automatic join request has been processed) | +| isMember(memberAddress) | boolean | | +| withdrawAll(\[options]) | Transaction receipt | Withdraw funds from Data Union | +| withdrawAllTo(recipientAddress, \[options]) | Transaction receipt | Donate/move your earnings to recipientAddress instead of your memberAddress | +| signWithdrawAllTo(recipientAddress) | Signature (string) | Signature that can be used to withdraw tokens to given recipientAddress | +| signWithdrawAmountTo(recipientAddress, amountTokenWei) | Signature (string) | Signature that can be used to withdraw tokens to given recipientAddress | -The options object for withdraw functions above may contain following overrides: +Here's an example how to sign off on a withdraw to (any) recipientAddress: + +```js +const client = new StreamrClient({ + auth: { privateKey }, + dataUnion, +}) -| Property | Default | Description | -| :------------- | :--------- | :------------------------------------------------------------ | -| wallet | auth | ethers.js Wallet object to use to sign and send withdraw transaction | -| provider | mainnet | ethers.js Provider to use if wallet wasn't provided | -| confirmations | 1 | Number of blocks to wait after the withdraw transaction is mined | -| gasPrice | ethers.js | Probably uses the network estimate | +const signature = await client.signWithdrawAllTo(recipientAddress) +``` -#### Query functions +### Query functions These are available for everyone and anyone, to query publicly available info from a Data Union: -| Name | Returns | Description | -| :--------------------------------------------------------- | :--------------------------------- | :--------------------------- | -| getMemberStats(dataUnionContractAddress[, memberAddress]) | {earnings, proof, ...} | Get member's stats | -| getDataUnionStats(dataUnionContractAddress) | {memberCount, totalEarnings, ...} | Get Data Union's statistics | -| getMembers(dataUnionContractAddress) | [{address, earnings}, ...] | Get Data Union's members | +| Name | Returns | Description | +| :--------------------------------------------------------- | :--------------------------------------------- | :-------------------------------------- | +| getStats() | {activeMemberCount, totalEarnings, ...} | Get Data Union's statistics | +| getMemberStats(memberAddress) | {earnings, proof, ...} | Get member's stats | +| getWithdrawableEarnings(memberAddress) | `BigNumber` withdrawable DATA tokens in the DU | | +| getAdminFee() | `Number` between 0.0 and 1.0 (inclusive) | Admin's cut from revenues | +| getAdminAddress() | Ethereum address | Data union admin's address | +| getVersion() | `0`, `1` or `2` | `0` if the contract is not a data union | -## Utility functions +Here's an example how to get a member's withdrawable token balance (in "wei", where 1 DATA = 10^18 wei) -| Name | Description | -| :--------------------------------------- | :------------------------------------------------------------ | -| StreamrClient.generateEthereumAccount() | Generates a random Ethereum private key and returns an object with fields `address` and privateKey. Note that this private key can be used to authenticate to the Streamr API by passing it in the authentication options, as described earlier in this document. | +```js +const client = new StreamrClient({ + dataUnion, +}) -## Events +const withdrawableWei = await client.getMemberBalance(memberAddress) +``` -#### Binding to events +## Utility functions -The client and the subscriptions can fire events as detailed below. You can bind to them using `on`: +| Name | Description | +| :-------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| StreamrClient.generateEthereumAccount() | Generates a random Ethereum private key and returns an object with fields `address` and privateKey. Note that this private key can be used to authenticate to the Streamr API by passing it in the authentication options, as described earlier in this document. | +| getTokenBalance(address) | `BigNumber` | Mainnet DATA token balance | -```javascript - // The StreamrClient emits various events - client.on('connected', () => { - console.log('Yeah, we are connected now!') - }) +## Events - // So does the Subscription object - const sub = client.subscribe(...) - sub.on('subscribed', () => { - console.log(`Subscribed to ${sub.streamId}`) - }) +The client and the subscriptions can fire events as detailed below. +You can bind to them using `on`. + +| Name | Description | +| :---------------------------------- | :--------------------------------------------------------------------------------------- | +| on(eventName, function) | Binds a `function` to an event called `eventName` | +| once(eventName, function) | Binds a `function` to an event called `eventName`. It gets called once and then removed. | +| removeListener(eventName, function) | Unbinds the `function` from events called `eventName` | + +### Events on the StreamrClient instance + +| Name | Handler Arguments | Description | +| :----------- | :---------------- | :--------------------------------------------------------------- | +| connected | | Fired when the client has connected (or reconnected). | +| disconnected | | Fired when the client has disconnected (or paused). | +| error | Error | Fired when the client encounters an error e.g. connection issues | + +```js +// The StreamrClient emits various events +client.on('connected', () => { + // note no need to wait for this before doing work, + // with autoconnect enabled the client will happily establish a connection for you as required. + console.log('Yeah, we are connected now!') +}) ``` -#### Events on the StreamrClient instance - -| Name | Handler Arguments | Description | -| :------------ | :----------------- | :----------------------------------------------------- | -| connected | | Fired when the client has connected (or reconnected). | -| disconnected | | Fired when the client has disconnected (or paused). | - -#### Events on the Subscription object +### Events on the Subscription object -| Name | Handler Arguments | Description | -| :------------ | :------------------------------------------------------------ | :------------------------------------------------------------ | -| subscribed | | Fired when a subscription request is acknowledged by the server. | -| unsubscribed | | Fired when an unsubscription is acknowledged by the server. | -| resending | [ResendResponseResending](https://github.com/streamr-dev/streamr-client-protocol-js/blob/master/src/protocol/control_layer/resend_response_resending/ResendResponseResendingV1.js) | Fired when the subscription starts resending. Followed by the `resent` event to mark completion of the resend after resent messages have been processed by the message handler function. | -| resent | [ResendResponseResent](https://github.com/streamr-dev/streamr-client-protocol-js/blob/master/src/protocol/control_layer/resend_response_resent/ResendResponseResentV1.js) | Fired after `resending` when the subscription has finished resending. | -| no_resend | [ResendResponseNoResend](https://github.com/streamr-dev/streamr-client-protocol-js/blob/master/src/protocol/control_layer/resend_response_no_resend/ResendResponseNoResendV1.js) | This will occur instead of the `resending` - `resent` sequence in case there were no messages to resend. | -| error | Error object | Reports errors, for example problems with message content | +| Name | Handler Arguments | Description | +| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------- | +| unsubscribed | | Fired when an unsubscription is acknowledged by the server. | +| resent | [ResendResponseResent](https://github.com/streamr-dev/streamr-client-protocol-js/blob/master/src/protocol/control_layer/resend_response_resent/ResendResponseResentV1.js) | Fired after `resending` when the subscription has finished resending and message has been processed | +| error | Error object | Reports errors, for example problems with message content | ## Partitioning Partitioning (sharding) enables streams to scale horizontally. This section describes how to use partitioned streams via this library. To learn the basics of partitioning, see [the docs](https://streamr.network/docs/streams#partitioning). -#### Creating partitioned streams +### Creating partitioned streams By default, streams only have 1 partition when they are created. The partition count can be set to any positive number (1-100 is reasonable). An example of creating a partitioned stream using the JS client: -```javascript -client.createStream({ +```js +const stream = await client.createStream({ name: 'My partitioned stream', partitions: 10, -}).then(stream => { - console.log(`Stream created: ${stream.id}. It has ${stream.partitions} partitions.`) }) +console.log(`Stream created: ${stream.id}. It has ${stream.partitions} partitions.`) ``` -#### Publishing to partitioned streams +### Publishing to partitioned streams In most use cases, a user wants related events (e.g. events from a particular device) to be assigned to the same partition, so that the events retain a deterministic order and reach the same subscriber(s) to allow them to compute stateful aggregates correctly. -The library allows the user to choose a *partition key*, which simplifies publishing to partitioned streams by not requiring the user to assign a partition number explicitly. The same partition key always maps to the same partition. In an IoT use case, the device id can be used as partition key; in user interaction data it could be the user id, and so on. +The library allows the user to choose a _partition key_, which simplifies publishing to partitioned streams by not requiring the user to assign a partition number explicitly. The same partition key always maps to the same partition. In an IoT use case, the device id can be used as partition key; in user interaction data it could be the user id, and so on. The partition key can be given as an argument to the `publish` methods, and the library assigns a deterministic partition number automatically: -```javascript -client.publish('my-stream-id', msg, Date.now(), msg.vehicleId) +```js +await client.publish('my-stream-id', msg, Date.now(), msg.vehicleId) // or, equivalently -stream.publish(msg, Date.now(), msg.vehicleId) +await stream.publish(msg, Date.now(), msg.vehicleId) ``` -#### Subscribing to partitioned streams +### Subscribing to partitioned streams By default, the JS client subscribes to the first partition (partition `0`) in a stream. The partition number can be explicitly given in the subscribe call: -```javascript -client.subscribe( - { - stream: 'my-stream-id', - partition: 4, // defaults to 0 - }, - (payload) => { - console.log(`Got message ${JSON.stringify(payload)}`) - }, -) +```js +const sub = await client.subscribe({ + stream: 'my-stream-id', + partition: 4, // defaults to 0 +}, (payload) => { + console.log('Got message %o', payload) +}) ``` Or, to subscribe to multiple partitions, if the subscriber can handle the volume: -```javascript +```js const handler = (payload, streamMessage) => { - console.log(`Got message ${JSON.stringify(payload)} from partition ${streamMessage.getStreamPartition()}`) + console.log('Got message %o from partition %d', payload, streamMessage.getStreamPartition()) } -[2,3,4].forEach(partition => { - client.subscribe( - { - stream: 'my-stream-id', - partition: partition, - }, - handler, - ) -}) +await Promise.all([2, 3, 4].map(async (partition) => { + await client.subscribe({ + stream: 'my-stream-id', + partition, + }, handler) +})) ``` ## Logging @@ -465,25 +515,32 @@ The Streamr JS client library supports [debug](https://github.com/visionmedia/de In node.js, start your app like this: `DEBUG=StreamrClient* node your-app.js` -In the browser, include `debug.js` and set `localStorage.debug = 'StreamrClient'` +In the browser, set `localStorage.debug = 'StreamrClient*'` + +## For Developers + +Publishing to npm is automated via Github Actions. Follow the steps below to publish `latest` or `beta`. + +### Publishing `latest` + +1. Update version with either `npm version [patch|minor|major]`. Use + semantic versioning . Files package.json and + package-lock.json will be automatically updated, and an appropriate + git commit and tag created. + +2. `git push --follow-tags` +3. Wait for Github Actions to run tests -## Publishing +4. If tests passed, Github Actions will publish the new version to npm -Publishing to NPM is automated via Github Actions. Follow the steps below to publish `latest` or `beta`. +### Publishing `beta` -#### Publishing `latest`: +1. Update version with either `npm version [prepatch|preminor|premajor] --preid=beta`. Use semantic versioning + . Files package.json and package-lock.json will be automatically updated, and an appropriate git commit and tag created. -1. Update version with either `npm version [patch|minor|major]`. Use semantic versioning - https://semver.org/. Files package.json and package-lock.json will be automatically updated, and an appropriate git commit and tag created. -2. `git push --follow-tags` -3. Wait for Github Actions to run tests -4. If tests passed, Github Actions will publish the new version to NPM +2. `git push --follow-tags` -#### Publishing `beta`: +3. Wait for Github Actions to run tests -1. Update version with either `npm version [prepatch|preminor|premajor] --preid=beta`. Use semantic versioning - https://semver.org/. Files package.json and package-lock.json will be automatically updated, and an appropriate git commit and tag created. -2. `git push --follow-tags` -3. Wait for Github Actions to run tests -4. If tests passed, Github Actions will publish the new version to NPM +4. If tests passed, Github Actions will publish the new version to npm diff --git a/contracts/DataUnion.json b/contracts/DataUnion.json deleted file mode 100644 index b48c64879..000000000 --- a/contracts/DataUnion.json +++ /dev/null @@ -1,1764 +0,0 @@ -{ - "contractName": "DataunionVault", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "string", - "name": "joinPartStreamId", - "type": "string" - }, - { - "internalType": "address", - "name": "tokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "blockFreezePeriodSeconds", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "adminFeeFraction", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "adminFee", - "type": "uint256" - } - ], - "name": "AdminFeeChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "rootHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "ipfsHash", - "type": "string" - } - ], - "name": "NewCommit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "newOperator", - "type": "address" - } - ], - "name": "OperatorChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "adminFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "blockFreezeSeconds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "blockTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "bytes32", - "name": "leafHash", - "type": "bytes32" - }, - { - "internalType": "bytes32[]", - "name": "others", - "type": "bytes32[]" - } - ], - "name": "calculateRootHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "root", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "claimOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "rootHash", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "ipfsHash", - "type": "string" - } - ], - "name": "commit", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "committedHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "earnings", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "joinPartStream", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "operator", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "pendingOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "proofIsCorrect", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "prove", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "signer", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalEarnings", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "proveAndWithdrawToSigned", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "newAdminFee", - "type": "uint256" - } - ], - "name": "setAdminFee", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "newOperator", - "type": "address" - } - ], - "name": "setOperator", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "signer", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "name": "signatureIsValid", - "outputs": [ - { - "internalType": "bool", - "name": "isValid", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "token", - "outputs": [ - { - "internalType": "contract IERC20", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalProven", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalWithdrawn", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalEarnings", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "withdrawAll", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalEarnings", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "withdrawAllFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalEarnings", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "withdrawAllTo", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "signer", - "type": "address" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "totalEarnings", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "name": "withdrawAllToSigned", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawFor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawTo", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "signer", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "name": "withdrawToSigned", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "withdrawn", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x60806040526001600d553480156200001657600080fd5b506040516200333838038062003338833981810160405260a08110156200003c57600080fd5b8101908080519060200190929190805160405193929190846401000000008211156200006757600080fd5b838201915060208201858111156200007e57600080fd5b82518660018202830111640100000000821117156200009c57600080fd5b8083526020830192505050908051906020019080838360005b83811015620000d2578082015181840152602081019050620000b5565b50505050905090810190601f168015620001005780820380516001836020036101000a031916815260200191505b5060405260200180519060200190929190805190602001909291908051906020019092919050505082828233600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160038190555082600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062000206816200023e60201b60201c565b5050506200021a85620003c460201b60201c565b83600c9080519060200190620002329291906200050f565b505050505050620005be565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462000302576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f6e6c794f776e6572000000000000000000000000000000000081525060200191505060405180910390fd5b670de0b6b3a764000081111562000381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6572726f725f61646d696e46656500000000000000000000000000000000000081525060200191505060405180910390fd5b806006819055507f11a80b766155f9b8f16a7da44d66269fd694cb1c247f4814244586f68dd534876006546040518082815260200191505060405180910390a150565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161462000488576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f6e6c794f776e6572000000000000000000000000000000000081525060200191505060405180910390fd5b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f4721129e0e676ed6a92909bb24e853ccdd63ad72280cc2e974e38e480e0e6e5460405160405180910390a250565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200055257805160ff191683800117855562000583565b8280016001018555821562000583579182015b828111156200058257825182559160200191906001019062000565565b5b50905062000592919062000596565b5090565b620005bb91905b80821115620005b75760008160009055506001016200059d565b5090565b90565b612d6a80620005ce6000396000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c80638beb60b61161010f578063b74d784e116100a2578063e1a9888e11610071578063e1a9888e14610fc3578063e30c397814611005578063f2fde38b1461104f578063fc0c546a14611093576101f0565b8063b74d784e14610dc6578063c3ac610d14610de4578063cb9b51c814610e71578063db518db214610f75576101f0565b8063a2d3cf4b116100de578063a2d3cf4b14610a3e578063adc4c87414610b5b578063b3ab15fb14610c60578063b619d3bd14610ca4576101f0565b80638beb60b61461087c5780638da5cb5b146108aa578063a0b9d101146108f4578063a0be06f914610a20576101f0565b8063543fd313116101875780636dd4a7c9116101565780636dd4a7c9146106ee5780636ef61092146107c457806371b150131461081c57806373d8903b1461083a576101f0565b8063543fd3131461054257806354fd4d501461059a578063570ca735146105b85780636c7a9d2414610602576101f0565b80634942e4cf116101c35780634942e4cf1461040a5780634b319713146104975780634beb62b7146104b55780634e71e0c814610538576101f0565b8063205c2878146101f5578063270231cc146102435780632e1a7d4d146102f057806332ef2b241461031e575b600080fd5b6102416004803603604081101561020b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506110dd565b005b6102ee6004803603608081101561025957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803590602001906401000000008111156102aa57600080fd5b8201836020820111156102bc57600080fd5b803590602001918460208302840111640100000000831117156102de57600080fd5b90919293919293905050506110ec565b005b61031c6004803603602081101561030657600080fd5b81019080803590602001909291905050506111a1565b005b6104086004803603608081101561033457600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561038557600080fd5b82018360208201111561039757600080fd5b803590602001918460208302840111640100000000831117156103b957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192905050506111af565b005b6104956004803603606081101561042057600080fd5b8101908080359060200190929190803590602001909291908035906020019064010000000081111561045157600080fd5b82018360208201111561046357600080fd5b8035906020019184602083028401116401000000008311171561048557600080fd5b909192939192939050505061123e565b005b61049f611291565b6040518082815260200191505060405180910390f35b6104bd611297565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104fd5780820151818401526020810190506104e2565b50505050905090810190601f16801561052a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610540611335565b005b6105846004803603602081101561055857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061153d565b6040518082815260200191505060405180910390f35b6105a2611555565b6040518082815260200191505060405180910390f35b6105c061155b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6106ec6004803603608081101561061857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561066957600080fd5b82018360208201111561067b57600080fd5b8035906020019184602083028401116401000000008311171561069d57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509192919290505050611581565b005b6107ae6004803603604081101561070457600080fd5b81019080803590602001909291908035906020019064010000000081111561072b57600080fd5b82018360208201111561073d57600080fd5b8035906020019184602083028401116401000000008311171561075f57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192905050506115f4565b6040518082815260200191505060405180910390f35b610806600480360360208110156107da57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506116ab565b6040518082815260200191505060405180910390f35b6108246116c3565b6040518082815260200191505060405180910390f35b6108666004803603602081101561085057600080fd5b81019080803590602001909291905050506116c9565b6040518082815260200191505060405180910390f35b6108a86004803603602081101561089257600080fd5b81019080803590602001909291905050506116e1565b005b6108b2611865565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a1e600480360360e081101561090a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561097157600080fd5b82018360208201111561098357600080fd5b803590602001918460018302840111640100000000831117156109a557600080fd5b90919293919293908035906020019092919080359060200190929190803590602001906401000000008111156109da57600080fd5b8201836020820111156109ec57600080fd5b80359060200191846020830284011164010000000083111715610a0e57600080fd5b909192939192939050505061188b565b005b610a286119b0565b6040518082815260200191505060405180910390f35b610b4160048036036080811015610a5457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610abb57600080fd5b820183602082011115610acd57600080fd5b80359060200191846001830284011164010000000083111715610aef57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506119b6565b604051808215151515815260200191505060405180910390f35b610c5e60048036036080811015610b7157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610bd857600080fd5b820183602082011115610bea57600080fd5b80359060200191846001830284011164010000000083111715610c0c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050611c97565b005b610ca260048036036020811015610c7657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611d26565b005b610dc4600480360360c0811015610cba57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610d1757600080fd5b820183602082011115610d2957600080fd5b80359060200191846001830284011164010000000083111715610d4b57600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190640100000000811115610d8057600080fd5b820183602082011115610d9257600080fd5b80359060200191846020830284011164010000000083111715610db457600080fd5b9091929391929390505050611e70565b005b610dce611fec565b6040518082815260200191505060405180910390f35b610e6f60048036036060811015610dfa57600080fd5b81019080803590602001909291908035906020019092919080359060200190640100000000811115610e2b57600080fd5b820183602082011115610e3d57600080fd5b80359060200191846001830284011164010000000083111715610e5f57600080fd5b9091929391929390505050611ff2565b005b610f5b60048036036080811015610e8757600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610ed857600080fd5b820183602082011115610eea57600080fd5b80359060200191846020830284011164010000000083111715610f0c57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050919291929050505061219a565b604051808215151515815260200191505060405180910390f35b610fc160048036036040811015610f8b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506122ad565b005b610fef60048036036020811015610fd957600080fd5b81019080803590602001909291905050506122bc565b6040518082815260200191505060405180910390f35b61100d6122d4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6110916004803603602081101561106557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506122fa565b005b61109b612401565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6110e8823383612427565b5050565b611139843385858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050506111af565b600061118d600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548561276390919063ffffffff16565b905061119986826110dd565b505050505050565b6111ac333383612427565b50565b6111bb8484848461219a565b61122d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f6572726f725f70726f6f6600000000000000000000000000000000000000000081525060200191505060405180910390fd5b6112388484846127ad565b50505050565b61128b338585858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050611581565b50505050565b60085481565b600c8054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561132d5780601f106113025761010080835404028352916020019161132d565b820191906000526020600020905b81548152906001019060200180831161131057829003601f168201915b505050505081565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146113f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6572726f725f6f6e6c7950656e64696e674f776e65720000000000000000000081525060200191505060405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600a6020528060005260406000206000915090505481565b600d5481565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61158d838584846111af565b60006115e1600b60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548461276390919063ffffffff16565b90506115ed85826122ad565b5050505050565b600082905060008090505b82518160ff1610156116a4576000838260ff168151811061161c57fe5b60200260200101519050808310156116645782816040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209250611696565b808360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092505b5080806001019150506115ff565b5092915050565b600b6020528060005260406000206000915090505481565b60035481565b60046020528060005260406000206000915090505481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146117a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f6e6c794f776e6572000000000000000000000000000000000081525060200191505060405180910390fd5b670de0b6b3a7640000811115611822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6572726f725f61646d696e46656500000000000000000000000000000000000081525060200191505060405180910390fd5b806006819055507f11a80b766155f9b8f16a7da44d66269fd694cb1c247f4814244586f68dd534876006546040518082815260200191505060405180910390a150565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6118db89898989898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506119b6565b61194d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f6261645369676e6174757265000000000000000000000000000081525060200191505060405180910390fd5b61199a848985858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050506111af565b6119a5898989612427565b505050505050505050565b60065481565b60006041825114611a2f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f6572726f725f6261645369676e61747572654c656e677468000000000000000081525060200191505060405180910390fd5b60008060006020850151925060408501519150606085015160001a9050601b8160ff161015611a5f57601b810190505b601b8160ff161480611a745750601c8160ff16145b611ae6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f6572726f725f6261645369676e617475726556657273696f6e0000000000000081525060200191505060405180910390fd5b6000888730600b60008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460405160200180807f19457468657265756d205369676e6564204d6573736167653a0a313034000000815250601d018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401828152602001945050505050604051602081830303815290604052805190602001209050600060018284878760405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611c4d573d6000803e3d6000fd5b5050506020604051035190508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161495505050505050949350505050565b611ca3848484846119b6565b611d15576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f6261645369676e6174757265000000000000000000000000000081525060200191505060405180910390fd5b611d20848484612427565b50505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611de9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f6e6c794f776e6572000000000000000000000000000000000081525060200191505060405180910390fd5b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f4721129e0e676ed6a92909bb24e853ccdd63ad72280cc2e974e38e480e0e6e5460405160405180910390a250565b611ec18888600089898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506119b6565b611f33576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f6261645369676e6174757265000000000000000000000000000081525060200191505060405180910390fd5b611f80848885858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050506111af565b6000611fd4600b60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548561276390919063ffffffff16565b9050611fe1898983612427565b505050505050505050565b60095481565b6000801b600080868152602001908152602001600020541461207c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f7665727772697465000000000000000000000000000000000081525060200191505060405180910390fd5b606082828080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505090506120d0858583612b0d565b83600080878152602001908152602001600020819055507f444dcb3cce8fbb3e1dabd2ff958f17fb1e673b759824d631d9cda0690d031eb98585836040518084815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561215757808201518184015260208101905061213c565b50505050905090810190601f1680156121845780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a15050505050565b600080848487604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401838152602001828152602001935050505060405160208183030381529060405280519060200120905060008060008881526020019081526020016000205490506000801b811415612295576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f6572726f725f626c6f636b4e6f74466f756e640000000000000000000000000081525060200191505060405180910390fd5b61229f82856115f4565b811492505050949350505050565b6122b8828383612427565b5050565b60006020528060005260406000206000915090505481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146123bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f6e6c794f776e6572000000000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161249d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f7a65726f5769746864726177000000000000000000000000000081525060200191505060405180910390fd5b60006124f182600b60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612bed90919063ffffffff16565b9050600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548111156125a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f7665726472616674000000000000000000000000000000000081525060200191505060405180910390fd5b80600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061260182600854612bed90919063ffffffff16565b600881905550600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156126b057600080fd5b505af11580156126c4573d6000803e3d6000fd5b505050506040513d60208110156126da57600080fd5b810190808051906020019092919050505061275d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6572726f725f7472616e7366657200000000000000000000000000000000000081525060200191505060405180910390fd5b50505050565b60006127a583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612c75565b905092915050565b6000600460008581526020019081526020016000205490506003548101421161283e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f6572726f725f66726f7a656e000000000000000000000000000000000000000081525060200191505060405180910390fd5b81600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054106128f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6572726f725f6f6c644561726e696e677300000000000000000000000000000081525060200191505060405180910390fd5b612958600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461294a84600954612bed90919063ffffffff16565b61276390919063ffffffff16565b600981905550600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156129fd57600080fd5b505afa158015612a11573d6000803e3d6000fd5b505050506040513d6020811015612a2757600080fd5b8101908080519060200190929190505050612a4f60085460095461276390919063ffffffff16565b1115612ac3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6572726f725f6d697373696e6742616c616e636500000000000000000000000081525060200191505060405180910390fd5b81600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612bd0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f6e6f745065726d6974746564000000000000000000000000000081525060200191505060405180910390fd5b426004600085815260200190815260200160002081905550505050565b600080828401905083811015612c6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000838311158290612d22576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612ce7578082015181840152602081019050612ccc565b50505050905090810190601f168015612d145780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838503905080915050939250505056fea265627a7a72315820c41307a82520f0f3c5d150a03d5d08db63f386017b9d416825cd59dd315625f564736f6c63430005100032", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101f05760003560e01c80638beb60b61161010f578063b74d784e116100a2578063e1a9888e11610071578063e1a9888e14610fc3578063e30c397814611005578063f2fde38b1461104f578063fc0c546a14611093576101f0565b8063b74d784e14610dc6578063c3ac610d14610de4578063cb9b51c814610e71578063db518db214610f75576101f0565b8063a2d3cf4b116100de578063a2d3cf4b14610a3e578063adc4c87414610b5b578063b3ab15fb14610c60578063b619d3bd14610ca4576101f0565b80638beb60b61461087c5780638da5cb5b146108aa578063a0b9d101146108f4578063a0be06f914610a20576101f0565b8063543fd313116101875780636dd4a7c9116101565780636dd4a7c9146106ee5780636ef61092146107c457806371b150131461081c57806373d8903b1461083a576101f0565b8063543fd3131461054257806354fd4d501461059a578063570ca735146105b85780636c7a9d2414610602576101f0565b80634942e4cf116101c35780634942e4cf1461040a5780634b319713146104975780634beb62b7146104b55780634e71e0c814610538576101f0565b8063205c2878146101f5578063270231cc146102435780632e1a7d4d146102f057806332ef2b241461031e575b600080fd5b6102416004803603604081101561020b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506110dd565b005b6102ee6004803603608081101561025957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803590602001906401000000008111156102aa57600080fd5b8201836020820111156102bc57600080fd5b803590602001918460208302840111640100000000831117156102de57600080fd5b90919293919293905050506110ec565b005b61031c6004803603602081101561030657600080fd5b81019080803590602001909291905050506111a1565b005b6104086004803603608081101561033457600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561038557600080fd5b82018360208201111561039757600080fd5b803590602001918460208302840111640100000000831117156103b957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192905050506111af565b005b6104956004803603606081101561042057600080fd5b8101908080359060200190929190803590602001909291908035906020019064010000000081111561045157600080fd5b82018360208201111561046357600080fd5b8035906020019184602083028401116401000000008311171561048557600080fd5b909192939192939050505061123e565b005b61049f611291565b6040518082815260200191505060405180910390f35b6104bd611297565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104fd5780820151818401526020810190506104e2565b50505050905090810190601f16801561052a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610540611335565b005b6105846004803603602081101561055857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061153d565b6040518082815260200191505060405180910390f35b6105a2611555565b6040518082815260200191505060405180910390f35b6105c061155b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6106ec6004803603608081101561061857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561066957600080fd5b82018360208201111561067b57600080fd5b8035906020019184602083028401116401000000008311171561069d57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509192919290505050611581565b005b6107ae6004803603604081101561070457600080fd5b81019080803590602001909291908035906020019064010000000081111561072b57600080fd5b82018360208201111561073d57600080fd5b8035906020019184602083028401116401000000008311171561075f57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192905050506115f4565b6040518082815260200191505060405180910390f35b610806600480360360208110156107da57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506116ab565b6040518082815260200191505060405180910390f35b6108246116c3565b6040518082815260200191505060405180910390f35b6108666004803603602081101561085057600080fd5b81019080803590602001909291905050506116c9565b6040518082815260200191505060405180910390f35b6108a86004803603602081101561089257600080fd5b81019080803590602001909291905050506116e1565b005b6108b2611865565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a1e600480360360e081101561090a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561097157600080fd5b82018360208201111561098357600080fd5b803590602001918460018302840111640100000000831117156109a557600080fd5b90919293919293908035906020019092919080359060200190929190803590602001906401000000008111156109da57600080fd5b8201836020820111156109ec57600080fd5b80359060200191846020830284011164010000000083111715610a0e57600080fd5b909192939192939050505061188b565b005b610a286119b0565b6040518082815260200191505060405180910390f35b610b4160048036036080811015610a5457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610abb57600080fd5b820183602082011115610acd57600080fd5b80359060200191846001830284011164010000000083111715610aef57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506119b6565b604051808215151515815260200191505060405180910390f35b610c5e60048036036080811015610b7157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610bd857600080fd5b820183602082011115610bea57600080fd5b80359060200191846001830284011164010000000083111715610c0c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050611c97565b005b610ca260048036036020811015610c7657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611d26565b005b610dc4600480360360c0811015610cba57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610d1757600080fd5b820183602082011115610d2957600080fd5b80359060200191846001830284011164010000000083111715610d4b57600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190640100000000811115610d8057600080fd5b820183602082011115610d9257600080fd5b80359060200191846020830284011164010000000083111715610db457600080fd5b9091929391929390505050611e70565b005b610dce611fec565b6040518082815260200191505060405180910390f35b610e6f60048036036060811015610dfa57600080fd5b81019080803590602001909291908035906020019092919080359060200190640100000000811115610e2b57600080fd5b820183602082011115610e3d57600080fd5b80359060200191846001830284011164010000000083111715610e5f57600080fd5b9091929391929390505050611ff2565b005b610f5b60048036036080811015610e8757600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610ed857600080fd5b820183602082011115610eea57600080fd5b80359060200191846020830284011164010000000083111715610f0c57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050919291929050505061219a565b604051808215151515815260200191505060405180910390f35b610fc160048036036040811015610f8b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506122ad565b005b610fef60048036036020811015610fd957600080fd5b81019080803590602001909291905050506122bc565b6040518082815260200191505060405180910390f35b61100d6122d4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6110916004803603602081101561106557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506122fa565b005b61109b612401565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6110e8823383612427565b5050565b611139843385858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050506111af565b600061118d600b60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548561276390919063ffffffff16565b905061119986826110dd565b505050505050565b6111ac333383612427565b50565b6111bb8484848461219a565b61122d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600b8152602001807f6572726f725f70726f6f6600000000000000000000000000000000000000000081525060200191505060405180910390fd5b6112388484846127ad565b50505050565b61128b338585858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050611581565b50505050565b60085481565b600c8054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561132d5780601f106113025761010080835404028352916020019161132d565b820191906000526020600020905b81548152906001019060200180831161131057829003601f168201915b505050505081565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146113f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6572726f725f6f6e6c7950656e64696e674f776e65720000000000000000000081525060200191505060405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600a6020528060005260406000206000915090505481565b600d5481565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61158d838584846111af565b60006115e1600b60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548461276390919063ffffffff16565b90506115ed85826122ad565b5050505050565b600082905060008090505b82518160ff1610156116a4576000838260ff168151811061161c57fe5b60200260200101519050808310156116645782816040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209250611696565b808360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092505b5080806001019150506115ff565b5092915050565b600b6020528060005260406000206000915090505481565b60035481565b60046020528060005260406000206000915090505481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146117a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f6e6c794f776e6572000000000000000000000000000000000081525060200191505060405180910390fd5b670de0b6b3a7640000811115611822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6572726f725f61646d696e46656500000000000000000000000000000000000081525060200191505060405180910390fd5b806006819055507f11a80b766155f9b8f16a7da44d66269fd694cb1c247f4814244586f68dd534876006546040518082815260200191505060405180910390a150565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6118db89898989898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506119b6565b61194d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f6261645369676e6174757265000000000000000000000000000081525060200191505060405180910390fd5b61199a848985858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050506111af565b6119a5898989612427565b505050505050505050565b60065481565b60006041825114611a2f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f6572726f725f6261645369676e61747572654c656e677468000000000000000081525060200191505060405180910390fd5b60008060006020850151925060408501519150606085015160001a9050601b8160ff161015611a5f57601b810190505b601b8160ff161480611a745750601c8160ff16145b611ae6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f6572726f725f6261645369676e617475726556657273696f6e0000000000000081525060200191505060405180910390fd5b6000888730600b60008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460405160200180807f19457468657265756d205369676e6564204d6573736167653a0a313034000000815250601d018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b81526014018481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401828152602001945050505050604051602081830303815290604052805190602001209050600060018284878760405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611c4d573d6000803e3d6000fd5b5050506020604051035190508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161495505050505050949350505050565b611ca3848484846119b6565b611d15576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f6261645369676e6174757265000000000000000000000000000081525060200191505060405180910390fd5b611d20848484612427565b50505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611de9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f6e6c794f776e6572000000000000000000000000000000000081525060200191505060405180910390fd5b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f4721129e0e676ed6a92909bb24e853ccdd63ad72280cc2e974e38e480e0e6e5460405160405180910390a250565b611ec18888600089898080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506119b6565b611f33576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f6261645369676e6174757265000000000000000000000000000081525060200191505060405180910390fd5b611f80848885858580806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050506111af565b6000611fd4600b60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548561276390919063ffffffff16565b9050611fe1898983612427565b505050505050505050565b60095481565b6000801b600080868152602001908152602001600020541461207c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f7665727772697465000000000000000000000000000000000081525060200191505060405180910390fd5b606082828080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505090506120d0858583612b0d565b83600080878152602001908152602001600020819055507f444dcb3cce8fbb3e1dabd2ff958f17fb1e673b759824d631d9cda0690d031eb98585836040518084815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561215757808201518184015260208101905061213c565b50505050905090810190601f1680156121845780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a15050505050565b600080848487604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b8152601401838152602001828152602001935050505060405160208183030381529060405280519060200120905060008060008881526020019081526020016000205490506000801b811415612295576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f6572726f725f626c6f636b4e6f74466f756e640000000000000000000000000081525060200191505060405180910390fd5b61229f82856115f4565b811492505050949350505050565b6122b8828383612427565b5050565b60006020528060005260406000206000915090505481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146123bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f6e6c794f776e6572000000000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161249d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f7a65726f5769746864726177000000000000000000000000000081525060200191505060405180910390fd5b60006124f182600b60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612bed90919063ffffffff16565b9050600a60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548111156125a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f6572726f725f6f7665726472616674000000000000000000000000000000000081525060200191505060405180910390fd5b80600b60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061260182600854612bed90919063ffffffff16565b600881905550600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156126b057600080fd5b505af11580156126c4573d6000803e3d6000fd5b505050506040513d60208110156126da57600080fd5b810190808051906020019092919050505061275d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6572726f725f7472616e7366657200000000000000000000000000000000000081525060200191505060405180910390fd5b50505050565b60006127a583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612c75565b905092915050565b6000600460008581526020019081526020016000205490506003548101421161283e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f6572726f725f66726f7a656e000000000000000000000000000000000000000081525060200191505060405180910390fd5b81600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054106128f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6572726f725f6f6c644561726e696e677300000000000000000000000000000081525060200191505060405180910390fd5b612958600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461294a84600954612bed90919063ffffffff16565b61276390919063ffffffff16565b600981905550600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156129fd57600080fd5b505afa158015612a11573d6000803e3d6000fd5b505050506040513d6020811015612a2757600080fd5b8101908080519060200190929190505050612a4f60085460095461276390919063ffffffff16565b1115612ac3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6572726f725f6d697373696e6742616c616e636500000000000000000000000081525060200191505060405180910390fd5b81600a60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050505050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612bd0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6572726f725f6e6f745065726d6974746564000000000000000000000000000081525060200191505060405180910390fd5b426004600085815260200190815260200160002081905550505050565b600080828401905083811015612c6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000838311158290612d22576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612ce7578082015181840152602081019050612ccc565b50505050905090810190601f168015612d145780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838503905080915050939250505056fea265627a7a72315820c41307a82520f0f3c5d150a03d5d08db63f386017b9d416825cd59dd315625f564736f6c63430005100032", - "sourceMap": "73:483:0:-;;;247:1;225:23;;255:299;8:9:-1;5:2;;;30:1;27;20:12;5:2;255:299:0;;;;;;;;;;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;255:299:0;;;;;;;;;;;;;;;;;;;;;;19:11:-1;14:3;11:20;8:2;;;44:1;41;34:12;8:2;71:11;66:3;62:21;55:28;;123:4;118:3;114:14;159:9;141:16;138:31;135:2;;;182:1;179;172:12;135:2;219:3;213:10;330:9;325:1;311:12;307:20;289:16;285:43;282:58;261:11;247:12;244:29;233:115;230:2;;;361:1;358;351:12;230:2;384:12;379:3;372:25;420:4;415:3;411:14;404:21;;0:432;;255:299:0;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;255:299:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;408:12;422:24;448:16;574:10:4;566:5;;:18;;;;;;;;;;;;;;;;;;2938:24:3;2917:18;:45;;;;2987:12;2972:5;;:28;;;;;;;;;;;;;;;;;;3021:10;3010:8;;:21;;;;;;;;;;;;;;;;;;3041:28;3053:15;3041:11;;;:28;;:::i;:::-;2813:263;;;483:21:0;495:8;483:11;;;:21;;:::i;:::-;531:16;514:14;:33;;;;;;;;;;;;:::i;:::-;;255:299;;;;;73:483;;3608:194:3;732:5:4;;;;;;;;;;;718:19;;:10;:19;;;710:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3697:7:3;3682:11;:22;;3674:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3744:11;3733:8;:22;;;;3770:25;3786:8;;3770:25;;;;;;;;;;;;;;;;;;3608:194;:::o;3212:141::-;732:5:4;;;;;;;;;;;718:19;;:10;:19;;;710:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3292:11:3;3281:8;;:22;;;;;;;;;;;;;;;;;;3334:11;3318:28;;;;;;;;;;;;3212:141;:::o;73:483:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;", - "deployedSourceMap": "73:483:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;73:483:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11565:116:3;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;11565:116:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;7426:299;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;7426:299:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;7426:299:3;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;7426:299:3;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;7426:299:3;;;;;;;;;;;;:::i;:::-;;10712:96;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;10712:96:3;;;;;;;;;;;;;;;;;:::i;:::-;;3724:244:2;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;3724:244:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;3724:244:2;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;3724:244:2;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;3724:244:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;3724:244:2;;;;;;;;;;;;;;;:::i;:::-;;6029:172:3;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;6029:172:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;6029:172:3;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;6029:172:3;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;6029:172:3;;;;;;;;;;;;:::i;:::-;;1899:26;;;:::i;:::-;;;;;;;;;;;;;;;;;;;118:28:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;118:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1122:232:4;;;:::i;:::-;;2667:41:3;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;2667:41:3;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;225:23:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1715::3;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;6679:295;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;6679:295:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;6679:295:3;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;6679:295:3;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;6679:295:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;6679:295:3;;;;;;;;;;;;;;;:::i;:::-;;4937:562:2;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;4937:562:2;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;4937:562:2;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;4937:562:2;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;4937:562:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;4937:562:2;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;2764:42:3;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;2764:42:3;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1267:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1594:44;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1594:44:3;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;3608:194;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3608:194:3;;;;;;;;;;;;;;;;;:::i;:::-;;239:20:4;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;10079:481:3;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;10079:481:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;10079:481:3;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;10079:481:3;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;10079:481:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;10079:481:3;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;10079:481:3;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;10079:481:3;;;;;;;;;;;;:::i;:::-;;1783:20;;;:::i;:::-;;;;;;;;;;;;;;;;;;;14582:961;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;14582:961:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;14582:961:3;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;14582:961:3;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;14582:961:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;14582:961:3;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;12199:253;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;12199:253:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;12199:253:3;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;12199:253:3;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;12199:253:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;12199:253:3;;;;;;;;;;;;;;;:::i;:::-;;3212:141;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3212:141:3;;;;;;;;;;;;;;;;;;;:::i;:::-;;8712:543;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;8712:543:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;8712:543:3;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;8712:543:3;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;8712:543:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;8712:543:3;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;8712:543:3;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;8712:543:3;;;;;;;;;;;;:::i;:::-;;2585:23;;;:::i;:::-;;;;;;;;;;;;;;;;;;;2973:402:2;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;2973:402:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;2973:402:2;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;2973:402:2;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;2973:402:2;;;;;;;;;;;;:::i;:::-;;4342:392;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;4342:392:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;4342:392:2;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;4342:392:2;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;4342:392:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;4342:392:2;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;11118:116:3;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;11118:116:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;1919:46:2;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1919:46:2;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;265:27:4;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;928:102;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;928:102:4;;;;;;;;;;;;;;;;;;;:::i;:::-;;1810:19:3;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;11565:116;11634:40;11644:9;11655:10;11667:6;11634:9;:40::i;:::-;11565:116;;:::o;7426:299::-;7551:52;7557:11;7570:10;7582:13;7597:5;;7551:52;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;7551:52:3;;;;;;:5;:52::i;:::-;7613:17;7633:40;7651:9;:21;7661:10;7651:21;;;;;;;;;;;;;;;;7633:13;:17;;:40;;;;:::i;:::-;7613:60;;7683:35;7694:9;7705:12;7683:10;:35::i;:::-;7426:299;;;;;;:::o;10712:96::-;10760:41;10770:10;10782;10794:6;10760:9;:41::i;:::-;10712:96;:::o;3724:244:2:-;3837:52;3852:11;3865:7;3874;3883:5;3837:14;:52::i;:::-;3829:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3915:46;3931:11;3944:7;3953;3915:15;:46::i;:::-;3724:244;;;;:::o;6029:172:3:-;6133:61;6148:10;6160:11;6173:13;6188:5;;6133:61;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;6133:61:3;;;;;;:14;:61::i;:::-;6029:172;;;;:::o;1899:26::-;;;;:::o;118:28:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1122:232:4:-;1187:12;;;;;;;;;;;1173:26;;:10;:26;;;1165:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1269:12;;;;;;;;;;;1241:41;;1262:5;;;;;;;;;;;1241:41;;;;;;;;;;;;1300:12;;;;;;;;;;;1292:5;;:20;;;;;;;;;;;;;;;;;;1345:1;1322:12;;:25;;;;;;;;;;;;;;;;;;1122:232::o;2667:41:3:-;;;;;;;;;;;;;;;;;:::o;225:23:0:-;;;;:::o;1715::3:-;;;;;;;;;;;;;:::o;6679:295::-;6801:51;6807:11;6820:9;6831:13;6846:5;6801;:51::i;:::-;6862:17;6882:39;6900:9;:20;6910:9;6900:20;;;;;;;;;;;;;;;;6882:13;:17;;:39;;;;:::i;:::-;6862:59;;6931:36;6943:9;6954:12;6931:11;:36::i;:::-;6679:295;;;;;:::o;4937:562:2:-;5028:12;5059:8;5052:15;;5082:7;5092:1;5082:11;;5077:416;5099:6;:13;5095:1;:17;;;5077:416;;;5133:13;5149:6;5156:1;5149:9;;;;;;;;;;;;;;;;5133:25;;5183:5;5176:4;:12;5172:311;;;5369:4;5375:5;5352:29;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;5352:29:2;;;5342:40;;;;;;5335:47;;5172:311;;;5455:5;5462:4;5438:29;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;5438:29:2;;;5428:40;;;;;;5421:47;;5172:311;5077:416;5114:3;;;;;;;5077:416;;;;4937:562;;;;:::o;2764:42:3:-;;;;;;;;;;;;;;;;;:::o;1267:30::-;;;;:::o;1594:44::-;;;;;;;;;;;;;;;;;:::o;3608:194::-;732:5:4;;;;;;;;;;;718:19;;:10;:19;;;710:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3697:7:3;3682:11;:22;;3674:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3744:11;3733:8;:22;;;;3770:25;3786:8;;3770:25;;;;;;;;;;;;;;;;;;3608:194;:::o;239:20:4:-;;;;;;;;;;;;;:::o;10079:481:3:-;10372:54;10389:9;10400:6;10408;10416:9;;10372:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;10372:54:3;;;;;;:16;:54::i;:::-;10364:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10459:48;10465:11;10478:6;10486:13;10501:5;;10459:48;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;10459:48:3;;;;;;:5;:48::i;:::-;10517:36;10527:9;10538:6;10546;10517:9;:36::i;:::-;10079:481;;;;;;;;;:::o;1783:20::-;;;;:::o;14582:961::-;14701:12;14753:2;14733:9;:16;:22;14725:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14795:9;14806;14817:7;14939:2;14928:9;14924:18;14918:25;14913:30;;14982:2;14971:9;14967:18;14961:25;14956:30;;15033:2;15022:9;15018:18;15012:25;15009:1;15004:34;14999:39;;15065:2;15061:1;:6;;;15057:44;;;15088:2;15083:7;;;;15057:44;15123:2;15118:1;:7;;;:18;;;;15134:2;15129:1;:7;;;15118:18;15110:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15272:19;15371:9;15382:6;15398:4;15405:9;:17;15415:6;15405:17;;;;;;;;;;;;;;;;15304:119;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;15304:119:3;;;15294:130;;;;;;15272:152;;15434:24;15461:31;15471:11;15484:1;15487;15490;15461:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15461:31:3;;;;;;;;15434:58;;15530:6;15510:26;;:16;:26;;;15503:33;;;;;;;14582:961;;;;;;:::o;12199:253::-;12322:54;12339:9;12350:6;12358;12366:9;12322:16;:54::i;:::-;12314:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12409:36;12419:9;12430:6;12438;12409:9;:36::i;:::-;12199:253;;;;:::o;3212:141::-;732:5:4;;;;;;;;;;;718:19;;:10;:19;;;710:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3292:11:3;3281:8;;:22;;;;;;;;;;;;;;;;;;3334:11;3318:28;;;;;;;;;;;;3212:141;:::o;8712:543::-;9000:49;9017:9;9028:6;9036:1;9039:9;;9000:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;9000:49:3;;;;;;:16;:49::i;:::-;8992:80;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9082:48;9088:11;9101:6;9109:13;9124:5;;9082:48;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;9082:48:3;;;;;;:5;:48::i;:::-;9140:17;9160:36;9178:9;:17;9188:6;9178:17;;;;;;;;;;;;;;;;9160:13;:17;;:36;;;;:::i;:::-;9140:56;;9206:42;9216:9;9227:6;9235:12;9206:9;:42::i;:::-;8712:543;;;;;;;;;:::o;2585:23::-;;;;:::o;2973:402:2:-;3108:1;3078:31;;:13;:26;3092:11;3078:26;;;;;;;;;;;;:31;3070:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3139:19;3161:8;;3139:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;3139:30:2;;;;;;;;3179:38;3188:11;3201:8;3211:5;3179:8;:38::i;:::-;3306:8;3277:13;:26;3291:11;3277:26;;;;;;;;;;;:37;;;;3329:39;3339:11;3352:8;3362:5;3329:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;3329:39:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2973:402;;;;;:::o;4342:392::-;4459:4;4475:16;4521:7;4530;4539:11;4504:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4504:47:2;;;4494:58;;;;;;4475:77;;4562:16;4581:13;:26;4595:11;4581:26;;;;;;;;;;;;4562:45;;4637:3;4625:15;;:8;:15;;4617:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4693:34;4711:8;4721:5;4693:17;:34::i;:::-;4681:8;:46;4674:53;;;;4342:392;;;;;;:::o;11118:116:3:-;11188:39;11198:9;11209;11220:6;11188:9;:39::i;:::-;11118:116;;:::o;1919:46:2:-;;;;;;;;;;;;;;;;;:::o;265:27:4:-;;;;;;;;;;;;;:::o;928:102::-;732:5;;;;;;;;;;;718:19;;:10;:19;;;710:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1015:8;1000:12;;:23;;;;;;;;;;;;;;;;;;928:102;:::o;1810:19:3:-;;;;;;;;;;;;;:::o;12973:399::-;13077:1;13068:6;:10;13060:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13111:6;13120:30;13143:6;13120:9;:18;13130:7;13120:18;;;;;;;;;;;;;;;;:22;;:30;;;;:::i;:::-;13111:39;;13173:8;:17;13182:7;13173:17;;;;;;;;;;;;;;;;13168:1;:22;;13160:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13241:1;13220:9;:18;13230:7;13220:18;;;;;;;;;;;;;;;:22;;;;13269:26;13288:6;13269:14;;:18;;:26;;;;:::i;:::-;13252:14;:43;;;;13313:5;;;;;;;;;;;:14;;;13328:9;13339:6;13313:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;13313:33:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13313:33:3;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;13313:33:3;;;;;;;;;;;;;;;;13305:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12973:399;;;;:::o;1274:134:8:-;1332:7;1358:43;1362:1;1365;1358:43;;;;;;;;;;;;;;;;;:3;:43::i;:::-;1351:50;;1274:134;;;;:::o;5148:577:3:-;5245:21;5269:14;:27;5284:11;5269:27;;;;;;;;;;;;5245:51;;5339:18;;5320:16;:37;5314:3;:43;5306:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5461:11;5441:8;:17;5450:7;5441:17;;;;;;;;;;;;;;;;:31;5433:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5518:51;5551:8;:17;5560:7;5551:17;;;;;;;;;;;;;;;;5518:28;5534:11;5518;;:15;;:28;;;;:::i;:::-;:32;;:51;;;;:::i;:::-;5504:11;:65;;;;5622:5;;;;;;;;;;;:15;;;5646:4;5622:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5622:30:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5622:30:3;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;5622:30:3;;;;;;;;;;;;;;;;5587:31;5603:14;;5587:11;;:15;;:31;;;;:::i;:::-;:65;;5579:98;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5707:11;5687:8;:17;5696:7;5687:17;;;;;;;;;;;;;;;:31;;;;5148:577;;;;:::o;4084:231::-;4185:8;;;;;;;;;;;4171:22;;:10;:22;;;4163:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4256:3;4226:14;:27;4241:11;4226:27;;;;;;;;;;;:33;;;;4084:231;;;:::o;834:176:8:-;892:7;911:9;927:1;923;:5;911:17;;951:1;946;:6;;938:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1002:1;995:8;;;834:176;;;;:::o;1732:187::-;1818:7;1850:1;1845;:6;;1853:12;1837:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;1837:29:8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1876:9;1892:1;1888;:5;1876:17;;1911:1;1904:8;;;1732:187;;;;;:::o", - "source": "pragma solidity ^0.5.16;\n\nimport \"monoplasma/contracts/Monoplasma.sol\";\n\ncontract DataunionVault is Monoplasma {\n\n string public joinPartStream;\n\n /** Server version. This must be kept in sync with src/server.js */\n uint public version = 1;\n\n constructor(address operator, string memory joinPartStreamId, address tokenAddress, uint blockFreezePeriodSeconds, uint adminFeeFraction)\n Monoplasma(tokenAddress, blockFreezePeriodSeconds, adminFeeFraction) public {\n setOperator(operator);\n joinPartStream = joinPartStreamId;\n }\n}\n", - "sourcePath": "/home/heynow/streamr/data-union-server/contracts/DataunionVault.sol", - "ast": { - "absolutePath": "/home/heynow/streamr/data-union-server/contracts/DataunionVault.sol", - "exportedSymbols": { - "DataunionVault": [ - 37 - ] - }, - "id": 38, - "nodeType": "SourceUnit", - "nodes": [ - { - "id": 1, - "literals": [ - "solidity", - "^", - "0.5", - ".16" - ], - "nodeType": "PragmaDirective", - "src": "0:24:0" - }, - { - "absolutePath": "monoplasma/contracts/Monoplasma.sol", - "file": "monoplasma/contracts/Monoplasma.sol", - "id": 2, - "nodeType": "ImportDirective", - "scope": 38, - "sourceUnit": 872, - "src": "26:45:0", - "symbolAliases": [], - "unitAlias": "" - }, - { - "baseContracts": [ - { - "arguments": null, - "baseName": { - "contractScope": null, - "id": 3, - "name": "Monoplasma", - "nodeType": "UserDefinedTypeName", - "referencedDeclaration": 871, - "src": "100:10:0", - "typeDescriptions": { - "typeIdentifier": "t_contract$_Monoplasma_$871", - "typeString": "contract Monoplasma" - } - }, - "id": 4, - "nodeType": "InheritanceSpecifier", - "src": "100:10:0" - } - ], - "contractDependencies": [ - 276, - 871, - 944 - ], - "contractKind": "contract", - "documentation": null, - "fullyImplemented": true, - "id": 37, - "linearizedBaseContracts": [ - 37, - 871, - 944, - 276 - ], - "name": "DataunionVault", - "nodeType": "ContractDefinition", - "nodes": [ - { - "constant": false, - "id": 6, - "name": "joinPartStream", - "nodeType": "VariableDeclaration", - "scope": 37, - "src": "118:28:0", - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_string_storage", - "typeString": "string" - }, - "typeName": { - "id": 5, - "name": "string", - "nodeType": "ElementaryTypeName", - "src": "118:6:0", - "typeDescriptions": { - "typeIdentifier": "t_string_storage_ptr", - "typeString": "string" - } - }, - "value": null, - "visibility": "public" - }, - { - "constant": false, - "id": 9, - "name": "version", - "nodeType": "VariableDeclaration", - "scope": 37, - "src": "225:23:0", - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 7, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "225:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "value": { - "argumentTypes": null, - "hexValue": "31", - "id": 8, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "247:1:0", - "subdenomination": null, - "typeDescriptions": { - "typeIdentifier": "t_rational_1_by_1", - "typeString": "int_const 1" - }, - "value": "1" - }, - "visibility": "public" - }, - { - "body": { - "id": 35, - "nodeType": "Block", - "src": "473:81:0", - "statements": [ - { - "expression": { - "argumentTypes": null, - "arguments": [ - { - "argumentTypes": null, - "id": 28, - "name": "operator", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 11, - "src": "495:8:0", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_address", - "typeString": "address" - } - ], - "id": 27, - "name": "setOperator", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 366, - "src": "483:11:0", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_nonpayable$_t_address_$returns$__$", - "typeString": "function (address)" - } - }, - "id": 29, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "names": [], - "nodeType": "FunctionCall", - "src": "483:21:0", - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 30, - "nodeType": "ExpressionStatement", - "src": "483:21:0" - }, - { - "expression": { - "argumentTypes": null, - "id": 33, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "argumentTypes": null, - "id": 31, - "name": "joinPartStream", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6, - "src": "514:14:0", - "typeDescriptions": { - "typeIdentifier": "t_string_storage", - "typeString": "string storage ref" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "argumentTypes": null, - "id": 32, - "name": "joinPartStreamId", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 13, - "src": "531:16:0", - "typeDescriptions": { - "typeIdentifier": "t_string_memory_ptr", - "typeString": "string memory" - } - }, - "src": "514:33:0", - "typeDescriptions": { - "typeIdentifier": "t_string_storage", - "typeString": "string storage ref" - } - }, - "id": 34, - "nodeType": "ExpressionStatement", - "src": "514:33:0" - } - ] - }, - "documentation": null, - "id": 36, - "implemented": true, - "kind": "constructor", - "modifiers": [ - { - "arguments": [ - { - "argumentTypes": null, - "id": 22, - "name": "tokenAddress", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 15, - "src": "408:12:0", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - { - "argumentTypes": null, - "id": 23, - "name": "blockFreezePeriodSeconds", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 17, - "src": "422:24:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "argumentTypes": null, - "id": 24, - "name": "adminFeeFraction", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 19, - "src": "448:16:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 25, - "modifierName": { - "argumentTypes": null, - "id": 21, - "name": "Monoplasma", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 871, - "src": "397:10:0", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_contract$_Monoplasma_$871_$", - "typeString": "type(contract Monoplasma)" - } - }, - "nodeType": "ModifierInvocation", - "src": "397:68:0" - } - ], - "name": "", - "nodeType": "FunctionDefinition", - "parameters": { - "id": 20, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 11, - "name": "operator", - "nodeType": "VariableDeclaration", - "scope": 36, - "src": "267:16:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 10, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "267:7:0", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "value": null, - "visibility": "internal" - }, - { - "constant": false, - "id": 13, - "name": "joinPartStreamId", - "nodeType": "VariableDeclaration", - "scope": 36, - "src": "285:30:0", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_string_memory_ptr", - "typeString": "string" - }, - "typeName": { - "id": 12, - "name": "string", - "nodeType": "ElementaryTypeName", - "src": "285:6:0", - "typeDescriptions": { - "typeIdentifier": "t_string_storage_ptr", - "typeString": "string" - } - }, - "value": null, - "visibility": "internal" - }, - { - "constant": false, - "id": 15, - "name": "tokenAddress", - "nodeType": "VariableDeclaration", - "scope": 36, - "src": "317:20:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 14, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "317:7:0", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "value": null, - "visibility": "internal" - }, - { - "constant": false, - "id": 17, - "name": "blockFreezePeriodSeconds", - "nodeType": "VariableDeclaration", - "scope": 36, - "src": "339:29:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 16, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "339:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "value": null, - "visibility": "internal" - }, - { - "constant": false, - "id": 19, - "name": "adminFeeFraction", - "nodeType": "VariableDeclaration", - "scope": 36, - "src": "370:21:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 18, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "370:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "value": null, - "visibility": "internal" - } - ], - "src": "266:126:0" - }, - "returnParameters": { - "id": 26, - "nodeType": "ParameterList", - "parameters": [], - "src": "473:0:0" - }, - "scope": 37, - "src": "255:299:0", - "stateMutability": "nonpayable", - "superFunction": null, - "visibility": "public" - } - ], - "scope": 38, - "src": "73:483:0" - } - ], - "src": "0:557:0" - }, - "legacyAST": { - "absolutePath": "/home/heynow/streamr/data-union-server/contracts/DataunionVault.sol", - "exportedSymbols": { - "DataunionVault": [ - 37 - ] - }, - "id": 38, - "nodeType": "SourceUnit", - "nodes": [ - { - "id": 1, - "literals": [ - "solidity", - "^", - "0.5", - ".16" - ], - "nodeType": "PragmaDirective", - "src": "0:24:0" - }, - { - "absolutePath": "monoplasma/contracts/Monoplasma.sol", - "file": "monoplasma/contracts/Monoplasma.sol", - "id": 2, - "nodeType": "ImportDirective", - "scope": 38, - "sourceUnit": 872, - "src": "26:45:0", - "symbolAliases": [], - "unitAlias": "" - }, - { - "baseContracts": [ - { - "arguments": null, - "baseName": { - "contractScope": null, - "id": 3, - "name": "Monoplasma", - "nodeType": "UserDefinedTypeName", - "referencedDeclaration": 871, - "src": "100:10:0", - "typeDescriptions": { - "typeIdentifier": "t_contract$_Monoplasma_$871", - "typeString": "contract Monoplasma" - } - }, - "id": 4, - "nodeType": "InheritanceSpecifier", - "src": "100:10:0" - } - ], - "contractDependencies": [ - 276, - 871, - 944 - ], - "contractKind": "contract", - "documentation": null, - "fullyImplemented": true, - "id": 37, - "linearizedBaseContracts": [ - 37, - 871, - 944, - 276 - ], - "name": "DataunionVault", - "nodeType": "ContractDefinition", - "nodes": [ - { - "constant": false, - "id": 6, - "name": "joinPartStream", - "nodeType": "VariableDeclaration", - "scope": 37, - "src": "118:28:0", - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_string_storage", - "typeString": "string" - }, - "typeName": { - "id": 5, - "name": "string", - "nodeType": "ElementaryTypeName", - "src": "118:6:0", - "typeDescriptions": { - "typeIdentifier": "t_string_storage_ptr", - "typeString": "string" - } - }, - "value": null, - "visibility": "public" - }, - { - "constant": false, - "id": 9, - "name": "version", - "nodeType": "VariableDeclaration", - "scope": 37, - "src": "225:23:0", - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 7, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "225:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "value": { - "argumentTypes": null, - "hexValue": "31", - "id": 8, - "isConstant": false, - "isLValue": false, - "isPure": true, - "kind": "number", - "lValueRequested": false, - "nodeType": "Literal", - "src": "247:1:0", - "subdenomination": null, - "typeDescriptions": { - "typeIdentifier": "t_rational_1_by_1", - "typeString": "int_const 1" - }, - "value": "1" - }, - "visibility": "public" - }, - { - "body": { - "id": 35, - "nodeType": "Block", - "src": "473:81:0", - "statements": [ - { - "expression": { - "argumentTypes": null, - "arguments": [ - { - "argumentTypes": null, - "id": 28, - "name": "operator", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 11, - "src": "495:8:0", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - } - ], - "expression": { - "argumentTypes": [ - { - "typeIdentifier": "t_address", - "typeString": "address" - } - ], - "id": 27, - "name": "setOperator", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 366, - "src": "483:11:0", - "typeDescriptions": { - "typeIdentifier": "t_function_internal_nonpayable$_t_address_$returns$__$", - "typeString": "function (address)" - } - }, - "id": 29, - "isConstant": false, - "isLValue": false, - "isPure": false, - "kind": "functionCall", - "lValueRequested": false, - "names": [], - "nodeType": "FunctionCall", - "src": "483:21:0", - "typeDescriptions": { - "typeIdentifier": "t_tuple$__$", - "typeString": "tuple()" - } - }, - "id": 30, - "nodeType": "ExpressionStatement", - "src": "483:21:0" - }, - { - "expression": { - "argumentTypes": null, - "id": 33, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "argumentTypes": null, - "id": 31, - "name": "joinPartStream", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 6, - "src": "514:14:0", - "typeDescriptions": { - "typeIdentifier": "t_string_storage", - "typeString": "string storage ref" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "argumentTypes": null, - "id": 32, - "name": "joinPartStreamId", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 13, - "src": "531:16:0", - "typeDescriptions": { - "typeIdentifier": "t_string_memory_ptr", - "typeString": "string memory" - } - }, - "src": "514:33:0", - "typeDescriptions": { - "typeIdentifier": "t_string_storage", - "typeString": "string storage ref" - } - }, - "id": 34, - "nodeType": "ExpressionStatement", - "src": "514:33:0" - } - ] - }, - "documentation": null, - "id": 36, - "implemented": true, - "kind": "constructor", - "modifiers": [ - { - "arguments": [ - { - "argumentTypes": null, - "id": 22, - "name": "tokenAddress", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 15, - "src": "408:12:0", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - { - "argumentTypes": null, - "id": 23, - "name": "blockFreezePeriodSeconds", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 17, - "src": "422:24:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - { - "argumentTypes": null, - "id": 24, - "name": "adminFeeFraction", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 19, - "src": "448:16:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - } - ], - "id": 25, - "modifierName": { - "argumentTypes": null, - "id": 21, - "name": "Monoplasma", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 871, - "src": "397:10:0", - "typeDescriptions": { - "typeIdentifier": "t_type$_t_contract$_Monoplasma_$871_$", - "typeString": "type(contract Monoplasma)" - } - }, - "nodeType": "ModifierInvocation", - "src": "397:68:0" - } - ], - "name": "", - "nodeType": "FunctionDefinition", - "parameters": { - "id": 20, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 11, - "name": "operator", - "nodeType": "VariableDeclaration", - "scope": 36, - "src": "267:16:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 10, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "267:7:0", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "value": null, - "visibility": "internal" - }, - { - "constant": false, - "id": 13, - "name": "joinPartStreamId", - "nodeType": "VariableDeclaration", - "scope": 36, - "src": "285:30:0", - "stateVariable": false, - "storageLocation": "memory", - "typeDescriptions": { - "typeIdentifier": "t_string_memory_ptr", - "typeString": "string" - }, - "typeName": { - "id": 12, - "name": "string", - "nodeType": "ElementaryTypeName", - "src": "285:6:0", - "typeDescriptions": { - "typeIdentifier": "t_string_storage_ptr", - "typeString": "string" - } - }, - "value": null, - "visibility": "internal" - }, - { - "constant": false, - "id": 15, - "name": "tokenAddress", - "nodeType": "VariableDeclaration", - "scope": 36, - "src": "317:20:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - }, - "typeName": { - "id": 14, - "name": "address", - "nodeType": "ElementaryTypeName", - "src": "317:7:0", - "stateMutability": "nonpayable", - "typeDescriptions": { - "typeIdentifier": "t_address", - "typeString": "address" - } - }, - "value": null, - "visibility": "internal" - }, - { - "constant": false, - "id": 17, - "name": "blockFreezePeriodSeconds", - "nodeType": "VariableDeclaration", - "scope": 36, - "src": "339:29:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 16, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "339:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "value": null, - "visibility": "internal" - }, - { - "constant": false, - "id": 19, - "name": "adminFeeFraction", - "nodeType": "VariableDeclaration", - "scope": 36, - "src": "370:21:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 18, - "name": "uint", - "nodeType": "ElementaryTypeName", - "src": "370:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "value": null, - "visibility": "internal" - } - ], - "src": "266:126:0" - }, - "returnParameters": { - "id": 26, - "nodeType": "ParameterList", - "parameters": [], - "src": "473:0:0" - }, - "scope": 37, - "src": "255:299:0", - "stateMutability": "nonpayable", - "superFunction": null, - "visibility": "public" - } - ], - "scope": 38, - "src": "73:483:0" - } - ], - "src": "0:557:0" - }, - "compiler": { - "name": "solc", - "version": "0.5.16+commit.9c3226ce.Emscripten.clang", - "optimizer": false, - "runs": 200 - }, - "networks": {}, - "schemaVersion": "2.2.4", - "updatedAt": "2020-05-14T11:43:55.112Z" -} \ No newline at end of file diff --git a/contracts/DataUnionFactoryMainnet.json b/contracts/DataUnionFactoryMainnet.json new file mode 100644 index 000000000..53de97168 --- /dev/null +++ b/contracts/DataUnionFactoryMainnet.json @@ -0,0 +1,6163 @@ +{ + "contractName": "DataUnionFactoryMainnet", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_token_mediator", + "type": "address" + }, + { + "internalType": "address", + "name": "_data_union_mainnet_template", + "type": "address" + }, + { + "internalType": "address", + "name": "_data_union_sidechain_template", + "type": "address" + }, + { + "internalType": "address", + "name": "_data_union_sidechain_factory", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_sidechain_maxgas", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "mainnet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sidechain", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "template", + "type": "address" + } + ], + "name": "MainnetDUCreated", + "type": "event" + }, + { + "inputs": [], + "name": "amb", + "outputs": [ + { + "internalType": "contract IAMB", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "data_union_mainnet_template", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "data_union_sidechain_factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "data_union_sidechain_template", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sidechain_maxgas", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token_mediator", + "outputs": [ + { + "internalType": "contract ITokenMediator", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "mainet_address", + "type": "address" + } + ], + "name": "sidechainAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "deployer", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "mainnetAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "adminFeeFraction", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "agents", + "type": "address[]" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "deployNewDataUnion", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "metadata": "{\"compiler\":{\"version\":\"0.6.6+commit.6c089d02\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token_mediator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_data_union_mainnet_template\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_data_union_sidechain_template\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_data_union_sidechain_factory\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_sidechain_maxgas\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"mainnet\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sidechain\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"template\",\"type\":\"address\"}],\"name\":\"MainnetDUCreated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"amb\",\"outputs\":[{\"internalType\":\"contract IAMB\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"data_union_mainnet_template\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"data_union_sidechain_factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"data_union_sidechain_template\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"adminFeeFraction\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"agents\",\"type\":\"address[]\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"deployNewDataUnion\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"deployer\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"mainnetAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"mainet_address\",\"type\":\"address\"}],\"name\":\"sidechainAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sidechain_maxgas\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_mediator\",\"outputs\":[{\"internalType\":\"contract ITokenMediator\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"/home/heynow/streamr/data-union-solidity/contracts/DataUnionFactoryMainnet.sol\":\"DataUnionFactoryMainnet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"/home/heynow/streamr/data-union-solidity/contracts/CloneLib.sol\":{\"keccak256\":\"0xf9082fe41a9e05b37cf87f0d1d67ca16d32c4100a2a27a6fc9d8f3f8364a7486\",\"urls\":[\"bzz-raw://b928f45b1904c399db9508c093604531bd215afeb4686827ab46daa7aee1938e\",\"dweb:/ipfs/QmdnBUvpCDc93fHZe7o6bitGRZo4PFTx9NprgziqHsVHFw\"]},\"/home/heynow/streamr/data-union-solidity/contracts/DataUnionFactoryMainnet.sol\":{\"keccak256\":\"0x6bd5ad2171e1b91d5bfe345192db0cc02abc6e2c753745a0abc5ed8fa04e6637\",\"urls\":[\"bzz-raw://003edd72510ebfede31c3f498338337c068a8ab0dd604f452798236199306dd4\",\"dweb:/ipfs/QmWL4QHskrmwvEM3auxSfjKG64WTXhuevayjhMwq3S8T9f\"]},\"/home/heynow/streamr/data-union-solidity/contracts/IAMB.sol\":{\"keccak256\":\"0x63b46d3087a8ba558cb36d99ffe5b2f0241446adc4c8df4219ce86f97727e168\",\"urls\":[\"bzz-raw://66d9c8c817e90b25f28b3d79a69b440018b49633a7bbaf6fe4d1788b2ff5e6eb\",\"dweb:/ipfs/QmSdrqpaZ3R3NGFuF6jnbo8cCgV5ghdW5iWrnV59qavYP2\"]},\"/home/heynow/streamr/data-union-solidity/contracts/ITokenMediator.sol\":{\"keccak256\":\"0x1f21e943f4e125dd1c4353db29880b63f8fa7a299ba862432c8a4e14807873e2\",\"urls\":[\"bzz-raw://4ddc233243efce6c2582b63e3be28c4f90f32d60b5d4b6fe8331106d970a8435\",\"dweb:/ipfs/QmQzLwvxU3ixfLbdpuYdpqvW61xjPbnXDTaaWNjRJUhvSK\"]},\"openzeppelin-solidity/contracts/math/SafeMath.sol\":{\"keccak256\":\"0x9a9cf02622cd7a64261b10534fc3260449da25c98c9e96d1b4ae8110a20e5806\",\"urls\":[\"bzz-raw://2df142592d1dc267d9549049ee3317fa190d2f87eaa565f86ab05ec83f7ab8f5\",\"dweb:/ipfs/QmSkJtcfWo7c42KnL5hho6GFxK6HRNV91XABx1P7xDtfLV\"]},\"openzeppelin-solidity/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x5c26b39d26f7ed489e555d955dcd3e01872972e71fdd1528e93ec164e4f23385\",\"urls\":[\"bzz-raw://efdc632af6960cf865dbc113665ea1f5b90eab75cc40ec062b2f6ae6da582017\",\"dweb:/ipfs/QmfAZFDuG62vxmAN9DnXApv7e7PMzPqi4RkqqZHLMSQiY5\"]}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50604051610aab380380610aab833981810160405260c081101561003357600080fd5b5080516020808301516040808501516060860151608087015160a090970151600680546001600160a01b03199081166001600160a01b03808b1691909117909255600580548216838916179081905560008054831684881617905560018054831684871617905560028054909216838c1617909155855163cd59658360e01b81529551989996989497939695929491169263cd5965839260048181019391829003018186803b1580156100e557600080fd5b505afa1580156100f9573d6000803e3d6000fd5b505050506040513d602081101561010f57600080fd5b5051600480546001600160a01b039092166001600160a01b03199092169190911790556003555050505050610962806101496000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c8063c5a8c91f11610066578063c5a8c91f14610117578063cb8a191b1461011f578063d4c31bd41461025e578063e4a154a414610314578063fc0c546a1461031c5761009e565b8063015a0da0146100a35780631062b39a146100c757806317c2a98c146100cf57806335813bc1146100f5578063692199d4146100fd575b600080fd5b6100ab610324565b604080516001600160a01b039092168252519081900360200190f35b6100ab610333565b6100ab600480360360208110156100e557600080fd5b50356001600160a01b0316610342565b6100ab61036c565b61010561037b565b60408051918252519081900360200190f35b6100ab610381565b6100ab6004803603608081101561013557600080fd5b6001600160a01b038235169160208101359181019060608101604082013564010000000081111561016557600080fd5b82018360208201111561017757600080fd5b8035906020019184602083028401116401000000008311171561019957600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092959493602081019350359150506401000000008111156101e957600080fd5b8201836020820111156101fb57600080fd5b8035906020019184600183028401116401000000008311171561021d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610390945050505050565b6100ab6004803603604081101561027457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561029f57600080fd5b8201836020820111156102b157600080fd5b803590602001918460018302840111640100000000831117156102d357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061062d945050505050565b6100ab6106ee565b6100ab6106fd565b6000546001600160a01b031681565b6004546001600160a01b031681565b600154600254600091610366916001600160a01b039182169190811690851661070c565b92915050565b6002546001600160a01b031681565b60035481565b6005546001600160a01b031681565b60008082336040516020018080602001836001600160a01b03166001600160a01b03168152602001828103825284818151815260200191508051906020019080838360005b838110156103ed5781810151838201526020016103d5565b50505050905090810190601f16801561041a5780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040528051906020012090506060600660009054906101000a90046001600160a01b0316600560009054906101000a90046001600160a01b0316600260009054906101000a90046001600160a01b0316600354600160009054906101000a90046001600160a01b03168b8b8b60405160240180896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019060200280838360005b8381101561055f578181015183820152602001610547565b50506040805193909501838103601f190184529094525060208101805163fb6470c960e01b6001600160e01b0390911617905260008054919e509c506105c59b506105be9a506001600160a01b03169850610778975050505050505050565b83856107ca565b9050876001600160a01b03166105da82610342565b600054604080516001600160a01b039283168152905192821692918516917f7bb36c64b37ae129eda8a24fd78defec04cc7a06bb27863c5a4571dd5d70acee9181900360200190a4979650505050505050565b604080516001600160a01b0384168183015260208082019283528351606083015283516000938493869388938392608001918601908083838a5b8381101561067f578181015183820152602001610667565b50505050905090810190601f1680156106ac5780820380516001836020036101000a031916815260200191505b5060408051601f1981840301815291905280516020909101206000549095506106e694506001600160a01b0316925030915084905061070c565b949350505050565b6001546001600160a01b031681565b6006546001600160a01b031681565b60008061071885610778565b8051602091820120604080516001600160f81b0319818501526bffffffffffffffffffffffff19606089901b1660218201526035810187905260558082019390935281518082039093018352607501905280519101209150509392505050565b604080516057810190915260378152733d602d80600a3d3981f3363d3d373d3d3d363d7360601b602082015260609190911b60348201526e5af43d82803e903d91602b57fd5bf360881b604882015290565b825160009082816020870184f591506001600160a01b03821661082b576040805162461bcd60e51b8152602060048201526014602482015273195c9c9bdc97d85b1c9958591e50dc99585d195960621b604482015290519081900360640190fd5b835115610924576000826001600160a01b0316856040518082805190602001908083835b6020831061086e5780518252601f19909201916020918201910161084f565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146108d0576040519150601f19603f3d011682016040523d82523d6000602084013e6108d5565b606091505b5050905080610922576040805162461bcd60e51b815260206004820152601460248201527332b93937b92fb4b734ba34b0b634bd30ba34b7b760611b604482015290519081900360640190fd5b505b50939250505056fea264697066735822122084945f9903b2d49dc74f1c2fb52a86a2b798a1ca3d19412037d748182369d7ea64736f6c63430006060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061009e5760003560e01c8063c5a8c91f11610066578063c5a8c91f14610117578063cb8a191b1461011f578063d4c31bd41461025e578063e4a154a414610314578063fc0c546a1461031c5761009e565b8063015a0da0146100a35780631062b39a146100c757806317c2a98c146100cf57806335813bc1146100f5578063692199d4146100fd575b600080fd5b6100ab610324565b604080516001600160a01b039092168252519081900360200190f35b6100ab610333565b6100ab600480360360208110156100e557600080fd5b50356001600160a01b0316610342565b6100ab61036c565b61010561037b565b60408051918252519081900360200190f35b6100ab610381565b6100ab6004803603608081101561013557600080fd5b6001600160a01b038235169160208101359181019060608101604082013564010000000081111561016557600080fd5b82018360208201111561017757600080fd5b8035906020019184602083028401116401000000008311171561019957600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092959493602081019350359150506401000000008111156101e957600080fd5b8201836020820111156101fb57600080fd5b8035906020019184600183028401116401000000008311171561021d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610390945050505050565b6100ab6004803603604081101561027457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561029f57600080fd5b8201836020820111156102b157600080fd5b803590602001918460018302840111640100000000831117156102d357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061062d945050505050565b6100ab6106ee565b6100ab6106fd565b6000546001600160a01b031681565b6004546001600160a01b031681565b600154600254600091610366916001600160a01b039182169190811690851661070c565b92915050565b6002546001600160a01b031681565b60035481565b6005546001600160a01b031681565b60008082336040516020018080602001836001600160a01b03166001600160a01b03168152602001828103825284818151815260200191508051906020019080838360005b838110156103ed5781810151838201526020016103d5565b50505050905090810190601f16801561041a5780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040528051906020012090506060600660009054906101000a90046001600160a01b0316600560009054906101000a90046001600160a01b0316600260009054906101000a90046001600160a01b0316600354600160009054906101000a90046001600160a01b03168b8b8b60405160240180896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b03168152602001868152602001856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019060200280838360005b8381101561055f578181015183820152602001610547565b50506040805193909501838103601f190184529094525060208101805163fb6470c960e01b6001600160e01b0390911617905260008054919e509c506105c59b506105be9a506001600160a01b03169850610778975050505050505050565b83856107ca565b9050876001600160a01b03166105da82610342565b600054604080516001600160a01b039283168152905192821692918516917f7bb36c64b37ae129eda8a24fd78defec04cc7a06bb27863c5a4571dd5d70acee9181900360200190a4979650505050505050565b604080516001600160a01b0384168183015260208082019283528351606083015283516000938493869388938392608001918601908083838a5b8381101561067f578181015183820152602001610667565b50505050905090810190601f1680156106ac5780820380516001836020036101000a031916815260200191505b5060408051601f1981840301815291905280516020909101206000549095506106e694506001600160a01b0316925030915084905061070c565b949350505050565b6001546001600160a01b031681565b6006546001600160a01b031681565b60008061071885610778565b8051602091820120604080516001600160f81b0319818501526bffffffffffffffffffffffff19606089901b1660218201526035810187905260558082019390935281518082039093018352607501905280519101209150509392505050565b604080516057810190915260378152733d602d80600a3d3981f3363d3d373d3d3d363d7360601b602082015260609190911b60348201526e5af43d82803e903d91602b57fd5bf360881b604882015290565b825160009082816020870184f591506001600160a01b03821661082b576040805162461bcd60e51b8152602060048201526014602482015273195c9c9bdc97d85b1c9958591e50dc99585d195960621b604482015290519081900360640190fd5b835115610924576000826001600160a01b0316856040518082805190602001908083835b6020831061086e5780518252601f19909201916020918201910161084f565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146108d0576040519150601f19603f3d011682016040523d82523d6000602084013e6108d5565b606091505b5050905080610922576040805162461bcd60e51b815260206004820152601460248201527332b93937b92fb4b734ba34b0b634bd30ba34b7b760611b604482015290519081900360640190fd5b505b50939250505056fea264697066735822122084945f9903b2d49dc74f1c2fb52a86a2b798a1ca3d19412037d748182369d7ea64736f6c63430006060033", + "immutableReferences": {}, + "sourceMap": "332:3065:1:-:0;;;825:694;5:9:-1;2:2;;;27:1;24;17:12;2:2;825:694:1;;;;;;;;;;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;825:694:1;;;;;;;;;;;;;;;;;;;;;;;;;1131:5;:14;;-1:-1:-1;;;;;;1131:14:1;;;-1:-1:-1;;;;;1131:14:1;;;;;;;;;;1155;:48;;;;;;;;;;;;-1:-1:-1;1213:58:1;;;;;;;;;;-1:-1:-1;1281:62:1;;;;;;;;;;1353:28;:60;;;;;;;;;;;;1434:31;;-1:-1:-1;;;1434:31:1;;;;825:694;;;;;;;;;;;1434:14;;;:29;;-1:-1:-1;1434:31:1;;;;;;;;;;:14;:31;;;2:2:-1;;;;27:1;24;17:12;2:2;1434:31:1;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1434:31:1;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;1434:31:1;1423:3;:43;;-1:-1:-1;;;;;1423:43:1;;;-1:-1:-1;;;;;;1423:43:1;;;;;;;;;1476:16;:36;-1:-1:-1;;;;;332:3065:1;;;;;;", + "deployedSourceMap": "332:3065:1:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;332:3065:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;493:42:1;;;:::i;:::-;;;;-1:-1:-1;;;;;493:42:1;;;;;;;;;;;;;;735:15;;;:::i;1526:300::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;1526:300:1;-1:-1:-1;;;;;1526:300:1;;:::i;649:43::-;;;:::i;698:31::-;;;:::i;:::-;;;;;;;;;;;;;;;;756:36;;;:::i;2546:849::-;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;2546:849:1;;;;;;;;;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;2546:849:1;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;2546:849:1;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;2546:849:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;2546:849:1;;;;;;;;-1:-1:-1;2546:849:1;;-1:-1:-1;;27:11;11:28;;8:2;;;52:1;49;42:12;8:2;2546:849:1;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;2546:849:1;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;2546:849:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;2546:849:1;;-1:-1:-1;2546:849:1;;-1:-1:-1;;;;;2546:849:1:i;1846:336::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;1846:336:1;;;;;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;1846:336:1;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;1846:336:1;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;1846:336:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;1846:336:1;;-1:-1:-1;1846:336:1;;-1:-1:-1;;;;;1846:336:1:i;599:44::-;;;:::i;798:20::-;;;:::i;493:42::-;;;-1:-1:-1;;;;;493:42:1;;:::o;735:15::-;;;-1:-1:-1;;;;;735:15:1;;:::o;1526:300::-;1692:29;;1735:28;;1613:7;;1643:176;;-1:-1:-1;;;;;1692:29:1;;;;1735:28;;;;1785:23;;1643:35;:176::i;:::-;1636:183;1526:300;-1:-1:-1;;1526:300:1:o;649:43::-;;;-1:-1:-1;;;;;649:43:1;;:::o;698:31::-;;;;:::o;756:36::-;;;-1:-1:-1;;;;;756:36:1;;:::o;2546:849::-;2692:7;2715:12;2757:4;2764:10;2740:35;;;;;;;;;-1:-1:-1;;;;;2740:35:1;-1:-1:-1;;;;;2740:35:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;2740:35:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;2740:35:1;;;2730:46;;;;;;2715:61;;2786:17;2923:5;;;;;;;;;-1:-1:-1;;;;;2923:5:1;2942:14;;;;;;;;;-1:-1:-1;;;;;2942:14:1;2970:28;;;;;;;;;-1:-1:-1;;;;;2970:28:1;3012:16;;3042:29;;;;;;;;;-1:-1:-1;;;;;3042:29:1;3085:5;3104:16;3134:6;2806:344;;;;;;-1:-1:-1;;;;;2806:344:1;-1:-1:-1;;;;;2806:344:1;;;;;;-1:-1:-1;;;;;2806:344:1;-1:-1:-1;;;;;2806:344:1;;;;;;-1:-1:-1;;;;;2806:344:1;-1:-1:-1;;;;;2806:344:1;;;;;;;;;;;-1:-1:-1;;;;;2806:344:1;-1:-1:-1;;;;;2806:344:1;;;;;;-1:-1:-1;;;;;2806:344:1;-1:-1:-1;;;;;2806:344:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;-1:-1;;2806:344:1;;;;;;;26:21:-1;;;-1:-1;;22:32;6:49;;2806:344:1;;;-1:-1:-1;49:4;25:18;;61:17;;-1:-1;;;;;;;;182:15;;;179:29;160:49;;-1:-1;3235:27:1;;2806:344;;-1:-1:-1;;;3173:103:1;;-1:-1:-1;3212:51:1;;-1:-1:-1;;;;;;3235:27:1;;-1:-1:-1;3212:22:1;;-1:-1:-1;;;;;;;;3212:51:1:i;:::-;3265:4;3271;3173:38;:103::i;:::-;3160:116;;3334:5;-1:-1:-1;;;;;3291:78:1;3312:20;3329:2;3312:16;:20::i;:::-;3341:27;;3291:78;;;-1:-1:-1;;;;;3341:27:1;;;3291:78;;;;;;;;;;;;;;;;;;;;;3386:2;2546:849;-1:-1:-1;;;;;;;2546:849:1:o;1846:336::-;1993:33;;;-1:-1:-1;;;;;1993:33:1;;;;;;;;;;;;;;;;;;;;;1945:7;;;;2010:4;;2017:8;;1993:33;;;;;;;;;;;1945:7;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;1993:33:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1993:33:1;;;-1:-1:-1;;26:21;;;22:32;6:49;;1993:33:1;;;1983:44;;49:4:-1;1983:44:1;;;;2093:27;;1983:44;;-1:-1:-1;2044:131:1;;-1:-1:-1;;;;;;2093:27:1;;-1:-1:-1;2142:4:1;;-1:-1:-1;1983:44:1;;-1:-1:-1;2044:35:1;:131::i;:::-;2037:138;1846:336;-1:-1:-1;;;;1846:336:1:o;599:44::-;;;-1:-1:-1;;;;;599:44:1;;:::o;798:20::-;;;-1:-1:-1;;;;;798:20:1;;:::o;1371:393:0:-;1510:13;1535:16;1564:23;1578:8;1564:13;:23::i;:::-;1554:34;;;;;;;1639:114;;;-1:-1:-1;;;;;;1639:114:0;;;;-1:-1:-1;;1639:114:0;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;1639:114:0;;;;1629:125;;;;;;-1:-1:-1;;1371:393:0;;;;;:::o;504:712::-;683:4;677:11;;724:4;714:15;;701:29;;;840:4;827:18;;-1:-1:-1;;;973:4:0;963:15;;956:91;568:17;619;;;;1077:4;1067:15;;1060:36;-1:-1:-1;;;1126:4:0;1116:15;;1109:91;677:11;655:555::o;2256:512::-;2446:11;;2399:21;;2532:4;2446:11;2520:4;2510:15;;2399:21;2499:38;2490:47;-1:-1:-1;;;;;;2564:19:0;;2556:52;;;;;-1:-1:-1;;;2556:52:0;;;;;;;;;;;;-1:-1:-1;;;2556:52:0;;;;;;;;;;;;;;;2622:15;;:20;2618:144;;2659:12;2677:5;-1:-1:-1;;;;;2677:10:0;2688:8;2677:20;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;2677:20:0;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;2658:39:0;;;2719:7;2711:40;;;;;-1:-1:-1;;;2711:40:0;;;;;;;;;;;;-1:-1:-1;;;2711:40:0;;;;;;;;;;;;;;;2618:144;;2256:512;;;;;;:::o", + "source": "pragma solidity 0.6.6;\n\nimport \"openzeppelin-solidity/contracts/token/ERC20/IERC20.sol\";\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\nimport \"./CloneLib.sol\";\nimport \"./IAMB.sol\";\nimport \"./ITokenMediator.sol\";\n\ninterface IDataUnionMainnet {\n function sidechainAddress() external view returns (address proxy);\n}\n\n\ncontract DataUnionFactoryMainnet {\n event MainnetDUCreated(address indexed mainnet, address indexed sidechain, address indexed owner, address template);\n\n address public data_union_mainnet_template;\n\n // needed to calculate address of sidechain contract\n address public data_union_sidechain_template;\n address public data_union_sidechain_factory;\n uint256 public sidechain_maxgas;\n IAMB public amb;\n ITokenMediator public token_mediator;\n address public token;\n\n constructor(address _token,\n address _token_mediator,\n address _data_union_mainnet_template,\n address _data_union_sidechain_template,\n address _data_union_sidechain_factory,\n uint256 _sidechain_maxgas)\n public\n {\n token = _token;\n token_mediator = ITokenMediator(_token_mediator);\n data_union_mainnet_template = _data_union_mainnet_template;\n data_union_sidechain_template = _data_union_sidechain_template;\n data_union_sidechain_factory = _data_union_sidechain_factory;\n amb = IAMB(token_mediator.bridgeContract());\n sidechain_maxgas = _sidechain_maxgas;\n }\n\n\n function sidechainAddress(address mainet_address)\n public view\n returns (address)\n {\n return CloneLib.predictCloneAddressCreate2(\n data_union_sidechain_template,\n data_union_sidechain_factory,\n bytes32(uint256(mainet_address))\n );\n }\n /*\n\n */\n function mainnetAddress(address deployer, string memory name)\n public view\n returns (address)\n {\n bytes32 salt = keccak256(abi.encode(bytes(name), deployer));\n return CloneLib.predictCloneAddressCreate2(\n data_union_mainnet_template,\n address(this),\n salt\n );\n }\n\n\n/*\n function initialize(\n address _token,\n address _token_mediator,\n address _sidechain_DU_factory,\n uint256 _sidechain_maxgas,\n address _sidechain_template_DU,\n address _owner,\n uint256 adminFeeFraction,\n address[] memory agents\n ) public {\n users can only deploy with salt = their key.\n*/\n function deployNewDataUnion(address owner, uint256 adminFeeFraction, address[] memory agents, string memory name)\n public\n returns (address)\n {\n bytes32 salt = keccak256(abi.encode(bytes(name), msg.sender));\n bytes memory data = abi.encodeWithSignature(\"initialize(address,address,address,uint256,address,address,uint256,address[])\",\n token,\n token_mediator,\n data_union_sidechain_factory,\n sidechain_maxgas,\n data_union_sidechain_template,\n owner,\n adminFeeFraction,\n agents\n );\n address du = CloneLib.deployCodeAndInitUsingCreate2(CloneLib.cloneBytecode(data_union_mainnet_template), data, salt);\n emit MainnetDUCreated(du, sidechainAddress(du), owner, data_union_mainnet_template);\n return du;\n }\n}\n", + "sourcePath": "/home/heynow/streamr/data-union-solidity/contracts/DataUnionFactoryMainnet.sol", + "ast": { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/DataUnionFactoryMainnet.sol", + "exportedSymbols": { + "DataUnionFactoryMainnet": [ + 363 + ], + "IDataUnionMainnet": [ + 167 + ] + }, + "id": 364, + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 156, + "literals": [ + "solidity", + "0.6", + ".6" + ], + "nodeType": "PragmaDirective", + "src": "0:22:1" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol", + "file": "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol", + "id": 157, + "nodeType": "ImportDirective", + "scope": 364, + "sourceUnit": 4283, + "src": "24:64:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "file": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "id": 158, + "nodeType": "ImportDirective", + "scope": 364, + "sourceUnit": 3642, + "src": "89:59:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/CloneLib.sol", + "file": "./CloneLib.sol", + "id": 159, + "nodeType": "ImportDirective", + "scope": 364, + "sourceUnit": 155, + "src": "149:24:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/IAMB.sol", + "file": "./IAMB.sol", + "id": 160, + "nodeType": "ImportDirective", + "scope": 364, + "sourceUnit": 2913, + "src": "174:20:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/ITokenMediator.sol", + "file": "./ITokenMediator.sol", + "id": 161, + "nodeType": "ImportDirective", + "scope": 364, + "sourceUnit": 2969, + "src": "195:30:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "abstract": false, + "baseContracts": [], + "contractDependencies": [], + "contractKind": "interface", + "documentation": null, + "fullyImplemented": false, + "id": 167, + "linearizedBaseContracts": [ + 167 + ], + "name": "IDataUnionMainnet", + "nodeType": "ContractDefinition", + "nodes": [ + { + "body": null, + "documentation": null, + "functionSelector": "37b43a94", + "id": 166, + "implemented": false, + "kind": "function", + "modifiers": [], + "name": "sidechainAddress", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 162, + "nodeType": "ParameterList", + "parameters": [], + "src": "286:2:1" + }, + "returnParameters": { + "id": 165, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 164, + "mutability": "mutable", + "name": "proxy", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 166, + "src": "312:13:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 163, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "312:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "311:15:1" + }, + "scope": 167, + "src": "261:66:1", + "stateMutability": "view", + "virtual": false, + "visibility": "external" + } + ], + "scope": 364, + "src": "227:102:1" + }, + { + "abstract": false, + "baseContracts": [], + "contractDependencies": [], + "contractKind": "contract", + "documentation": null, + "fullyImplemented": true, + "id": 363, + "linearizedBaseContracts": [ + 363 + ], + "name": "DataUnionFactoryMainnet", + "nodeType": "ContractDefinition", + "nodes": [ + { + "anonymous": false, + "documentation": null, + "id": 177, + "name": "MainnetDUCreated", + "nodeType": "EventDefinition", + "parameters": { + "id": 176, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 169, + "indexed": true, + "mutability": "mutable", + "name": "mainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 177, + "src": "394:23:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 168, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "394:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 171, + "indexed": true, + "mutability": "mutable", + "name": "sidechain", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 177, + "src": "419:25:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 170, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "419:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 173, + "indexed": true, + "mutability": "mutable", + "name": "owner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 177, + "src": "446:21:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 172, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "446:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 175, + "indexed": false, + "mutability": "mutable", + "name": "template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 177, + "src": "469:16:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 174, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "469:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "393:93:1" + }, + "src": "371:116:1" + }, + { + "constant": false, + "functionSelector": "015a0da0", + "id": 179, + "mutability": "mutable", + "name": "data_union_mainnet_template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "493:42:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 178, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "493:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "e4a154a4", + "id": 181, + "mutability": "mutable", + "name": "data_union_sidechain_template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "599:44:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 180, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "599:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "35813bc1", + "id": 183, + "mutability": "mutable", + "name": "data_union_sidechain_factory", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "649:43:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 182, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "649:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "692199d4", + "id": 185, + "mutability": "mutable", + "name": "sidechain_maxgas", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "698:31:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 184, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "698:7:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "1062b39a", + "id": 187, + "mutability": "mutable", + "name": "amb", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "735:15:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + }, + "typeName": { + "contractScope": null, + "id": 186, + "name": "IAMB", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2912, + "src": "735:4:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "c5a8c91f", + "id": 189, + "mutability": "mutable", + "name": "token_mediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "756:36:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + }, + "typeName": { + "contractScope": null, + "id": 188, + "name": "ITokenMediator", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2968, + "src": "756:14:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "fc0c546a", + "id": 191, + "mutability": "mutable", + "name": "token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "798:20:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 190, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "798:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "body": { + "id": 240, + "nodeType": "Block", + "src": "1121:398:1", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 208, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 206, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 191, + "src": "1131:5:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 207, + "name": "_token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 193, + "src": "1139:6:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1131:14:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 209, + "nodeType": "ExpressionStatement", + "src": "1131:14:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 214, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 210, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 189, + "src": "1155:14:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 212, + "name": "_token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 195, + "src": "1187:15:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 211, + "name": "ITokenMediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2968, + "src": "1172:14:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_ITokenMediator_$2968_$", + "typeString": "type(contract ITokenMediator)" + } + }, + "id": 213, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1172:31:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "src": "1155:48:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 215, + "nodeType": "ExpressionStatement", + "src": "1155:48:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 218, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 216, + "name": "data_union_mainnet_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 179, + "src": "1213:27:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 217, + "name": "_data_union_mainnet_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 197, + "src": "1243:28:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1213:58:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 219, + "nodeType": "ExpressionStatement", + "src": "1213:58:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 222, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 220, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 181, + "src": "1281:29:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 221, + "name": "_data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 199, + "src": "1313:30:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1281:62:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 223, + "nodeType": "ExpressionStatement", + "src": "1281:62:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 226, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 224, + "name": "data_union_sidechain_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 183, + "src": "1353:28:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 225, + "name": "_data_union_sidechain_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 201, + "src": "1384:29:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1353:60:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 227, + "nodeType": "ExpressionStatement", + "src": "1353:60:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 234, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 228, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 187, + "src": "1423:3:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "argumentTypes": null, + "id": 230, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 189, + "src": "1434:14:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 231, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "bridgeContract", + "nodeType": "MemberAccess", + "referencedDeclaration": 2946, + "src": "1434:29:1", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$__$returns$_t_address_$", + "typeString": "function () view external returns (address)" + } + }, + "id": 232, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1434:31:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 229, + "name": "IAMB", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2912, + "src": "1429:4:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_IAMB_$2912_$", + "typeString": "type(contract IAMB)" + } + }, + "id": 233, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1429:37:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "src": "1423:43:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "id": 235, + "nodeType": "ExpressionStatement", + "src": "1423:43:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 238, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 236, + "name": "sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 185, + "src": "1476:16:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 237, + "name": "_sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 203, + "src": "1495:17:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1476:36:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 239, + "nodeType": "ExpressionStatement", + "src": "1476:36:1" + } + ] + }, + "documentation": null, + "id": 241, + "implemented": true, + "kind": "constructor", + "modifiers": [], + "name": "", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 204, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 193, + "mutability": "mutable", + "name": "_token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 241, + "src": "837:14:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 192, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "837:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 195, + "mutability": "mutable", + "name": "_token_mediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 241, + "src": "869:23:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 194, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "869:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 197, + "mutability": "mutable", + "name": "_data_union_mainnet_template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 241, + "src": "910:36:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 196, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "910:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 199, + "mutability": "mutable", + "name": "_data_union_sidechain_template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 241, + "src": "964:38:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 198, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "964:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 201, + "mutability": "mutable", + "name": "_data_union_sidechain_factory", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 241, + "src": "1020:37:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 200, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1020:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 203, + "mutability": "mutable", + "name": "_sidechain_maxgas", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 241, + "src": "1075:25:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 202, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1075:7:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "836:265:1" + }, + "returnParameters": { + "id": 205, + "nodeType": "ParameterList", + "parameters": [], + "src": "1121:0:1" + }, + "scope": 363, + "src": "825:694:1", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 261, + "nodeType": "Block", + "src": "1626:200:1", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 250, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 181, + "src": "1692:29:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 251, + "name": "data_union_sidechain_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 183, + "src": "1735:28:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 256, + "name": "mainet_address", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 243, + "src": "1793:14:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 255, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "1785:7:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 254, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1785:7:1", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 257, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1785:23:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 253, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "1777:7:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes32_$", + "typeString": "type(bytes32)" + }, + "typeName": { + "id": 252, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1777:7:1", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 258, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1777:32:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "argumentTypes": null, + "id": 248, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "1643:8:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 249, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "predictCloneAddressCreate2", + "nodeType": "MemberAccess", + "referencedDeclaration": 61, + "src": "1643:35:1", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$_t_address_$_t_bytes32_$returns$_t_address_$", + "typeString": "function (address,address,bytes32) pure returns (address)" + } + }, + "id": 259, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1643:176:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 247, + "id": 260, + "nodeType": "Return", + "src": "1636:183:1" + } + ] + }, + "documentation": null, + "functionSelector": "17c2a98c", + "id": 262, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "sidechainAddress", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 244, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 243, + "mutability": "mutable", + "name": "mainet_address", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 262, + "src": "1552:22:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 242, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1552:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1551:24:1" + }, + "returnParameters": { + "id": 247, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 246, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 262, + "src": "1613:7:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 245, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1613:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1612:9:1" + }, + "scope": 363, + "src": "1526:300:1", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 294, + "nodeType": "Block", + "src": "1958:224:1", + "statements": [ + { + "assignments": [ + 272 + ], + "declarations": [ + { + "constant": false, + "id": 272, + "mutability": "mutable", + "name": "salt", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 294, + "src": "1968:12:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 271, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1968:7:1", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 283, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 278, + "name": "name", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 266, + "src": "2010:4:1", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "id": 277, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2004:5:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes_storage_ptr_$", + "typeString": "type(bytes storage pointer)" + }, + "typeName": { + "id": 276, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "2004:5:1", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 279, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2004:11:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 280, + "name": "deployer", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 264, + "src": "2017:8:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "argumentTypes": null, + "id": 274, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "1993:3:1", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 275, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encode", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "1993:10:1", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencode_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 281, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1993:33:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 273, + "name": "keccak256", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -8, + "src": "1983:9:1", + "typeDescriptions": { + "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", + "typeString": "function (bytes memory) pure returns (bytes32)" + } + }, + "id": 282, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1983:44:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "1968:59:1" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 286, + "name": "data_union_mainnet_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 179, + "src": "2093:27:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 289, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "2142:4:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionFactoryMainnet_$363", + "typeString": "contract DataUnionFactoryMainnet" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionFactoryMainnet_$363", + "typeString": "contract DataUnionFactoryMainnet" + } + ], + "id": 288, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2134:7:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 287, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2134:7:1", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 290, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2134:13:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 291, + "name": "salt", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 272, + "src": "2161:4:1", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "argumentTypes": null, + "id": 284, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "2044:8:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 285, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "predictCloneAddressCreate2", + "nodeType": "MemberAccess", + "referencedDeclaration": 61, + "src": "2044:35:1", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$_t_address_$_t_bytes32_$returns$_t_address_$", + "typeString": "function (address,address,bytes32) pure returns (address)" + } + }, + "id": 292, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2044:131:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 270, + "id": 293, + "nodeType": "Return", + "src": "2037:138:1" + } + ] + }, + "documentation": null, + "functionSelector": "d4c31bd4", + "id": 295, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "mainnetAddress", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 267, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 264, + "mutability": "mutable", + "name": "deployer", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 295, + "src": "1870:16:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 263, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1870:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 266, + "mutability": "mutable", + "name": "name", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 295, + "src": "1888:18:1", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 265, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "1888:6:1", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1869:38:1" + }, + "returnParameters": { + "id": 270, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 269, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 295, + "src": "1945:7:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 268, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1945:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1944:9:1" + }, + "scope": 363, + "src": "1846:336:1", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 361, + "nodeType": "Block", + "src": "2705:690:1", + "statements": [ + { + "assignments": [ + 310 + ], + "declarations": [ + { + "constant": false, + "id": 310, + "mutability": "mutable", + "name": "salt", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 361, + "src": "2715:12:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 309, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "2715:7:1", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 322, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 316, + "name": "name", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 304, + "src": "2757:4:1", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "id": 315, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2751:5:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes_storage_ptr_$", + "typeString": "type(bytes storage pointer)" + }, + "typeName": { + "id": 314, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "2751:5:1", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 317, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2751:11:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 318, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "2764:3:1", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 319, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2764:10:1", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "expression": { + "argumentTypes": null, + "id": 312, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "2740:3:1", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 313, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encode", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2740:10:1", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencode_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 320, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2740:35:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 311, + "name": "keccak256", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -8, + "src": "2730:9:1", + "typeDescriptions": { + "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", + "typeString": "function (bytes memory) pure returns (bytes32)" + } + }, + "id": 321, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2730:46:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2715:61:1" + }, + { + "assignments": [ + 324 + ], + "declarations": [ + { + "constant": false, + "id": 324, + "mutability": "mutable", + "name": "data", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 361, + "src": "2786:17:1", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 323, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "2786:5:1", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 337, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "696e697469616c697a6528616464726573732c616464726573732c616464726573732c75696e743235362c616464726573732c616464726573732c75696e743235362c616464726573735b5d29", + "id": 327, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2830:79:1", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_fb6470c99ff27472c874d5b7a3935111326af310466bebb9ef42dc6569bc2cec", + "typeString": "literal_string \"initialize(address,address,address,uint256,address,address,uint256,address[])\"" + }, + "value": "initialize(address,address,address,uint256,address,address,uint256,address[])" + }, + { + "argumentTypes": null, + "id": 328, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 191, + "src": "2923:5:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 329, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 189, + "src": "2942:14:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + { + "argumentTypes": null, + "id": 330, + "name": "data_union_sidechain_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 183, + "src": "2970:28:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 331, + "name": "sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 185, + "src": "3012:16:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 332, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 181, + "src": "3042:29:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 333, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 297, + "src": "3085:5:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 334, + "name": "adminFeeFraction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 299, + "src": "3104:16:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 335, + "name": "agents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 302, + "src": "3134:6:1", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_fb6470c99ff27472c874d5b7a3935111326af310466bebb9ef42dc6569bc2cec", + "typeString": "literal_string \"initialize(address,address,address,uint256,address,address,uint256,address[])\"" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + ], + "expression": { + "argumentTypes": null, + "id": 325, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "2806:3:1", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 326, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encodeWithSignature", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2806:23:1", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (string memory) pure returns (bytes memory)" + } + }, + "id": 336, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2806:344:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2786:364:1" + }, + { + "assignments": [ + 339 + ], + "declarations": [ + { + "constant": false, + "id": 339, + "mutability": "mutable", + "name": "du", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 361, + "src": "3160:10:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 338, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3160:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 349, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 344, + "name": "data_union_mainnet_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 179, + "src": "3235:27:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "argumentTypes": null, + "id": 342, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "3212:8:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 343, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "cloneBytecode", + "nodeType": "MemberAccess", + "referencedDeclaration": 18, + "src": "3212:22:1", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (address) pure returns (bytes memory)" + } + }, + "id": 345, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3212:51:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 346, + "name": "data", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 324, + "src": "3265:4:1", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 347, + "name": "salt", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 310, + "src": "3271:4:1", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "argumentTypes": null, + "id": 340, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "3173:8:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 341, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "deployCodeAndInitUsingCreate2", + "nodeType": "MemberAccess", + "referencedDeclaration": 108, + "src": "3173:38:1", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_bytes_memory_ptr_$_t_bytes_memory_ptr_$_t_bytes32_$returns$_t_address_payable_$", + "typeString": "function (bytes memory,bytes memory,bytes32) returns (address payable)" + } + }, + "id": 348, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3173:103:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "3160:116:1" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 351, + "name": "du", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 339, + "src": "3308:2:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 353, + "name": "du", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 339, + "src": "3329:2:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 352, + "name": "sidechainAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 262, + "src": "3312:16:1", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_address_$", + "typeString": "function (address) view returns (address)" + } + }, + "id": 354, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3312:20:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 355, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 297, + "src": "3334:5:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 356, + "name": "data_union_mainnet_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 179, + "src": "3341:27:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 350, + "name": "MainnetDUCreated", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 177, + "src": "3291:16:1", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_address_$_t_address_$_t_address_$returns$__$", + "typeString": "function (address,address,address,address)" + } + }, + "id": 357, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3291:78:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 358, + "nodeType": "EmitStatement", + "src": "3286:83:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 359, + "name": "du", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 339, + "src": "3386:2:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 308, + "id": 360, + "nodeType": "Return", + "src": "3379:9:1" + } + ] + }, + "documentation": null, + "functionSelector": "cb8a191b", + "id": 362, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "deployNewDataUnion", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 305, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 297, + "mutability": "mutable", + "name": "owner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 362, + "src": "2574:13:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 296, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2574:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 299, + "mutability": "mutable", + "name": "adminFeeFraction", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 362, + "src": "2589:24:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 298, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2589:7:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 302, + "mutability": "mutable", + "name": "agents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 362, + "src": "2615:23:1", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 300, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2615:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 301, + "length": null, + "nodeType": "ArrayTypeName", + "src": "2615:9:1", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 304, + "mutability": "mutable", + "name": "name", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 362, + "src": "2640:18:1", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 303, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "2640:6:1", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2573:86:1" + }, + "returnParameters": { + "id": 308, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 307, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 362, + "src": "2692:7:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 306, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2692:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2691:9:1" + }, + "scope": 363, + "src": "2546:849:1", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + } + ], + "scope": 364, + "src": "332:3065:1" + } + ], + "src": "0:3398:1" + }, + "legacyAST": { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/DataUnionFactoryMainnet.sol", + "exportedSymbols": { + "DataUnionFactoryMainnet": [ + 363 + ], + "IDataUnionMainnet": [ + 167 + ] + }, + "id": 364, + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 156, + "literals": [ + "solidity", + "0.6", + ".6" + ], + "nodeType": "PragmaDirective", + "src": "0:22:1" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol", + "file": "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol", + "id": 157, + "nodeType": "ImportDirective", + "scope": 364, + "sourceUnit": 4283, + "src": "24:64:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "file": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "id": 158, + "nodeType": "ImportDirective", + "scope": 364, + "sourceUnit": 3642, + "src": "89:59:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/CloneLib.sol", + "file": "./CloneLib.sol", + "id": 159, + "nodeType": "ImportDirective", + "scope": 364, + "sourceUnit": 155, + "src": "149:24:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/IAMB.sol", + "file": "./IAMB.sol", + "id": 160, + "nodeType": "ImportDirective", + "scope": 364, + "sourceUnit": 2913, + "src": "174:20:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/ITokenMediator.sol", + "file": "./ITokenMediator.sol", + "id": 161, + "nodeType": "ImportDirective", + "scope": 364, + "sourceUnit": 2969, + "src": "195:30:1", + "symbolAliases": [], + "unitAlias": "" + }, + { + "abstract": false, + "baseContracts": [], + "contractDependencies": [], + "contractKind": "interface", + "documentation": null, + "fullyImplemented": false, + "id": 167, + "linearizedBaseContracts": [ + 167 + ], + "name": "IDataUnionMainnet", + "nodeType": "ContractDefinition", + "nodes": [ + { + "body": null, + "documentation": null, + "functionSelector": "37b43a94", + "id": 166, + "implemented": false, + "kind": "function", + "modifiers": [], + "name": "sidechainAddress", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 162, + "nodeType": "ParameterList", + "parameters": [], + "src": "286:2:1" + }, + "returnParameters": { + "id": 165, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 164, + "mutability": "mutable", + "name": "proxy", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 166, + "src": "312:13:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 163, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "312:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "311:15:1" + }, + "scope": 167, + "src": "261:66:1", + "stateMutability": "view", + "virtual": false, + "visibility": "external" + } + ], + "scope": 364, + "src": "227:102:1" + }, + { + "abstract": false, + "baseContracts": [], + "contractDependencies": [], + "contractKind": "contract", + "documentation": null, + "fullyImplemented": true, + "id": 363, + "linearizedBaseContracts": [ + 363 + ], + "name": "DataUnionFactoryMainnet", + "nodeType": "ContractDefinition", + "nodes": [ + { + "anonymous": false, + "documentation": null, + "id": 177, + "name": "MainnetDUCreated", + "nodeType": "EventDefinition", + "parameters": { + "id": 176, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 169, + "indexed": true, + "mutability": "mutable", + "name": "mainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 177, + "src": "394:23:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 168, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "394:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 171, + "indexed": true, + "mutability": "mutable", + "name": "sidechain", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 177, + "src": "419:25:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 170, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "419:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 173, + "indexed": true, + "mutability": "mutable", + "name": "owner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 177, + "src": "446:21:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 172, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "446:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 175, + "indexed": false, + "mutability": "mutable", + "name": "template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 177, + "src": "469:16:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 174, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "469:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "393:93:1" + }, + "src": "371:116:1" + }, + { + "constant": false, + "functionSelector": "015a0da0", + "id": 179, + "mutability": "mutable", + "name": "data_union_mainnet_template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "493:42:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 178, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "493:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "e4a154a4", + "id": 181, + "mutability": "mutable", + "name": "data_union_sidechain_template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "599:44:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 180, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "599:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "35813bc1", + "id": 183, + "mutability": "mutable", + "name": "data_union_sidechain_factory", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "649:43:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 182, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "649:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "692199d4", + "id": 185, + "mutability": "mutable", + "name": "sidechain_maxgas", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "698:31:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 184, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "698:7:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "1062b39a", + "id": 187, + "mutability": "mutable", + "name": "amb", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "735:15:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + }, + "typeName": { + "contractScope": null, + "id": 186, + "name": "IAMB", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2912, + "src": "735:4:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "c5a8c91f", + "id": 189, + "mutability": "mutable", + "name": "token_mediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "756:36:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + }, + "typeName": { + "contractScope": null, + "id": 188, + "name": "ITokenMediator", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2968, + "src": "756:14:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "fc0c546a", + "id": 191, + "mutability": "mutable", + "name": "token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 363, + "src": "798:20:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 190, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "798:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "body": { + "id": 240, + "nodeType": "Block", + "src": "1121:398:1", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 208, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 206, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 191, + "src": "1131:5:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 207, + "name": "_token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 193, + "src": "1139:6:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1131:14:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 209, + "nodeType": "ExpressionStatement", + "src": "1131:14:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 214, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 210, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 189, + "src": "1155:14:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 212, + "name": "_token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 195, + "src": "1187:15:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 211, + "name": "ITokenMediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2968, + "src": "1172:14:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_ITokenMediator_$2968_$", + "typeString": "type(contract ITokenMediator)" + } + }, + "id": 213, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1172:31:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "src": "1155:48:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 215, + "nodeType": "ExpressionStatement", + "src": "1155:48:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 218, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 216, + "name": "data_union_mainnet_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 179, + "src": "1213:27:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 217, + "name": "_data_union_mainnet_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 197, + "src": "1243:28:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1213:58:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 219, + "nodeType": "ExpressionStatement", + "src": "1213:58:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 222, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 220, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 181, + "src": "1281:29:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 221, + "name": "_data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 199, + "src": "1313:30:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1281:62:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 223, + "nodeType": "ExpressionStatement", + "src": "1281:62:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 226, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 224, + "name": "data_union_sidechain_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 183, + "src": "1353:28:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 225, + "name": "_data_union_sidechain_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 201, + "src": "1384:29:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1353:60:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 227, + "nodeType": "ExpressionStatement", + "src": "1353:60:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 234, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 228, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 187, + "src": "1423:3:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "argumentTypes": null, + "id": 230, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 189, + "src": "1434:14:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 231, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "bridgeContract", + "nodeType": "MemberAccess", + "referencedDeclaration": 2946, + "src": "1434:29:1", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$__$returns$_t_address_$", + "typeString": "function () view external returns (address)" + } + }, + "id": 232, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1434:31:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 229, + "name": "IAMB", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2912, + "src": "1429:4:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_IAMB_$2912_$", + "typeString": "type(contract IAMB)" + } + }, + "id": 233, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1429:37:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "src": "1423:43:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "id": 235, + "nodeType": "ExpressionStatement", + "src": "1423:43:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 238, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 236, + "name": "sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 185, + "src": "1476:16:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 237, + "name": "_sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 203, + "src": "1495:17:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1476:36:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 239, + "nodeType": "ExpressionStatement", + "src": "1476:36:1" + } + ] + }, + "documentation": null, + "id": 241, + "implemented": true, + "kind": "constructor", + "modifiers": [], + "name": "", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 204, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 193, + "mutability": "mutable", + "name": "_token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 241, + "src": "837:14:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 192, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "837:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 195, + "mutability": "mutable", + "name": "_token_mediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 241, + "src": "869:23:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 194, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "869:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 197, + "mutability": "mutable", + "name": "_data_union_mainnet_template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 241, + "src": "910:36:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 196, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "910:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 199, + "mutability": "mutable", + "name": "_data_union_sidechain_template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 241, + "src": "964:38:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 198, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "964:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 201, + "mutability": "mutable", + "name": "_data_union_sidechain_factory", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 241, + "src": "1020:37:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 200, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1020:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 203, + "mutability": "mutable", + "name": "_sidechain_maxgas", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 241, + "src": "1075:25:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 202, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1075:7:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "836:265:1" + }, + "returnParameters": { + "id": 205, + "nodeType": "ParameterList", + "parameters": [], + "src": "1121:0:1" + }, + "scope": 363, + "src": "825:694:1", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 261, + "nodeType": "Block", + "src": "1626:200:1", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 250, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 181, + "src": "1692:29:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 251, + "name": "data_union_sidechain_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 183, + "src": "1735:28:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 256, + "name": "mainet_address", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 243, + "src": "1793:14:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 255, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "1785:7:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 254, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1785:7:1", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 257, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1785:23:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 253, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "1777:7:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes32_$", + "typeString": "type(bytes32)" + }, + "typeName": { + "id": 252, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1777:7:1", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 258, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1777:32:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "argumentTypes": null, + "id": 248, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "1643:8:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 249, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "predictCloneAddressCreate2", + "nodeType": "MemberAccess", + "referencedDeclaration": 61, + "src": "1643:35:1", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$_t_address_$_t_bytes32_$returns$_t_address_$", + "typeString": "function (address,address,bytes32) pure returns (address)" + } + }, + "id": 259, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1643:176:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 247, + "id": 260, + "nodeType": "Return", + "src": "1636:183:1" + } + ] + }, + "documentation": null, + "functionSelector": "17c2a98c", + "id": 262, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "sidechainAddress", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 244, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 243, + "mutability": "mutable", + "name": "mainet_address", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 262, + "src": "1552:22:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 242, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1552:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1551:24:1" + }, + "returnParameters": { + "id": 247, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 246, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 262, + "src": "1613:7:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 245, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1613:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1612:9:1" + }, + "scope": 363, + "src": "1526:300:1", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 294, + "nodeType": "Block", + "src": "1958:224:1", + "statements": [ + { + "assignments": [ + 272 + ], + "declarations": [ + { + "constant": false, + "id": 272, + "mutability": "mutable", + "name": "salt", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 294, + "src": "1968:12:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 271, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1968:7:1", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 283, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 278, + "name": "name", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 266, + "src": "2010:4:1", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "id": 277, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2004:5:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes_storage_ptr_$", + "typeString": "type(bytes storage pointer)" + }, + "typeName": { + "id": 276, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "2004:5:1", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 279, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2004:11:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 280, + "name": "deployer", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 264, + "src": "2017:8:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "argumentTypes": null, + "id": 274, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "1993:3:1", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 275, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encode", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "1993:10:1", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencode_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 281, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1993:33:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 273, + "name": "keccak256", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -8, + "src": "1983:9:1", + "typeDescriptions": { + "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", + "typeString": "function (bytes memory) pure returns (bytes32)" + } + }, + "id": 282, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1983:44:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "1968:59:1" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 286, + "name": "data_union_mainnet_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 179, + "src": "2093:27:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 289, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "2142:4:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionFactoryMainnet_$363", + "typeString": "contract DataUnionFactoryMainnet" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionFactoryMainnet_$363", + "typeString": "contract DataUnionFactoryMainnet" + } + ], + "id": 288, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2134:7:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 287, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2134:7:1", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 290, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2134:13:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 291, + "name": "salt", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 272, + "src": "2161:4:1", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "argumentTypes": null, + "id": 284, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "2044:8:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 285, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "predictCloneAddressCreate2", + "nodeType": "MemberAccess", + "referencedDeclaration": 61, + "src": "2044:35:1", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$_t_address_$_t_bytes32_$returns$_t_address_$", + "typeString": "function (address,address,bytes32) pure returns (address)" + } + }, + "id": 292, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2044:131:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 270, + "id": 293, + "nodeType": "Return", + "src": "2037:138:1" + } + ] + }, + "documentation": null, + "functionSelector": "d4c31bd4", + "id": 295, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "mainnetAddress", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 267, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 264, + "mutability": "mutable", + "name": "deployer", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 295, + "src": "1870:16:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 263, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1870:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 266, + "mutability": "mutable", + "name": "name", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 295, + "src": "1888:18:1", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 265, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "1888:6:1", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1869:38:1" + }, + "returnParameters": { + "id": 270, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 269, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 295, + "src": "1945:7:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 268, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1945:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1944:9:1" + }, + "scope": 363, + "src": "1846:336:1", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 361, + "nodeType": "Block", + "src": "2705:690:1", + "statements": [ + { + "assignments": [ + 310 + ], + "declarations": [ + { + "constant": false, + "id": 310, + "mutability": "mutable", + "name": "salt", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 361, + "src": "2715:12:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 309, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "2715:7:1", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 322, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 316, + "name": "name", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 304, + "src": "2757:4:1", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "id": 315, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2751:5:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes_storage_ptr_$", + "typeString": "type(bytes storage pointer)" + }, + "typeName": { + "id": 314, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "2751:5:1", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 317, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2751:11:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 318, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "2764:3:1", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 319, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2764:10:1", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "expression": { + "argumentTypes": null, + "id": 312, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "2740:3:1", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 313, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encode", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2740:10:1", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencode_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 320, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2740:35:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 311, + "name": "keccak256", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -8, + "src": "2730:9:1", + "typeDescriptions": { + "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", + "typeString": "function (bytes memory) pure returns (bytes32)" + } + }, + "id": 321, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2730:46:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2715:61:1" + }, + { + "assignments": [ + 324 + ], + "declarations": [ + { + "constant": false, + "id": 324, + "mutability": "mutable", + "name": "data", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 361, + "src": "2786:17:1", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 323, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "2786:5:1", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 337, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "696e697469616c697a6528616464726573732c616464726573732c616464726573732c75696e743235362c616464726573732c616464726573732c75696e743235362c616464726573735b5d29", + "id": 327, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2830:79:1", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_fb6470c99ff27472c874d5b7a3935111326af310466bebb9ef42dc6569bc2cec", + "typeString": "literal_string \"initialize(address,address,address,uint256,address,address,uint256,address[])\"" + }, + "value": "initialize(address,address,address,uint256,address,address,uint256,address[])" + }, + { + "argumentTypes": null, + "id": 328, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 191, + "src": "2923:5:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 329, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 189, + "src": "2942:14:1", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + { + "argumentTypes": null, + "id": 330, + "name": "data_union_sidechain_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 183, + "src": "2970:28:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 331, + "name": "sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 185, + "src": "3012:16:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 332, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 181, + "src": "3042:29:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 333, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 297, + "src": "3085:5:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 334, + "name": "adminFeeFraction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 299, + "src": "3104:16:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 335, + "name": "agents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 302, + "src": "3134:6:1", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_fb6470c99ff27472c874d5b7a3935111326af310466bebb9ef42dc6569bc2cec", + "typeString": "literal_string \"initialize(address,address,address,uint256,address,address,uint256,address[])\"" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + ], + "expression": { + "argumentTypes": null, + "id": 325, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "2806:3:1", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 326, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encodeWithSignature", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2806:23:1", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (string memory) pure returns (bytes memory)" + } + }, + "id": 336, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2806:344:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2786:364:1" + }, + { + "assignments": [ + 339 + ], + "declarations": [ + { + "constant": false, + "id": 339, + "mutability": "mutable", + "name": "du", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 361, + "src": "3160:10:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 338, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3160:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 349, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 344, + "name": "data_union_mainnet_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 179, + "src": "3235:27:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "argumentTypes": null, + "id": 342, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "3212:8:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 343, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "cloneBytecode", + "nodeType": "MemberAccess", + "referencedDeclaration": 18, + "src": "3212:22:1", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (address) pure returns (bytes memory)" + } + }, + "id": 345, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3212:51:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 346, + "name": "data", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 324, + "src": "3265:4:1", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 347, + "name": "salt", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 310, + "src": "3271:4:1", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "argumentTypes": null, + "id": 340, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "3173:8:1", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 341, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "deployCodeAndInitUsingCreate2", + "nodeType": "MemberAccess", + "referencedDeclaration": 108, + "src": "3173:38:1", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_bytes_memory_ptr_$_t_bytes_memory_ptr_$_t_bytes32_$returns$_t_address_payable_$", + "typeString": "function (bytes memory,bytes memory,bytes32) returns (address payable)" + } + }, + "id": 348, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3173:103:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "3160:116:1" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 351, + "name": "du", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 339, + "src": "3308:2:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 353, + "name": "du", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 339, + "src": "3329:2:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 352, + "name": "sidechainAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 262, + "src": "3312:16:1", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_address_$", + "typeString": "function (address) view returns (address)" + } + }, + "id": 354, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3312:20:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 355, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 297, + "src": "3334:5:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 356, + "name": "data_union_mainnet_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 179, + "src": "3341:27:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 350, + "name": "MainnetDUCreated", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 177, + "src": "3291:16:1", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_address_$_t_address_$_t_address_$returns$__$", + "typeString": "function (address,address,address,address)" + } + }, + "id": 357, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3291:78:1", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 358, + "nodeType": "EmitStatement", + "src": "3286:83:1" + }, + { + "expression": { + "argumentTypes": null, + "id": 359, + "name": "du", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 339, + "src": "3386:2:1", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 308, + "id": 360, + "nodeType": "Return", + "src": "3379:9:1" + } + ] + }, + "documentation": null, + "functionSelector": "cb8a191b", + "id": 362, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "deployNewDataUnion", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 305, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 297, + "mutability": "mutable", + "name": "owner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 362, + "src": "2574:13:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 296, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2574:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 299, + "mutability": "mutable", + "name": "adminFeeFraction", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 362, + "src": "2589:24:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 298, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2589:7:1", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 302, + "mutability": "mutable", + "name": "agents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 362, + "src": "2615:23:1", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 300, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2615:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 301, + "length": null, + "nodeType": "ArrayTypeName", + "src": "2615:9:1", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 304, + "mutability": "mutable", + "name": "name", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 362, + "src": "2640:18:1", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 303, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "2640:6:1", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2573:86:1" + }, + "returnParameters": { + "id": 308, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 307, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 362, + "src": "2692:7:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 306, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2692:7:1", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2691:9:1" + }, + "scope": 363, + "src": "2546:849:1", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + } + ], + "scope": 364, + "src": "332:3065:1" + } + ], + "src": "0:3398:1" + }, + "compiler": { + "name": "solc", + "version": "0.6.6+commit.6c089d02.Emscripten.clang" + }, + "networks": {}, + "schemaVersion": "3.2.3", + "updatedAt": "2020-12-09T11:44:39.453Z", + "devdoc": { + "methods": {} + }, + "userdoc": { + "methods": {} + } +} \ No newline at end of file diff --git a/contracts/DataUnionFactorySidechain.json b/contracts/DataUnionFactorySidechain.json new file mode 100644 index 000000000..478df27ad --- /dev/null +++ b/contracts/DataUnionFactorySidechain.json @@ -0,0 +1,8461 @@ +{ + "contractName": "DataUnionFactorySidechain", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_token_mediator", + "type": "address" + }, + { + "internalType": "address", + "name": "_data_union_sidechain_template", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountWei", + "type": "uint256" + } + ], + "name": "DUInitialEthSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountWei", + "type": "uint256" + } + ], + "name": "OwnerInitialEthSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "mainnet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sidenet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "template", + "type": "address" + } + ], + "name": "SidechainDUCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "UpdateDefaultNewMemberInitialEth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "UpdateNewDUInitialEth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "UpdateNewDUOwnerInitialEth", + "type": "event" + }, + { + "inputs": [], + "name": "amb", + "outputs": [ + { + "internalType": "contract IAMB", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claimOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "data_union_sidechain_template", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "defaultNewMemberEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "newDUInitialEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "newDUOwnerInitialEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token_mediator", + "outputs": [ + { + "internalType": "contract ITokenMediator", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "val", + "type": "uint256" + } + ], + "name": "setNewDUInitialEth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "val", + "type": "uint256" + } + ], + "name": "setNewDUOwnerInitialEth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "val", + "type": "uint256" + } + ], + "name": "setNewMemberInitialEth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "mainet_address", + "type": "address" + } + ], + "name": "sidechainAddress", + "outputs": [ + { + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "agents", + "type": "address[]" + } + ], + "name": "deployNewDUSidechain", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "metadata": "{\"compiler\":{\"version\":\"0.6.6+commit.6c089d02\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token_mediator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_data_union_sidechain_template\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountWei\",\"type\":\"uint256\"}],\"name\":\"DUInitialEthSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountWei\",\"type\":\"uint256\"}],\"name\":\"OwnerInitialEthSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"mainnet\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sidenet\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"template\",\"type\":\"address\"}],\"name\":\"SidechainDUCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"UpdateDefaultNewMemberInitialEth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"UpdateNewDUInitialEth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"UpdateNewDUOwnerInitialEth\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"amb\",\"outputs\":[{\"internalType\":\"contract IAMB\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"data_union_sidechain_template\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"defaultNewMemberEth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"agents\",\"type\":\"address[]\"}],\"name\":\"deployNewDUSidechain\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"newDUInitialEth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"newDUOwnerInitialEth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"setNewDUInitialEth\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"setNewDUOwnerInitialEth\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"setNewMemberInitialEth\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"mainet_address\",\"type\":\"address\"}],\"name\":\"sidechainAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_mediator\",\"outputs\":[{\"internalType\":\"contract ITokenMediator\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"methods\":{\"claimOwnership()\":{\"details\":\"Allows the pendingOwner address to finalize the transfer.\"},\"transferOwnership(address)\":{\"details\":\"Allows the current owner to set the pendingOwner address.\",\"params\":{\"newOwner\":\"The address to transfer ownership to.\"}}}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"/home/heynow/streamr/data-union-solidity/contracts/DataUnionFactorySidechain.sol\":\"DataUnionFactorySidechain\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"/home/heynow/streamr/data-union-solidity/contracts/CloneLib.sol\":{\"keccak256\":\"0xf9082fe41a9e05b37cf87f0d1d67ca16d32c4100a2a27a6fc9d8f3f8364a7486\",\"urls\":[\"bzz-raw://b928f45b1904c399db9508c093604531bd215afeb4686827ab46daa7aee1938e\",\"dweb:/ipfs/QmdnBUvpCDc93fHZe7o6bitGRZo4PFTx9NprgziqHsVHFw\"]},\"/home/heynow/streamr/data-union-solidity/contracts/DataUnionFactorySidechain.sol\":{\"keccak256\":\"0xc288c62f30298711897bd47d5f2a08e12542f59e5bbf55de066b2bd865276921\",\"urls\":[\"bzz-raw://144897a0f71e8440f8c2ab182cd4589c1f588dae3d8e8879a4902da1bd622914\",\"dweb:/ipfs/QmVpdWc3bK5QEw3hF5FnNG9DTuzMKTzjAmTtVEcu2WDSFM\"]},\"/home/heynow/streamr/data-union-solidity/contracts/IAMB.sol\":{\"keccak256\":\"0x63b46d3087a8ba558cb36d99ffe5b2f0241446adc4c8df4219ce86f97727e168\",\"urls\":[\"bzz-raw://66d9c8c817e90b25f28b3d79a69b440018b49633a7bbaf6fe4d1788b2ff5e6eb\",\"dweb:/ipfs/QmSdrqpaZ3R3NGFuF6jnbo8cCgV5ghdW5iWrnV59qavYP2\"]},\"/home/heynow/streamr/data-union-solidity/contracts/ITokenMediator.sol\":{\"keccak256\":\"0x1f21e943f4e125dd1c4353db29880b63f8fa7a299ba862432c8a4e14807873e2\",\"urls\":[\"bzz-raw://4ddc233243efce6c2582b63e3be28c4f90f32d60b5d4b6fe8331106d970a8435\",\"dweb:/ipfs/QmQzLwvxU3ixfLbdpuYdpqvW61xjPbnXDTaaWNjRJUhvSK\"]},\"/home/heynow/streamr/data-union-solidity/contracts/Ownable.sol\":{\"keccak256\":\"0x0d96dac82f3bf17d2cdc90863a61c8957622c305bc3bbf9cd8f47facfa71dea1\",\"urls\":[\"bzz-raw://1cd621b81754be8073fc89bd2bc864e7b0169ba5f153edc5b9212a19f4890aa3\",\"dweb:/ipfs/QmcE5HTf3pptr2s7oiDqYtotCLrb736g8N7YyRZj8k5mHg\"]},\"openzeppelin-solidity/contracts/math/SafeMath.sol\":{\"keccak256\":\"0x9a9cf02622cd7a64261b10534fc3260449da25c98c9e96d1b4ae8110a20e5806\",\"urls\":[\"bzz-raw://2df142592d1dc267d9549049ee3317fa190d2f87eaa565f86ab05ec83f7ab8f5\",\"dweb:/ipfs/QmSkJtcfWo7c42KnL5hho6GFxK6HRNV91XABx1P7xDtfLV\"]},\"openzeppelin-solidity/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x5c26b39d26f7ed489e555d955dcd3e01872972e71fdd1528e93ec164e4f23385\",\"urls\":[\"bzz-raw://efdc632af6960cf865dbc113665ea1f5b90eab75cc40ec062b2f6ae6da582017\",\"dweb:/ipfs/QmfAZFDuG62vxmAN9DnXApv7e7PMzPqi4RkqqZHLMSQiY5\"]}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50604051610d96380380610d968339818101604052606081101561003357600080fd5b50805160208083015160409384015160008054336001600160a01b0319918216179091556008805482166001600160a01b0380881691909117909155600480548316828616178082556002805490941683861617909355875163cd59658360e01b81529751969794969395929091169363cd5965839381830193929091829003018186803b1580156100c457600080fd5b505afa1580156100d8573d6000803e3d6000fd5b505050506040513d60208110156100ee57600080fd5b5051600380546001600160a01b039092166001600160a01b0319909216919091179055505050610c73806101236000396000f3fe6080604052600436106100f75760003560e01c8063c5a8c91f1161008a578063f0ef0b0611610059578063f0ef0b0614610322578063f2fde38b1461034c578063f7c1329e1461037f578063fc0c546a14610394576100fe565b8063c5a8c91f146102ce578063e22ab5ae146102e3578063e30c3978146102f8578063e4a154a41461030d576100fe565b80634e51a863116100c65780634e51a863146102535780634e71e0c81461027d5780638da5cb5b14610292578063afc6224b146102a7576100fe565b80631062b39a1461010357806317c2a98c14610134578063325ff66f1461016757806337dd8b0514610227576100fe565b366100fe57005b600080fd5b34801561010f57600080fd5b506101186103a9565b604080516001600160a01b039092168252519081900360200190f35b34801561014057600080fd5b506101186004803603602081101561015757600080fd5b50356001600160a01b03166103b8565b34801561017357600080fd5b506101186004803603604081101561018a57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156101b557600080fd5b8201836020820111156101c757600080fd5b803590602001918460208302840111640100000000831117156101e957600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506103dd945050505050565b34801561023357600080fd5b506102516004803603602081101561024a57600080fd5b50356106dd565b005b34801561025f57600080fd5b506102516004803603602081101561027657600080fd5b5035610773565b34801561028957600080fd5b50610251610808565b34801561029e57600080fd5b506101186108be565b3480156102b357600080fd5b506102bc6108cd565b60408051918252519081900360200190f35b3480156102da57600080fd5b506101186108d3565b3480156102ef57600080fd5b506102bc6108e2565b34801561030457600080fd5b506101186108e8565b34801561031957600080fd5b506101186108f7565b34801561032e57600080fd5b506102516004803603602081101561034557600080fd5b5035610906565b34801561035857600080fd5b506102516004803603602081101561036f57600080fd5b50356001600160a01b031661099b565b34801561038b57600080fd5b506102bc610a08565b3480156103a057600080fd5b50610118610a0e565b6003546001600160a01b031681565b6002546000906103d7906001600160a01b039081169030908516610a1d565b92915050565b6003546000906001600160a01b0316331461042a576040805162461bcd60e51b815260206004820152600860248201526737b7363cafa0a6a160c11b604482015290519081900360640190fd5b6003546040805163d67bdd2560e01b815290516000926001600160a01b03169163d67bdd25916004808301926020929190829003018186803b15801561046f57600080fd5b505afa158015610483573d6000803e3d6000fd5b505050506040513d602081101561049957600080fd5b50516008546004546007546040516001600160a01b0389811660248301908152948116604483018190529381166084830181905290861660a4830181905260c4830184905260c0606484019081528a5160e48501528a5197985090966060968c96958c958b949193610104909101906020888101910280838360005b8381101561052d578181015183820152602001610515565b50506040805193909501838103601f190184529094525060208101805163015c7f5160e01b6001600160e01b03909116179052600254909b5060009a50610592995061058b98506001600160a01b03169650610a8995505050505050565b8385610adb565b600254604080516001600160a01b0392831681529051929350818a1692828516928816917f90d0a5d098b9a181ff8ddc866f840cc210e5b91eaf27bc267d5822a0deafad25919081900360200190a4600554158015906105f457506005544710155b1561065a576005546040516001600160a01b0383169180156108fc02916000818181858888f193505050501561065a5760055460408051918252517f517165f169759cdb94227d1c50f4f47895eb099a7f04a780f519bf1739face6f9181900360200190a15b6006541580159061066d57506006544710155b156106d3576006546040516001600160a01b0389169180156108fc02916000818181858888f19350505050156106d35760065460408051918252517f69e30c0bf438d0d3e0afb7f68d57ef394a0d5e8712f82fa00aa599e42574bc2a9181900360200190a15b9695505050505050565b6000546001600160a01b03163314610728576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b60075481141561073757610770565b60078190556040805182815290517f7a78bdfbfb2e909f35c05c77e80038cfd0a22c704748eba8b1d20aab76cd5d9c9181900360200190a15b50565b6000546001600160a01b031633146107be576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b6005548114156107cd57610770565b60058190556040805182815290517fa02ce31a8a8adcdc2e2811a0c7f5d1eb1aa920ca9fdfaeaebfe3a2163e69a6549181900360200190a150565b6001546001600160a01b0316331461085a576040805162461bcd60e51b815260206004820152601060248201526f37b7363ca832b73234b733a7bbb732b960811b604482015290519081900360640190fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6000546001600160a01b031681565b60065481565b6004546001600160a01b031681565b60075481565b6001546001600160a01b031681565b6002546001600160a01b031681565b6000546001600160a01b03163314610951576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b60065481141561096057610770565b60068190556040805182815290517fe08bf32e9c0e823a76d0088908afba678014c513e2311bba64fc72f38ae809709181900360200190a150565b6000546001600160a01b031633146109e6576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60055481565b6008546001600160a01b031681565b600080610a2985610a89565b8051602091820120604080516001600160f81b0319818501526bffffffffffffffffffffffff19606089901b1660218201526035810187905260558082019390935281518082039093018352607501905280519101209150509392505050565b604080516057810190915260378152733d602d80600a3d3981f3363d3d373d3d3d363d7360601b602082015260609190911b60348201526e5af43d82803e903d91602b57fd5bf360881b604882015290565b825160009082816020870184f591506001600160a01b038216610b3c576040805162461bcd60e51b8152602060048201526014602482015273195c9c9bdc97d85b1c9958591e50dc99585d195960621b604482015290519081900360640190fd5b835115610c35576000826001600160a01b0316856040518082805190602001908083835b60208310610b7f5780518252601f199092019160209182019101610b60565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610be1576040519150601f19603f3d011682016040523d82523d6000602084013e610be6565b606091505b5050905080610c33576040805162461bcd60e51b815260206004820152601460248201527332b93937b92fb4b734ba34b0b634bd30ba34b7b760611b604482015290519081900360640190fd5b505b50939250505056fea2646970667358221220393a459d6b64473d1209ef5ca9a87312b5cca4b2065323b7ab4866081ede390164736f6c63430006060033", + "deployedBytecode": "0x6080604052600436106100f75760003560e01c8063c5a8c91f1161008a578063f0ef0b0611610059578063f0ef0b0614610322578063f2fde38b1461034c578063f7c1329e1461037f578063fc0c546a14610394576100fe565b8063c5a8c91f146102ce578063e22ab5ae146102e3578063e30c3978146102f8578063e4a154a41461030d576100fe565b80634e51a863116100c65780634e51a863146102535780634e71e0c81461027d5780638da5cb5b14610292578063afc6224b146102a7576100fe565b80631062b39a1461010357806317c2a98c14610134578063325ff66f1461016757806337dd8b0514610227576100fe565b366100fe57005b600080fd5b34801561010f57600080fd5b506101186103a9565b604080516001600160a01b039092168252519081900360200190f35b34801561014057600080fd5b506101186004803603602081101561015757600080fd5b50356001600160a01b03166103b8565b34801561017357600080fd5b506101186004803603604081101561018a57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156101b557600080fd5b8201836020820111156101c757600080fd5b803590602001918460208302840111640100000000831117156101e957600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506103dd945050505050565b34801561023357600080fd5b506102516004803603602081101561024a57600080fd5b50356106dd565b005b34801561025f57600080fd5b506102516004803603602081101561027657600080fd5b5035610773565b34801561028957600080fd5b50610251610808565b34801561029e57600080fd5b506101186108be565b3480156102b357600080fd5b506102bc6108cd565b60408051918252519081900360200190f35b3480156102da57600080fd5b506101186108d3565b3480156102ef57600080fd5b506102bc6108e2565b34801561030457600080fd5b506101186108e8565b34801561031957600080fd5b506101186108f7565b34801561032e57600080fd5b506102516004803603602081101561034557600080fd5b5035610906565b34801561035857600080fd5b506102516004803603602081101561036f57600080fd5b50356001600160a01b031661099b565b34801561038b57600080fd5b506102bc610a08565b3480156103a057600080fd5b50610118610a0e565b6003546001600160a01b031681565b6002546000906103d7906001600160a01b039081169030908516610a1d565b92915050565b6003546000906001600160a01b0316331461042a576040805162461bcd60e51b815260206004820152600860248201526737b7363cafa0a6a160c11b604482015290519081900360640190fd5b6003546040805163d67bdd2560e01b815290516000926001600160a01b03169163d67bdd25916004808301926020929190829003018186803b15801561046f57600080fd5b505afa158015610483573d6000803e3d6000fd5b505050506040513d602081101561049957600080fd5b50516008546004546007546040516001600160a01b0389811660248301908152948116604483018190529381166084830181905290861660a4830181905260c4830184905260c0606484019081528a5160e48501528a5197985090966060968c96958c958b949193610104909101906020888101910280838360005b8381101561052d578181015183820152602001610515565b50506040805193909501838103601f190184529094525060208101805163015c7f5160e01b6001600160e01b03909116179052600254909b5060009a50610592995061058b98506001600160a01b03169650610a8995505050505050565b8385610adb565b600254604080516001600160a01b0392831681529051929350818a1692828516928816917f90d0a5d098b9a181ff8ddc866f840cc210e5b91eaf27bc267d5822a0deafad25919081900360200190a4600554158015906105f457506005544710155b1561065a576005546040516001600160a01b0383169180156108fc02916000818181858888f193505050501561065a5760055460408051918252517f517165f169759cdb94227d1c50f4f47895eb099a7f04a780f519bf1739face6f9181900360200190a15b6006541580159061066d57506006544710155b156106d3576006546040516001600160a01b0389169180156108fc02916000818181858888f19350505050156106d35760065460408051918252517f69e30c0bf438d0d3e0afb7f68d57ef394a0d5e8712f82fa00aa599e42574bc2a9181900360200190a15b9695505050505050565b6000546001600160a01b03163314610728576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b60075481141561073757610770565b60078190556040805182815290517f7a78bdfbfb2e909f35c05c77e80038cfd0a22c704748eba8b1d20aab76cd5d9c9181900360200190a15b50565b6000546001600160a01b031633146107be576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b6005548114156107cd57610770565b60058190556040805182815290517fa02ce31a8a8adcdc2e2811a0c7f5d1eb1aa920ca9fdfaeaebfe3a2163e69a6549181900360200190a150565b6001546001600160a01b0316331461085a576040805162461bcd60e51b815260206004820152601060248201526f37b7363ca832b73234b733a7bbb732b960811b604482015290519081900360640190fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6000546001600160a01b031681565b60065481565b6004546001600160a01b031681565b60075481565b6001546001600160a01b031681565b6002546001600160a01b031681565b6000546001600160a01b03163314610951576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b60065481141561096057610770565b60068190556040805182815290517fe08bf32e9c0e823a76d0088908afba678014c513e2311bba64fc72f38ae809709181900360200190a150565b6000546001600160a01b031633146109e6576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60055481565b6008546001600160a01b031681565b600080610a2985610a89565b8051602091820120604080516001600160f81b0319818501526bffffffffffffffffffffffff19606089901b1660218201526035810187905260558082019390935281518082039093018352607501905280519101209150509392505050565b604080516057810190915260378152733d602d80600a3d3981f3363d3d373d3d3d363d7360601b602082015260609190911b60348201526e5af43d82803e903d91602b57fd5bf360881b604882015290565b825160009082816020870184f591506001600160a01b038216610b3c576040805162461bcd60e51b8152602060048201526014602482015273195c9c9bdc97d85b1c9958591e50dc99585d195960621b604482015290519081900360640190fd5b835115610c35576000826001600160a01b0316856040518082805190602001908083835b60208310610b7f5780518252601f199092019160209182019101610b60565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610be1576040519150601f19603f3d011682016040523d82523d6000602084013e610be6565b606091505b5050905080610c33576040805162461bcd60e51b815260206004820152601460248201527332b93937b92fb4b734ba34b0b634bd30ba34b7b760611b604482015290519081900360640190fd5b505b50939250505056fea2646970667358221220393a459d6b64473d1209ef5ca9a87312b5cca4b2065323b7ab4866081ede390164736f6c63430006060033", + "immutableReferences": {}, + "sourceMap": "324:3380:2:-:0;;;1087:334;5:9:-1;2:2;;;27:1;24;17:12;2:2;1087:334:2;;;;;;;;;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;1087:334:2;;;;;;;;;;;;577:5:12;:14;;1195:10:2;-1:-1:-1;;;;;;577:14:12;;;;;;;1217:5:2::1;:14:::0;;;::::1;-1:-1:-1::0;;;;;1217:14:2;;::::1;::::0;;;::::1;::::0;;;1241::::1;:48:::0;;;::::1;::::0;;::::1;;::::0;;;1299:29:::1;:62:::0;;;;::::1;::::0;;::::1;;::::0;;;1382:31;;-1:-1:-1;;;1382:31:2;;;;1087:334;;;;;;1382:14;;;::::1;::::0;:29:::1;::::0;:31;;::::1;::::0;1087:334;1382:31;;;;;;;:14;:31;::::1;;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;1382:31:2;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;1382:31:2;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::1;4:2;-1:-1:::0;1382:31:2;1371:3:::1;:43:::0;;-1:-1:-1;;;;;1371:43:2;;::::1;-1:-1:-1::0;;;;;;1371:43:2;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;;;324:3380:2;;;;;;", + "deployedSourceMap": "324:3380:2:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;792:15:2;;5:9:-1;2:2;;;27:1;24;17:12;2:2;792:15:2;;;:::i;:::-;;;;-1:-1:-1;;;;;792:15:2;;;;;;;;;;;;;;2081:245;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2081:245:2;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;2081:245:2;-1:-1:-1;;;;;2081:245:2;;:::i;2431:1271::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2431:1271:2;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;2431:1271:2;;;;;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;2431:1271:2;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;2431:1271:2;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;2431:1271:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;2431:1271:2;;-1:-1:-1;2431:1271:2;;-1:-1:-1;;;;;2431:1271:2:i;1874:200::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1874:200:2;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;1874:200:2;;:::i;:::-;;1488:177;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1488:177:2;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;1488:177:2;;:::i;1123:226:12:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1123:226:12;;;:::i;236:20::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;236:20:12;;;:::i;986:32:2:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;986:32:2;;;:::i;:::-;;;;;;;;;;;;;;;;813:36;;5:9:-1;2:2;;;27:1;24;17:12;2:2;813:36:2;;;:::i;1024:31::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1024:31:2;;;:::i;262:27:12:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;262:27:12;;;:::i;742:44:2:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;742:44:2;;;:::i;1671:197::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1671:197:2;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;1671:197:2;;:::i;929:102:12:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;929:102:12;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;929:102:12;-1:-1:-1;;;;;929:102:12;;:::i;953:27:2:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;953:27:2;;;:::i;1061:20::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1061:20:2;;;:::i;792:15::-;;;-1:-1:-1;;;;;792:15:2;;:::o;2081:245::-;2240:29;;2168:13;;2204:115;;-1:-1:-1;;;;;2240:29:2;;;;2279:4;;2294:23;;2204:35;:115::i;:::-;2197:122;2081:245;-1:-1:-1;;2081:245:2:o;2431:1271::-;2574:3;;2525:7;;-1:-1:-1;;;;;2574:3:2;2552:10;:26;2544:47;;;;;-1:-1:-1;;;2544:47:2;;;;;;;;;;;;-1:-1:-1;;;2544:47:2;;;;;;;;;;;;;;;2621:3;;:19;;;-1:-1:-1;;;2621:19:2;;;;2601:17;;-1:-1:-1;;;;;2621:3:2;;:17;;:19;;;;;;;;;;;;;;:3;:19;;;2:2:-1;;;;27:1;24;17:12;2:2;2621:19:2;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2621:19:2;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;2621:19:2;2842:5;;2889:14;;2941:19;;2722:248;;-1:-1:-1;;;;;2722:248:2;;;;;;;;;2842:5;;;2722:248;;;;;;2889:14;;;2722:248;;;;;;2673:18;;;2722:248;;;;;;;;;;;;;;;;;;;;;;;;;;;2621:19;;-1:-1:-1;2673:18:2;;2702:17;;2823:5;;2842;2861:6;;2621:19;;2941;;2722:248;;;;;2621:19;2722:248;;;;;;;;2650:12;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;-1:-1;;2722:248:2;;;;;;;26:21:-1;;;-1:-1;;22:32;6:49;;2722:248:2;;;-1:-1:-1;49:4;25:18;;61:17;;-1:-1;;;;;;;;182:15;;;179:29;160:49;;3063:29:2;;2722:248;;-1:-1:-1;;;;3001:105:2;;-1:-1:-1;3040:53:2;;-1:-1:-1;;;;;;3063:29:2;;-1:-1:-1;3040:22:2;;-1:-1:-1;;;;;;3040:53:2:i;:::-;3095:4;3101;3001:38;:105::i;:::-;3162:29;;3121:71;;;-1:-1:-1;;;;;3162:29:2;;;3121:71;;;;2980:126;;-1:-1:-1;3121:71:2;;;;;;;;;;;;;;;;;;;;;3256:15;;:20;;;;:64;;;3305:15;;3280:21;:40;;3256:64;3252:195;;;3348:15;;3340:24;;-1:-1:-1;;;;;3340:7:2;;;:24;;;;;;;;;3348:15;3340:7;:24;;;;;;;3336:101;;;3406:15;;3389:33;;;;;;;;;;;;;;;;3336:101;3460:20;;:25;;;;:74;;;3514:20;;3489:21;:45;;3460:74;3456:221;;;3565:20;;3554:32;;-1:-1:-1;;;;;3554:10:2;;;:32;;;;;;;;;3565:20;3554:10;:32;;;;;;;3550:117;;;3631:20;;3611:41;;;;;;;;;;;;;;;;3550:117;3693:2;2431:1271;-1:-1:-1;;;;;;2431:1271:2:o;1874:200::-;739:5:12;;-1:-1:-1;;;;;739:5:12;725:10;:19;717:41;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;;;;1953:19:2::1;;1946:3;:26;1943:38;;;1974:7;;1943:38;1990:19;:25:::0;;;2030:37:::1;::::0;;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;768:1:12;1874:200:2::0;:::o;1488:177::-;739:5:12;;-1:-1:-1;;;;;739:5:12;725:10;:19;717:41;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;;;;1563:15:2::1;;1556:3;:22;1553:34;;;1580:7;;1553:34;1596:15;:21:::0;;;1632:26:::1;::::0;;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;1488:177:::0;:::o;1123:226:12:-;1188:12;;-1:-1:-1;;;;;1188:12:12;1174:10;:26;1166:55;;;;;-1:-1:-1;;;1166:55:12;;;;;;;;;;;;-1:-1:-1;;;1166:55:12;;;;;;;;;;;;;;;1264:12;;;1257:5;;1236:41;;-1:-1:-1;;;;;1264:12:12;;;;1257:5;;;;1236:41;;;1295:12;;;;1287:20;;-1:-1:-1;;;;;;1287:20:12;;;-1:-1:-1;;;;;1295:12:12;;1287:20;;;;1317:25;;;1123:226::o;236:20::-;;;-1:-1:-1;;;;;236:20:12;;:::o;986:32:2:-;;;;:::o;813:36::-;;;-1:-1:-1;;;;;813:36:2;;:::o;1024:31::-;;;;:::o;262:27:12:-;;;-1:-1:-1;;;;;262:27:12;;:::o;742:44:2:-;;;-1:-1:-1;;;;;742:44:2;;:::o;1671:197::-;739:5:12;;-1:-1:-1;;;;;739:5:12;725:10;:19;717:41;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;;;;1751:20:2::1;;1744:3;:27;1741:39;;;1773:7;;1741:39;1789:20;:26:::0;;;1830:31:::1;::::0;;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;1671:197:::0;:::o;929:102:12:-;739:5;;-1:-1:-1;;;;;739:5:12;725:10;:19;717:41;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;;;;1001:12:::1;:23:::0;;-1:-1:-1;;;;;;1001:23:12::1;-1:-1:-1::0;;;;;1001:23:12;;;::::1;::::0;;;::::1;::::0;;929:102::o;953:27:2:-;;;;:::o;1061:20::-;;;-1:-1:-1;;;;;1061:20:2;;:::o;1371:393:0:-;1510:13;1535:16;1564:23;1578:8;1564:13;:23::i;:::-;1554:34;;;;;;;1639:114;;;-1:-1:-1;;;;;;1639:114:0;;;;-1:-1:-1;;1639:114:0;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;1639:114:0;;;;1629:125;;;;;;-1:-1:-1;;1371:393:0;;;;;:::o;504:712::-;683:4;677:11;;724:4;714:15;;701:29;;;840:4;827:18;;-1:-1:-1;;;973:4:0;963:15;;956:91;568:17;619;;;;1077:4;1067:15;;1060:36;-1:-1:-1;;;1126:4:0;1116:15;;1109:91;677:11;655:555::o;2256:512::-;2446:11;;2399:21;;2532:4;2446:11;2520:4;2510:15;;2399:21;2499:38;2490:47;-1:-1:-1;;;;;;2564:19:0;;2556:52;;;;;-1:-1:-1;;;2556:52:0;;;;;;;;;;;;-1:-1:-1;;;2556:52:0;;;;;;;;;;;;;;;2622:15;;:20;2618:144;;2659:12;2677:5;-1:-1:-1;;;;;2677:10:0;2688:8;2677:20;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;2677:20:0;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;2658:39:0;;;2719:7;2711:40;;;;;-1:-1:-1;;;2711:40:0;;;;;;;;;;;;-1:-1:-1;;;2711:40:0;;;;;;;;;;;;;;;2618:144;;2256:512;;;;;;:::o", + "source": "pragma solidity 0.6.6;\n\nimport \"openzeppelin-solidity/contracts/token/ERC20/IERC20.sol\";\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\nimport \"./CloneLib.sol\";\nimport \"./IAMB.sol\";\nimport \"./ITokenMediator.sol\";\nimport \"./Ownable.sol\"; // TODO: switch to \"openzeppelin-solidity/contracts/access/Ownable.sol\";\n\ncontract DataUnionFactorySidechain is Ownable{\n event SidechainDUCreated(address indexed mainnet, address indexed sidenet, address indexed owner, address template);\n event UpdateNewDUInitialEth(uint amount);\n event UpdateNewDUOwnerInitialEth(uint amount);\n event UpdateDefaultNewMemberInitialEth(uint amount);\n event DUInitialEthSent(uint amountWei);\n event OwnerInitialEthSent(uint amountWei);\n\n address public data_union_sidechain_template;\n IAMB public amb;\n ITokenMediator public token_mediator;\n \n // when sidechain DU is created, the factory sends a bit of sETH to the DU and the owner\n uint public newDUInitialEth;\n uint public newDUOwnerInitialEth;\n uint public defaultNewMemberEth;\n address public token;\n constructor(address _token, address _token_mediator, address _data_union_sidechain_template) public Ownable(msg.sender) {\n token = _token;\n token_mediator = ITokenMediator(_token_mediator);\n data_union_sidechain_template = _data_union_sidechain_template;\n amb = IAMB(token_mediator.bridgeContract());\n }\n\n //contract is payable\n receive() external payable {}\n\n function setNewDUInitialEth(uint val) public onlyOwner {\n if(val == newDUInitialEth) return;\n newDUInitialEth = val;\n emit UpdateNewDUInitialEth(val);\n }\n\n function setNewDUOwnerInitialEth(uint val) public onlyOwner {\n if(val == newDUOwnerInitialEth) return;\n newDUOwnerInitialEth = val;\n emit UpdateNewDUOwnerInitialEth(val);\n }\n\n function setNewMemberInitialEth(uint val) public onlyOwner {\n if(val == defaultNewMemberEth) return;\n defaultNewMemberEth = val;\n emit UpdateDefaultNewMemberInitialEth(val);\n }\n\n\n function sidechainAddress(address mainet_address)\n public view\n returns (address proxy)\n {\n return CloneLib.predictCloneAddressCreate2(data_union_sidechain_template, address(this), bytes32(uint256(mainet_address)));\n }\n\n /*\n Must be called by AMB. Use MockAMB for testing.\n salt = mainnet_address.\n */\n \n function deployNewDUSidechain(address payable owner, address[] memory agents) public returns (address) {\n require(msg.sender == address(amb), \"only_AMB\");\n address duMainnet = amb.messageSender();\n bytes32 salt = bytes32(uint256(duMainnet));\n bytes memory data = abi.encodeWithSignature(\"initialize(address,address,address[],address,address,uint256)\",\n owner,\n token,\n agents,\n address(token_mediator),\n duMainnet,\n defaultNewMemberEth\n );\n address payable du = CloneLib.deployCodeAndInitUsingCreate2(CloneLib.cloneBytecode(data_union_sidechain_template), data, salt);\n emit SidechainDUCreated(duMainnet, du, owner, data_union_sidechain_template);\n\n // continue whether or not send succeeds\n if (newDUInitialEth != 0 && address(this).balance >= newDUInitialEth) {\n if (du.send(newDUInitialEth)) {\n emit DUInitialEthSent(newDUInitialEth);\n }\n }\n if (newDUOwnerInitialEth != 0 && address(this).balance >= newDUOwnerInitialEth) {\n if (owner.send(newDUOwnerInitialEth)) {\n emit OwnerInitialEthSent(newDUOwnerInitialEth);\n }\n }\n return du;\n }\n}\n", + "sourcePath": "/home/heynow/streamr/data-union-solidity/contracts/DataUnionFactorySidechain.sol", + "ast": { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/DataUnionFactorySidechain.sol", + "exportedSymbols": { + "DataUnionFactorySidechain": [ + 666 + ] + }, + "id": 667, + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 365, + "literals": [ + "solidity", + "0.6", + ".6" + ], + "nodeType": "PragmaDirective", + "src": "0:22:2" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol", + "file": "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol", + "id": 366, + "nodeType": "ImportDirective", + "scope": 667, + "sourceUnit": 4283, + "src": "24:64:2", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "file": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "id": 367, + "nodeType": "ImportDirective", + "scope": 667, + "sourceUnit": 3642, + "src": "89:59:2", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/CloneLib.sol", + "file": "./CloneLib.sol", + "id": 368, + "nodeType": "ImportDirective", + "scope": 667, + "sourceUnit": 155, + "src": "149:24:2", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/IAMB.sol", + "file": "./IAMB.sol", + "id": 369, + "nodeType": "ImportDirective", + "scope": 667, + "sourceUnit": 2913, + "src": "174:20:2", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/ITokenMediator.sol", + "file": "./ITokenMediator.sol", + "id": 370, + "nodeType": "ImportDirective", + "scope": 667, + "sourceUnit": 2969, + "src": "195:30:2", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/Ownable.sol", + "file": "./Ownable.sol", + "id": 371, + "nodeType": "ImportDirective", + "scope": 667, + "sourceUnit": 3181, + "src": "226:23:2", + "symbolAliases": [], + "unitAlias": "" + }, + { + "abstract": false, + "baseContracts": [ + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 372, + "name": "Ownable", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 3180, + "src": "362:7:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_Ownable_$3180", + "typeString": "contract Ownable" + } + }, + "id": 373, + "nodeType": "InheritanceSpecifier", + "src": "362:7:2" + } + ], + "contractDependencies": [ + 3180 + ], + "contractKind": "contract", + "documentation": null, + "fullyImplemented": true, + "id": 666, + "linearizedBaseContracts": [ + 666, + 3180 + ], + "name": "DataUnionFactorySidechain", + "nodeType": "ContractDefinition", + "nodes": [ + { + "anonymous": false, + "documentation": null, + "id": 383, + "name": "SidechainDUCreated", + "nodeType": "EventDefinition", + "parameters": { + "id": 382, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 375, + "indexed": true, + "mutability": "mutable", + "name": "mainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 383, + "src": "400:23:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 374, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "400:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 377, + "indexed": true, + "mutability": "mutable", + "name": "sidenet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 383, + "src": "425:23:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 376, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "425:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 379, + "indexed": true, + "mutability": "mutable", + "name": "owner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 383, + "src": "450:21:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 378, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "450:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 381, + "indexed": false, + "mutability": "mutable", + "name": "template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 383, + "src": "473:16:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 380, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "473:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "399:91:2" + }, + "src": "375:116:2" + }, + { + "anonymous": false, + "documentation": null, + "id": 387, + "name": "UpdateNewDUInitialEth", + "nodeType": "EventDefinition", + "parameters": { + "id": 386, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 385, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 387, + "src": "524:11:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 384, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "524:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "523:13:2" + }, + "src": "496:41:2" + }, + { + "anonymous": false, + "documentation": null, + "id": 391, + "name": "UpdateNewDUOwnerInitialEth", + "nodeType": "EventDefinition", + "parameters": { + "id": 390, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 389, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 391, + "src": "575:11:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 388, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "575:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "574:13:2" + }, + "src": "542:46:2" + }, + { + "anonymous": false, + "documentation": null, + "id": 395, + "name": "UpdateDefaultNewMemberInitialEth", + "nodeType": "EventDefinition", + "parameters": { + "id": 394, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 393, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 395, + "src": "632:11:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 392, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "632:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "631:13:2" + }, + "src": "593:52:2" + }, + { + "anonymous": false, + "documentation": null, + "id": 399, + "name": "DUInitialEthSent", + "nodeType": "EventDefinition", + "parameters": { + "id": 398, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 397, + "indexed": false, + "mutability": "mutable", + "name": "amountWei", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 399, + "src": "673:14:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 396, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "673:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "672:16:2" + }, + "src": "650:39:2" + }, + { + "anonymous": false, + "documentation": null, + "id": 403, + "name": "OwnerInitialEthSent", + "nodeType": "EventDefinition", + "parameters": { + "id": 402, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 401, + "indexed": false, + "mutability": "mutable", + "name": "amountWei", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 403, + "src": "720:14:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 400, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "720:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "719:16:2" + }, + "src": "694:42:2" + }, + { + "constant": false, + "functionSelector": "e4a154a4", + "id": 405, + "mutability": "mutable", + "name": "data_union_sidechain_template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "742:44:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 404, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "742:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "1062b39a", + "id": 407, + "mutability": "mutable", + "name": "amb", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "792:15:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + }, + "typeName": { + "contractScope": null, + "id": 406, + "name": "IAMB", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2912, + "src": "792:4:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "c5a8c91f", + "id": 409, + "mutability": "mutable", + "name": "token_mediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "813:36:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + }, + "typeName": { + "contractScope": null, + "id": 408, + "name": "ITokenMediator", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2968, + "src": "813:14:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "f7c1329e", + "id": 411, + "mutability": "mutable", + "name": "newDUInitialEth", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "953:27:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 410, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "953:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "afc6224b", + "id": 413, + "mutability": "mutable", + "name": "newDUOwnerInitialEth", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "986:32:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 412, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "986:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "e22ab5ae", + "id": 415, + "mutability": "mutable", + "name": "defaultNewMemberEth", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "1024:31:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 414, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1024:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "fc0c546a", + "id": 417, + "mutability": "mutable", + "name": "token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "1061:20:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 416, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1061:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "body": { + "id": 452, + "nodeType": "Block", + "src": "1207:214:2", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 432, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 430, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 417, + "src": "1217:5:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 431, + "name": "_token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 419, + "src": "1225:6:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1217:14:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 433, + "nodeType": "ExpressionStatement", + "src": "1217:14:2" + }, + { + "expression": { + "argumentTypes": null, + "id": 438, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 434, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 409, + "src": "1241:14:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 436, + "name": "_token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 421, + "src": "1273:15:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 435, + "name": "ITokenMediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2968, + "src": "1258:14:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_ITokenMediator_$2968_$", + "typeString": "type(contract ITokenMediator)" + } + }, + "id": 437, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1258:31:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "src": "1241:48:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 439, + "nodeType": "ExpressionStatement", + "src": "1241:48:2" + }, + { + "expression": { + "argumentTypes": null, + "id": 442, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 440, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 405, + "src": "1299:29:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 441, + "name": "_data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 423, + "src": "1331:30:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1299:62:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 443, + "nodeType": "ExpressionStatement", + "src": "1299:62:2" + }, + { + "expression": { + "argumentTypes": null, + "id": 450, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 444, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 407, + "src": "1371:3:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "argumentTypes": null, + "id": 446, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 409, + "src": "1382:14:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 447, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "bridgeContract", + "nodeType": "MemberAccess", + "referencedDeclaration": 2946, + "src": "1382:29:2", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$__$returns$_t_address_$", + "typeString": "function () view external returns (address)" + } + }, + "id": 448, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1382:31:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 445, + "name": "IAMB", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2912, + "src": "1377:4:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_IAMB_$2912_$", + "typeString": "type(contract IAMB)" + } + }, + "id": 449, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1377:37:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "src": "1371:43:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "id": 451, + "nodeType": "ExpressionStatement", + "src": "1371:43:2" + } + ] + }, + "documentation": null, + "id": 453, + "implemented": true, + "kind": "constructor", + "modifiers": [ + { + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 426, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "1195:3:2", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 427, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "1195:10:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "id": 428, + "modifierName": { + "argumentTypes": null, + "id": 425, + "name": "Ownable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3180, + "src": "1187:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_Ownable_$3180_$", + "typeString": "type(contract Ownable)" + } + }, + "nodeType": "ModifierInvocation", + "src": "1187:19:2" + } + ], + "name": "", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 424, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 419, + "mutability": "mutable", + "name": "_token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 453, + "src": "1099:14:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 418, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1099:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 421, + "mutability": "mutable", + "name": "_token_mediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 453, + "src": "1115:23:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 420, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1115:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 423, + "mutability": "mutable", + "name": "_data_union_sidechain_template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 453, + "src": "1140:38:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 422, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1140:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1098:81:2" + }, + "returnParameters": { + "id": 429, + "nodeType": "ParameterList", + "parameters": [], + "src": "1207:0:2" + }, + "scope": 666, + "src": "1087:334:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 456, + "nodeType": "Block", + "src": "1480:2:2", + "statements": [] + }, + "documentation": null, + "id": 457, + "implemented": true, + "kind": "receive", + "modifiers": [], + "name": "", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 454, + "nodeType": "ParameterList", + "parameters": [], + "src": "1460:2:2" + }, + "returnParameters": { + "id": 455, + "nodeType": "ParameterList", + "parameters": [], + "src": "1480:0:2" + }, + "scope": 666, + "src": "1453:29:2", + "stateMutability": "payable", + "virtual": false, + "visibility": "external" + }, + { + "body": { + "id": 477, + "nodeType": "Block", + "src": "1543:122:2", + "statements": [ + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 466, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 464, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 459, + "src": "1556:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 465, + "name": "newDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 411, + "src": "1563:15:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1556:22:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 468, + "nodeType": "IfStatement", + "src": "1553:34:2", + "trueBody": { + "expression": null, + "functionReturnParameters": 463, + "id": 467, + "nodeType": "Return", + "src": "1580:7:2" + } + }, + { + "expression": { + "argumentTypes": null, + "id": 471, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 469, + "name": "newDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 411, + "src": "1596:15:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 470, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 459, + "src": "1614:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1596:21:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 472, + "nodeType": "ExpressionStatement", + "src": "1596:21:2" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 474, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 459, + "src": "1654:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 473, + "name": "UpdateNewDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 387, + "src": "1632:21:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 475, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1632:26:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 476, + "nodeType": "EmitStatement", + "src": "1627:31:2" + } + ] + }, + "documentation": null, + "functionSelector": "4e51a863", + "id": 478, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 462, + "modifierName": { + "argumentTypes": null, + "id": 461, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "1533:9:2", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "1533:9:2" + } + ], + "name": "setNewDUInitialEth", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 460, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 459, + "mutability": "mutable", + "name": "val", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 478, + "src": "1516:8:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 458, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1516:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1515:10:2" + }, + "returnParameters": { + "id": 463, + "nodeType": "ParameterList", + "parameters": [], + "src": "1543:0:2" + }, + "scope": 666, + "src": "1488:177:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 498, + "nodeType": "Block", + "src": "1731:137:2", + "statements": [ + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 487, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 485, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 480, + "src": "1744:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 486, + "name": "newDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 413, + "src": "1751:20:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1744:27:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 489, + "nodeType": "IfStatement", + "src": "1741:39:2", + "trueBody": { + "expression": null, + "functionReturnParameters": 484, + "id": 488, + "nodeType": "Return", + "src": "1773:7:2" + } + }, + { + "expression": { + "argumentTypes": null, + "id": 492, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 490, + "name": "newDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 413, + "src": "1789:20:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 491, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 480, + "src": "1812:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1789:26:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 493, + "nodeType": "ExpressionStatement", + "src": "1789:26:2" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 495, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 480, + "src": "1857:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 494, + "name": "UpdateNewDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 391, + "src": "1830:26:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 496, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1830:31:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 497, + "nodeType": "EmitStatement", + "src": "1825:36:2" + } + ] + }, + "documentation": null, + "functionSelector": "f0ef0b06", + "id": 499, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 483, + "modifierName": { + "argumentTypes": null, + "id": 482, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "1721:9:2", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "1721:9:2" + } + ], + "name": "setNewDUOwnerInitialEth", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 481, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 480, + "mutability": "mutable", + "name": "val", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 499, + "src": "1704:8:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 479, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1704:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1703:10:2" + }, + "returnParameters": { + "id": 484, + "nodeType": "ParameterList", + "parameters": [], + "src": "1731:0:2" + }, + "scope": 666, + "src": "1671:197:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 519, + "nodeType": "Block", + "src": "1933:141:2", + "statements": [ + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 508, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 506, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 501, + "src": "1946:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 507, + "name": "defaultNewMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 415, + "src": "1953:19:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1946:26:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 510, + "nodeType": "IfStatement", + "src": "1943:38:2", + "trueBody": { + "expression": null, + "functionReturnParameters": 505, + "id": 509, + "nodeType": "Return", + "src": "1974:7:2" + } + }, + { + "expression": { + "argumentTypes": null, + "id": 513, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 511, + "name": "defaultNewMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 415, + "src": "1990:19:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 512, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 501, + "src": "2012:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1990:25:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 514, + "nodeType": "ExpressionStatement", + "src": "1990:25:2" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 516, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 501, + "src": "2063:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 515, + "name": "UpdateDefaultNewMemberInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 395, + "src": "2030:32:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 517, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2030:37:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 518, + "nodeType": "EmitStatement", + "src": "2025:42:2" + } + ] + }, + "documentation": null, + "functionSelector": "37dd8b05", + "id": 520, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 504, + "modifierName": { + "argumentTypes": null, + "id": 503, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "1923:9:2", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "1923:9:2" + } + ], + "name": "setNewMemberInitialEth", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 502, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 501, + "mutability": "mutable", + "name": "val", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 520, + "src": "1906:8:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 500, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1906:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1905:10:2" + }, + "returnParameters": { + "id": 505, + "nodeType": "ParameterList", + "parameters": [], + "src": "1933:0:2" + }, + "scope": 666, + "src": "1874:200:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 543, + "nodeType": "Block", + "src": "2187:139:2", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 529, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 405, + "src": "2240:29:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 532, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "2279:4:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionFactorySidechain_$666", + "typeString": "contract DataUnionFactorySidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionFactorySidechain_$666", + "typeString": "contract DataUnionFactorySidechain" + } + ], + "id": 531, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2271:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 530, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2271:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 533, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2271:13:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 538, + "name": "mainet_address", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 522, + "src": "2302:14:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 537, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2294:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 536, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2294:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 539, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2294:23:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 535, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2286:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes32_$", + "typeString": "type(bytes32)" + }, + "typeName": { + "id": 534, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "2286:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 540, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2286:32:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "argumentTypes": null, + "id": 527, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "2204:8:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 528, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "predictCloneAddressCreate2", + "nodeType": "MemberAccess", + "referencedDeclaration": 61, + "src": "2204:35:2", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$_t_address_$_t_bytes32_$returns$_t_address_$", + "typeString": "function (address,address,bytes32) pure returns (address)" + } + }, + "id": 541, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2204:115:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 526, + "id": 542, + "nodeType": "Return", + "src": "2197:122:2" + } + ] + }, + "documentation": null, + "functionSelector": "17c2a98c", + "id": 544, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "sidechainAddress", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 523, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 522, + "mutability": "mutable", + "name": "mainet_address", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 544, + "src": "2107:22:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 521, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2107:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2106:24:2" + }, + "returnParameters": { + "id": 526, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 525, + "mutability": "mutable", + "name": "proxy", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 544, + "src": "2168:13:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 524, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2168:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2167:15:2" + }, + "scope": 666, + "src": "2081:245:2", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 664, + "nodeType": "Block", + "src": "2534:1168:2", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 561, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 555, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "2552:3:2", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 556, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2552:10:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 559, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 407, + "src": "2574:3:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + ], + "id": 558, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2566:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 557, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2566:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 560, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2566:12:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2552:26:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6f6e6c795f414d42", + "id": 562, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2580:10:2", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_7698dac7a74e78fd5d71d9ff5c3f048a6bfa330cbd49f847a9726ba9ad094965", + "typeString": "literal_string \"only_AMB\"" + }, + "value": "only_AMB" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_7698dac7a74e78fd5d71d9ff5c3f048a6bfa330cbd49f847a9726ba9ad094965", + "typeString": "literal_string \"only_AMB\"" + } + ], + "id": 554, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "2544:7:2", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 563, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2544:47:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 564, + "nodeType": "ExpressionStatement", + "src": "2544:47:2" + }, + { + "assignments": [ + 566 + ], + "declarations": [ + { + "constant": false, + "id": 566, + "mutability": "mutable", + "name": "duMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 664, + "src": "2601:17:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 565, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2601:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 570, + "initialValue": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "argumentTypes": null, + "id": 567, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 407, + "src": "2621:3:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "id": 568, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "messageSender", + "nodeType": "MemberAccess", + "referencedDeclaration": 2852, + "src": "2621:17:2", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$__$returns$_t_address_$", + "typeString": "function () view external returns (address)" + } + }, + "id": 569, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2621:19:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2601:39:2" + }, + { + "assignments": [ + 572 + ], + "declarations": [ + { + "constant": false, + "id": 572, + "mutability": "mutable", + "name": "salt", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 664, + "src": "2650:12:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 571, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "2650:7:2", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 580, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 577, + "name": "duMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 566, + "src": "2681:9:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 576, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2673:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 575, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2673:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 578, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2673:18:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 574, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2665:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes32_$", + "typeString": "type(bytes32)" + }, + "typeName": { + "id": 573, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "2665:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 579, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2665:27:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2650:42:2" + }, + { + "assignments": [ + 582 + ], + "declarations": [ + { + "constant": false, + "id": 582, + "mutability": "mutable", + "name": "data", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 664, + "src": "2702:17:2", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 581, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "2702:5:2", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 596, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "696e697469616c697a6528616464726573732c616464726573732c616464726573735b5d2c616464726573732c616464726573732c75696e7432353629", + "id": 585, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2746:63:2", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_015c7f51e2589abfef5a1063cf7321fa0da4fb1756a7b671e8b1ca6858d2b75f", + "typeString": "literal_string \"initialize(address,address,address[],address,address,uint256)\"" + }, + "value": "initialize(address,address,address[],address,address,uint256)" + }, + { + "argumentTypes": null, + "id": 586, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 546, + "src": "2823:5:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 587, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 417, + "src": "2842:5:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 588, + "name": "agents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 549, + "src": "2861:6:2", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 591, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 409, + "src": "2889:14:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + ], + "id": 590, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2881:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 589, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2881:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 592, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2881:23:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 593, + "name": "duMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 566, + "src": "2918:9:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 594, + "name": "defaultNewMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 415, + "src": "2941:19:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_015c7f51e2589abfef5a1063cf7321fa0da4fb1756a7b671e8b1ca6858d2b75f", + "typeString": "literal_string \"initialize(address,address,address[],address,address,uint256)\"" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 583, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "2722:3:2", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 584, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encodeWithSignature", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2722:23:2", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (string memory) pure returns (bytes memory)" + } + }, + "id": 595, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2722:248:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2702:268:2" + }, + { + "assignments": [ + 598 + ], + "declarations": [ + { + "constant": false, + "id": 598, + "mutability": "mutable", + "name": "du", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 664, + "src": "2980:18:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + "typeName": { + "id": 597, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2980:15:2", + "stateMutability": "payable", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 608, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 603, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 405, + "src": "3063:29:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "argumentTypes": null, + "id": 601, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "3040:8:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 602, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "cloneBytecode", + "nodeType": "MemberAccess", + "referencedDeclaration": 18, + "src": "3040:22:2", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (address) pure returns (bytes memory)" + } + }, + "id": 604, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3040:53:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 605, + "name": "data", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 582, + "src": "3095:4:2", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 606, + "name": "salt", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 572, + "src": "3101:4:2", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "argumentTypes": null, + "id": 599, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "3001:8:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 600, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "deployCodeAndInitUsingCreate2", + "nodeType": "MemberAccess", + "referencedDeclaration": 108, + "src": "3001:38:2", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_bytes_memory_ptr_$_t_bytes_memory_ptr_$_t_bytes32_$returns$_t_address_payable_$", + "typeString": "function (bytes memory,bytes memory,bytes32) returns (address payable)" + } + }, + "id": 607, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3001:105:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2980:126:2" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 610, + "name": "duMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 566, + "src": "3140:9:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 611, + "name": "du", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 598, + "src": "3151:2:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 612, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 546, + "src": "3155:5:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 613, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 405, + "src": "3162:29:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 609, + "name": "SidechainDUCreated", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 383, + "src": "3121:18:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_address_$_t_address_$_t_address_$returns$__$", + "typeString": "function (address,address,address,address)" + } + }, + "id": 614, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3121:71:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 615, + "nodeType": "EmitStatement", + "src": "3116:76:2" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 626, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 618, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 616, + "name": "newDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 411, + "src": "3256:15:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 617, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3275:1:2", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "3256:20:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "&&", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 625, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 621, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "3288:4:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionFactorySidechain_$666", + "typeString": "contract DataUnionFactorySidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionFactorySidechain_$666", + "typeString": "contract DataUnionFactorySidechain" + } + ], + "id": 620, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "3280:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 619, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3280:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 622, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3280:13:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 623, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balance", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3280:21:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": ">=", + "rightExpression": { + "argumentTypes": null, + "id": 624, + "name": "newDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 411, + "src": "3305:15:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "3280:40:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "3256:64:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 638, + "nodeType": "IfStatement", + "src": "3252:195:2", + "trueBody": { + "id": 637, + "nodeType": "Block", + "src": "3322:125:2", + "statements": [ + { + "condition": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 629, + "name": "newDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 411, + "src": "3348:15:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 627, + "name": "du", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 598, + "src": "3340:2:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 628, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "send", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3340:7:2", + "typeDescriptions": { + "typeIdentifier": "t_function_send_nonpayable$_t_uint256_$returns$_t_bool_$", + "typeString": "function (uint256) returns (bool)" + } + }, + "id": 630, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3340:24:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 636, + "nodeType": "IfStatement", + "src": "3336:101:2", + "trueBody": { + "id": 635, + "nodeType": "Block", + "src": "3366:71:2", + "statements": [ + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 632, + "name": "newDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 411, + "src": "3406:15:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 631, + "name": "DUInitialEthSent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 399, + "src": "3389:16:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 633, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3389:33:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 634, + "nodeType": "EmitStatement", + "src": "3384:38:2" + } + ] + } + } + ] + } + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 649, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 641, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 639, + "name": "newDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 413, + "src": "3460:20:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 640, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3484:1:2", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "3460:25:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "&&", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 648, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 644, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "3497:4:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionFactorySidechain_$666", + "typeString": "contract DataUnionFactorySidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionFactorySidechain_$666", + "typeString": "contract DataUnionFactorySidechain" + } + ], + "id": 643, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "3489:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 642, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3489:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 645, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3489:13:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 646, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balance", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3489:21:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": ">=", + "rightExpression": { + "argumentTypes": null, + "id": 647, + "name": "newDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 413, + "src": "3514:20:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "3489:45:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "3460:74:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 661, + "nodeType": "IfStatement", + "src": "3456:221:2", + "trueBody": { + "id": 660, + "nodeType": "Block", + "src": "3536:141:2", + "statements": [ + { + "condition": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 652, + "name": "newDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 413, + "src": "3565:20:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 650, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 546, + "src": "3554:5:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 651, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "send", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3554:10:2", + "typeDescriptions": { + "typeIdentifier": "t_function_send_nonpayable$_t_uint256_$returns$_t_bool_$", + "typeString": "function (uint256) returns (bool)" + } + }, + "id": 653, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3554:32:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 659, + "nodeType": "IfStatement", + "src": "3550:117:2", + "trueBody": { + "id": 658, + "nodeType": "Block", + "src": "3588:79:2", + "statements": [ + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 655, + "name": "newDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 413, + "src": "3631:20:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 654, + "name": "OwnerInitialEthSent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 403, + "src": "3611:19:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 656, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3611:41:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 657, + "nodeType": "EmitStatement", + "src": "3606:46:2" + } + ] + } + } + ] + } + }, + { + "expression": { + "argumentTypes": null, + "id": 662, + "name": "du", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 598, + "src": "3693:2:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "functionReturnParameters": 553, + "id": 663, + "nodeType": "Return", + "src": "3686:9:2" + } + ] + }, + "documentation": null, + "functionSelector": "325ff66f", + "id": 665, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "deployNewDUSidechain", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 550, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 546, + "mutability": "mutable", + "name": "owner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 665, + "src": "2461:21:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + "typeName": { + "id": 545, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2461:15:2", + "stateMutability": "payable", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 549, + "mutability": "mutable", + "name": "agents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 665, + "src": "2484:23:2", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 547, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2484:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 548, + "length": null, + "nodeType": "ArrayTypeName", + "src": "2484:9:2", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2460:48:2" + }, + "returnParameters": { + "id": 553, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 552, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 665, + "src": "2525:7:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 551, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2525:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2524:9:2" + }, + "scope": 666, + "src": "2431:1271:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + } + ], + "scope": 667, + "src": "324:3380:2" + } + ], + "src": "0:3705:2" + }, + "legacyAST": { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/DataUnionFactorySidechain.sol", + "exportedSymbols": { + "DataUnionFactorySidechain": [ + 666 + ] + }, + "id": 667, + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 365, + "literals": [ + "solidity", + "0.6", + ".6" + ], + "nodeType": "PragmaDirective", + "src": "0:22:2" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol", + "file": "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol", + "id": 366, + "nodeType": "ImportDirective", + "scope": 667, + "sourceUnit": 4283, + "src": "24:64:2", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "file": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "id": 367, + "nodeType": "ImportDirective", + "scope": 667, + "sourceUnit": 3642, + "src": "89:59:2", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/CloneLib.sol", + "file": "./CloneLib.sol", + "id": 368, + "nodeType": "ImportDirective", + "scope": 667, + "sourceUnit": 155, + "src": "149:24:2", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/IAMB.sol", + "file": "./IAMB.sol", + "id": 369, + "nodeType": "ImportDirective", + "scope": 667, + "sourceUnit": 2913, + "src": "174:20:2", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/ITokenMediator.sol", + "file": "./ITokenMediator.sol", + "id": 370, + "nodeType": "ImportDirective", + "scope": 667, + "sourceUnit": 2969, + "src": "195:30:2", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/Ownable.sol", + "file": "./Ownable.sol", + "id": 371, + "nodeType": "ImportDirective", + "scope": 667, + "sourceUnit": 3181, + "src": "226:23:2", + "symbolAliases": [], + "unitAlias": "" + }, + { + "abstract": false, + "baseContracts": [ + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 372, + "name": "Ownable", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 3180, + "src": "362:7:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_Ownable_$3180", + "typeString": "contract Ownable" + } + }, + "id": 373, + "nodeType": "InheritanceSpecifier", + "src": "362:7:2" + } + ], + "contractDependencies": [ + 3180 + ], + "contractKind": "contract", + "documentation": null, + "fullyImplemented": true, + "id": 666, + "linearizedBaseContracts": [ + 666, + 3180 + ], + "name": "DataUnionFactorySidechain", + "nodeType": "ContractDefinition", + "nodes": [ + { + "anonymous": false, + "documentation": null, + "id": 383, + "name": "SidechainDUCreated", + "nodeType": "EventDefinition", + "parameters": { + "id": 382, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 375, + "indexed": true, + "mutability": "mutable", + "name": "mainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 383, + "src": "400:23:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 374, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "400:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 377, + "indexed": true, + "mutability": "mutable", + "name": "sidenet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 383, + "src": "425:23:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 376, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "425:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 379, + "indexed": true, + "mutability": "mutable", + "name": "owner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 383, + "src": "450:21:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 378, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "450:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 381, + "indexed": false, + "mutability": "mutable", + "name": "template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 383, + "src": "473:16:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 380, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "473:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "399:91:2" + }, + "src": "375:116:2" + }, + { + "anonymous": false, + "documentation": null, + "id": 387, + "name": "UpdateNewDUInitialEth", + "nodeType": "EventDefinition", + "parameters": { + "id": 386, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 385, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 387, + "src": "524:11:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 384, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "524:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "523:13:2" + }, + "src": "496:41:2" + }, + { + "anonymous": false, + "documentation": null, + "id": 391, + "name": "UpdateNewDUOwnerInitialEth", + "nodeType": "EventDefinition", + "parameters": { + "id": 390, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 389, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 391, + "src": "575:11:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 388, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "575:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "574:13:2" + }, + "src": "542:46:2" + }, + { + "anonymous": false, + "documentation": null, + "id": 395, + "name": "UpdateDefaultNewMemberInitialEth", + "nodeType": "EventDefinition", + "parameters": { + "id": 394, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 393, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 395, + "src": "632:11:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 392, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "632:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "631:13:2" + }, + "src": "593:52:2" + }, + { + "anonymous": false, + "documentation": null, + "id": 399, + "name": "DUInitialEthSent", + "nodeType": "EventDefinition", + "parameters": { + "id": 398, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 397, + "indexed": false, + "mutability": "mutable", + "name": "amountWei", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 399, + "src": "673:14:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 396, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "673:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "672:16:2" + }, + "src": "650:39:2" + }, + { + "anonymous": false, + "documentation": null, + "id": 403, + "name": "OwnerInitialEthSent", + "nodeType": "EventDefinition", + "parameters": { + "id": 402, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 401, + "indexed": false, + "mutability": "mutable", + "name": "amountWei", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 403, + "src": "720:14:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 400, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "720:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "719:16:2" + }, + "src": "694:42:2" + }, + { + "constant": false, + "functionSelector": "e4a154a4", + "id": 405, + "mutability": "mutable", + "name": "data_union_sidechain_template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "742:44:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 404, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "742:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "1062b39a", + "id": 407, + "mutability": "mutable", + "name": "amb", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "792:15:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + }, + "typeName": { + "contractScope": null, + "id": 406, + "name": "IAMB", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2912, + "src": "792:4:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "c5a8c91f", + "id": 409, + "mutability": "mutable", + "name": "token_mediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "813:36:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + }, + "typeName": { + "contractScope": null, + "id": 408, + "name": "ITokenMediator", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2968, + "src": "813:14:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "f7c1329e", + "id": 411, + "mutability": "mutable", + "name": "newDUInitialEth", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "953:27:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 410, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "953:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "afc6224b", + "id": 413, + "mutability": "mutable", + "name": "newDUOwnerInitialEth", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "986:32:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 412, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "986:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "e22ab5ae", + "id": 415, + "mutability": "mutable", + "name": "defaultNewMemberEth", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "1024:31:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 414, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1024:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "fc0c546a", + "id": 417, + "mutability": "mutable", + "name": "token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 666, + "src": "1061:20:2", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 416, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1061:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "body": { + "id": 452, + "nodeType": "Block", + "src": "1207:214:2", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 432, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 430, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 417, + "src": "1217:5:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 431, + "name": "_token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 419, + "src": "1225:6:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1217:14:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 433, + "nodeType": "ExpressionStatement", + "src": "1217:14:2" + }, + { + "expression": { + "argumentTypes": null, + "id": 438, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 434, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 409, + "src": "1241:14:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 436, + "name": "_token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 421, + "src": "1273:15:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 435, + "name": "ITokenMediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2968, + "src": "1258:14:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_ITokenMediator_$2968_$", + "typeString": "type(contract ITokenMediator)" + } + }, + "id": 437, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1258:31:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "src": "1241:48:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 439, + "nodeType": "ExpressionStatement", + "src": "1241:48:2" + }, + { + "expression": { + "argumentTypes": null, + "id": 442, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 440, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 405, + "src": "1299:29:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 441, + "name": "_data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 423, + "src": "1331:30:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1299:62:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 443, + "nodeType": "ExpressionStatement", + "src": "1299:62:2" + }, + { + "expression": { + "argumentTypes": null, + "id": 450, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 444, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 407, + "src": "1371:3:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "argumentTypes": null, + "id": 446, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 409, + "src": "1382:14:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 447, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "bridgeContract", + "nodeType": "MemberAccess", + "referencedDeclaration": 2946, + "src": "1382:29:2", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$__$returns$_t_address_$", + "typeString": "function () view external returns (address)" + } + }, + "id": 448, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1382:31:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 445, + "name": "IAMB", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2912, + "src": "1377:4:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_IAMB_$2912_$", + "typeString": "type(contract IAMB)" + } + }, + "id": 449, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1377:37:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "src": "1371:43:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "id": 451, + "nodeType": "ExpressionStatement", + "src": "1371:43:2" + } + ] + }, + "documentation": null, + "id": 453, + "implemented": true, + "kind": "constructor", + "modifiers": [ + { + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 426, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "1195:3:2", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 427, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "1195:10:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "id": 428, + "modifierName": { + "argumentTypes": null, + "id": 425, + "name": "Ownable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3180, + "src": "1187:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_Ownable_$3180_$", + "typeString": "type(contract Ownable)" + } + }, + "nodeType": "ModifierInvocation", + "src": "1187:19:2" + } + ], + "name": "", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 424, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 419, + "mutability": "mutable", + "name": "_token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 453, + "src": "1099:14:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 418, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1099:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 421, + "mutability": "mutable", + "name": "_token_mediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 453, + "src": "1115:23:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 420, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1115:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 423, + "mutability": "mutable", + "name": "_data_union_sidechain_template", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 453, + "src": "1140:38:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 422, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1140:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1098:81:2" + }, + "returnParameters": { + "id": 429, + "nodeType": "ParameterList", + "parameters": [], + "src": "1207:0:2" + }, + "scope": 666, + "src": "1087:334:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 456, + "nodeType": "Block", + "src": "1480:2:2", + "statements": [] + }, + "documentation": null, + "id": 457, + "implemented": true, + "kind": "receive", + "modifiers": [], + "name": "", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 454, + "nodeType": "ParameterList", + "parameters": [], + "src": "1460:2:2" + }, + "returnParameters": { + "id": 455, + "nodeType": "ParameterList", + "parameters": [], + "src": "1480:0:2" + }, + "scope": 666, + "src": "1453:29:2", + "stateMutability": "payable", + "virtual": false, + "visibility": "external" + }, + { + "body": { + "id": 477, + "nodeType": "Block", + "src": "1543:122:2", + "statements": [ + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 466, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 464, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 459, + "src": "1556:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 465, + "name": "newDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 411, + "src": "1563:15:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1556:22:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 468, + "nodeType": "IfStatement", + "src": "1553:34:2", + "trueBody": { + "expression": null, + "functionReturnParameters": 463, + "id": 467, + "nodeType": "Return", + "src": "1580:7:2" + } + }, + { + "expression": { + "argumentTypes": null, + "id": 471, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 469, + "name": "newDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 411, + "src": "1596:15:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 470, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 459, + "src": "1614:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1596:21:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 472, + "nodeType": "ExpressionStatement", + "src": "1596:21:2" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 474, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 459, + "src": "1654:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 473, + "name": "UpdateNewDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 387, + "src": "1632:21:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 475, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1632:26:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 476, + "nodeType": "EmitStatement", + "src": "1627:31:2" + } + ] + }, + "documentation": null, + "functionSelector": "4e51a863", + "id": 478, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 462, + "modifierName": { + "argumentTypes": null, + "id": 461, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "1533:9:2", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "1533:9:2" + } + ], + "name": "setNewDUInitialEth", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 460, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 459, + "mutability": "mutable", + "name": "val", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 478, + "src": "1516:8:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 458, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1516:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1515:10:2" + }, + "returnParameters": { + "id": 463, + "nodeType": "ParameterList", + "parameters": [], + "src": "1543:0:2" + }, + "scope": 666, + "src": "1488:177:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 498, + "nodeType": "Block", + "src": "1731:137:2", + "statements": [ + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 487, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 485, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 480, + "src": "1744:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 486, + "name": "newDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 413, + "src": "1751:20:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1744:27:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 489, + "nodeType": "IfStatement", + "src": "1741:39:2", + "trueBody": { + "expression": null, + "functionReturnParameters": 484, + "id": 488, + "nodeType": "Return", + "src": "1773:7:2" + } + }, + { + "expression": { + "argumentTypes": null, + "id": 492, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 490, + "name": "newDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 413, + "src": "1789:20:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 491, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 480, + "src": "1812:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1789:26:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 493, + "nodeType": "ExpressionStatement", + "src": "1789:26:2" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 495, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 480, + "src": "1857:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 494, + "name": "UpdateNewDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 391, + "src": "1830:26:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 496, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1830:31:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 497, + "nodeType": "EmitStatement", + "src": "1825:36:2" + } + ] + }, + "documentation": null, + "functionSelector": "f0ef0b06", + "id": 499, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 483, + "modifierName": { + "argumentTypes": null, + "id": 482, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "1721:9:2", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "1721:9:2" + } + ], + "name": "setNewDUOwnerInitialEth", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 481, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 480, + "mutability": "mutable", + "name": "val", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 499, + "src": "1704:8:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 479, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1704:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1703:10:2" + }, + "returnParameters": { + "id": 484, + "nodeType": "ParameterList", + "parameters": [], + "src": "1731:0:2" + }, + "scope": 666, + "src": "1671:197:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 519, + "nodeType": "Block", + "src": "1933:141:2", + "statements": [ + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 508, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 506, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 501, + "src": "1946:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 507, + "name": "defaultNewMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 415, + "src": "1953:19:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1946:26:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 510, + "nodeType": "IfStatement", + "src": "1943:38:2", + "trueBody": { + "expression": null, + "functionReturnParameters": 505, + "id": 509, + "nodeType": "Return", + "src": "1974:7:2" + } + }, + { + "expression": { + "argumentTypes": null, + "id": 513, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 511, + "name": "defaultNewMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 415, + "src": "1990:19:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 512, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 501, + "src": "2012:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "1990:25:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 514, + "nodeType": "ExpressionStatement", + "src": "1990:25:2" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 516, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 501, + "src": "2063:3:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 515, + "name": "UpdateDefaultNewMemberInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 395, + "src": "2030:32:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 517, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2030:37:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 518, + "nodeType": "EmitStatement", + "src": "2025:42:2" + } + ] + }, + "documentation": null, + "functionSelector": "37dd8b05", + "id": 520, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 504, + "modifierName": { + "argumentTypes": null, + "id": 503, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "1923:9:2", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "1923:9:2" + } + ], + "name": "setNewMemberInitialEth", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 502, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 501, + "mutability": "mutable", + "name": "val", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 520, + "src": "1906:8:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 500, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1906:4:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1905:10:2" + }, + "returnParameters": { + "id": 505, + "nodeType": "ParameterList", + "parameters": [], + "src": "1933:0:2" + }, + "scope": 666, + "src": "1874:200:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 543, + "nodeType": "Block", + "src": "2187:139:2", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 529, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 405, + "src": "2240:29:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 532, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "2279:4:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionFactorySidechain_$666", + "typeString": "contract DataUnionFactorySidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionFactorySidechain_$666", + "typeString": "contract DataUnionFactorySidechain" + } + ], + "id": 531, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2271:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 530, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2271:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 533, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2271:13:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 538, + "name": "mainet_address", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 522, + "src": "2302:14:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 537, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2294:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 536, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2294:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 539, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2294:23:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 535, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2286:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes32_$", + "typeString": "type(bytes32)" + }, + "typeName": { + "id": 534, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "2286:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 540, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2286:32:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "argumentTypes": null, + "id": 527, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "2204:8:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 528, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "predictCloneAddressCreate2", + "nodeType": "MemberAccess", + "referencedDeclaration": 61, + "src": "2204:35:2", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$_t_address_$_t_bytes32_$returns$_t_address_$", + "typeString": "function (address,address,bytes32) pure returns (address)" + } + }, + "id": 541, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2204:115:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 526, + "id": 542, + "nodeType": "Return", + "src": "2197:122:2" + } + ] + }, + "documentation": null, + "functionSelector": "17c2a98c", + "id": 544, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "sidechainAddress", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 523, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 522, + "mutability": "mutable", + "name": "mainet_address", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 544, + "src": "2107:22:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 521, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2107:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2106:24:2" + }, + "returnParameters": { + "id": 526, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 525, + "mutability": "mutable", + "name": "proxy", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 544, + "src": "2168:13:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 524, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2168:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2167:15:2" + }, + "scope": 666, + "src": "2081:245:2", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 664, + "nodeType": "Block", + "src": "2534:1168:2", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 561, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 555, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "2552:3:2", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 556, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2552:10:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 559, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 407, + "src": "2574:3:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + ], + "id": 558, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2566:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 557, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2566:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 560, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2566:12:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2552:26:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6f6e6c795f414d42", + "id": 562, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2580:10:2", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_7698dac7a74e78fd5d71d9ff5c3f048a6bfa330cbd49f847a9726ba9ad094965", + "typeString": "literal_string \"only_AMB\"" + }, + "value": "only_AMB" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_7698dac7a74e78fd5d71d9ff5c3f048a6bfa330cbd49f847a9726ba9ad094965", + "typeString": "literal_string \"only_AMB\"" + } + ], + "id": 554, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "2544:7:2", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 563, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2544:47:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 564, + "nodeType": "ExpressionStatement", + "src": "2544:47:2" + }, + { + "assignments": [ + 566 + ], + "declarations": [ + { + "constant": false, + "id": 566, + "mutability": "mutable", + "name": "duMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 664, + "src": "2601:17:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 565, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2601:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 570, + "initialValue": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "argumentTypes": null, + "id": 567, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 407, + "src": "2621:3:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "id": 568, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "messageSender", + "nodeType": "MemberAccess", + "referencedDeclaration": 2852, + "src": "2621:17:2", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$__$returns$_t_address_$", + "typeString": "function () view external returns (address)" + } + }, + "id": 569, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2621:19:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2601:39:2" + }, + { + "assignments": [ + 572 + ], + "declarations": [ + { + "constant": false, + "id": 572, + "mutability": "mutable", + "name": "salt", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 664, + "src": "2650:12:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 571, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "2650:7:2", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 580, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 577, + "name": "duMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 566, + "src": "2681:9:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 576, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2673:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 575, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2673:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 578, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2673:18:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 574, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2665:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes32_$", + "typeString": "type(bytes32)" + }, + "typeName": { + "id": 573, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "2665:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 579, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2665:27:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2650:42:2" + }, + { + "assignments": [ + 582 + ], + "declarations": [ + { + "constant": false, + "id": 582, + "mutability": "mutable", + "name": "data", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 664, + "src": "2702:17:2", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 581, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "2702:5:2", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 596, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "696e697469616c697a6528616464726573732c616464726573732c616464726573735b5d2c616464726573732c616464726573732c75696e7432353629", + "id": 585, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2746:63:2", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_015c7f51e2589abfef5a1063cf7321fa0da4fb1756a7b671e8b1ca6858d2b75f", + "typeString": "literal_string \"initialize(address,address,address[],address,address,uint256)\"" + }, + "value": "initialize(address,address,address[],address,address,uint256)" + }, + { + "argumentTypes": null, + "id": 586, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 546, + "src": "2823:5:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 587, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 417, + "src": "2842:5:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 588, + "name": "agents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 549, + "src": "2861:6:2", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 591, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 409, + "src": "2889:14:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + ], + "id": 590, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2881:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 589, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2881:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 592, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2881:23:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 593, + "name": "duMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 566, + "src": "2918:9:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 594, + "name": "defaultNewMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 415, + "src": "2941:19:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_015c7f51e2589abfef5a1063cf7321fa0da4fb1756a7b671e8b1ca6858d2b75f", + "typeString": "literal_string \"initialize(address,address,address[],address,address,uint256)\"" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 583, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "2722:3:2", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 584, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encodeWithSignature", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2722:23:2", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (string memory) pure returns (bytes memory)" + } + }, + "id": 595, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2722:248:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2702:268:2" + }, + { + "assignments": [ + 598 + ], + "declarations": [ + { + "constant": false, + "id": 598, + "mutability": "mutable", + "name": "du", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 664, + "src": "2980:18:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + "typeName": { + "id": 597, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2980:15:2", + "stateMutability": "payable", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 608, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 603, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 405, + "src": "3063:29:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "argumentTypes": null, + "id": 601, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "3040:8:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 602, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "cloneBytecode", + "nodeType": "MemberAccess", + "referencedDeclaration": 18, + "src": "3040:22:2", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (address) pure returns (bytes memory)" + } + }, + "id": 604, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3040:53:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 605, + "name": "data", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 582, + "src": "3095:4:2", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 606, + "name": "salt", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 572, + "src": "3101:4:2", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "argumentTypes": null, + "id": 599, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "3001:8:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 600, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "deployCodeAndInitUsingCreate2", + "nodeType": "MemberAccess", + "referencedDeclaration": 108, + "src": "3001:38:2", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_bytes_memory_ptr_$_t_bytes_memory_ptr_$_t_bytes32_$returns$_t_address_payable_$", + "typeString": "function (bytes memory,bytes memory,bytes32) returns (address payable)" + } + }, + "id": 607, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3001:105:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2980:126:2" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 610, + "name": "duMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 566, + "src": "3140:9:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 611, + "name": "du", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 598, + "src": "3151:2:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 612, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 546, + "src": "3155:5:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 613, + "name": "data_union_sidechain_template", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 405, + "src": "3162:29:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 609, + "name": "SidechainDUCreated", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 383, + "src": "3121:18:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_address_$_t_address_$_t_address_$returns$__$", + "typeString": "function (address,address,address,address)" + } + }, + "id": 614, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3121:71:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 615, + "nodeType": "EmitStatement", + "src": "3116:76:2" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 626, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 618, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 616, + "name": "newDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 411, + "src": "3256:15:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 617, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3275:1:2", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "3256:20:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "&&", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 625, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 621, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "3288:4:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionFactorySidechain_$666", + "typeString": "contract DataUnionFactorySidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionFactorySidechain_$666", + "typeString": "contract DataUnionFactorySidechain" + } + ], + "id": 620, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "3280:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 619, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3280:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 622, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3280:13:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 623, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balance", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3280:21:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": ">=", + "rightExpression": { + "argumentTypes": null, + "id": 624, + "name": "newDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 411, + "src": "3305:15:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "3280:40:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "3256:64:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 638, + "nodeType": "IfStatement", + "src": "3252:195:2", + "trueBody": { + "id": 637, + "nodeType": "Block", + "src": "3322:125:2", + "statements": [ + { + "condition": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 629, + "name": "newDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 411, + "src": "3348:15:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 627, + "name": "du", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 598, + "src": "3340:2:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 628, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "send", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3340:7:2", + "typeDescriptions": { + "typeIdentifier": "t_function_send_nonpayable$_t_uint256_$returns$_t_bool_$", + "typeString": "function (uint256) returns (bool)" + } + }, + "id": 630, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3340:24:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 636, + "nodeType": "IfStatement", + "src": "3336:101:2", + "trueBody": { + "id": 635, + "nodeType": "Block", + "src": "3366:71:2", + "statements": [ + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 632, + "name": "newDUInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 411, + "src": "3406:15:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 631, + "name": "DUInitialEthSent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 399, + "src": "3389:16:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 633, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3389:33:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 634, + "nodeType": "EmitStatement", + "src": "3384:38:2" + } + ] + } + } + ] + } + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 649, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 641, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 639, + "name": "newDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 413, + "src": "3460:20:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 640, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3484:1:2", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "3460:25:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "&&", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 648, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 644, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "3497:4:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionFactorySidechain_$666", + "typeString": "contract DataUnionFactorySidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionFactorySidechain_$666", + "typeString": "contract DataUnionFactorySidechain" + } + ], + "id": 643, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "3489:7:2", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 642, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3489:7:2", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 645, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3489:13:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 646, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balance", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3489:21:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": ">=", + "rightExpression": { + "argumentTypes": null, + "id": 647, + "name": "newDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 413, + "src": "3514:20:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "3489:45:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "3460:74:2", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 661, + "nodeType": "IfStatement", + "src": "3456:221:2", + "trueBody": { + "id": 660, + "nodeType": "Block", + "src": "3536:141:2", + "statements": [ + { + "condition": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 652, + "name": "newDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 413, + "src": "3565:20:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 650, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 546, + "src": "3554:5:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 651, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "send", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3554:10:2", + "typeDescriptions": { + "typeIdentifier": "t_function_send_nonpayable$_t_uint256_$returns$_t_bool_$", + "typeString": "function (uint256) returns (bool)" + } + }, + "id": 653, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3554:32:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 659, + "nodeType": "IfStatement", + "src": "3550:117:2", + "trueBody": { + "id": 658, + "nodeType": "Block", + "src": "3588:79:2", + "statements": [ + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 655, + "name": "newDUOwnerInitialEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 413, + "src": "3631:20:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 654, + "name": "OwnerInitialEthSent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 403, + "src": "3611:19:2", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 656, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3611:41:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 657, + "nodeType": "EmitStatement", + "src": "3606:46:2" + } + ] + } + } + ] + } + }, + { + "expression": { + "argumentTypes": null, + "id": 662, + "name": "du", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 598, + "src": "3693:2:2", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "functionReturnParameters": 553, + "id": 663, + "nodeType": "Return", + "src": "3686:9:2" + } + ] + }, + "documentation": null, + "functionSelector": "325ff66f", + "id": 665, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "deployNewDUSidechain", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 550, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 546, + "mutability": "mutable", + "name": "owner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 665, + "src": "2461:21:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + "typeName": { + "id": 545, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2461:15:2", + "stateMutability": "payable", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 549, + "mutability": "mutable", + "name": "agents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 665, + "src": "2484:23:2", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 547, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2484:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 548, + "length": null, + "nodeType": "ArrayTypeName", + "src": "2484:9:2", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2460:48:2" + }, + "returnParameters": { + "id": 553, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 552, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 665, + "src": "2525:7:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 551, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2525:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2524:9:2" + }, + "scope": 666, + "src": "2431:1271:2", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + } + ], + "scope": 667, + "src": "324:3380:2" + } + ], + "src": "0:3705:2" + }, + "compiler": { + "name": "solc", + "version": "0.6.6+commit.6c089d02.Emscripten.clang" + }, + "networks": {}, + "schemaVersion": "3.2.3", + "updatedAt": "2020-12-09T11:44:39.469Z", + "devdoc": { + "methods": { + "claimOwnership()": { + "details": "Allows the pendingOwner address to finalize the transfer." + }, + "transferOwnership(address)": { + "details": "Allows the current owner to set the pendingOwner address.", + "params": { + "newOwner": "The address to transfer ownership to." + } + } + } + }, + "userdoc": { + "methods": {} + } +} \ No newline at end of file diff --git a/contracts/DataUnionMainnet.json b/contracts/DataUnionMainnet.json new file mode 100644 index 000000000..62394dc33 --- /dev/null +++ b/contracts/DataUnionMainnet.json @@ -0,0 +1,14011 @@ +{ + "contractName": "DataUnionMainnet", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "adminFee", + "type": "uint256" + } + ], + "name": "AdminFeeChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AdminFeeCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "AdminFeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RevenueReceived", + "type": "event" + }, + { + "inputs": [], + "name": "adminFeeFraction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "amb", + "outputs": [ + { + "internalType": "contract IAMB", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "autoSendAdminFee", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claimOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sidechain_DU_factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sidechain_maxgas", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sidechain_template_DU", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract ERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token_mediator", + "outputs": [ + { + "internalType": "contract ITokenMediator", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalAdminFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalAdminFeesWithdrawn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalEarnings", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_token_mediator", + "type": "address" + }, + { + "internalType": "address", + "name": "_sidechain_DU_factory", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_sidechain_maxgas", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_sidechain_template_DU", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_adminFeeFraction", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "agents", + "type": "address[]" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newAdminFee", + "type": "uint256" + } + ], + "name": "setAdminFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "autoSend", + "type": "bool" + } + ], + "name": "setAutoSendAdminFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "agents", + "type": "address[]" + } + ], + "name": "deployNewDUSidechain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sidechainAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "onPurchase", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "adminFeesWithdrawable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unaccountedTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sendTokensToBridge", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawAdminFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "metadata": "{\"compiler\":{\"version\":\"0.6.6+commit.6c089d02\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"adminFee\",\"type\":\"uint256\"}],\"name\":\"AdminFeeChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AdminFeeCharged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"AdminFeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"RevenueReceived\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"adminFeeFraction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"adminFeesWithdrawable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"amb\",\"outputs\":[{\"internalType\":\"contract IAMB\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"autoSendAdminFee\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"agents\",\"type\":\"address[]\"}],\"name\":\"deployNewDUSidechain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token_mediator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_sidechain_DU_factory\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_sidechain_maxgas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sidechain_template_DU\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_adminFeeFraction\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"agents\",\"type\":\"address[]\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"onPurchase\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sendTokensToBridge\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newAdminFee\",\"type\":\"uint256\"}],\"name\":\"setAdminFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"autoSend\",\"type\":\"bool\"}],\"name\":\"setAutoSendAdminFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sidechainAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sidechain_DU_factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sidechain_maxgas\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sidechain_template_DU\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token_mediator\",\"outputs\":[{\"internalType\":\"contract ITokenMediator\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalAdminFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalAdminFeesWithdrawn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalEarnings\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unaccountedTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawAdminFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{\"claimOwnership()\":{\"details\":\"Allows the pendingOwner address to finalize the transfer.\"},\"setAdminFee(uint256)\":{\"params\":{\"newAdminFee\":\"fixed-point decimal in the same way as ether: 50% === 0.5 ether === \\\"500000000000000000\\\"\"}},\"transferOwnership(address)\":{\"details\":\"Allows the current owner to set the pendingOwner address.\",\"params\":{\"newOwner\":\"The address to transfer ownership to.\"}}}},\"userdoc\":{\"methods\":{\"setAdminFee(uint256)\":{\"notice\":\"Admin fee as a fraction of revenue.\"}}}},\"settings\":{\"compilationTarget\":{\"/home/heynow/streamr/data-union-solidity/contracts/DataUnionMainnet.sol\":\"DataUnionMainnet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"/home/heynow/streamr/data-union-solidity/contracts/CloneLib.sol\":{\"keccak256\":\"0xf9082fe41a9e05b37cf87f0d1d67ca16d32c4100a2a27a6fc9d8f3f8364a7486\",\"urls\":[\"bzz-raw://b928f45b1904c399db9508c093604531bd215afeb4686827ab46daa7aee1938e\",\"dweb:/ipfs/QmdnBUvpCDc93fHZe7o6bitGRZo4PFTx9NprgziqHsVHFw\"]},\"/home/heynow/streamr/data-union-solidity/contracts/DataUnionMainnet.sol\":{\"keccak256\":\"0x4365bae70a1d10cf57cbc9d323f33824cacb8bba41308bb65954b30b65f22868\",\"urls\":[\"bzz-raw://065a556347a0862e0c23b9c70c527736bca2c6c146dbac976587dd963b62eea4\",\"dweb:/ipfs/Qmf6ujfdwgHhp9oMyb9S6RjY8N2ckUpk4HhUdJM4FXkQVQ\"]},\"/home/heynow/streamr/data-union-solidity/contracts/IAMB.sol\":{\"keccak256\":\"0x63b46d3087a8ba558cb36d99ffe5b2f0241446adc4c8df4219ce86f97727e168\",\"urls\":[\"bzz-raw://66d9c8c817e90b25f28b3d79a69b440018b49633a7bbaf6fe4d1788b2ff5e6eb\",\"dweb:/ipfs/QmSdrqpaZ3R3NGFuF6jnbo8cCgV5ghdW5iWrnV59qavYP2\"]},\"/home/heynow/streamr/data-union-solidity/contracts/ITokenMediator.sol\":{\"keccak256\":\"0x1f21e943f4e125dd1c4353db29880b63f8fa7a299ba862432c8a4e14807873e2\",\"urls\":[\"bzz-raw://4ddc233243efce6c2582b63e3be28c4f90f32d60b5d4b6fe8331106d970a8435\",\"dweb:/ipfs/QmQzLwvxU3ixfLbdpuYdpqvW61xjPbnXDTaaWNjRJUhvSK\"]},\"/home/heynow/streamr/data-union-solidity/contracts/Ownable.sol\":{\"keccak256\":\"0x0d96dac82f3bf17d2cdc90863a61c8957622c305bc3bbf9cd8f47facfa71dea1\",\"urls\":[\"bzz-raw://1cd621b81754be8073fc89bd2bc864e7b0169ba5f153edc5b9212a19f4890aa3\",\"dweb:/ipfs/QmcE5HTf3pptr2s7oiDqYtotCLrb736g8N7YyRZj8k5mHg\"]},\"/home/heynow/streamr/data-union-solidity/contracts/PurchaseListener.sol\":{\"keccak256\":\"0x2eed0264d535450c36dc5385247e200d5e1defaecbf20ace3d2eee6d5bcd78cd\",\"urls\":[\"bzz-raw://292464cafc307356e6c53d613c8bbb3cc2ccb60212d5b0e6e8a91f5304fbd67b\",\"dweb:/ipfs/QmX3MMED2EYBTHVwnaCVQEf3yd2e3M2MfR4paDcuBEtmLD\"]},\"openzeppelin-solidity/contracts/GSN/Context.sol\":{\"keccak256\":\"0xdb26cbf4d028490f49831a7865c2fe1b28db44b535ca8d343785a3b768aae183\",\"urls\":[\"bzz-raw://840b14ce0315c47d49ba328f1f9fa7654ded1c9e1559e6c5e777a7b2dc28bf0a\",\"dweb:/ipfs/QmTLLabn4wcfGro9LEmUXUN2nwKqZSotXMvjDCLXEnLtZP\"]},\"openzeppelin-solidity/contracts/math/SafeMath.sol\":{\"keccak256\":\"0x9a9cf02622cd7a64261b10534fc3260449da25c98c9e96d1b4ae8110a20e5806\",\"urls\":[\"bzz-raw://2df142592d1dc267d9549049ee3317fa190d2f87eaa565f86ab05ec83f7ab8f5\",\"dweb:/ipfs/QmSkJtcfWo7c42KnL5hho6GFxK6HRNV91XABx1P7xDtfLV\"]},\"openzeppelin-solidity/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0xf204d98eef08edacf5a02a2af1516ea4febdb6aba7a1ae5ac8deb6e568fd3dbb\",\"urls\":[\"bzz-raw://c4dea62bffbd180772a6cfe7cb90e3a045c52d6b502bdb2fdff83193da42d8d0\",\"dweb:/ipfs/QmW8qGZ5nngajmv5Aamdrpkeuq7S5YCVaR7rtcqNekKHtK\"]},\"openzeppelin-solidity/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x5c26b39d26f7ed489e555d955dcd3e01872972e71fdd1528e93ec164e4f23385\",\"urls\":[\"bzz-raw://efdc632af6960cf865dbc113665ea1f5b90eab75cc40ec062b2f6ae6da582017\",\"dweb:/ipfs/QmfAZFDuG62vxmAN9DnXApv7e7PMzPqi4RkqqZHLMSQiY5\"]},\"openzeppelin-solidity/contracts/utils/Address.sol\":{\"keccak256\":\"0xdfb4f812600ba4ce6738c35584ceb8c9433472583051b48ba5b1f66cb758a498\",\"urls\":[\"bzz-raw://df02dffe1c1de089d9b4f6192f0dcf464526f2230f420b3deec4645e0cdd2bff\",\"dweb:/ipfs/QmcqXGAU3KJqwrgUVoGJ2W8osomhSJ4R5kdsRpbuW3fELS\"]}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a01b0319169055611652806100306000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c8063692199d4116100f9578063c5a8c91f11610097578063e30c397811610071578063e30c3978146103a7578063f2fde38b146103af578063fb6470c9146103d5578063fc0c546a146104b8576101a9565b8063c5a8c91f1461038f578063d35cec4014610397578063e22ec1121461039f576101a9565b806399dd1c81116100d357806399dd1c81146102d45780639eeba07c14610377578063a65c87d91461037f578063a913f41d14610387576101a9565b8063692199d4146102a75780638beb60b6146102af5780638da5cb5b146102cc576101a9565b80632efc1007116101665780634a439cc0116101405780634a439cc0146102515780634e71e0c81461028f57806354fd4d501461029757806361feacff1461029f576101a9565b80632efc10071461022557806337b43a941461022d578063392e53cd14610235576101a9565b80630419b45a146101ae5780630f3afcbe146101c85780631062b39a146101e9578063132b41941461020d57806313fd3c56146102155780632df3eba41461021d575b600080fd5b6101b66104c0565b60408051918252519081900360200190f35b6101e7600480360360208110156101de57600080fd5b50351515610606565b005b6101f1610664565b604080516001600160a01b039092168252519081900360200190f35b6101b6610673565b6101b6610708565b6101b6610721565b6101b6610727565b6101f1610d35565b61023d610d55565b604080519115158252519081900360200190f35b61023d600480360360a081101561026757600080fd5b508035906001600160a01b036020820135169060408101359060608101359060800135610d66565b6101e7610d7d565b6101b6610e33565b6101b6610e38565b6101b6610e3e565b6101e7600480360360208110156102c557600080fd5b5035610e44565b6101f1610f18565b6101e7600480360360208110156102ea57600080fd5b81019060208101813564010000000081111561030557600080fd5b82018360208201111561031757600080fd5b8035906020019184602083028401116401000000008311171561033957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610f27945050505050565b61023d6110cb565b6101f16110d4565b6101b66110e3565b6101f16110e9565b6101b66110f8565b6101f16110fe565b6101f161110d565b6101e7600480360360208110156103c557600080fd5b50356001600160a01b031661111c565b6101e760048036036101008110156103ec57600080fd5b6001600160a01b03823581169260208101358216926040820135831692606083013592608081013582169260a08201359092169160c08201359190810190610100810160e082013564010000000081111561044657600080fd5b82018360208201111561045857600080fd5b8035906020019184602083028401116401000000008311171561047a57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611189945050505050565b6101f16112f2565b6000806104cb610708565b9050806104dc576000915050610603565b600a546104ef908263ffffffff61130116565b600a55600654600080546040805163a9059cbb60e01b81526001600160a01b039283166004820152602481018690529051919093169263a9059cbb9260448083019360209390929083900390910190829087803b15801561054f57600080fd5b505af1158015610563573d6000803e3d6000fd5b505050506040513d602081101561057957600080fd5b50516105be576040805162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c97d9985a5b1959608a1b604482015290519081900360640190fd5b6000546040805183815290516001600160a01b03909216917fcdcaff67ac16639664e5f9343c9223a1dc9c972ec367b69ae9fc1325c7be54749181900360200190a290505b90565b6000546001600160a01b03163314610651576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b600b805460ff1916911515919091179055565b6002546001600160a01b031681565b6000610703610680610708565b600654604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156106cb57600080fd5b505afa1580156106df573d6000803e3d6000fd5b505050506040513d60208110156106f557600080fd5b50519063ffffffff61136416565b905090565b6000610703600a5460095461136490919063ffffffff16565b600c5481565b600080610732610673565b905080610743576000915050610603565b6040805182815290517f41b06c6e0a1531dcb4b86d53ec6268666aa12d55775f8e5a63596fc935cdcc229181900360200190a160006107a5670de0b6b3a7640000610799600854856113a690919063ffffffff16565b9063ffffffff6113ff16565b905060006107b9838363ffffffff61136416565b6009549091506107cf908363ffffffff61130116565b6009556040805183815290517f538d1b2114be2374c7010694167f3db7f2d56f864a4e1555582b9716b7d11c3d9181900360200190a1600b5460ff161561081a576108186104c0565b505b6006546003546040805163095ea7b360e01b81526001600160a01b0392831660048201526000602482018190529151929093169263095ea7b39260448083019360209383900390910190829087803b15801561087557600080fd5b505af1158015610889573d6000803e3d6000fd5b505050506040513d602081101561089f57600080fd5b50516108e3576040805162461bcd60e51b815260206004820152600e60248201526d185c1c1c9bdd9957d9985a5b195960921b604482015290519081900360640190fd5b6006546003546040805163095ea7b360e01b81526001600160a01b039283166004820152602481018590529051919092169163095ea7b39160448083019260209291908290030181600087803b15801561093c57600080fd5b505af1158015610950573d6000803e3d6000fd5b505050506040513d602081101561096657600080fd5b50516109aa576040805162461bcd60e51b815260206004820152600e60248201526d185c1c1c9bdd9957d9985a5b195960921b604482015290519081900360640190fd5b6003546040805163437764df60e01b815290516000926001600160a01b03169163437764df916004808301926020929190829003018186803b1580156109ef57600080fd5b505afa158015610a03573d6000803e3d6000fd5b505050506040513d6020811015610a1957600080fd5b505190506358a8b61360e11b6001600160e01b031982161415610add576003546006546001600160a01b039182169163ad58bdd19116610a57610d35565b856040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015610ac057600080fd5b505af1158015610ad4573d6000803e3d6000fd5b50505050610ba2565b633b2cadab60e11b6001600160e01b031982161415610b5f576003546001600160a01b03166301e4f53a610b0f610d35565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015610ac057600080fd5b6040805162461bcd60e51b8152602060048201526013602482015272756e6b6e6f776e5f6272696467655f6d6f646560681b604482015290519081900360640190fd5b610baa610673565b15610bee576040805162461bcd60e51b815260206004820152600f60248201526e1b9bdd17dd1c985b9cd9995c9c9959608a1b604482015290519081900360640190fd5b600c54610c01908363ffffffff61130116565b600c556040805160048152602481019091526020810180516001600160e01b031663331beb5f60e01b1790526002546001600160a01b031663dc8601b3610c46610d35565b6005546040516001600160e01b031960e085901b1681526001600160a01b038316600482019081526044820183905260606024830190815287516064840152875188949360840190602086019080838360005b83811015610cb1578181015183820152602001610c99565b50505050905090810190601f168015610cde5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015610cff57600080fd5b505af1158015610d13573d6000803e3d6000fd5b505050506040513d6020811015610d2957600080fd5b50949550505050505090565b600754600454600091610703916001600160a01b03918216911630611441565b6006546001600160a01b0316151590565b6000610d70610727565b5060019695505050505050565b6001546001600160a01b03163314610dcf576040805162461bcd60e51b815260206004820152601060248201526f37b7363ca832b73234b733a7bbb732b960811b604482015290519081900360640190fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b600290565b60095481565b60055481565b6000546001600160a01b03163314610e8f576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b670de0b6b3a7640000811115610edd576040805162461bcd60e51b815260206004820152600e60248201526d6572726f725f61646d696e46656560901b604482015290519081900360640190fd5b60088190556040805182815290517f11a80b766155f9b8f16a7da44d66269fd694cb1c247f4814244586f68dd534879181900360200190a150565b6000546001600160a01b031681565b60606000809054906101000a90046001600160a01b03168260405160240180836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019060200280838360005b83811015610f9a578181015183820152602001610f82565b50506040805193909501838103601f190184528552505060208101805163325ff66f60e01b6001600160e01b0390911617815260025460048054600554965163dc8601b360e01b81526001600160a01b0391821692810183815260448201899052606060248301908152875160648401528751979e50929094169b5063dc8601b39a509198508b975091945090926084909101919080838360005b8381101561104d578181015183820152602001611035565b50505050905090810190601f16801561107a5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561109b57600080fd5b505af11580156110af573d6000803e3d6000fd5b505050506040513d60208110156110c557600080fd5b50505050565b600b5460ff1681565b6007546001600160a01b031681565b600a5481565b6003546001600160a01b031681565b60085481565b6004546001600160a01b031681565b6001546001600160a01b031681565b6000546001600160a01b03163314611167576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b611191610d55565b156111cf576040805162461bcd60e51b8152602060048201526009602482015268696e69745f6f6e636560b81b604482015290519081900360640190fd5b600b805460ff19166001179055600080546001600160a01b03199081163317909155600380546001600160a01b038a81169190931617908190556040805163cd59658360e01b81529051919092169163cd596583916004808301926020929190829003018186803b15801561124357600080fd5b505afa158015611257573d6000803e3d6000fd5b505050506040513d602081101561126d57600080fd5b5051600280546001600160a01b03199081166001600160a01b03938416179091556006805482168b84161790556004805482168984161790556005879055600780549091169186169190911790556112c482610e44565b600080546001600160a01b0319166001600160a01b0385161790556112e881610f27565b5050505050505050565b6006546001600160a01b031681565b60008282018381101561135b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b600061135b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506114ad565b6000826113b55750600061135e565b828202828482816113c257fe5b041461135b5760405162461bcd60e51b81526004018080602001828103825260218152602001806115fc6021913960400191505060405180910390fd5b600061135b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611544565b60008061144d856115a9565b8051602091820120604080516001600160f81b0319818501526bffffffffffffffffffffffff19606089901b1660218201526035810187905260558082019390935281518082039093018352607501905280519101209150509392505050565b6000818484111561153c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156115015781810151838201526020016114e9565b50505050905090810190601f16801561152e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836115935760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156115015781810151838201526020016114e9565b50600083858161159f57fe5b0495945050505050565b604080516057810190915260378152733d602d80600a3d3981f3363d3d373d3d3d363d7360601b602082015260609190911b60348201526e5af43d82803e903d91602b57fd5bf360881b60488201529056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220e5d0a1ab0c140b32158b43f1340885836a7589a9e16b58cccb1a4bfd9ef73ab964736f6c63430006060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101a95760003560e01c8063692199d4116100f9578063c5a8c91f11610097578063e30c397811610071578063e30c3978146103a7578063f2fde38b146103af578063fb6470c9146103d5578063fc0c546a146104b8576101a9565b8063c5a8c91f1461038f578063d35cec4014610397578063e22ec1121461039f576101a9565b806399dd1c81116100d357806399dd1c81146102d45780639eeba07c14610377578063a65c87d91461037f578063a913f41d14610387576101a9565b8063692199d4146102a75780638beb60b6146102af5780638da5cb5b146102cc576101a9565b80632efc1007116101665780634a439cc0116101405780634a439cc0146102515780634e71e0c81461028f57806354fd4d501461029757806361feacff1461029f576101a9565b80632efc10071461022557806337b43a941461022d578063392e53cd14610235576101a9565b80630419b45a146101ae5780630f3afcbe146101c85780631062b39a146101e9578063132b41941461020d57806313fd3c56146102155780632df3eba41461021d575b600080fd5b6101b66104c0565b60408051918252519081900360200190f35b6101e7600480360360208110156101de57600080fd5b50351515610606565b005b6101f1610664565b604080516001600160a01b039092168252519081900360200190f35b6101b6610673565b6101b6610708565b6101b6610721565b6101b6610727565b6101f1610d35565b61023d610d55565b604080519115158252519081900360200190f35b61023d600480360360a081101561026757600080fd5b508035906001600160a01b036020820135169060408101359060608101359060800135610d66565b6101e7610d7d565b6101b6610e33565b6101b6610e38565b6101b6610e3e565b6101e7600480360360208110156102c557600080fd5b5035610e44565b6101f1610f18565b6101e7600480360360208110156102ea57600080fd5b81019060208101813564010000000081111561030557600080fd5b82018360208201111561031757600080fd5b8035906020019184602083028401116401000000008311171561033957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610f27945050505050565b61023d6110cb565b6101f16110d4565b6101b66110e3565b6101f16110e9565b6101b66110f8565b6101f16110fe565b6101f161110d565b6101e7600480360360208110156103c557600080fd5b50356001600160a01b031661111c565b6101e760048036036101008110156103ec57600080fd5b6001600160a01b03823581169260208101358216926040820135831692606083013592608081013582169260a08201359092169160c08201359190810190610100810160e082013564010000000081111561044657600080fd5b82018360208201111561045857600080fd5b8035906020019184602083028401116401000000008311171561047a57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611189945050505050565b6101f16112f2565b6000806104cb610708565b9050806104dc576000915050610603565b600a546104ef908263ffffffff61130116565b600a55600654600080546040805163a9059cbb60e01b81526001600160a01b039283166004820152602481018690529051919093169263a9059cbb9260448083019360209390929083900390910190829087803b15801561054f57600080fd5b505af1158015610563573d6000803e3d6000fd5b505050506040513d602081101561057957600080fd5b50516105be576040805162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c97d9985a5b1959608a1b604482015290519081900360640190fd5b6000546040805183815290516001600160a01b03909216917fcdcaff67ac16639664e5f9343c9223a1dc9c972ec367b69ae9fc1325c7be54749181900360200190a290505b90565b6000546001600160a01b03163314610651576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b600b805460ff1916911515919091179055565b6002546001600160a01b031681565b6000610703610680610708565b600654604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156106cb57600080fd5b505afa1580156106df573d6000803e3d6000fd5b505050506040513d60208110156106f557600080fd5b50519063ffffffff61136416565b905090565b6000610703600a5460095461136490919063ffffffff16565b600c5481565b600080610732610673565b905080610743576000915050610603565b6040805182815290517f41b06c6e0a1531dcb4b86d53ec6268666aa12d55775f8e5a63596fc935cdcc229181900360200190a160006107a5670de0b6b3a7640000610799600854856113a690919063ffffffff16565b9063ffffffff6113ff16565b905060006107b9838363ffffffff61136416565b6009549091506107cf908363ffffffff61130116565b6009556040805183815290517f538d1b2114be2374c7010694167f3db7f2d56f864a4e1555582b9716b7d11c3d9181900360200190a1600b5460ff161561081a576108186104c0565b505b6006546003546040805163095ea7b360e01b81526001600160a01b0392831660048201526000602482018190529151929093169263095ea7b39260448083019360209383900390910190829087803b15801561087557600080fd5b505af1158015610889573d6000803e3d6000fd5b505050506040513d602081101561089f57600080fd5b50516108e3576040805162461bcd60e51b815260206004820152600e60248201526d185c1c1c9bdd9957d9985a5b195960921b604482015290519081900360640190fd5b6006546003546040805163095ea7b360e01b81526001600160a01b039283166004820152602481018590529051919092169163095ea7b39160448083019260209291908290030181600087803b15801561093c57600080fd5b505af1158015610950573d6000803e3d6000fd5b505050506040513d602081101561096657600080fd5b50516109aa576040805162461bcd60e51b815260206004820152600e60248201526d185c1c1c9bdd9957d9985a5b195960921b604482015290519081900360640190fd5b6003546040805163437764df60e01b815290516000926001600160a01b03169163437764df916004808301926020929190829003018186803b1580156109ef57600080fd5b505afa158015610a03573d6000803e3d6000fd5b505050506040513d6020811015610a1957600080fd5b505190506358a8b61360e11b6001600160e01b031982161415610add576003546006546001600160a01b039182169163ad58bdd19116610a57610d35565b856040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015610ac057600080fd5b505af1158015610ad4573d6000803e3d6000fd5b50505050610ba2565b633b2cadab60e11b6001600160e01b031982161415610b5f576003546001600160a01b03166301e4f53a610b0f610d35565b846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015610ac057600080fd5b6040805162461bcd60e51b8152602060048201526013602482015272756e6b6e6f776e5f6272696467655f6d6f646560681b604482015290519081900360640190fd5b610baa610673565b15610bee576040805162461bcd60e51b815260206004820152600f60248201526e1b9bdd17dd1c985b9cd9995c9c9959608a1b604482015290519081900360640190fd5b600c54610c01908363ffffffff61130116565b600c556040805160048152602481019091526020810180516001600160e01b031663331beb5f60e01b1790526002546001600160a01b031663dc8601b3610c46610d35565b6005546040516001600160e01b031960e085901b1681526001600160a01b038316600482019081526044820183905260606024830190815287516064840152875188949360840190602086019080838360005b83811015610cb1578181015183820152602001610c99565b50505050905090810190601f168015610cde5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015610cff57600080fd5b505af1158015610d13573d6000803e3d6000fd5b505050506040513d6020811015610d2957600080fd5b50949550505050505090565b600754600454600091610703916001600160a01b03918216911630611441565b6006546001600160a01b0316151590565b6000610d70610727565b5060019695505050505050565b6001546001600160a01b03163314610dcf576040805162461bcd60e51b815260206004820152601060248201526f37b7363ca832b73234b733a7bbb732b960811b604482015290519081900360640190fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b600290565b60095481565b60055481565b6000546001600160a01b03163314610e8f576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b670de0b6b3a7640000811115610edd576040805162461bcd60e51b815260206004820152600e60248201526d6572726f725f61646d696e46656560901b604482015290519081900360640190fd5b60088190556040805182815290517f11a80b766155f9b8f16a7da44d66269fd694cb1c247f4814244586f68dd534879181900360200190a150565b6000546001600160a01b031681565b60606000809054906101000a90046001600160a01b03168260405160240180836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019060200280838360005b83811015610f9a578181015183820152602001610f82565b50506040805193909501838103601f190184528552505060208101805163325ff66f60e01b6001600160e01b0390911617815260025460048054600554965163dc8601b360e01b81526001600160a01b0391821692810183815260448201899052606060248301908152875160648401528751979e50929094169b5063dc8601b39a509198508b975091945090926084909101919080838360005b8381101561104d578181015183820152602001611035565b50505050905090810190601f16801561107a5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b15801561109b57600080fd5b505af11580156110af573d6000803e3d6000fd5b505050506040513d60208110156110c557600080fd5b50505050565b600b5460ff1681565b6007546001600160a01b031681565b600a5481565b6003546001600160a01b031681565b60085481565b6004546001600160a01b031681565b6001546001600160a01b031681565b6000546001600160a01b03163314611167576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b611191610d55565b156111cf576040805162461bcd60e51b8152602060048201526009602482015268696e69745f6f6e636560b81b604482015290519081900360640190fd5b600b805460ff19166001179055600080546001600160a01b03199081163317909155600380546001600160a01b038a81169190931617908190556040805163cd59658360e01b81529051919092169163cd596583916004808301926020929190829003018186803b15801561124357600080fd5b505afa158015611257573d6000803e3d6000fd5b505050506040513d602081101561126d57600080fd5b5051600280546001600160a01b03199081166001600160a01b03938416179091556006805482168b84161790556004805482168984161790556005879055600780549091169186169190911790556112c482610e44565b600080546001600160a01b0319166001600160a01b0385161790556112e881610f27565b5050505050505050565b6006546001600160a01b031681565b60008282018381101561135b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b600061135b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506114ad565b6000826113b55750600061135e565b828202828482816113c257fe5b041461135b5760405162461bcd60e51b81526004018080602001828103825260218152602001806115fc6021913960400191505060405180910390fd5b600061135b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611544565b60008061144d856115a9565b8051602091820120604080516001600160f81b0319818501526bffffffffffffffffffffffff19606089901b1660218201526035810187905260558082019390935281518082039093018352607501905280519101209150509392505050565b6000818484111561153c5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156115015781810151838201526020016114e9565b50505050905090810190601f16801561152e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836115935760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156115015781810151838201526020016114e9565b50600083858161159f57fe5b0495945050505050565b604080516057810190915260378152733d602d80600a3d3981f3363d3d373d3d3d363d7360601b602082015260609190911b60348201526e5af43d82803e903d91602b57fd5bf360881b60488201529056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220e5d0a1ab0c140b32158b43f1340885836a7589a9e16b58cccb1a4bfd9ef73ab964736f6c63430006060033", + "immutableReferences": {}, + "sourceMap": "356:6155:3:-:0;;;1479:43;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;1516:1:3;577:14:12;;-1:-1:-1;;;;;;577:14:12;;;356:6155:3;;;;;;", + "deployedSourceMap": "356:6155:3:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;356:6155:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;6118:391:3;;;:::i;:::-;;;;;;;;;;;;;;;;3002:105;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;3002:105:3;;;;:::i;:::-;;652:15;;;:::i;:::-;;;;-1:-1:-1;;;;;652:15:3;;;;;;;;;;;;;;4358:142;;;:::i;4222:130::-;;;:::i;1443:28::-;;;:::i;4507:1605::-;;;:::i;3380:195::-;;;:::i;2499:104::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;4060:156;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;4060:156:3;;;-1:-1:-1;;;;;4060:156:3;;;;;;;;;;;;;;;;;;;;:::i;1123:226:12:-;;;:::i;1171:62:3:-;;;:::i;1057:29::-;;;:::i;756:31::-;;;:::i;2783:213::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;2783:213:3;;:::i;236:20:12:-;;;:::i;3114:260:3:-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;3114:260:3;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;3114:260:3;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;3114:260:3;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;3114:260:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;3114:260:3;;-1:-1:-1;3114:260:3;;-1:-1:-1;;;;;3114:260:3:i;1136:28::-;;;:::i;978:36::-;;;:::i;1092:38::-;;;:::i;673:36::-;;;:::i;1020:31::-;;;:::i;715:35::-;;;:::i;262:27:12:-;;;:::i;929:102::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;929:102:12;-1:-1:-1;;;;;929:102:12;;:::i;1528:965:3:-;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;1528:965:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;1528:965:3;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;1528:965:3;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;1528:965:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;1528:965:3;;-1:-1:-1;1528:965:3;;-1:-1:-1;;;;;1528:965:3:i;793:18::-;;;:::i;6118:391::-;6163:7;6182:20;6205:23;:21;:23::i;:::-;6182:46;-1:-1:-1;6242:17:3;6238:31;;6268:1;6261:8;;;;;6238:31;6305:23;;:41;;6333:12;6305:41;:27;:41;:::i;:::-;6279:23;:67;6364:5;;;6379;;6364:35;;;-1:-1:-1;;;6364:35:3;;-1:-1:-1;;;;;6379:5:3;;;6364:35;;;;;;;;;;;;:5;;;;;:14;;:35;;;;;;;;;;;;;;;;;;;:5;:35;;;2:2:-1;;;;27:1;24;17:12;2:2;6364:35:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6364:35:3;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;6364:35:3;6356:63;;;;;-1:-1:-1;;;6356:63:3;;;;;;;;;;;;-1:-1:-1;;;6356:63:3;;;;;;;;;;;;;;;6453:5;;6434:39;;;;;;;;-1:-1:-1;;;;;6453:5:3;;;;6434:39;;;;;;;;;6490:12;-1:-1:-1;6118:391:3;;:::o;3002:105::-;739:5:12;;-1:-1:-1;;;;;739:5:12;725:10;:19;717:41;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;;;;3073:16:3::1;:27:::0;;-1:-1:-1;;3073:27:3::1;::::0;::::1;;::::0;;;::::1;::::0;;3002:105::o;652:15::-;;;-1:-1:-1;;;;;652:15:3;;:::o;4358:142::-;4408:7;4434:59;4469:23;:21;:23::i;:::-;4434:5;;:30;;;-1:-1:-1;;;4434:30:3;;4458:4;4434:30;;;;;;-1:-1:-1;;;;;4434:5:3;;;;:15;;:30;;;;;;;;;;;;;;;:5;:30;;;2:2:-1;;;;27:1;24;17:12;2:2;4434:30:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;4434:30:3;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;4434:30:3;;:59;:34;:59;:::i;:::-;4427:66;;4358:142;:::o;4222:130::-;4276:7;4302:43;4321:23;;4302:14;;:18;;:43;;;;:::i;1443:28::-;;;;:::o;4507:1605::-;4553:7;4572:17;4592:19;:17;:19::i;:::-;4572:39;-1:-1:-1;4625:14:3;4621:28;;4648:1;4641:8;;;;;4621:28;4665:26;;;;;;;;;;;;;;;;;4702:16;4721:43;4757:6;4721:31;4735:16;;4721:9;:13;;:31;;;;:::i;:::-;:35;:43;:35;:43;:::i;:::-;4702:62;-1:-1:-1;4774:22:3;4799:23;:9;4702:62;4799:23;:13;:23;:::i;:::-;4850:14;;4774:48;;-1:-1:-1;4850:28:3;;4869:8;4850:28;:18;:28;:::i;:::-;4833:14;:45;4893:25;;;;;;;;;;;;;;;;;4931:16;;;;4928:40;;;4949:19;:17;:19::i;:::-;;4928:40;5022:5;;5044:14;;5022:41;;;-1:-1:-1;;;5022:41:3;;-1:-1:-1;;;;;5044:14:3;;;5022:41;;;;:5;:41;;;;;;;;:5;;;;;:13;;:41;;;;;;;;;;;;;;;;:5;:41;;;2:2:-1;;;;27:1;24;17:12;2:2;5022:41:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5022:41:3;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;5022:41:3;5014:68;;;;;-1:-1:-1;;;5014:68:3;;;;;;;;;;;;-1:-1:-1;;;5014:68:3;;;;;;;;;;;;;;;5100:5;;5122:14;;5100:54;;;-1:-1:-1;;;5100:54:3;;-1:-1:-1;;;;;5122:14:3;;;5100:54;;;;;;;;;;;;:5;;;;;:13;;:54;;;;;;;;;;;;;;:5;;:54;;;2:2:-1;;;;27:1;24;17:12;2:2;5100:54:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5100:54:3;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;5100:54:3;5092:81;;;;;-1:-1:-1;;;5092:81:3;;;;;;;;;;;;-1:-1:-1;;;5092:81:3;;;;;;;;;;;;;;;5203:14;;:30;;;-1:-1:-1;;;5203:30:3;;;;5183:17;;-1:-1:-1;;;;;5203:14:3;;:28;;:30;;;;;;;;;;;;;;:14;:30;;;2:2:-1;;;;27:1;24;17:12;2:2;5203:30:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5203:30:3;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;5203:30:3;;-1:-1:-1;;;;;;;;;;5435:24:3;;;5432:328;;;5475:14;;5510:5;;-1:-1:-1;;;;;5475:14:3;;;;:26;;5510:5;5518:18;:16;:18::i;:::-;5538:14;5475:78;;;;;;;;;;;;;-1:-1:-1;;;;;5475:78:3;-1:-1:-1;;;;;5475:78:3;;;;;;-1:-1:-1;;;;;5475:78:3;-1:-1:-1;;;;;5475:78:3;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5475:78:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5475:78:3;;;;5432:328;;;-1:-1:-1;;;;;;;;;5581:24:3;;;5578:182;;;5620:14;;-1:-1:-1;;;;;5620:14:3;:26;5647:18;:16;:18::i;:::-;5667:14;5620:62;;;;;;;;;;;;;-1:-1:-1;;;;;5620:62:3;-1:-1:-1;;;;;5620:62:3;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;5578:182:3;5720:29;;;-1:-1:-1;;;5720:29:3;;;;;;;;;;;;-1:-1:-1;;;5720:29:3;;;;;;;;;;;;;;5578:182;5824:19;:17;:19::i;:::-;:24;5816:52;;;;;-1:-1:-1;;;5816:52:3;;;;;;;;;;;;-1:-1:-1;;;5816:52:3;;;;;;;;;;;;;;;5894:13;;:33;;5912:14;5894:33;:17;:33;:::i;:::-;5878:13;:49;5958:43;;;22:32:-1;6:49;;5958:43:3;;;;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;6011:3:3;;-1:-1:-1;;;;;6011:3:3;:24;6036:18;:16;:18::i;:::-;6062:16;;6011:68;;-1:-1:-1;;;;;;6011:68:3;;;;;;;-1:-1:-1;;;;;6011:68:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6056:4;;6062:16;6011:68;;;;;;;;;;-1:-1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;6011:68:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;6011:68:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6011:68:3;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;6096:9:3;;-1:-1:-1;;;;;;4507:1605:3;:::o;3380:195::-;3491:21;;3514:20;;3429:7;;3455:113;;-1:-1:-1;;;;;3491:21:3;;;;3514:20;3560:4;3455:35;:113::i;2499:104::-;2576:5;;-1:-1:-1;;;;;2576:5:3;2568:28;;2499:104;:::o;4060:156::-;4152:4;4168:20;:18;:20::i;:::-;-1:-1:-1;4205:4:3;;4060:156;-1:-1:-1;;;;;;4060:156:3:o;1123:226:12:-;1188:12;;-1:-1:-1;;;;;1188:12:12;1174:10;:26;1166:55;;;;;-1:-1:-1;;;1166:55:12;;;;;;;;;;;;-1:-1:-1;;;1166:55:12;;;;;;;;;;;;;;;1264:12;;;1257:5;;1236:41;;-1:-1:-1;;;;;1264:12:12;;;;1257:5;;;;1236:41;;;1295:12;;;;1287:20;;-1:-1:-1;;;;;;1287:20:12;;;-1:-1:-1;;;;;1295:12:12;;1287:20;;;;1317:25;;;1123:226::o;1171:62:3:-;1229:1;1171:62;:::o;1057:29::-;;;;:::o;756:31::-;;;;:::o;2783:213::-;739:5:12;;-1:-1:-1;;;;;739:5:12;725:10;:19;717:41;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;;;;2875:7:3::1;2860:11;:22;;2852:49;;;::::0;;-1:-1:-1;;;2852:49:3;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;2852:49:3;;;;;;;;;;;;;::::1;;2911:16;:30:::0;;;2956:33:::1;::::0;;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;2783:213:::0;:::o;236:20:12:-;;;-1:-1:-1;;;;;236:20:12;;:::o;3114:260:3:-;3186:17;3273:5;;;;;;;;;-1:-1:-1;;;;;3273:5:3;3280:6;3206:81;;;;;;-1:-1:-1;;;;;3206:81:3;-1:-1:-1;;;;;3206:81:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;-1:-1;;3206:81:3;;;;;;;26:21:-1;;;-1:-1;;22:32;6:49;;3206:81:3;;-1:-1:-1;;49:4;25:18;;61:17;;-1:-1;;;;;;;;182:15;;;179:29;160:49;;3297:3:3;;3322:20;;;3350:16;;3297:70;;-1:-1:-1;;;3297:70:3;;-1:-1:-1;;;;;3322:20:3;;;3297:70;;;;;;;;;;;;;;;;;;;;;;;;;;;3206:81;;-1:-1:-1;3297:3:3;;;;;-1:-1:-1;3297:24:3;;-1:-1:-1;3322:20:3;;-1:-1:-1;3206:81:3;;-1:-1:-1;3297:70:3;;-1:-1:-1;3297:70:3;;;;;;;25:18:-1;3297:70:3;;25:18:-1;-1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;3297:70:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3297:70:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3297:70:3;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;3114:260:3:o;1136:28::-;;;;;;:::o;978:36::-;;;-1:-1:-1;;;;;978:36:3;;:::o;1092:38::-;;;;:::o;673:36::-;;;-1:-1:-1;;;;;673:36:3;;:::o;1020:31::-;;;;:::o;715:35::-;;;-1:-1:-1;;;;;715:35:3;;:::o;262:27:12:-;;;-1:-1:-1;;;;;262:27:12;;:::o;929:102::-;739:5;;-1:-1:-1;;;;;739:5:12;725:10;:19;717:41;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;;;;1001:12:::1;:23:::0;;-1:-1:-1;;;;;;1001:23:12::1;-1:-1:-1::0;;;;;1001:23:12;;;::::1;::::0;;;::::1;::::0;;929:102::o;1528:965:3:-;1844:15;:13;:15::i;:::-;1843:16;1835:38;;;;;-1:-1:-1;;;1835:38:3;;;;;;;;;;;;-1:-1:-1;;;1835:38:3;;;;;;;;;;;;;;;1956:16;:23;;-1:-1:-1;;1956:23:3;1975:4;1956:23;;;:16;2034:18;;-1:-1:-1;;;;;;2034:18:3;;;2042:10;2034:18;;;;2063:14;:48;;-1:-1:-1;;;;;2063:48:3;;;;;;;;;;;;2132:31;;;-1:-1:-1;;;2132:31:3;;;;:14;;;;;:29;;:31;;;;;;;;;;;;;;:14;:31;;;2:2:-1;;;;27:1;24;17:12;2:2;2132:31:3;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2132:31:3;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;2132:31:3;2121:3;:43;;-1:-1:-1;;;;;;2121:43:3;;;-1:-1:-1;;;;;2121:43:3;;;;;;;2174:5;:21;;;;;;;;;;2205:20;:44;;;;;;;;;;2259:16;:36;;;2305:21;:46;;;;;;;;;;;;;;2361:30;2373:17;2361:11;:30::i;:::-;2434:5;:14;;-1:-1:-1;;;;;;2434:14:3;-1:-1:-1;;;;;2434:14:3;;;;;2458:28;2479:6;2458:20;:28::i;:::-;1528:965;;;;;;;;:::o;793:18::-;;;-1:-1:-1;;;;;793:18:3;;:::o;874:176:17:-;932:7;963:5;;;986:6;;;;978:46;;;;;-1:-1:-1;;;978:46:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;-1:-1:-1;874:176:17;;;;;:::o;1321:134::-;1379:7;1405:43;1409:1;1412;1405:43;;;;;;;;;;;;;;;;;:3;:43::i;2180:459::-;2238:7;2479:6;2475:45;;-1:-1:-1;2508:1:17;2501:8;;2475:45;2542:5;;;2546:1;2542;:5;:1;2565:5;;;;;:10;2557:56;;;;-1:-1:-1;;;2557:56:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3101:130;3159:7;3185:39;3189:1;3192;3185:39;;;;;;;;;;;;;;;;;:3;:39::i;1371:393:0:-;1510:13;1535:16;1564:23;1578:8;1564:13;:23::i;:::-;1554:34;;;;;;;1639:114;;;-1:-1:-1;;;;;;1639:114:0;;;;-1:-1:-1;;1639:114:0;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;1639:114:0;;;;1629:125;;;;;;-1:-1:-1;;1371:393:0;;;;;:::o;1746:187:17:-;1832:7;1867:12;1859:6;;;;1851:29;;;;-1:-1:-1;;;1851:29:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;1851:29:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1902:5:17;;;1746:187::o;3713:272::-;3799:7;3833:12;3826:5;3818:28;;;;-1:-1:-1;;;3818:28:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;3818:28:17;;3856:9;3872:1;3868;:5;;;;;;;3713:272;-1:-1:-1;;;;;3713:272:17:o;504:712:0:-;683:4;677:11;;724:4;714:15;;701:29;;;840:4;827:18;;-1:-1:-1;;;973:4:0;963:15;;956:91;568:17;619;;;;1077:4;1067:15;;1060:36;-1:-1:-1;;;1126:4:0;1116:15;;1109:91;677:11;655:555::o", + "source": "pragma solidity 0.6.6;\n\nimport \"openzeppelin-solidity/contracts/token/ERC20/ERC20.sol\";\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\nimport \"./Ownable.sol\"; // TODO: switch to \"openzeppelin-solidity/contracts/access/Ownable.sol\";\nimport \"./PurchaseListener.sol\";\nimport \"./CloneLib.sol\";\nimport \"./IAMB.sol\";\nimport \"./ITokenMediator.sol\";\n\ncontract DataUnionMainnet is Ownable, PurchaseListener {\n using SafeMath for uint256;\n\n event AdminFeeChanged(uint256 adminFee);\n event AdminFeeCharged(uint256 amount);\n event AdminFeesWithdrawn(address indexed admin, uint256 amount);\n\n event RevenueReceived(uint256 amount);\n\n IAMB public amb;\n ITokenMediator public token_mediator;\n address public sidechain_DU_factory;\n uint256 public sidechain_maxgas;\n ERC20 public token;\n\n/*\n NOTE: any variables set below will NOT be visible in clones\n clones must set variables in initialize()\n*/\n\n // needed to compute sidechain address\n address public sidechain_template_DU;\n uint256 public adminFeeFraction;\n uint256 public totalAdminFees;\n uint256 public totalAdminFeesWithdrawn;\n bool public autoSendAdminFee;\n\n function version() public pure returns (uint256) { return 2; }\n\n /*\n totalEarnings includes:\n member earnings (ie revenue - admin fees)\n tokens held for members via transferToMemberInContract()\n\n totalRevenue = totalEarnings + totalAdminFees;\n*/\n uint256 public totalEarnings;\n\n\n constructor() public Ownable(address(0)) {}\n\n function initialize(\n address _token,\n address _token_mediator,\n address _sidechain_DU_factory,\n uint256 _sidechain_maxgas,\n address _sidechain_template_DU,\n address _owner,\n uint256 _adminFeeFraction,\n address[] memory agents\n ) public {\n require(!isInitialized(), \"init_once\");\n // must set default values here so that there are in clone state\n autoSendAdminFee = true;\n\n //during setup, msg.sender is admin\n owner = msg.sender;\n\n token_mediator = ITokenMediator(_token_mediator);\n amb = IAMB(token_mediator.bridgeContract());\n token = ERC20(_token);\n sidechain_DU_factory = _sidechain_DU_factory;\n sidechain_maxgas = _sidechain_maxgas;\n sidechain_template_DU = _sidechain_template_DU;\n setAdminFee(_adminFeeFraction);\n //transfer to real admin\n owner = _owner;\n deployNewDUSidechain(agents);\n }\n\n function isInitialized() public view returns (bool) {\n return address(token) != address(0);\n }\n\n /**\n * Admin fee as a fraction of revenue.\n * @param newAdminFee fixed-point decimal in the same way as ether: 50% === 0.5 ether === \"500000000000000000\"\n */\n function setAdminFee(uint256 newAdminFee) public onlyOwner {\n require(newAdminFee <= 1 ether, \"error_adminFee\");\n adminFeeFraction = newAdminFee;\n emit AdminFeeChanged(adminFeeFraction);\n }\n\n function setAutoSendAdminFee(bool autoSend) public onlyOwner {\n autoSendAdminFee = autoSend;\n }\n\n\n function deployNewDUSidechain(address[] memory agents) public {\n bytes memory data = abi.encodeWithSignature(\"deployNewDUSidechain(address,address[])\", owner, agents);\n amb.requireToPassMessage(sidechain_DU_factory, data, sidechain_maxgas);\n }\n\n function sidechainAddress() public view returns (address) {\n return CloneLib.predictCloneAddressCreate2(sidechain_template_DU, sidechain_DU_factory, bytes32(uint256(address(this))));\n }\n\n/*\n2 way doesnt work atm\n //calls withdraw(member) on home network\n function withdraw(address member) public {\n bytes memory data = abi.encodeWithSignature(\n \"withdraw(address,bool)\",\n member,\n true\n );\n amb.requireToPassMessage(sidechainAddress(), data, sidechain_maxgas);\n }\n */\n\n //function onPurchase(bytes32 productId, address subscriber, uint256 endTimestamp, uint256 priceDatacoin, uint256 feeDatacoin)\n function onPurchase(bytes32, address, uint256, uint256, uint256) external override returns (bool) {\n sendTokensToBridge();\n return true;\n }\n\n function adminFeesWithdrawable() public view returns (uint256) {\n return totalAdminFees.sub(totalAdminFeesWithdrawn);\n }\n\n function unaccountedTokens() public view returns (uint256) {\n return token.balanceOf(address(this)).sub(adminFeesWithdrawable());\n }\n\n\n function sendTokensToBridge() public returns (uint256) {\n uint256 newTokens = unaccountedTokens();\n if (newTokens == 0) return 0;\n\n emit RevenueReceived(newTokens);\n\n uint256 adminFee = newTokens.mul(adminFeeFraction).div(10**18);\n uint256 memberEarnings = newTokens.sub(adminFee);\n\n totalAdminFees = totalAdminFees.add(adminFee);\n emit AdminFeeCharged(adminFee);\n if(autoSendAdminFee) withdrawAdminFees();\n\n // transfer memberEarnings\n require(token.approve(address(token_mediator), 0), \"approve_failed\");\n require(token.approve(address(token_mediator), memberEarnings), \"approve_failed\");\n bytes4 bridgeMode = token_mediator.getBridgeMode();\n //MultiAMB 0xb1516c26 == bytes4(keccak256(abi.encodePacked(\"multi-erc-to-erc-amb\")))\n //Single token AMB 0x76595b56 == bytes4(keccak256(abi.encodePacked(\"erc-to-erc-amb\")))\n if(bridgeMode == 0xb1516c26) {\n token_mediator.relayTokens(address(token), sidechainAddress(), memberEarnings);\n }\n else if(bridgeMode == 0x76595b56){\n token_mediator.relayTokens(sidechainAddress(), memberEarnings);\n }\n else{\n revert(\"unknown_bridge_mode\");\n }\n\n //check that memberEarnings were sent\n require(unaccountedTokens() == 0, \"not_transferred\");\n totalEarnings = totalEarnings.add(memberEarnings);\n\n bytes memory data = abi.encodeWithSignature(\"refreshRevenue()\");\n amb.requireToPassMessage(sidechainAddress(), data, sidechain_maxgas);\n return newTokens;\n }\n\n function withdrawAdminFees() public returns (uint256) {\n uint256 withdrawable = adminFeesWithdrawable();\n if (withdrawable == 0) return 0;\n totalAdminFeesWithdrawn = totalAdminFeesWithdrawn.add(withdrawable);\n require(token.transfer(owner, withdrawable), \"transfer_failed\");\n emit AdminFeesWithdrawn(owner, withdrawable);\n return withdrawable;\n }\n}\n", + "sourcePath": "/home/heynow/streamr/data-union-solidity/contracts/DataUnionMainnet.sol", + "ast": { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/DataUnionMainnet.sol", + "exportedSymbols": { + "DataUnionMainnet": [ + 1165 + ] + }, + "id": 1166, + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 668, + "literals": [ + "solidity", + "0.6", + ".6" + ], + "nodeType": "PragmaDirective", + "src": "0:22:3" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol", + "file": "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol", + "id": 669, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 4149, + "src": "24:63:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "file": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "id": 670, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 3642, + "src": "88:59:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/Ownable.sol", + "file": "./Ownable.sol", + "id": 671, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 3181, + "src": "148:23:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/PurchaseListener.sol", + "file": "./PurchaseListener.sol", + "id": 672, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 3200, + "src": "245:32:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/CloneLib.sol", + "file": "./CloneLib.sol", + "id": 673, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 155, + "src": "278:24:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/IAMB.sol", + "file": "./IAMB.sol", + "id": 674, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 2913, + "src": "303:20:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/ITokenMediator.sol", + "file": "./ITokenMediator.sol", + "id": 675, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 2969, + "src": "324:30:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "abstract": false, + "baseContracts": [ + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 676, + "name": "Ownable", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 3180, + "src": "385:7:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_Ownable_$3180", + "typeString": "contract Ownable" + } + }, + "id": 677, + "nodeType": "InheritanceSpecifier", + "src": "385:7:3" + }, + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 678, + "name": "PurchaseListener", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 3199, + "src": "394:16:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_PurchaseListener_$3199", + "typeString": "contract PurchaseListener" + } + }, + "id": 679, + "nodeType": "InheritanceSpecifier", + "src": "394:16:3" + } + ], + "contractDependencies": [ + 3180, + 3199 + ], + "contractKind": "contract", + "documentation": null, + "fullyImplemented": true, + "id": 1165, + "linearizedBaseContracts": [ + 1165, + 3199, + 3180 + ], + "name": "DataUnionMainnet", + "nodeType": "ContractDefinition", + "nodes": [ + { + "id": 682, + "libraryName": { + "contractScope": null, + "id": 680, + "name": "SafeMath", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 3641, + "src": "423:8:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_SafeMath_$3641", + "typeString": "library SafeMath" + } + }, + "nodeType": "UsingForDirective", + "src": "417:27:3", + "typeName": { + "id": 681, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "436:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + }, + { + "anonymous": false, + "documentation": null, + "id": 686, + "name": "AdminFeeChanged", + "nodeType": "EventDefinition", + "parameters": { + "id": 685, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 684, + "indexed": false, + "mutability": "mutable", + "name": "adminFee", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 686, + "src": "472:16:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 683, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "472:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "471:18:3" + }, + "src": "450:40:3" + }, + { + "anonymous": false, + "documentation": null, + "id": 690, + "name": "AdminFeeCharged", + "nodeType": "EventDefinition", + "parameters": { + "id": 689, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 688, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 690, + "src": "517:14:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 687, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "517:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "516:16:3" + }, + "src": "495:38:3" + }, + { + "anonymous": false, + "documentation": null, + "id": 696, + "name": "AdminFeesWithdrawn", + "nodeType": "EventDefinition", + "parameters": { + "id": 695, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 692, + "indexed": true, + "mutability": "mutable", + "name": "admin", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 696, + "src": "563:21:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 691, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "563:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 694, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 696, + "src": "586:14:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 693, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "586:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "562:39:3" + }, + "src": "538:64:3" + }, + { + "anonymous": false, + "documentation": null, + "id": 700, + "name": "RevenueReceived", + "nodeType": "EventDefinition", + "parameters": { + "id": 699, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 698, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 700, + "src": "630:14:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 697, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "630:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "629:16:3" + }, + "src": "608:38:3" + }, + { + "constant": false, + "functionSelector": "1062b39a", + "id": 702, + "mutability": "mutable", + "name": "amb", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "652:15:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + }, + "typeName": { + "contractScope": null, + "id": 701, + "name": "IAMB", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2912, + "src": "652:4:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "c5a8c91f", + "id": 704, + "mutability": "mutable", + "name": "token_mediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "673:36:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + }, + "typeName": { + "contractScope": null, + "id": 703, + "name": "ITokenMediator", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2968, + "src": "673:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "e22ec112", + "id": 706, + "mutability": "mutable", + "name": "sidechain_DU_factory", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "715:35:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 705, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "715:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "692199d4", + "id": 708, + "mutability": "mutable", + "name": "sidechain_maxgas", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "756:31:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 707, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "756:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "fc0c546a", + "id": 710, + "mutability": "mutable", + "name": "token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "793:18:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + }, + "typeName": { + "contractScope": null, + "id": 709, + "name": "ERC20", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 4148, + "src": "793:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "a65c87d9", + "id": 712, + "mutability": "mutable", + "name": "sidechain_template_DU", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "978:36:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 711, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "978:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "d35cec40", + "id": 714, + "mutability": "mutable", + "name": "adminFeeFraction", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "1020:31:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 713, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1020:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "61feacff", + "id": 716, + "mutability": "mutable", + "name": "totalAdminFees", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "1057:29:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 715, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1057:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "a913f41d", + "id": 718, + "mutability": "mutable", + "name": "totalAdminFeesWithdrawn", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "1092:38:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 717, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1092:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "9eeba07c", + "id": 720, + "mutability": "mutable", + "name": "autoSendAdminFee", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "1136:28:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 719, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "1136:4:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "public" + }, + { + "body": { + "id": 727, + "nodeType": "Block", + "src": "1220:13:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "hexValue": "32", + "id": 725, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1229:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_2_by_1", + "typeString": "int_const 2" + }, + "value": "2" + }, + "functionReturnParameters": 724, + "id": 726, + "nodeType": "Return", + "src": "1222:8:3" + } + ] + }, + "documentation": null, + "functionSelector": "54fd4d50", + "id": 728, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "version", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 721, + "nodeType": "ParameterList", + "parameters": [], + "src": "1187:2:3" + }, + "returnParameters": { + "id": 724, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 723, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 728, + "src": "1211:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 722, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1211:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1210:9:3" + }, + "scope": 1165, + "src": "1171:62:3", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "2df3eba4", + "id": 730, + "mutability": "mutable", + "name": "totalEarnings", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "1443:28:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 729, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1443:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "body": { + "id": 739, + "nodeType": "Block", + "src": "1520:2:3", + "statements": [] + }, + "documentation": null, + "id": 740, + "implemented": true, + "kind": "constructor", + "modifiers": [ + { + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "30", + "id": 735, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1516:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "id": 734, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "1508:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 733, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1508:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 736, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1508:10:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "id": 737, + "modifierName": { + "argumentTypes": null, + "id": 732, + "name": "Ownable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3180, + "src": "1500:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_Ownable_$3180_$", + "typeString": "type(contract Ownable)" + } + }, + "nodeType": "ModifierInvocation", + "src": "1500:19:3" + } + ], + "name": "", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 731, + "nodeType": "ParameterList", + "parameters": [], + "src": "1490:2:3" + }, + "returnParameters": { + "id": 738, + "nodeType": "ParameterList", + "parameters": [], + "src": "1520:0:3" + }, + "scope": 1165, + "src": "1479:43:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 820, + "nodeType": "Block", + "src": "1825:668:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 763, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "!", + "prefix": true, + "src": "1843:16:3", + "subExpression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 761, + "name": "isInitialized", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 837, + "src": "1844:13:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_bool_$", + "typeString": "function () view returns (bool)" + } + }, + "id": 762, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1844:15:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "696e69745f6f6e6365", + "id": 764, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1861:11:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_489583184b3bb72a2d8c2cf7b5f4c46635517588498db21bc763656f9e5ab21e", + "typeString": "literal_string \"init_once\"" + }, + "value": "init_once" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_489583184b3bb72a2d8c2cf7b5f4c46635517588498db21bc763656f9e5ab21e", + "typeString": "literal_string \"init_once\"" + } + ], + "id": 760, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "1835:7:3", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 765, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1835:38:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 766, + "nodeType": "ExpressionStatement", + "src": "1835:38:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 769, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 767, + "name": "autoSendAdminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 720, + "src": "1956:16:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "hexValue": "74727565", + "id": 768, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "bool", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1975:4:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "value": "true" + }, + "src": "1956:23:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 770, + "nodeType": "ExpressionStatement", + "src": "1956:23:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 774, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 771, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "2034:5:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 772, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "2042:3:3", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 773, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2042:10:3", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "src": "2034:18:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 775, + "nodeType": "ExpressionStatement", + "src": "2034:18:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 780, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 776, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "2063:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 778, + "name": "_token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 744, + "src": "2095:15:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 777, + "name": "ITokenMediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2968, + "src": "2080:14:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_ITokenMediator_$2968_$", + "typeString": "type(contract ITokenMediator)" + } + }, + "id": 779, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2080:31:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "src": "2063:48:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 781, + "nodeType": "ExpressionStatement", + "src": "2063:48:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 788, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 782, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 702, + "src": "2121:3:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "argumentTypes": null, + "id": 784, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "2132:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 785, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "bridgeContract", + "nodeType": "MemberAccess", + "referencedDeclaration": 2946, + "src": "2132:29:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$__$returns$_t_address_$", + "typeString": "function () view external returns (address)" + } + }, + "id": 786, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2132:31:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 783, + "name": "IAMB", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2912, + "src": "2127:4:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_IAMB_$2912_$", + "typeString": "type(contract IAMB)" + } + }, + "id": 787, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2127:37:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "src": "2121:43:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "id": 789, + "nodeType": "ExpressionStatement", + "src": "2121:43:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 794, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 790, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "2174:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 792, + "name": "_token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 742, + "src": "2188:6:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 791, + "name": "ERC20", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 4148, + "src": "2182:5:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_ERC20_$4148_$", + "typeString": "type(contract ERC20)" + } + }, + "id": 793, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2182:13:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "src": "2174:21:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "id": 795, + "nodeType": "ExpressionStatement", + "src": "2174:21:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 798, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 796, + "name": "sidechain_DU_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 706, + "src": "2205:20:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 797, + "name": "_sidechain_DU_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 746, + "src": "2228:21:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2205:44:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 799, + "nodeType": "ExpressionStatement", + "src": "2205:44:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 802, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 800, + "name": "sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 708, + "src": "2259:16:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 801, + "name": "_sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 748, + "src": "2278:17:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "2259:36:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 803, + "nodeType": "ExpressionStatement", + "src": "2259:36:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 806, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 804, + "name": "sidechain_template_DU", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 712, + "src": "2305:21:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 805, + "name": "_sidechain_template_DU", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 750, + "src": "2329:22:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2305:46:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 807, + "nodeType": "ExpressionStatement", + "src": "2305:46:3" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 809, + "name": "_adminFeeFraction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 754, + "src": "2373:17:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 808, + "name": "setAdminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 861, + "src": "2361:11:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 810, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2361:30:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 811, + "nodeType": "ExpressionStatement", + "src": "2361:30:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 814, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 812, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "2434:5:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 813, + "name": "_owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 752, + "src": "2442:6:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2434:14:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 815, + "nodeType": "ExpressionStatement", + "src": "2434:14:3" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 817, + "name": "agents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 757, + "src": "2479:6:3", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + ], + "id": 816, + "name": "deployNewDUSidechain", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 897, + "src": "2458:20:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_array$_t_address_$dyn_memory_ptr_$returns$__$", + "typeString": "function (address[] memory)" + } + }, + "id": 818, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2458:28:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 819, + "nodeType": "ExpressionStatement", + "src": "2458:28:3" + } + ] + }, + "documentation": null, + "functionSelector": "fb6470c9", + "id": 821, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "initialize", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 758, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 742, + "mutability": "mutable", + "name": "_token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1557:14:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 741, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1557:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 744, + "mutability": "mutable", + "name": "_token_mediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1581:23:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 743, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1581:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 746, + "mutability": "mutable", + "name": "_sidechain_DU_factory", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1614:29:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 745, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1614:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 748, + "mutability": "mutable", + "name": "_sidechain_maxgas", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1653:25:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 747, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1653:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 750, + "mutability": "mutable", + "name": "_sidechain_template_DU", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1688:30:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 749, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1688:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 752, + "mutability": "mutable", + "name": "_owner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1728:14:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 751, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1728:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 754, + "mutability": "mutable", + "name": "_adminFeeFraction", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1752:25:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 753, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1752:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 757, + "mutability": "mutable", + "name": "agents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1787:23:3", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 755, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1787:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 756, + "length": null, + "nodeType": "ArrayTypeName", + "src": "1787:9:3", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1547:269:3" + }, + "returnParameters": { + "id": 759, + "nodeType": "ParameterList", + "parameters": [], + "src": "1825:0:3" + }, + "scope": 1165, + "src": "1528:965:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 836, + "nodeType": "Block", + "src": "2551:52:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 834, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 828, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "2576:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + ], + "id": 827, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2568:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 826, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2568:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 829, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2568:14:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "30", + "id": 832, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2594:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "id": 831, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2586:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 830, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2586:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 833, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2586:10:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "src": "2568:28:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "functionReturnParameters": 825, + "id": 835, + "nodeType": "Return", + "src": "2561:35:3" + } + ] + }, + "documentation": null, + "functionSelector": "392e53cd", + "id": 837, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "isInitialized", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 822, + "nodeType": "ParameterList", + "parameters": [], + "src": "2521:2:3" + }, + "returnParameters": { + "id": 825, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 824, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 837, + "src": "2545:4:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 823, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "2545:4:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2544:6:3" + }, + "scope": 1165, + "src": "2499:104:3", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 860, + "nodeType": "Block", + "src": "2842:154:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 848, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 846, + "name": "newAdminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 840, + "src": "2860:11:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "<=", + "rightExpression": { + "argumentTypes": null, + "hexValue": "31", + "id": 847, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2875:7:3", + "subdenomination": "ether", + "typeDescriptions": { + "typeIdentifier": "t_rational_1000000000000000000_by_1", + "typeString": "int_const 1000000000000000000" + }, + "value": "1" + }, + "src": "2860:22:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f61646d696e466565", + "id": 849, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2884:16:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_c137fd2ee13f1c30c5cc71b65e2c7f49f5120b580d70d8298b6185b09e6c1e40", + "typeString": "literal_string \"error_adminFee\"" + }, + "value": "error_adminFee" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_c137fd2ee13f1c30c5cc71b65e2c7f49f5120b580d70d8298b6185b09e6c1e40", + "typeString": "literal_string \"error_adminFee\"" + } + ], + "id": 845, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "2852:7:3", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 850, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2852:49:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 851, + "nodeType": "ExpressionStatement", + "src": "2852:49:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 854, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 852, + "name": "adminFeeFraction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 714, + "src": "2911:16:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 853, + "name": "newAdminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 840, + "src": "2930:11:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "2911:30:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 855, + "nodeType": "ExpressionStatement", + "src": "2911:30:3" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 857, + "name": "adminFeeFraction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 714, + "src": "2972:16:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 856, + "name": "AdminFeeChanged", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 686, + "src": "2956:15:3", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 858, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2956:33:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 859, + "nodeType": "EmitStatement", + "src": "2951:38:3" + } + ] + }, + "documentation": { + "id": 838, + "nodeType": "StructuredDocumentation", + "src": "2609:169:3", + "text": "Admin fee as a fraction of revenue.\n@param newAdminFee fixed-point decimal in the same way as ether: 50% === 0.5 ether === \"500000000000000000\"" + }, + "functionSelector": "8beb60b6", + "id": 861, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 843, + "modifierName": { + "argumentTypes": null, + "id": 842, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "2832:9:3", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "2832:9:3" + } + ], + "name": "setAdminFee", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 841, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 840, + "mutability": "mutable", + "name": "newAdminFee", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 861, + "src": "2804:19:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 839, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2804:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2803:21:3" + }, + "returnParameters": { + "id": 844, + "nodeType": "ParameterList", + "parameters": [], + "src": "2842:0:3" + }, + "scope": 1165, + "src": "2783:213:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 872, + "nodeType": "Block", + "src": "3063:44:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 870, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 868, + "name": "autoSendAdminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 720, + "src": "3073:16:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 869, + "name": "autoSend", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 863, + "src": "3092:8:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "3073:27:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 871, + "nodeType": "ExpressionStatement", + "src": "3073:27:3" + } + ] + }, + "documentation": null, + "functionSelector": "0f3afcbe", + "id": 873, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 866, + "modifierName": { + "argumentTypes": null, + "id": 865, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "3053:9:3", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "3053:9:3" + } + ], + "name": "setAutoSendAdminFee", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 864, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 863, + "mutability": "mutable", + "name": "autoSend", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 873, + "src": "3031:13:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 862, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "3031:4:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3030:15:3" + }, + "returnParameters": { + "id": 867, + "nodeType": "ParameterList", + "parameters": [], + "src": "3063:0:3" + }, + "scope": 1165, + "src": "3002:105:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 896, + "nodeType": "Block", + "src": "3176:198:3", + "statements": [ + { + "assignments": [ + 880 + ], + "declarations": [ + { + "constant": false, + "id": 880, + "mutability": "mutable", + "name": "data", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 896, + "src": "3186:17:3", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 879, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "3186:5:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 887, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "6465706c6f794e6577445553696465636861696e28616464726573732c616464726573735b5d29", + "id": 883, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3230:41:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_325ff66f80d01e2243bd492c3b38e663416cd478dca0ff43243ddb11328dca3f", + "typeString": "literal_string \"deployNewDUSidechain(address,address[])\"" + }, + "value": "deployNewDUSidechain(address,address[])" + }, + { + "argumentTypes": null, + "id": 884, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "3273:5:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 885, + "name": "agents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 876, + "src": "3280:6:3", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_325ff66f80d01e2243bd492c3b38e663416cd478dca0ff43243ddb11328dca3f", + "typeString": "literal_string \"deployNewDUSidechain(address,address[])\"" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + ], + "expression": { + "argumentTypes": null, + "id": 881, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "3206:3:3", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 882, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encodeWithSignature", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3206:23:3", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (string memory) pure returns (bytes memory)" + } + }, + "id": 886, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3206:81:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "3186:101:3" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 891, + "name": "sidechain_DU_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 706, + "src": "3322:20:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 892, + "name": "data", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 880, + "src": "3344:4:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 893, + "name": "sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 708, + "src": "3350:16:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 888, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 702, + "src": "3297:3:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "id": 890, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "requireToPassMessage", + "nodeType": "MemberAccess", + "referencedDeclaration": 2911, + "src": "3297:24:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_bytes_memory_ptr_$_t_uint256_$returns$_t_bytes32_$", + "typeString": "function (address,bytes memory,uint256) external returns (bytes32)" + } + }, + "id": 894, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3297:70:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "id": 895, + "nodeType": "ExpressionStatement", + "src": "3297:70:3" + } + ] + }, + "documentation": null, + "functionSelector": "99dd1c81", + "id": 897, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "deployNewDUSidechain", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 877, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 876, + "mutability": "mutable", + "name": "agents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 897, + "src": "3144:23:3", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 874, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3144:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 875, + "length": null, + "nodeType": "ArrayTypeName", + "src": "3144:9:3", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3143:25:3" + }, + "returnParameters": { + "id": 878, + "nodeType": "ParameterList", + "parameters": [], + "src": "3176:0:3" + }, + "scope": 1165, + "src": "3114:260:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 918, + "nodeType": "Block", + "src": "3438:137:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 904, + "name": "sidechain_template_DU", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 712, + "src": "3491:21:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 905, + "name": "sidechain_DU_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 706, + "src": "3514:20:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 912, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "3560:4:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionMainnet_$1165", + "typeString": "contract DataUnionMainnet" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionMainnet_$1165", + "typeString": "contract DataUnionMainnet" + } + ], + "id": 911, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "3552:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 910, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3552:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 913, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3552:13:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 909, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "3544:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 908, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "3544:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 914, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3544:22:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 907, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "3536:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes32_$", + "typeString": "type(bytes32)" + }, + "typeName": { + "id": 906, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "3536:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 915, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3536:31:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "argumentTypes": null, + "id": 902, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "3455:8:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 903, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "predictCloneAddressCreate2", + "nodeType": "MemberAccess", + "referencedDeclaration": 61, + "src": "3455:35:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$_t_address_$_t_bytes32_$returns$_t_address_$", + "typeString": "function (address,address,bytes32) pure returns (address)" + } + }, + "id": 916, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3455:113:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 901, + "id": 917, + "nodeType": "Return", + "src": "3448:120:3" + } + ] + }, + "documentation": null, + "functionSelector": "37b43a94", + "id": 919, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "sidechainAddress", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 898, + "nodeType": "ParameterList", + "parameters": [], + "src": "3405:2:3" + }, + "returnParameters": { + "id": 901, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 900, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 919, + "src": "3429:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 899, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3429:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3428:9:3" + }, + "scope": 1165, + "src": "3380:195:3", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "baseFunctions": [ + 3198 + ], + "body": { + "id": 940, + "nodeType": "Block", + "src": "4158:58:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 935, + "name": "sendTokensToBridge", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1124, + "src": "4168:18:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$__$returns$_t_uint256_$", + "typeString": "function () returns (uint256)" + } + }, + "id": 936, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4168:20:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 937, + "nodeType": "ExpressionStatement", + "src": "4168:20:3" + }, + { + "expression": { + "argumentTypes": null, + "hexValue": "74727565", + "id": 938, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "bool", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4205:4:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "value": "true" + }, + "functionReturnParameters": 934, + "id": 939, + "nodeType": "Return", + "src": "4198:11:3" + } + ] + }, + "documentation": null, + "functionSelector": "4a439cc0", + "id": 941, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "onPurchase", + "nodeType": "FunctionDefinition", + "overrides": { + "id": 931, + "nodeType": "OverrideSpecifier", + "overrides": [], + "src": "4134:8:3" + }, + "parameters": { + "id": 930, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 921, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 941, + "src": "4080:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 920, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "4080:7:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 923, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 941, + "src": "4089:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 922, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4089:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 925, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 941, + "src": "4098:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 924, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4098:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 927, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 941, + "src": "4107:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 926, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4107:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 929, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 941, + "src": "4116:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 928, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4116:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4079:45:3" + }, + "returnParameters": { + "id": 934, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 933, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 941, + "src": "4152:4:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 932, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "4152:4:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4151:6:3" + }, + "scope": 1165, + "src": "4060:156:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "external" + }, + { + "body": { + "id": 951, + "nodeType": "Block", + "src": "4285:67:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 948, + "name": "totalAdminFeesWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 718, + "src": "4321:23:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 946, + "name": "totalAdminFees", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 716, + "src": "4302:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 947, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "4302:18:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 949, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4302:43:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 945, + "id": 950, + "nodeType": "Return", + "src": "4295:50:3" + } + ] + }, + "documentation": null, + "functionSelector": "13fd3c56", + "id": 952, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "adminFeesWithdrawable", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 942, + "nodeType": "ParameterList", + "parameters": [], + "src": "4252:2:3" + }, + "returnParameters": { + "id": 945, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 944, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 952, + "src": "4276:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 943, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4276:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4275:9:3" + }, + "scope": 1165, + "src": "4222:130:3", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 969, + "nodeType": "Block", + "src": "4417:83:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 965, + "name": "adminFeesWithdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 952, + "src": "4469:21:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 966, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4469:23:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 961, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "4458:4:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionMainnet_$1165", + "typeString": "contract DataUnionMainnet" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionMainnet_$1165", + "typeString": "contract DataUnionMainnet" + } + ], + "id": 960, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "4450:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 959, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4450:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 962, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4450:13:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "argumentTypes": null, + "id": 957, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "4434:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "id": 958, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balanceOf", + "nodeType": "MemberAccess", + "referencedDeclaration": 3748, + "src": "4434:15:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view external returns (uint256)" + } + }, + "id": 963, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4434:30:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 964, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "4434:34:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 967, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4434:59:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 956, + "id": 968, + "nodeType": "Return", + "src": "4427:66:3" + } + ] + }, + "documentation": null, + "functionSelector": "132b4194", + "id": 970, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "unaccountedTokens", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 953, + "nodeType": "ParameterList", + "parameters": [], + "src": "4384:2:3" + }, + "returnParameters": { + "id": 956, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 955, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 970, + "src": "4408:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 954, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4408:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4407:9:3" + }, + "scope": 1165, + "src": "4358:142:3", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1123, + "nodeType": "Block", + "src": "4562:1550:3", + "statements": [ + { + "assignments": [ + 976 + ], + "declarations": [ + { + "constant": false, + "id": 976, + "mutability": "mutable", + "name": "newTokens", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1123, + "src": "4572:17:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 975, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4572:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 979, + "initialValue": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 977, + "name": "unaccountedTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 970, + "src": "4592:17:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 978, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4592:19:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "4572:39:3" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 982, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 980, + "name": "newTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 976, + "src": "4625:9:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 981, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4638:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "4625:14:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 985, + "nodeType": "IfStatement", + "src": "4621:28:3", + "trueBody": { + "expression": { + "argumentTypes": null, + "hexValue": "30", + "id": 983, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4648:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "functionReturnParameters": 974, + "id": 984, + "nodeType": "Return", + "src": "4641:8:3" + } + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 987, + "name": "newTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 976, + "src": "4681:9:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 986, + "name": "RevenueReceived", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 700, + "src": "4665:15:3", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 988, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4665:26:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 989, + "nodeType": "EmitStatement", + "src": "4660:31:3" + }, + { + "assignments": [ + 991 + ], + "declarations": [ + { + "constant": false, + "id": 991, + "mutability": "mutable", + "name": "adminFee", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1123, + "src": "4702:16:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 990, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4702:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1001, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_rational_1000000000000000000_by_1", + "typeString": "int_const 1000000000000000000" + }, + "id": 999, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "hexValue": "3130", + "id": 997, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4757:2:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_10_by_1", + "typeString": "int_const 10" + }, + "value": "10" + }, + "nodeType": "BinaryOperation", + "operator": "**", + "rightExpression": { + "argumentTypes": null, + "hexValue": "3138", + "id": 998, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4761:2:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_18_by_1", + "typeString": "int_const 18" + }, + "value": "18" + }, + "src": "4757:6:3", + "typeDescriptions": { + "typeIdentifier": "t_rational_1000000000000000000_by_1", + "typeString": "int_const 1000000000000000000" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1000000000000000000_by_1", + "typeString": "int_const 1000000000000000000" + } + ], + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 994, + "name": "adminFeeFraction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 714, + "src": "4735:16:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 992, + "name": "newTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 976, + "src": "4721:9:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 993, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "mul", + "nodeType": "MemberAccess", + "referencedDeclaration": 3554, + "src": "4721:13:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 995, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4721:31:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 996, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "div", + "nodeType": "MemberAccess", + "referencedDeclaration": 3571, + "src": "4721:35:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1000, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4721:43:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "4702:62:3" + }, + { + "assignments": [ + 1003 + ], + "declarations": [ + { + "constant": false, + "id": 1003, + "mutability": "mutable", + "name": "memberEarnings", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1123, + "src": "4774:22:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1002, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4774:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1008, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1006, + "name": "adminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 991, + "src": "4813:8:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1004, + "name": "newTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 976, + "src": "4799:9:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1005, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "4799:13:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1007, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4799:23:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "4774:48:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 1014, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1009, + "name": "totalAdminFees", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 716, + "src": "4833:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1012, + "name": "adminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 991, + "src": "4869:8:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1010, + "name": "totalAdminFees", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 716, + "src": "4850:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1011, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "4850:18:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1013, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4850:28:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "4833:45:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1015, + "nodeType": "ExpressionStatement", + "src": "4833:45:3" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1017, + "name": "adminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 991, + "src": "4909:8:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1016, + "name": "AdminFeeCharged", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 690, + "src": "4893:15:3", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 1018, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4893:25:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1019, + "nodeType": "EmitStatement", + "src": "4888:30:3" + }, + { + "condition": { + "argumentTypes": null, + "id": 1020, + "name": "autoSendAdminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 720, + "src": "4931:16:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1024, + "nodeType": "IfStatement", + "src": "4928:40:3", + "trueBody": { + "expression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1021, + "name": "withdrawAdminFees", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1164, + "src": "4949:17:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$__$returns$_t_uint256_$", + "typeString": "function () returns (uint256)" + } + }, + "id": 1022, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4949:19:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1023, + "nodeType": "ExpressionStatement", + "src": "4949:19:3" + } + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1030, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "5044:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + ], + "id": 1029, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "5036:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1028, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "5036:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1031, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5036:23:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "hexValue": "30", + "id": 1032, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5061:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "expression": { + "argumentTypes": null, + "id": 1026, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "5022:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "id": 1027, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "approve", + "nodeType": "MemberAccess", + "referencedDeclaration": 3808, + "src": "5022:13:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_uint256_$returns$_t_bool_$", + "typeString": "function (address,uint256) external returns (bool)" + } + }, + "id": 1033, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5022:41:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "617070726f76655f6661696c6564", + "id": 1034, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5065:16:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_0b99e75f7873826fa8b33e45f5babad412309f79417b9b0000257bd68fa2b8a3", + "typeString": "literal_string \"approve_failed\"" + }, + "value": "approve_failed" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_0b99e75f7873826fa8b33e45f5babad412309f79417b9b0000257bd68fa2b8a3", + "typeString": "literal_string \"approve_failed\"" + } + ], + "id": 1025, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "5014:7:3", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1035, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5014:68:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1036, + "nodeType": "ExpressionStatement", + "src": "5014:68:3" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1042, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "5122:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + ], + "id": 1041, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "5114:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1040, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "5114:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1043, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5114:23:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1044, + "name": "memberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1003, + "src": "5139:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1038, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "5100:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "id": 1039, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "approve", + "nodeType": "MemberAccess", + "referencedDeclaration": 3808, + "src": "5100:13:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_uint256_$returns$_t_bool_$", + "typeString": "function (address,uint256) external returns (bool)" + } + }, + "id": 1045, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5100:54:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "617070726f76655f6661696c6564", + "id": 1046, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5156:16:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_0b99e75f7873826fa8b33e45f5babad412309f79417b9b0000257bd68fa2b8a3", + "typeString": "literal_string \"approve_failed\"" + }, + "value": "approve_failed" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_0b99e75f7873826fa8b33e45f5babad412309f79417b9b0000257bd68fa2b8a3", + "typeString": "literal_string \"approve_failed\"" + } + ], + "id": 1037, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "5092:7:3", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1047, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5092:81:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1048, + "nodeType": "ExpressionStatement", + "src": "5092:81:3" + }, + { + "assignments": [ + 1050 + ], + "declarations": [ + { + "constant": false, + "id": 1050, + "mutability": "mutable", + "name": "bridgeMode", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1123, + "src": "5183:17:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + }, + "typeName": { + "id": 1049, + "name": "bytes4", + "nodeType": "ElementaryTypeName", + "src": "5183:6:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1054, + "initialValue": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "argumentTypes": null, + "id": 1051, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "5203:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 1052, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "getBridgeMode", + "nodeType": "MemberAccess", + "referencedDeclaration": 2967, + "src": "5203:28:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_pure$__$returns$_t_bytes4_$", + "typeString": "function () pure external returns (bytes4)" + } + }, + "id": 1053, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5203:30:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "5183:50:3" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + }, + "id": 1057, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1055, + "name": "bridgeMode", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1050, + "src": "5435:10:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30786231353136633236", + "id": 1056, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5449:10:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_2974903334_by_1", + "typeString": "int_const 2974903334" + }, + "value": "0xb1516c26" + }, + "src": "5435:24:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + }, + "id": 1073, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1071, + "name": "bridgeMode", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1050, + "src": "5581:10:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30783736353935623536", + "id": 1072, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5595:10:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1985567574_by_1", + "typeString": "int_const 1985567574" + }, + "value": "0x76595b56" + }, + "src": "5581:24:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": { + "id": 1087, + "nodeType": "Block", + "src": "5706:54:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "756e6b6e6f776e5f6272696467655f6d6f6465", + "id": 1084, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5727:21:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_445d91fc79f5d76a26706ce2f1c866b8b57fad4e5d19ffc80c8c136306007969", + "typeString": "literal_string \"unknown_bridge_mode\"" + }, + "value": "unknown_bridge_mode" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_445d91fc79f5d76a26706ce2f1c866b8b57fad4e5d19ffc80c8c136306007969", + "typeString": "literal_string \"unknown_bridge_mode\"" + } + ], + "id": 1083, + "name": "revert", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -19, + -19 + ], + "referencedDeclaration": -19, + "src": "5720:6:3", + "typeDescriptions": { + "typeIdentifier": "t_function_revert_pure$_t_string_memory_ptr_$returns$__$", + "typeString": "function (string memory) pure" + } + }, + "id": 1085, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5720:29:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1086, + "nodeType": "ExpressionStatement", + "src": "5720:29:3" + } + ] + }, + "id": 1088, + "nodeType": "IfStatement", + "src": "5578:182:3", + "trueBody": { + "id": 1082, + "nodeType": "Block", + "src": "5606:87:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1077, + "name": "sidechainAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 919, + "src": "5647:16:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_address_$", + "typeString": "function () view returns (address)" + } + }, + "id": 1078, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5647:18:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1079, + "name": "memberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1003, + "src": "5667:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1074, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "5620:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 1076, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "relayTokens", + "nodeType": "MemberAccess", + "referencedDeclaration": 2962, + "src": "5620:26:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256) external" + } + }, + "id": 1080, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5620:62:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1081, + "nodeType": "ExpressionStatement", + "src": "5620:62:3" + } + ] + } + }, + "id": 1089, + "nodeType": "IfStatement", + "src": "5432:328:3", + "trueBody": { + "id": 1070, + "nodeType": "Block", + "src": "5461:103:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1063, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "5510:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + ], + "id": 1062, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "5502:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1061, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "5502:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1064, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5502:14:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1065, + "name": "sidechainAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 919, + "src": "5518:16:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_address_$", + "typeString": "function () view returns (address)" + } + }, + "id": 1066, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5518:18:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1067, + "name": "memberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1003, + "src": "5538:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1058, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "5475:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 1060, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "relayTokens", + "nodeType": "MemberAccess", + "referencedDeclaration": 2955, + "src": "5475:26:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,address,uint256) external" + } + }, + "id": 1068, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5475:78:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1069, + "nodeType": "ExpressionStatement", + "src": "5475:78:3" + } + ] + } + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1094, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1091, + "name": "unaccountedTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 970, + "src": "5824:17:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 1092, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5824:19:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1093, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5847:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "5824:24:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6e6f745f7472616e73666572726564", + "id": 1095, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5850:17:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_f8c2113376f862fd95528ef214ec6c4df8073d6ec53e0649e3a444e38c7f206c", + "typeString": "literal_string \"not_transferred\"" + }, + "value": "not_transferred" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_f8c2113376f862fd95528ef214ec6c4df8073d6ec53e0649e3a444e38c7f206c", + "typeString": "literal_string \"not_transferred\"" + } + ], + "id": 1090, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "5816:7:3", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1096, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5816:52:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1097, + "nodeType": "ExpressionStatement", + "src": "5816:52:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 1103, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1098, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 730, + "src": "5878:13:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1101, + "name": "memberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1003, + "src": "5912:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1099, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 730, + "src": "5894:13:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1100, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "5894:17:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1102, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5894:33:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "5878:49:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1104, + "nodeType": "ExpressionStatement", + "src": "5878:49:3" + }, + { + "assignments": [ + 1106 + ], + "declarations": [ + { + "constant": false, + "id": 1106, + "mutability": "mutable", + "name": "data", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1123, + "src": "5938:17:3", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 1105, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "5938:5:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1111, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "72656672657368526576656e75652829", + "id": 1109, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5982:18:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_331beb5f2892eb3ad8da75941af8f45f6a0e8580b91ecbb4c7fdf0219d1442a8", + "typeString": "literal_string \"refreshRevenue()\"" + }, + "value": "refreshRevenue()" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_331beb5f2892eb3ad8da75941af8f45f6a0e8580b91ecbb4c7fdf0219d1442a8", + "typeString": "literal_string \"refreshRevenue()\"" + } + ], + "expression": { + "argumentTypes": null, + "id": 1107, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "5958:3:3", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 1108, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encodeWithSignature", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "5958:23:3", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (string memory) pure returns (bytes memory)" + } + }, + "id": 1110, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5958:43:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "5938:63:3" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1115, + "name": "sidechainAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 919, + "src": "6036:16:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_address_$", + "typeString": "function () view returns (address)" + } + }, + "id": 1116, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6036:18:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1117, + "name": "data", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1106, + "src": "6056:4:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 1118, + "name": "sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 708, + "src": "6062:16:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1112, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 702, + "src": "6011:3:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "id": 1114, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "requireToPassMessage", + "nodeType": "MemberAccess", + "referencedDeclaration": 2911, + "src": "6011:24:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_bytes_memory_ptr_$_t_uint256_$returns$_t_bytes32_$", + "typeString": "function (address,bytes memory,uint256) external returns (bytes32)" + } + }, + "id": 1119, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6011:68:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "id": 1120, + "nodeType": "ExpressionStatement", + "src": "6011:68:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 1121, + "name": "newTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 976, + "src": "6096:9:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 974, + "id": 1122, + "nodeType": "Return", + "src": "6089:16:3" + } + ] + }, + "documentation": null, + "functionSelector": "2efc1007", + "id": 1124, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "sendTokensToBridge", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 971, + "nodeType": "ParameterList", + "parameters": [], + "src": "4534:2:3" + }, + "returnParameters": { + "id": 974, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 973, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1124, + "src": "4553:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 972, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4553:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4552:9:3" + }, + "scope": 1165, + "src": "4507:1605:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1163, + "nodeType": "Block", + "src": "6172:337:3", + "statements": [ + { + "assignments": [ + 1130 + ], + "declarations": [ + { + "constant": false, + "id": 1130, + "mutability": "mutable", + "name": "withdrawable", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1163, + "src": "6182:20:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1129, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "6182:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1133, + "initialValue": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1131, + "name": "adminFeesWithdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 952, + "src": "6205:21:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 1132, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6205:23:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "6182:46:3" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1136, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1134, + "name": "withdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1130, + "src": "6242:12:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1135, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6258:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "6242:17:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1139, + "nodeType": "IfStatement", + "src": "6238:31:3", + "trueBody": { + "expression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1137, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6268:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "functionReturnParameters": 1128, + "id": 1138, + "nodeType": "Return", + "src": "6261:8:3" + } + }, + { + "expression": { + "argumentTypes": null, + "id": 1145, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1140, + "name": "totalAdminFeesWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 718, + "src": "6279:23:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1143, + "name": "withdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1130, + "src": "6333:12:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1141, + "name": "totalAdminFeesWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 718, + "src": "6305:23:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1142, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "6305:27:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1144, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6305:41:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6279:67:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1146, + "nodeType": "ExpressionStatement", + "src": "6279:67:3" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1150, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "6379:5:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1151, + "name": "withdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1130, + "src": "6386:12:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1148, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "6364:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "id": 1149, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "transfer", + "nodeType": "MemberAccess", + "referencedDeclaration": 3769, + "src": "6364:14:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_uint256_$returns$_t_bool_$", + "typeString": "function (address,uint256) external returns (bool)" + } + }, + "id": 1152, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6364:35:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "7472616e736665725f6661696c6564", + "id": 1153, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6401:17:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_b8e9fee0fffb4680cf1dadd39ef447f97bcb04e1ca58d043770ea51a3c935e6c", + "typeString": "literal_string \"transfer_failed\"" + }, + "value": "transfer_failed" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_b8e9fee0fffb4680cf1dadd39ef447f97bcb04e1ca58d043770ea51a3c935e6c", + "typeString": "literal_string \"transfer_failed\"" + } + ], + "id": 1147, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "6356:7:3", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1154, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6356:63:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1155, + "nodeType": "ExpressionStatement", + "src": "6356:63:3" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1157, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "6453:5:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1158, + "name": "withdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1130, + "src": "6460:12:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1156, + "name": "AdminFeesWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 696, + "src": "6434:18:3", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256)" + } + }, + "id": 1159, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6434:39:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1160, + "nodeType": "EmitStatement", + "src": "6429:44:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 1161, + "name": "withdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1130, + "src": "6490:12:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 1128, + "id": 1162, + "nodeType": "Return", + "src": "6483:19:3" + } + ] + }, + "documentation": null, + "functionSelector": "0419b45a", + "id": 1164, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawAdminFees", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1125, + "nodeType": "ParameterList", + "parameters": [], + "src": "6144:2:3" + }, + "returnParameters": { + "id": 1128, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1127, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1164, + "src": "6163:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1126, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "6163:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "6162:9:3" + }, + "scope": 1165, + "src": "6118:391:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + } + ], + "scope": 1166, + "src": "356:6155:3" + } + ], + "src": "0:6512:3" + }, + "legacyAST": { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/DataUnionMainnet.sol", + "exportedSymbols": { + "DataUnionMainnet": [ + 1165 + ] + }, + "id": 1166, + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 668, + "literals": [ + "solidity", + "0.6", + ".6" + ], + "nodeType": "PragmaDirective", + "src": "0:22:3" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol", + "file": "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol", + "id": 669, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 4149, + "src": "24:63:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "file": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "id": 670, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 3642, + "src": "88:59:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/Ownable.sol", + "file": "./Ownable.sol", + "id": 671, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 3181, + "src": "148:23:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/PurchaseListener.sol", + "file": "./PurchaseListener.sol", + "id": 672, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 3200, + "src": "245:32:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/CloneLib.sol", + "file": "./CloneLib.sol", + "id": 673, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 155, + "src": "278:24:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/IAMB.sol", + "file": "./IAMB.sol", + "id": 674, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 2913, + "src": "303:20:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/ITokenMediator.sol", + "file": "./ITokenMediator.sol", + "id": 675, + "nodeType": "ImportDirective", + "scope": 1166, + "sourceUnit": 2969, + "src": "324:30:3", + "symbolAliases": [], + "unitAlias": "" + }, + { + "abstract": false, + "baseContracts": [ + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 676, + "name": "Ownable", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 3180, + "src": "385:7:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_Ownable_$3180", + "typeString": "contract Ownable" + } + }, + "id": 677, + "nodeType": "InheritanceSpecifier", + "src": "385:7:3" + }, + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 678, + "name": "PurchaseListener", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 3199, + "src": "394:16:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_PurchaseListener_$3199", + "typeString": "contract PurchaseListener" + } + }, + "id": 679, + "nodeType": "InheritanceSpecifier", + "src": "394:16:3" + } + ], + "contractDependencies": [ + 3180, + 3199 + ], + "contractKind": "contract", + "documentation": null, + "fullyImplemented": true, + "id": 1165, + "linearizedBaseContracts": [ + 1165, + 3199, + 3180 + ], + "name": "DataUnionMainnet", + "nodeType": "ContractDefinition", + "nodes": [ + { + "id": 682, + "libraryName": { + "contractScope": null, + "id": 680, + "name": "SafeMath", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 3641, + "src": "423:8:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_SafeMath_$3641", + "typeString": "library SafeMath" + } + }, + "nodeType": "UsingForDirective", + "src": "417:27:3", + "typeName": { + "id": 681, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "436:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + }, + { + "anonymous": false, + "documentation": null, + "id": 686, + "name": "AdminFeeChanged", + "nodeType": "EventDefinition", + "parameters": { + "id": 685, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 684, + "indexed": false, + "mutability": "mutable", + "name": "adminFee", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 686, + "src": "472:16:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 683, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "472:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "471:18:3" + }, + "src": "450:40:3" + }, + { + "anonymous": false, + "documentation": null, + "id": 690, + "name": "AdminFeeCharged", + "nodeType": "EventDefinition", + "parameters": { + "id": 689, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 688, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 690, + "src": "517:14:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 687, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "517:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "516:16:3" + }, + "src": "495:38:3" + }, + { + "anonymous": false, + "documentation": null, + "id": 696, + "name": "AdminFeesWithdrawn", + "nodeType": "EventDefinition", + "parameters": { + "id": 695, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 692, + "indexed": true, + "mutability": "mutable", + "name": "admin", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 696, + "src": "563:21:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 691, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "563:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 694, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 696, + "src": "586:14:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 693, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "586:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "562:39:3" + }, + "src": "538:64:3" + }, + { + "anonymous": false, + "documentation": null, + "id": 700, + "name": "RevenueReceived", + "nodeType": "EventDefinition", + "parameters": { + "id": 699, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 698, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 700, + "src": "630:14:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 697, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "630:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "629:16:3" + }, + "src": "608:38:3" + }, + { + "constant": false, + "functionSelector": "1062b39a", + "id": 702, + "mutability": "mutable", + "name": "amb", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "652:15:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + }, + "typeName": { + "contractScope": null, + "id": 701, + "name": "IAMB", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2912, + "src": "652:4:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "c5a8c91f", + "id": 704, + "mutability": "mutable", + "name": "token_mediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "673:36:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + }, + "typeName": { + "contractScope": null, + "id": 703, + "name": "ITokenMediator", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2968, + "src": "673:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "e22ec112", + "id": 706, + "mutability": "mutable", + "name": "sidechain_DU_factory", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "715:35:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 705, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "715:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "692199d4", + "id": 708, + "mutability": "mutable", + "name": "sidechain_maxgas", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "756:31:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 707, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "756:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "fc0c546a", + "id": 710, + "mutability": "mutable", + "name": "token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "793:18:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + }, + "typeName": { + "contractScope": null, + "id": 709, + "name": "ERC20", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 4148, + "src": "793:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "a65c87d9", + "id": 712, + "mutability": "mutable", + "name": "sidechain_template_DU", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "978:36:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 711, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "978:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "d35cec40", + "id": 714, + "mutability": "mutable", + "name": "adminFeeFraction", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "1020:31:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 713, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1020:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "61feacff", + "id": 716, + "mutability": "mutable", + "name": "totalAdminFees", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "1057:29:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 715, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1057:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "a913f41d", + "id": 718, + "mutability": "mutable", + "name": "totalAdminFeesWithdrawn", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "1092:38:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 717, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1092:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "9eeba07c", + "id": 720, + "mutability": "mutable", + "name": "autoSendAdminFee", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "1136:28:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 719, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "1136:4:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "public" + }, + { + "body": { + "id": 727, + "nodeType": "Block", + "src": "1220:13:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "hexValue": "32", + "id": 725, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1229:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_2_by_1", + "typeString": "int_const 2" + }, + "value": "2" + }, + "functionReturnParameters": 724, + "id": 726, + "nodeType": "Return", + "src": "1222:8:3" + } + ] + }, + "documentation": null, + "functionSelector": "54fd4d50", + "id": 728, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "version", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 721, + "nodeType": "ParameterList", + "parameters": [], + "src": "1187:2:3" + }, + "returnParameters": { + "id": 724, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 723, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 728, + "src": "1211:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 722, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1211:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1210:9:3" + }, + "scope": 1165, + "src": "1171:62:3", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "2df3eba4", + "id": 730, + "mutability": "mutable", + "name": "totalEarnings", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1165, + "src": "1443:28:3", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 729, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1443:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "body": { + "id": 739, + "nodeType": "Block", + "src": "1520:2:3", + "statements": [] + }, + "documentation": null, + "id": 740, + "implemented": true, + "kind": "constructor", + "modifiers": [ + { + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "30", + "id": 735, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1516:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "id": 734, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "1508:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 733, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1508:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 736, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1508:10:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "id": 737, + "modifierName": { + "argumentTypes": null, + "id": 732, + "name": "Ownable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3180, + "src": "1500:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_Ownable_$3180_$", + "typeString": "type(contract Ownable)" + } + }, + "nodeType": "ModifierInvocation", + "src": "1500:19:3" + } + ], + "name": "", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 731, + "nodeType": "ParameterList", + "parameters": [], + "src": "1490:2:3" + }, + "returnParameters": { + "id": 738, + "nodeType": "ParameterList", + "parameters": [], + "src": "1520:0:3" + }, + "scope": 1165, + "src": "1479:43:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 820, + "nodeType": "Block", + "src": "1825:668:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 763, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "!", + "prefix": true, + "src": "1843:16:3", + "subExpression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 761, + "name": "isInitialized", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 837, + "src": "1844:13:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_bool_$", + "typeString": "function () view returns (bool)" + } + }, + "id": 762, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1844:15:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "696e69745f6f6e6365", + "id": 764, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1861:11:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_489583184b3bb72a2d8c2cf7b5f4c46635517588498db21bc763656f9e5ab21e", + "typeString": "literal_string \"init_once\"" + }, + "value": "init_once" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_489583184b3bb72a2d8c2cf7b5f4c46635517588498db21bc763656f9e5ab21e", + "typeString": "literal_string \"init_once\"" + } + ], + "id": 760, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "1835:7:3", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 765, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1835:38:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 766, + "nodeType": "ExpressionStatement", + "src": "1835:38:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 769, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 767, + "name": "autoSendAdminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 720, + "src": "1956:16:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "hexValue": "74727565", + "id": 768, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "bool", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1975:4:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "value": "true" + }, + "src": "1956:23:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 770, + "nodeType": "ExpressionStatement", + "src": "1956:23:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 774, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 771, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "2034:5:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 772, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "2042:3:3", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 773, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2042:10:3", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "src": "2034:18:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 775, + "nodeType": "ExpressionStatement", + "src": "2034:18:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 780, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 776, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "2063:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 778, + "name": "_token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 744, + "src": "2095:15:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 777, + "name": "ITokenMediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2968, + "src": "2080:14:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_ITokenMediator_$2968_$", + "typeString": "type(contract ITokenMediator)" + } + }, + "id": 779, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2080:31:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "src": "2063:48:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 781, + "nodeType": "ExpressionStatement", + "src": "2063:48:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 788, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 782, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 702, + "src": "2121:3:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "argumentTypes": null, + "id": 784, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "2132:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 785, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "bridgeContract", + "nodeType": "MemberAccess", + "referencedDeclaration": 2946, + "src": "2132:29:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$__$returns$_t_address_$", + "typeString": "function () view external returns (address)" + } + }, + "id": 786, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2132:31:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 783, + "name": "IAMB", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2912, + "src": "2127:4:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_IAMB_$2912_$", + "typeString": "type(contract IAMB)" + } + }, + "id": 787, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2127:37:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "src": "2121:43:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "id": 789, + "nodeType": "ExpressionStatement", + "src": "2121:43:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 794, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 790, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "2174:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 792, + "name": "_token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 742, + "src": "2188:6:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 791, + "name": "ERC20", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 4148, + "src": "2182:5:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_ERC20_$4148_$", + "typeString": "type(contract ERC20)" + } + }, + "id": 793, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2182:13:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "src": "2174:21:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "id": 795, + "nodeType": "ExpressionStatement", + "src": "2174:21:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 798, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 796, + "name": "sidechain_DU_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 706, + "src": "2205:20:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 797, + "name": "_sidechain_DU_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 746, + "src": "2228:21:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2205:44:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 799, + "nodeType": "ExpressionStatement", + "src": "2205:44:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 802, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 800, + "name": "sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 708, + "src": "2259:16:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 801, + "name": "_sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 748, + "src": "2278:17:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "2259:36:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 803, + "nodeType": "ExpressionStatement", + "src": "2259:36:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 806, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 804, + "name": "sidechain_template_DU", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 712, + "src": "2305:21:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 805, + "name": "_sidechain_template_DU", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 750, + "src": "2329:22:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2305:46:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 807, + "nodeType": "ExpressionStatement", + "src": "2305:46:3" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 809, + "name": "_adminFeeFraction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 754, + "src": "2373:17:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 808, + "name": "setAdminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 861, + "src": "2361:11:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 810, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2361:30:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 811, + "nodeType": "ExpressionStatement", + "src": "2361:30:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 814, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 812, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "2434:5:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 813, + "name": "_owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 752, + "src": "2442:6:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2434:14:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 815, + "nodeType": "ExpressionStatement", + "src": "2434:14:3" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 817, + "name": "agents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 757, + "src": "2479:6:3", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + ], + "id": 816, + "name": "deployNewDUSidechain", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 897, + "src": "2458:20:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_array$_t_address_$dyn_memory_ptr_$returns$__$", + "typeString": "function (address[] memory)" + } + }, + "id": 818, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2458:28:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 819, + "nodeType": "ExpressionStatement", + "src": "2458:28:3" + } + ] + }, + "documentation": null, + "functionSelector": "fb6470c9", + "id": 821, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "initialize", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 758, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 742, + "mutability": "mutable", + "name": "_token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1557:14:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 741, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1557:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 744, + "mutability": "mutable", + "name": "_token_mediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1581:23:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 743, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1581:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 746, + "mutability": "mutable", + "name": "_sidechain_DU_factory", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1614:29:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 745, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1614:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 748, + "mutability": "mutable", + "name": "_sidechain_maxgas", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1653:25:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 747, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1653:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 750, + "mutability": "mutable", + "name": "_sidechain_template_DU", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1688:30:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 749, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1688:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 752, + "mutability": "mutable", + "name": "_owner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1728:14:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 751, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1728:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 754, + "mutability": "mutable", + "name": "_adminFeeFraction", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1752:25:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 753, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1752:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 757, + "mutability": "mutable", + "name": "agents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 821, + "src": "1787:23:3", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 755, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1787:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 756, + "length": null, + "nodeType": "ArrayTypeName", + "src": "1787:9:3", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1547:269:3" + }, + "returnParameters": { + "id": 759, + "nodeType": "ParameterList", + "parameters": [], + "src": "1825:0:3" + }, + "scope": 1165, + "src": "1528:965:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 836, + "nodeType": "Block", + "src": "2551:52:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 834, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 828, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "2576:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + ], + "id": 827, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2568:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 826, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2568:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 829, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2568:14:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "30", + "id": 832, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2594:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "id": 831, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2586:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 830, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2586:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 833, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2586:10:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "src": "2568:28:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "functionReturnParameters": 825, + "id": 835, + "nodeType": "Return", + "src": "2561:35:3" + } + ] + }, + "documentation": null, + "functionSelector": "392e53cd", + "id": 837, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "isInitialized", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 822, + "nodeType": "ParameterList", + "parameters": [], + "src": "2521:2:3" + }, + "returnParameters": { + "id": 825, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 824, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 837, + "src": "2545:4:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 823, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "2545:4:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2544:6:3" + }, + "scope": 1165, + "src": "2499:104:3", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 860, + "nodeType": "Block", + "src": "2842:154:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 848, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 846, + "name": "newAdminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 840, + "src": "2860:11:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "<=", + "rightExpression": { + "argumentTypes": null, + "hexValue": "31", + "id": 847, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2875:7:3", + "subdenomination": "ether", + "typeDescriptions": { + "typeIdentifier": "t_rational_1000000000000000000_by_1", + "typeString": "int_const 1000000000000000000" + }, + "value": "1" + }, + "src": "2860:22:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f61646d696e466565", + "id": 849, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2884:16:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_c137fd2ee13f1c30c5cc71b65e2c7f49f5120b580d70d8298b6185b09e6c1e40", + "typeString": "literal_string \"error_adminFee\"" + }, + "value": "error_adminFee" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_c137fd2ee13f1c30c5cc71b65e2c7f49f5120b580d70d8298b6185b09e6c1e40", + "typeString": "literal_string \"error_adminFee\"" + } + ], + "id": 845, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "2852:7:3", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 850, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2852:49:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 851, + "nodeType": "ExpressionStatement", + "src": "2852:49:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 854, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 852, + "name": "adminFeeFraction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 714, + "src": "2911:16:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 853, + "name": "newAdminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 840, + "src": "2930:11:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "2911:30:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 855, + "nodeType": "ExpressionStatement", + "src": "2911:30:3" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 857, + "name": "adminFeeFraction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 714, + "src": "2972:16:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 856, + "name": "AdminFeeChanged", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 686, + "src": "2956:15:3", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 858, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2956:33:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 859, + "nodeType": "EmitStatement", + "src": "2951:38:3" + } + ] + }, + "documentation": { + "id": 838, + "nodeType": "StructuredDocumentation", + "src": "2609:169:3", + "text": "Admin fee as a fraction of revenue.\n@param newAdminFee fixed-point decimal in the same way as ether: 50% === 0.5 ether === \"500000000000000000\"" + }, + "functionSelector": "8beb60b6", + "id": 861, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 843, + "modifierName": { + "argumentTypes": null, + "id": 842, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "2832:9:3", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "2832:9:3" + } + ], + "name": "setAdminFee", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 841, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 840, + "mutability": "mutable", + "name": "newAdminFee", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 861, + "src": "2804:19:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 839, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2804:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2803:21:3" + }, + "returnParameters": { + "id": 844, + "nodeType": "ParameterList", + "parameters": [], + "src": "2842:0:3" + }, + "scope": 1165, + "src": "2783:213:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 872, + "nodeType": "Block", + "src": "3063:44:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 870, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 868, + "name": "autoSendAdminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 720, + "src": "3073:16:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 869, + "name": "autoSend", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 863, + "src": "3092:8:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "3073:27:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 871, + "nodeType": "ExpressionStatement", + "src": "3073:27:3" + } + ] + }, + "documentation": null, + "functionSelector": "0f3afcbe", + "id": 873, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 866, + "modifierName": { + "argumentTypes": null, + "id": 865, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "3053:9:3", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "3053:9:3" + } + ], + "name": "setAutoSendAdminFee", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 864, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 863, + "mutability": "mutable", + "name": "autoSend", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 873, + "src": "3031:13:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 862, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "3031:4:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3030:15:3" + }, + "returnParameters": { + "id": 867, + "nodeType": "ParameterList", + "parameters": [], + "src": "3063:0:3" + }, + "scope": 1165, + "src": "3002:105:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 896, + "nodeType": "Block", + "src": "3176:198:3", + "statements": [ + { + "assignments": [ + 880 + ], + "declarations": [ + { + "constant": false, + "id": 880, + "mutability": "mutable", + "name": "data", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 896, + "src": "3186:17:3", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 879, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "3186:5:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 887, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "6465706c6f794e6577445553696465636861696e28616464726573732c616464726573735b5d29", + "id": 883, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3230:41:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_325ff66f80d01e2243bd492c3b38e663416cd478dca0ff43243ddb11328dca3f", + "typeString": "literal_string \"deployNewDUSidechain(address,address[])\"" + }, + "value": "deployNewDUSidechain(address,address[])" + }, + { + "argumentTypes": null, + "id": 884, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "3273:5:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 885, + "name": "agents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 876, + "src": "3280:6:3", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_325ff66f80d01e2243bd492c3b38e663416cd478dca0ff43243ddb11328dca3f", + "typeString": "literal_string \"deployNewDUSidechain(address,address[])\"" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + ], + "expression": { + "argumentTypes": null, + "id": 881, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "3206:3:3", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 882, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encodeWithSignature", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3206:23:3", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (string memory) pure returns (bytes memory)" + } + }, + "id": 886, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3206:81:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "3186:101:3" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 891, + "name": "sidechain_DU_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 706, + "src": "3322:20:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 892, + "name": "data", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 880, + "src": "3344:4:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 893, + "name": "sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 708, + "src": "3350:16:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 888, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 702, + "src": "3297:3:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "id": 890, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "requireToPassMessage", + "nodeType": "MemberAccess", + "referencedDeclaration": 2911, + "src": "3297:24:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_bytes_memory_ptr_$_t_uint256_$returns$_t_bytes32_$", + "typeString": "function (address,bytes memory,uint256) external returns (bytes32)" + } + }, + "id": 894, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3297:70:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "id": 895, + "nodeType": "ExpressionStatement", + "src": "3297:70:3" + } + ] + }, + "documentation": null, + "functionSelector": "99dd1c81", + "id": 897, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "deployNewDUSidechain", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 877, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 876, + "mutability": "mutable", + "name": "agents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 897, + "src": "3144:23:3", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 874, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3144:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 875, + "length": null, + "nodeType": "ArrayTypeName", + "src": "3144:9:3", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3143:25:3" + }, + "returnParameters": { + "id": 878, + "nodeType": "ParameterList", + "parameters": [], + "src": "3176:0:3" + }, + "scope": 1165, + "src": "3114:260:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 918, + "nodeType": "Block", + "src": "3438:137:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 904, + "name": "sidechain_template_DU", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 712, + "src": "3491:21:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 905, + "name": "sidechain_DU_factory", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 706, + "src": "3514:20:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 912, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "3560:4:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionMainnet_$1165", + "typeString": "contract DataUnionMainnet" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionMainnet_$1165", + "typeString": "contract DataUnionMainnet" + } + ], + "id": 911, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "3552:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 910, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3552:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 913, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3552:13:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 909, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "3544:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 908, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "3544:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 914, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3544:22:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 907, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "3536:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes32_$", + "typeString": "type(bytes32)" + }, + "typeName": { + "id": 906, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "3536:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 915, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3536:31:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "argumentTypes": null, + "id": 902, + "name": "CloneLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 154, + "src": "3455:8:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_CloneLib_$154_$", + "typeString": "type(library CloneLib)" + } + }, + "id": 903, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "predictCloneAddressCreate2", + "nodeType": "MemberAccess", + "referencedDeclaration": 61, + "src": "3455:35:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$_t_address_$_t_bytes32_$returns$_t_address_$", + "typeString": "function (address,address,bytes32) pure returns (address)" + } + }, + "id": 916, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3455:113:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 901, + "id": 917, + "nodeType": "Return", + "src": "3448:120:3" + } + ] + }, + "documentation": null, + "functionSelector": "37b43a94", + "id": 919, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "sidechainAddress", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 898, + "nodeType": "ParameterList", + "parameters": [], + "src": "3405:2:3" + }, + "returnParameters": { + "id": 901, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 900, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 919, + "src": "3429:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 899, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3429:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3428:9:3" + }, + "scope": 1165, + "src": "3380:195:3", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "baseFunctions": [ + 3198 + ], + "body": { + "id": 940, + "nodeType": "Block", + "src": "4158:58:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 935, + "name": "sendTokensToBridge", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1124, + "src": "4168:18:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$__$returns$_t_uint256_$", + "typeString": "function () returns (uint256)" + } + }, + "id": 936, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4168:20:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 937, + "nodeType": "ExpressionStatement", + "src": "4168:20:3" + }, + { + "expression": { + "argumentTypes": null, + "hexValue": "74727565", + "id": 938, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "bool", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4205:4:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "value": "true" + }, + "functionReturnParameters": 934, + "id": 939, + "nodeType": "Return", + "src": "4198:11:3" + } + ] + }, + "documentation": null, + "functionSelector": "4a439cc0", + "id": 941, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "onPurchase", + "nodeType": "FunctionDefinition", + "overrides": { + "id": 931, + "nodeType": "OverrideSpecifier", + "overrides": [], + "src": "4134:8:3" + }, + "parameters": { + "id": 930, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 921, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 941, + "src": "4080:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 920, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "4080:7:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 923, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 941, + "src": "4089:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 922, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4089:7:3", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 925, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 941, + "src": "4098:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 924, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4098:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 927, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 941, + "src": "4107:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 926, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4107:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 929, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 941, + "src": "4116:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 928, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4116:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4079:45:3" + }, + "returnParameters": { + "id": 934, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 933, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 941, + "src": "4152:4:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 932, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "4152:4:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4151:6:3" + }, + "scope": 1165, + "src": "4060:156:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "external" + }, + { + "body": { + "id": 951, + "nodeType": "Block", + "src": "4285:67:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 948, + "name": "totalAdminFeesWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 718, + "src": "4321:23:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 946, + "name": "totalAdminFees", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 716, + "src": "4302:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 947, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "4302:18:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 949, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4302:43:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 945, + "id": 950, + "nodeType": "Return", + "src": "4295:50:3" + } + ] + }, + "documentation": null, + "functionSelector": "13fd3c56", + "id": 952, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "adminFeesWithdrawable", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 942, + "nodeType": "ParameterList", + "parameters": [], + "src": "4252:2:3" + }, + "returnParameters": { + "id": 945, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 944, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 952, + "src": "4276:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 943, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4276:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4275:9:3" + }, + "scope": 1165, + "src": "4222:130:3", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 969, + "nodeType": "Block", + "src": "4417:83:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 965, + "name": "adminFeesWithdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 952, + "src": "4469:21:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 966, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4469:23:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 961, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "4458:4:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionMainnet_$1165", + "typeString": "contract DataUnionMainnet" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionMainnet_$1165", + "typeString": "contract DataUnionMainnet" + } + ], + "id": 960, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "4450:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 959, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4450:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 962, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4450:13:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "expression": { + "argumentTypes": null, + "id": 957, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "4434:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "id": 958, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balanceOf", + "nodeType": "MemberAccess", + "referencedDeclaration": 3748, + "src": "4434:15:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view external returns (uint256)" + } + }, + "id": 963, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4434:30:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 964, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "4434:34:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 967, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4434:59:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 956, + "id": 968, + "nodeType": "Return", + "src": "4427:66:3" + } + ] + }, + "documentation": null, + "functionSelector": "132b4194", + "id": 970, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "unaccountedTokens", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 953, + "nodeType": "ParameterList", + "parameters": [], + "src": "4384:2:3" + }, + "returnParameters": { + "id": 956, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 955, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 970, + "src": "4408:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 954, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4408:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4407:9:3" + }, + "scope": 1165, + "src": "4358:142:3", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1123, + "nodeType": "Block", + "src": "4562:1550:3", + "statements": [ + { + "assignments": [ + 976 + ], + "declarations": [ + { + "constant": false, + "id": 976, + "mutability": "mutable", + "name": "newTokens", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1123, + "src": "4572:17:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 975, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4572:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 979, + "initialValue": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 977, + "name": "unaccountedTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 970, + "src": "4592:17:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 978, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4592:19:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "4572:39:3" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 982, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 980, + "name": "newTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 976, + "src": "4625:9:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 981, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4638:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "4625:14:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 985, + "nodeType": "IfStatement", + "src": "4621:28:3", + "trueBody": { + "expression": { + "argumentTypes": null, + "hexValue": "30", + "id": 983, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4648:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "functionReturnParameters": 974, + "id": 984, + "nodeType": "Return", + "src": "4641:8:3" + } + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 987, + "name": "newTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 976, + "src": "4681:9:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 986, + "name": "RevenueReceived", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 700, + "src": "4665:15:3", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 988, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4665:26:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 989, + "nodeType": "EmitStatement", + "src": "4660:31:3" + }, + { + "assignments": [ + 991 + ], + "declarations": [ + { + "constant": false, + "id": 991, + "mutability": "mutable", + "name": "adminFee", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1123, + "src": "4702:16:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 990, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4702:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1001, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_rational_1000000000000000000_by_1", + "typeString": "int_const 1000000000000000000" + }, + "id": 999, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "hexValue": "3130", + "id": 997, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4757:2:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_10_by_1", + "typeString": "int_const 10" + }, + "value": "10" + }, + "nodeType": "BinaryOperation", + "operator": "**", + "rightExpression": { + "argumentTypes": null, + "hexValue": "3138", + "id": 998, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4761:2:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_18_by_1", + "typeString": "int_const 18" + }, + "value": "18" + }, + "src": "4757:6:3", + "typeDescriptions": { + "typeIdentifier": "t_rational_1000000000000000000_by_1", + "typeString": "int_const 1000000000000000000" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1000000000000000000_by_1", + "typeString": "int_const 1000000000000000000" + } + ], + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 994, + "name": "adminFeeFraction", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 714, + "src": "4735:16:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 992, + "name": "newTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 976, + "src": "4721:9:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 993, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "mul", + "nodeType": "MemberAccess", + "referencedDeclaration": 3554, + "src": "4721:13:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 995, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4721:31:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 996, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "div", + "nodeType": "MemberAccess", + "referencedDeclaration": 3571, + "src": "4721:35:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1000, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4721:43:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "4702:62:3" + }, + { + "assignments": [ + 1003 + ], + "declarations": [ + { + "constant": false, + "id": 1003, + "mutability": "mutable", + "name": "memberEarnings", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1123, + "src": "4774:22:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1002, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4774:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1008, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1006, + "name": "adminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 991, + "src": "4813:8:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1004, + "name": "newTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 976, + "src": "4799:9:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1005, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "4799:13:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1007, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4799:23:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "4774:48:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 1014, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1009, + "name": "totalAdminFees", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 716, + "src": "4833:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1012, + "name": "adminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 991, + "src": "4869:8:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1010, + "name": "totalAdminFees", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 716, + "src": "4850:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1011, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "4850:18:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1013, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4850:28:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "4833:45:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1015, + "nodeType": "ExpressionStatement", + "src": "4833:45:3" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1017, + "name": "adminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 991, + "src": "4909:8:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1016, + "name": "AdminFeeCharged", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 690, + "src": "4893:15:3", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 1018, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4893:25:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1019, + "nodeType": "EmitStatement", + "src": "4888:30:3" + }, + { + "condition": { + "argumentTypes": null, + "id": 1020, + "name": "autoSendAdminFee", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 720, + "src": "4931:16:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1024, + "nodeType": "IfStatement", + "src": "4928:40:3", + "trueBody": { + "expression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1021, + "name": "withdrawAdminFees", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1164, + "src": "4949:17:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$__$returns$_t_uint256_$", + "typeString": "function () returns (uint256)" + } + }, + "id": 1022, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4949:19:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1023, + "nodeType": "ExpressionStatement", + "src": "4949:19:3" + } + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1030, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "5044:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + ], + "id": 1029, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "5036:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1028, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "5036:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1031, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5036:23:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "hexValue": "30", + "id": 1032, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5061:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "expression": { + "argumentTypes": null, + "id": 1026, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "5022:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "id": 1027, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "approve", + "nodeType": "MemberAccess", + "referencedDeclaration": 3808, + "src": "5022:13:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_uint256_$returns$_t_bool_$", + "typeString": "function (address,uint256) external returns (bool)" + } + }, + "id": 1033, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5022:41:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "617070726f76655f6661696c6564", + "id": 1034, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5065:16:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_0b99e75f7873826fa8b33e45f5babad412309f79417b9b0000257bd68fa2b8a3", + "typeString": "literal_string \"approve_failed\"" + }, + "value": "approve_failed" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_0b99e75f7873826fa8b33e45f5babad412309f79417b9b0000257bd68fa2b8a3", + "typeString": "literal_string \"approve_failed\"" + } + ], + "id": 1025, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "5014:7:3", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1035, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5014:68:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1036, + "nodeType": "ExpressionStatement", + "src": "5014:68:3" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1042, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "5122:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + ], + "id": 1041, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "5114:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1040, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "5114:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1043, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5114:23:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1044, + "name": "memberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1003, + "src": "5139:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1038, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "5100:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "id": 1039, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "approve", + "nodeType": "MemberAccess", + "referencedDeclaration": 3808, + "src": "5100:13:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_uint256_$returns$_t_bool_$", + "typeString": "function (address,uint256) external returns (bool)" + } + }, + "id": 1045, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5100:54:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "617070726f76655f6661696c6564", + "id": 1046, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5156:16:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_0b99e75f7873826fa8b33e45f5babad412309f79417b9b0000257bd68fa2b8a3", + "typeString": "literal_string \"approve_failed\"" + }, + "value": "approve_failed" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_0b99e75f7873826fa8b33e45f5babad412309f79417b9b0000257bd68fa2b8a3", + "typeString": "literal_string \"approve_failed\"" + } + ], + "id": 1037, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "5092:7:3", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1047, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5092:81:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1048, + "nodeType": "ExpressionStatement", + "src": "5092:81:3" + }, + { + "assignments": [ + 1050 + ], + "declarations": [ + { + "constant": false, + "id": 1050, + "mutability": "mutable", + "name": "bridgeMode", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1123, + "src": "5183:17:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + }, + "typeName": { + "id": 1049, + "name": "bytes4", + "nodeType": "ElementaryTypeName", + "src": "5183:6:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1054, + "initialValue": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "argumentTypes": null, + "id": 1051, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "5203:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 1052, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "getBridgeMode", + "nodeType": "MemberAccess", + "referencedDeclaration": 2967, + "src": "5203:28:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_pure$__$returns$_t_bytes4_$", + "typeString": "function () pure external returns (bytes4)" + } + }, + "id": 1053, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5203:30:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "5183:50:3" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + }, + "id": 1057, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1055, + "name": "bridgeMode", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1050, + "src": "5435:10:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30786231353136633236", + "id": 1056, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5449:10:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_2974903334_by_1", + "typeString": "int_const 2974903334" + }, + "value": "0xb1516c26" + }, + "src": "5435:24:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + }, + "id": 1073, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1071, + "name": "bridgeMode", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1050, + "src": "5581:10:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes4", + "typeString": "bytes4" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30783736353935623536", + "id": 1072, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5595:10:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1985567574_by_1", + "typeString": "int_const 1985567574" + }, + "value": "0x76595b56" + }, + "src": "5581:24:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": { + "id": 1087, + "nodeType": "Block", + "src": "5706:54:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "756e6b6e6f776e5f6272696467655f6d6f6465", + "id": 1084, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5727:21:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_445d91fc79f5d76a26706ce2f1c866b8b57fad4e5d19ffc80c8c136306007969", + "typeString": "literal_string \"unknown_bridge_mode\"" + }, + "value": "unknown_bridge_mode" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_445d91fc79f5d76a26706ce2f1c866b8b57fad4e5d19ffc80c8c136306007969", + "typeString": "literal_string \"unknown_bridge_mode\"" + } + ], + "id": 1083, + "name": "revert", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -19, + -19 + ], + "referencedDeclaration": -19, + "src": "5720:6:3", + "typeDescriptions": { + "typeIdentifier": "t_function_revert_pure$_t_string_memory_ptr_$returns$__$", + "typeString": "function (string memory) pure" + } + }, + "id": 1085, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5720:29:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1086, + "nodeType": "ExpressionStatement", + "src": "5720:29:3" + } + ] + }, + "id": 1088, + "nodeType": "IfStatement", + "src": "5578:182:3", + "trueBody": { + "id": 1082, + "nodeType": "Block", + "src": "5606:87:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1077, + "name": "sidechainAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 919, + "src": "5647:16:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_address_$", + "typeString": "function () view returns (address)" + } + }, + "id": 1078, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5647:18:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1079, + "name": "memberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1003, + "src": "5667:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1074, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "5620:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 1076, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "relayTokens", + "nodeType": "MemberAccess", + "referencedDeclaration": 2962, + "src": "5620:26:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256) external" + } + }, + "id": 1080, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5620:62:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1081, + "nodeType": "ExpressionStatement", + "src": "5620:62:3" + } + ] + } + }, + "id": 1089, + "nodeType": "IfStatement", + "src": "5432:328:3", + "trueBody": { + "id": 1070, + "nodeType": "Block", + "src": "5461:103:3", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1063, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "5510:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + ], + "id": 1062, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "5502:7:3", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1061, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "5502:7:3", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1064, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5502:14:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1065, + "name": "sidechainAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 919, + "src": "5518:16:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_address_$", + "typeString": "function () view returns (address)" + } + }, + "id": 1066, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5518:18:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1067, + "name": "memberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1003, + "src": "5538:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1058, + "name": "token_mediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 704, + "src": "5475:14:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ITokenMediator_$2968", + "typeString": "contract ITokenMediator" + } + }, + "id": 1060, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "relayTokens", + "nodeType": "MemberAccess", + "referencedDeclaration": 2955, + "src": "5475:26:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,address,uint256) external" + } + }, + "id": 1068, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5475:78:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1069, + "nodeType": "ExpressionStatement", + "src": "5475:78:3" + } + ] + } + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1094, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1091, + "name": "unaccountedTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 970, + "src": "5824:17:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 1092, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5824:19:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1093, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5847:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "5824:24:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6e6f745f7472616e73666572726564", + "id": 1095, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5850:17:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_f8c2113376f862fd95528ef214ec6c4df8073d6ec53e0649e3a444e38c7f206c", + "typeString": "literal_string \"not_transferred\"" + }, + "value": "not_transferred" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_f8c2113376f862fd95528ef214ec6c4df8073d6ec53e0649e3a444e38c7f206c", + "typeString": "literal_string \"not_transferred\"" + } + ], + "id": 1090, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "5816:7:3", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1096, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5816:52:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1097, + "nodeType": "ExpressionStatement", + "src": "5816:52:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 1103, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1098, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 730, + "src": "5878:13:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1101, + "name": "memberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1003, + "src": "5912:14:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1099, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 730, + "src": "5894:13:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1100, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "5894:17:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1102, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5894:33:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "5878:49:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1104, + "nodeType": "ExpressionStatement", + "src": "5878:49:3" + }, + { + "assignments": [ + 1106 + ], + "declarations": [ + { + "constant": false, + "id": 1106, + "mutability": "mutable", + "name": "data", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1123, + "src": "5938:17:3", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 1105, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "5938:5:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1111, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "72656672657368526576656e75652829", + "id": 1109, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5982:18:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_331beb5f2892eb3ad8da75941af8f45f6a0e8580b91ecbb4c7fdf0219d1442a8", + "typeString": "literal_string \"refreshRevenue()\"" + }, + "value": "refreshRevenue()" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_331beb5f2892eb3ad8da75941af8f45f6a0e8580b91ecbb4c7fdf0219d1442a8", + "typeString": "literal_string \"refreshRevenue()\"" + } + ], + "expression": { + "argumentTypes": null, + "id": 1107, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "5958:3:3", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 1108, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encodeWithSignature", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "5958:23:3", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (string memory) pure returns (bytes memory)" + } + }, + "id": 1110, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5958:43:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "5938:63:3" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1115, + "name": "sidechainAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 919, + "src": "6036:16:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_address_$", + "typeString": "function () view returns (address)" + } + }, + "id": 1116, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6036:18:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1117, + "name": "data", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1106, + "src": "6056:4:3", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "argumentTypes": null, + "id": 1118, + "name": "sidechain_maxgas", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 708, + "src": "6062:16:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1112, + "name": "amb", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 702, + "src": "6011:3:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IAMB_$2912", + "typeString": "contract IAMB" + } + }, + "id": 1114, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "requireToPassMessage", + "nodeType": "MemberAccess", + "referencedDeclaration": 2911, + "src": "6011:24:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_bytes_memory_ptr_$_t_uint256_$returns$_t_bytes32_$", + "typeString": "function (address,bytes memory,uint256) external returns (bytes32)" + } + }, + "id": 1119, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6011:68:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "id": 1120, + "nodeType": "ExpressionStatement", + "src": "6011:68:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 1121, + "name": "newTokens", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 976, + "src": "6096:9:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 974, + "id": 1122, + "nodeType": "Return", + "src": "6089:16:3" + } + ] + }, + "documentation": null, + "functionSelector": "2efc1007", + "id": 1124, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "sendTokensToBridge", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 971, + "nodeType": "ParameterList", + "parameters": [], + "src": "4534:2:3" + }, + "returnParameters": { + "id": 974, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 973, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1124, + "src": "4553:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 972, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4553:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4552:9:3" + }, + "scope": 1165, + "src": "4507:1605:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1163, + "nodeType": "Block", + "src": "6172:337:3", + "statements": [ + { + "assignments": [ + 1130 + ], + "declarations": [ + { + "constant": false, + "id": 1130, + "mutability": "mutable", + "name": "withdrawable", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1163, + "src": "6182:20:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1129, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "6182:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1133, + "initialValue": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1131, + "name": "adminFeesWithdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 952, + "src": "6205:21:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 1132, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6205:23:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "6182:46:3" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1136, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1134, + "name": "withdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1130, + "src": "6242:12:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1135, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6258:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "6242:17:3", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1139, + "nodeType": "IfStatement", + "src": "6238:31:3", + "trueBody": { + "expression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1137, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6268:1:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "functionReturnParameters": 1128, + "id": 1138, + "nodeType": "Return", + "src": "6261:8:3" + } + }, + { + "expression": { + "argumentTypes": null, + "id": 1145, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1140, + "name": "totalAdminFeesWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 718, + "src": "6279:23:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1143, + "name": "withdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1130, + "src": "6333:12:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1141, + "name": "totalAdminFeesWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 718, + "src": "6305:23:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1142, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "6305:27:3", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1144, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6305:41:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6279:67:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1146, + "nodeType": "ExpressionStatement", + "src": "6279:67:3" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1150, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "6379:5:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1151, + "name": "withdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1130, + "src": "6386:12:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1148, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 710, + "src": "6364:5:3", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$4148", + "typeString": "contract ERC20" + } + }, + "id": 1149, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "transfer", + "nodeType": "MemberAccess", + "referencedDeclaration": 3769, + "src": "6364:14:3", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_uint256_$returns$_t_bool_$", + "typeString": "function (address,uint256) external returns (bool)" + } + }, + "id": 1152, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6364:35:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "7472616e736665725f6661696c6564", + "id": 1153, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6401:17:3", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_b8e9fee0fffb4680cf1dadd39ef447f97bcb04e1ca58d043770ea51a3c935e6c", + "typeString": "literal_string \"transfer_failed\"" + }, + "value": "transfer_failed" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_b8e9fee0fffb4680cf1dadd39ef447f97bcb04e1ca58d043770ea51a3c935e6c", + "typeString": "literal_string \"transfer_failed\"" + } + ], + "id": 1147, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "6356:7:3", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1154, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6356:63:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1155, + "nodeType": "ExpressionStatement", + "src": "6356:63:3" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1157, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "6453:5:3", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1158, + "name": "withdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1130, + "src": "6460:12:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1156, + "name": "AdminFeesWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 696, + "src": "6434:18:3", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256)" + } + }, + "id": 1159, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6434:39:3", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1160, + "nodeType": "EmitStatement", + "src": "6429:44:3" + }, + { + "expression": { + "argumentTypes": null, + "id": 1161, + "name": "withdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1130, + "src": "6490:12:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 1128, + "id": 1162, + "nodeType": "Return", + "src": "6483:19:3" + } + ] + }, + "documentation": null, + "functionSelector": "0419b45a", + "id": 1164, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawAdminFees", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1125, + "nodeType": "ParameterList", + "parameters": [], + "src": "6144:2:3" + }, + "returnParameters": { + "id": 1128, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1127, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1164, + "src": "6163:7:3", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1126, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "6163:7:3", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "6162:9:3" + }, + "scope": 1165, + "src": "6118:391:3", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + } + ], + "scope": 1166, + "src": "356:6155:3" + } + ], + "src": "0:6512:3" + }, + "compiler": { + "name": "solc", + "version": "0.6.6+commit.6c089d02.Emscripten.clang" + }, + "networks": {}, + "schemaVersion": "3.2.3", + "updatedAt": "2020-12-09T11:44:39.479Z", + "devdoc": { + "methods": { + "claimOwnership()": { + "details": "Allows the pendingOwner address to finalize the transfer." + }, + "setAdminFee(uint256)": { + "params": { + "newAdminFee": "fixed-point decimal in the same way as ether: 50% === 0.5 ether === \"500000000000000000\"" + } + }, + "transferOwnership(address)": { + "details": "Allows the current owner to set the pendingOwner address.", + "params": { + "newOwner": "The address to transfer ownership to." + } + } + } + }, + "userdoc": { + "methods": { + "setAdminFee(uint256)": { + "notice": "Admin fee as a fraction of revenue." + } + } + } +} \ No newline at end of file diff --git a/contracts/DataUnionSidechain.json b/contracts/DataUnionSidechain.json new file mode 100644 index 000000000..6d9526c99 --- /dev/null +++ b/contracts/DataUnionSidechain.json @@ -0,0 +1,36293 @@ +{ + "contractName": "DataUnionSidechain", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "member", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "EarningsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "agent", + "type": "address" + } + ], + "name": "JoinPartAgentAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "agent", + "type": "address" + } + ], + "name": "JoinPartAgentRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "member", + "type": "address" + } + ], + "name": "MemberJoined", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "member", + "type": "address" + } + ], + "name": "MemberParted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "earningsPerMember", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "activeMemberCount", + "type": "uint256" + } + ], + "name": "NewEarnings", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountWei", + "type": "uint256" + } + ], + "name": "NewMemberEthSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RevenueReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TransferToAddressInContract", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TransferWithinContract", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "UpdateNewMemberEth", + "type": "event" + }, + { + "inputs": [], + "name": "activeMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claimOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "dataUnionMainnet", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "inactiveMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "joinPartAgentCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "joinPartAgents", + "outputs": [ + { + "internalType": "enum DataUnionSidechain.ActiveStatus", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lifetimeMemberEarnings", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "memberData", + "outputs": [ + { + "internalType": "enum DataUnionSidechain.ActiveStatus", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "earningsBeforeLastJoin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lmeAtJoin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrawnEarnings", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "newMemberEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC677", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenMediator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalEarnings", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalEarningsWithdrawn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "address[]", + "name": "initialJoinPartAgents", + "type": "address[]" + }, + { + "internalType": "address", + "name": "tokenMediatorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "mainnetDataUnionAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "defaultNewMemberEth", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStats", + "outputs": [ + { + "internalType": "uint256[6]", + "name": "", + "type": "uint256[6]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "val", + "type": "uint256" + } + ], + "name": "setNewMemberEth", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "member", + "type": "address" + } + ], + "name": "getEarnings", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "member", + "type": "address" + } + ], + "name": "getWithdrawn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "member", + "type": "address" + } + ], + "name": "getWithdrawableEarnings", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalWithdrawable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "agents", + "type": "address[]" + } + ], + "name": "addJoinPartAgents", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "agent", + "type": "address" + } + ], + "name": "addJoinPartAgent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "agent", + "type": "address" + } + ], + "name": "removeJoinPartAgent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "refreshRevenue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "member", + "type": "address" + } + ], + "name": "addMember", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "member", + "type": "address" + } + ], + "name": "partMember", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable[]", + "name": "members", + "type": "address[]" + } + ], + "name": "addMembers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "members", + "type": "address[]" + } + ], + "name": "partMembers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferToMemberInContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferWithinContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "members", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "sendToMainnet", + "type": "bool" + } + ], + "name": "withdrawMembers", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "member", + "type": "address" + }, + { + "internalType": "bool", + "name": "sendToMainnet", + "type": "bool" + } + ], + "name": "withdrawAll", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "member", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "sendToMainnet", + "type": "bool" + } + ], + "name": "withdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "sendToMainnet", + "type": "bool" + } + ], + "name": "withdrawAllTo", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "sendToMainnet", + "type": "bool" + } + ], + "name": "withdrawTo", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "signatureIsValid", + "outputs": [ + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromSigner", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "sendToMainnet", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "withdrawAllToSigned", + "outputs": [ + { + "internalType": "uint256", + "name": "withdrawn", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromSigner", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "sendToMainnet", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "withdrawToSigned", + "outputs": [ + { + "internalType": "uint256", + "name": "withdrawn", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "a", + "type": "address" + } + ], + "name": "toBytes", + "outputs": [ + { + "internalType": "bytes", + "name": "b", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "metadata": "{\"compiler\":{\"version\":\"0.6.6+commit.6c089d02\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"member\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"EarningsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"JoinPartAgentAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"JoinPartAgentRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"member\",\"type\":\"address\"}],\"name\":\"MemberJoined\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"member\",\"type\":\"address\"}],\"name\":\"MemberParted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"earningsPerMember\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"activeMemberCount\",\"type\":\"uint256\"}],\"name\":\"NewEarnings\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountWei\",\"type\":\"uint256\"}],\"name\":\"NewMemberEthSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"RevenueReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferToAddressInContract\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferWithinContract\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"UpdateNewMemberEth\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"activeMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"addJoinPartAgent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"agents\",\"type\":\"address[]\"}],\"name\":\"addJoinPartAgents\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"member\",\"type\":\"address\"}],\"name\":\"addMember\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable[]\",\"name\":\"members\",\"type\":\"address[]\"}],\"name\":\"addMembers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dataUnionMainnet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"member\",\"type\":\"address\"}],\"name\":\"getEarnings\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStats\",\"outputs\":[{\"internalType\":\"uint256[6]\",\"name\":\"\",\"type\":\"uint256[6]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"member\",\"type\":\"address\"}],\"name\":\"getWithdrawableEarnings\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"member\",\"type\":\"address\"}],\"name\":\"getWithdrawn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"inactiveMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"initialOwner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"initialJoinPartAgents\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"tokenMediatorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"mainnetDataUnionAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"defaultNewMemberEth\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"joinPartAgentCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"joinPartAgents\",\"outputs\":[{\"internalType\":\"enum DataUnionSidechain.ActiveStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lifetimeMemberEarnings\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"memberData\",\"outputs\":[{\"internalType\":\"enum DataUnionSidechain.ActiveStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"earningsBeforeLastJoin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lmeAtJoin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"withdrawnEarnings\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"newMemberEth\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"member\",\"type\":\"address\"}],\"name\":\"partMember\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"members\",\"type\":\"address[]\"}],\"name\":\"partMembers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"refreshRevenue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"agent\",\"type\":\"address\"}],\"name\":\"removeJoinPartAgent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"val\",\"type\":\"uint256\"}],\"name\":\"setNewMemberEth\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"signatureIsValid\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"a\",\"type\":\"address\"}],\"name\":\"toBytes\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"b\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC677\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tokenMediator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalEarnings\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalEarningsWithdrawn\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalWithdrawable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferToMemberInContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferWithinContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"member\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendToMainnet\",\"type\":\"bool\"}],\"name\":\"withdraw\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"member\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"sendToMainnet\",\"type\":\"bool\"}],\"name\":\"withdrawAll\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"sendToMainnet\",\"type\":\"bool\"}],\"name\":\"withdrawAllTo\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromSigner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"sendToMainnet\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"withdrawAllToSigned\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"withdrawn\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"members\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"sendToMainnet\",\"type\":\"bool\"}],\"name\":\"withdrawMembers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendToMainnet\",\"type\":\"bool\"}],\"name\":\"withdrawTo\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromSigner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sendToMainnet\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"withdrawToSigned\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"withdrawn\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"methods\":{\"claimOwnership()\":{\"details\":\"Allows the pendingOwner address to finalize the transfer.\"},\"signatureIsValid(address,address,uint256,bytes)\":{\"params\":{\"amount\":\"how much is authorized for withdraw, or zero for unlimited (withdrawAll)\",\"recipient\":\"of the tokens\",\"signature\":\"byte array from `web3.eth.accounts.sign`\",\"signer\":\"whose earnings are being withdrawn\"},\"returns\":{\"isValid\":\"true iff signer of the authorization (member whose earnings are going to be withdrawn) matches the signature\"}},\"transferOwnership(address)\":{\"details\":\"Allows the current owner to set the pendingOwner address.\",\"params\":{\"newOwner\":\"The address to transfer ownership to.\"}},\"transferWithinContract(address,uint256)\":{\"params\":{\"amount\":\"how much withdrawable earnings is transferred\",\"recipient\":\"whose withdrawable earnings will increase\"}},\"withdrawAllToSigned(address,address,bool,bytes)\":{\"params\":{\"fromSigner\":\"whose earnings are being withdrawn\",\"sendToMainnet\":\"if the tokens should be sent to mainnet or only withdrawn into sidechain address\",\"signature\":\"from the member, see `signatureIsValid` how signature generated for unlimited amount\",\"to\":\"the address the tokens will be sent to (instead of `msg.sender`)\"}},\"withdrawToSigned(address,address,uint256,bool,bytes)\":{\"params\":{\"amount\":\"of tokens to withdraw\",\"fromSigner\":\"whose earnings are being withdrawn\",\"sendToMainnet\":\"if the tokens should be sent to mainnet or only withdrawn into sidechain address\",\"signature\":\"from the member, see `signatureIsValid` how signature generated for unlimited amount\",\"to\":\"the address the tokens will be sent to (instead of `msg.sender`)\"}}}},\"userdoc\":{\"methods\":{\"getStats()\":{\"notice\":\"Atomic getter to get all state variables in one call This alleviates the fact that JSON RPC batch requests aren't available in ethers.js\"},\"refreshRevenue()\":{\"notice\":\"Process unaccounted tokens that have been sent previously Called by AMB (see DataUnionMainnet:sendTokensToBridge)\"},\"signatureIsValid(address,address,uint256,bytes)\":{\"notice\":\"Check signature from a member authorizing withdrawing its earnings to another account. Throws if the signature is badly formatted or doesn't match the given signer and amount. Signature has parts the act as replay protection: 1) `address(this)`: signature can't be used for other contracts; 2) `withdrawn[signer]`: signature only works once (for unspecified amount), and can be \\\"cancelled\\\" by sending a withdraw tx. Generated in Javascript with: `web3.eth.accounts.sign(recipientAddress + amount.toString(16, 64) + contractAddress.slice(2) + withdrawnTokens.toString(16, 64), signerPrivateKey)`, or for unlimited amount: `web3.eth.accounts.sign(recipientAddress + \\\"0\\\".repeat(64) + contractAddress.slice(2) + withdrawnTokens.toString(16, 64), signerPrivateKey)`.\"},\"transferToMemberInContract(address,uint256)\":{\"notice\":\"Transfer tokens from outside contract, add to a recipient's in-contract balance\"},\"transferWithinContract(address,uint256)\":{\"notice\":\"Transfer tokens from sender's in-contract balance to recipient's in-contract balance This is done by \\\"withdrawing\\\" sender's earnings and crediting them to recipient's unwithdrawn earnings, so withdrawnEarnings never decreases for anyone (within this function)\"},\"withdrawAllToSigned(address,address,bool,bytes)\":{\"notice\":\"Do an \\\"unlimited donate withdraw\\\" on behalf of someone else, to an address they've specified. Sponsored withdraw is paid by admin, but target account could be whatever the member specifies. The signature gives a \\\"blank cheque\\\" for admin to withdraw all tokens to `recipient` in the future, and it's valid until next withdraw (and so can be nullified by withdrawing any amount). A new signature needs to be obtained for each subsequent future withdraw.\"},\"withdrawToSigned(address,address,uint256,bool,bytes)\":{\"notice\":\"Do a \\\"donate withdraw\\\" on behalf of someone else, to an address they've specified. Sponsored withdraw is paid by admin, but target account could be whatever the member specifies. The signature is valid only for given amount of tokens that may be different from maximum withdrawable tokens.\"}}}},\"settings\":{\"compilationTarget\":{\"/home/heynow/streamr/data-union-solidity/contracts/DataUnionSidechain.sol\":\"DataUnionSidechain\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"/home/heynow/streamr/data-union-solidity/contracts/DataUnionSidechain.sol\":{\"keccak256\":\"0x4642307a0866b24635ea7719ce499a371049ad8f0a87eb21c54cb829eb02b642\",\"urls\":[\"bzz-raw://2d5ea931bc6611d7fcce11f2d484aeef29e8e5a40e47e65aaa859dda6f4dacd1\",\"dweb:/ipfs/QmVwS7VYzQxuqwTwV3333ZmUztoq56CvuXZhLX2fbrB2Ai\"]},\"/home/heynow/streamr/data-union-solidity/contracts/IERC677.sol\":{\"keccak256\":\"0xe1eb10f511abe1922d4cac9b0c18b4119dc8096bcdfb0c53e2ad08d71ab193b4\",\"urls\":[\"bzz-raw://4b6846c8996809a49e275679d133ecff1b15aa2d8781bab9d6627b6c6bb4d1ed\",\"dweb:/ipfs/QmcYMawWrLWUVynAxEMK2dDCP6z4TbcAEyV7PYh8H3kuHh\"]},\"/home/heynow/streamr/data-union-solidity/contracts/Ownable.sol\":{\"keccak256\":\"0x0d96dac82f3bf17d2cdc90863a61c8957622c305bc3bbf9cd8f47facfa71dea1\",\"urls\":[\"bzz-raw://1cd621b81754be8073fc89bd2bc864e7b0169ba5f153edc5b9212a19f4890aa3\",\"dweb:/ipfs/QmcE5HTf3pptr2s7oiDqYtotCLrb736g8N7YyRZj8k5mHg\"]},\"openzeppelin-solidity/contracts/math/SafeMath.sol\":{\"keccak256\":\"0x9a9cf02622cd7a64261b10534fc3260449da25c98c9e96d1b4ae8110a20e5806\",\"urls\":[\"bzz-raw://2df142592d1dc267d9549049ee3317fa190d2f87eaa565f86ab05ec83f7ab8f5\",\"dweb:/ipfs/QmSkJtcfWo7c42KnL5hho6GFxK6HRNV91XABx1P7xDtfLV\"]},\"openzeppelin-solidity/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x5c26b39d26f7ed489e555d955dcd3e01872972e71fdd1528e93ec164e4f23385\",\"urls\":[\"bzz-raw://efdc632af6960cf865dbc113665ea1f5b90eab75cc40ec062b2f6ae6da582017\",\"dweb:/ipfs/QmfAZFDuG62vxmAN9DnXApv7e7PMzPqi4RkqqZHLMSQiY5\"]}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a01b0319169055612989806100306000396000f3fe6080604052600436106102605760003560e01c806371cdfd6811610144578063bf1e42c0116100b6578063ce7b78641161007a578063ce7b786414610d5e578063e30c397814610e31578063e6018c3114610e46578063ead5d35914610e70578063f2fde38b14610eb1578063fc0c546a14610ee457610267565b8063bf1e42c014610c5d578063c44b73a314610c72578063c59d484714610cc9578063ca6d56dc14610d16578063cc77244014610d4957610267565b80638da5cb5b116101085780638da5cb5b146109d35780639107d08e14610a04578063a2d3cf4b14610a70578063a4d6ddc014610b41578063ae66d94814610bf1578063b274bcc714610c2457610267565b806371cdfd681461088157806373e2290c146108ba57806379049017146108fb5780637b30ed431461091057806385a21246146109be57610267565b8063392e53cd116101dd5780634e71e0c8116101a15780634e71e0c8146106b9578063593b79fe146106ce5780635fb6c6ed14610776578063662d45a21461078b5780636d8018b8146107be5780636f4d469b146107d357610267565b8063392e53cd146105f85780633d8e36a3146106215780633ebff90e146106365780634bee91371461064b5780634e40ea641461068657610267565b80631a79246c116102245780631a79246c146104885780632b94411f146105605780632df3eba41461059b5780632e0d4212146105b0578063331beb5f146105e357610267565b8063015c7f511461026c5780630600a8651461034d57806309a6400b14610374578063131b9c04146103a75780631796621a146103da57610267565b3661026757005b600080fd5b34801561027857600080fd5b5061034b600480360360c081101561028f57600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156102c257600080fd5b8201836020820111156102d457600080fd5b803590602001918460208302840111600160201b831117156102f557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550506001600160a01b0383358116945060208401351692604001359150610ef99050565b005b34801561035957600080fd5b50610362610fe6565b60408051918252519081900360200190f35b34801561038057600080fd5b5061034b6004803603602081101561039757600080fd5b50356001600160a01b0316611005565b3480156103b357600080fd5b50610362600480360360208110156103ca57600080fd5b50356001600160a01b0316611125565b3480156103e657600080fd5b5061034b600480360360208110156103fd57600080fd5b810190602081018135600160201b81111561041757600080fd5b82018360208201111561042957600080fd5b803590602001918460208302840111600160201b8311171561044a57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506111d5945050505050565b34801561049457600080fd5b50610362600480360360a08110156104ab57600080fd5b6001600160a01b038235811692602081013590911691604082013591606081013515159181019060a081016080820135600160201b8111156104ec57600080fd5b8201836020820111156104fe57600080fd5b803590602001918460018302840111600160201b8311171561051f57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611254945050505050565b34801561056c57600080fd5b506103626004803603604081101561058357600080fd5b506001600160a01b03813516906020013515156112be565b3480156105a757600080fd5b506103626112da565b3480156105bc57600080fd5b50610362600480360360208110156105d357600080fd5b50356001600160a01b03166112e0565b3480156105ef57600080fd5b50610362611309565b34801561060457600080fd5b5061060d61147e565b604080519115158252519081900360200190f35b34801561062d57600080fd5b5061036261148f565b34801561064257600080fd5b50610362611495565b34801561065757600080fd5b506103626004803603604081101561066e57600080fd5b506001600160a01b038135169060200135151561149b565b34801561069257600080fd5b5061034b600480360360208110156106a957600080fd5b50356001600160a01b03166114b0565b3480156106c557600080fd5b5061034b611619565b3480156106da57600080fd5b50610701600480360360208110156106f157600080fd5b50356001600160a01b03166116cf565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561073b578181015183820152602001610723565b50505050905090810190601f1680156107685780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561078257600080fd5b506103626116f3565b34801561079757600080fd5b5061034b600480360360208110156107ae57600080fd5b50356001600160a01b03166116f9565b3480156107ca57600080fd5b5061036261181d565b3480156107df57600080fd5b5061034b600480360360208110156107f657600080fd5b810190602081018135600160201b81111561081057600080fd5b82018360208201111561082257600080fd5b803590602001918460208302840111600160201b8311171561084357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611823945050505050565b34801561088d57600080fd5b5061034b600480360360408110156108a457600080fd5b506001600160a01b0381351690602001356118bf565b3480156108c657600080fd5b50610362600480360360608110156108dd57600080fd5b506001600160a01b0381351690602081013590604001351515611990565b34801561090757600080fd5b506103626119a6565b34801561091c57600080fd5b5061034b6004803603602081101561093357600080fd5b810190602081018135600160201b81111561094d57600080fd5b82018360208201111561095f57600080fd5b803590602001918460208302840111600160201b8311171561098057600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506119ac945050505050565b3480156109ca57600080fd5b506103626119dc565b3480156109df57600080fd5b506109e86119e2565b604080516001600160a01b039092168252519081900360200190f35b348015610a1057600080fd5b50610a3760048036036020811015610a2757600080fd5b50356001600160a01b03166119f1565b60405180856002811115610a4757fe5b60ff16815260200184815260200183815260200182815260200194505050505060405180910390f35b348015610a7c57600080fd5b5061060d60048036036080811015610a9357600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610acd57600080fd5b820183602082011115610adf57600080fd5b803590602001918460018302840111600160201b83111715610b0057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611a1c945050505050565b348015610b4d57600080fd5b5061036260048036036040811015610b6457600080fd5b810190602081018135600160201b811115610b7e57600080fd5b820183602082011115610b9057600080fd5b803590602001918460208302840111600160201b83111715610bb157600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505050503515159050611c1d565b348015610bfd57600080fd5b5061036260048036036020811015610c1457600080fd5b50356001600160a01b0316611c6a565b348015610c3057600080fd5b5061034b60048036036040811015610c4757600080fd5b506001600160a01b038135169060200135611ce2565b348015610c6957600080fd5b506109e8611f58565b348015610c7e57600080fd5b50610ca560048036036020811015610c9557600080fd5b50356001600160a01b0316611f67565b60405180826002811115610cb557fe5b60ff16815260200191505060405180910390f35b348015610cd557600080fd5b50610cde611f7c565b604051808260c080838360005b83811015610d03578181015183820152602001610ceb565b5050505090500191505060405180910390f35b348015610d2257600080fd5b5061034b60048036036020811015610d3957600080fd5b50356001600160a01b0316611fc2565b348015610d5557600080fd5b506109e86121c8565b348015610d6a57600080fd5b5061036260048036036080811015610d8157600080fd5b6001600160a01b038235811692602081013590911691604082013515159190810190608081016060820135600160201b811115610dbd57600080fd5b820183602082011115610dcf57600080fd5b803590602001918460018302840111600160201b83111715610df057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506121d7945050505050565b348015610e3d57600080fd5b506109e8612249565b348015610e5257600080fd5b5061034b60048036036020811015610e6957600080fd5b5035612258565b348015610e7c57600080fd5b5061036260048036036060811015610e9357600080fd5b506001600160a01b03813516906020810135906040013515156122ee565b348015610ebd57600080fd5b5061034b60048036036020811015610ed457600080fd5b50356001600160a01b0316612363565b348015610ef057600080fd5b506109e86123d0565b610f0161147e565b15610f53576040805162461bcd60e51b815260206004820152601860248201527f6572726f725f616c7265616479496e697469616c697a65640000000000000000604482015290519081900360640190fd5b60008054336001600160a01b031991821617909155600280549091166001600160a01b038716179055610f85846111d5565b600380546001600160a01b038086166001600160a01b0319928316179092556004805492851692909116919091179055610fbe81612258565b5050600080546001600160a01b0319166001600160a01b039590951694909417909355505050565b6000610fff6006546005546123df90919063ffffffff16565b90505b90565b6000546001600160a01b03163314611050576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b60016001600160a01b0382166000908152600d602052604090205460ff16600281111561107957fe5b146110c2576040805162461bcd60e51b8152602060048201526014602482015273195c9c9bdc97db9bdd1058dd1a5d995059d95b9d60621b604482015290519081900360640190fd5b6001600160a01b0381166000818152600d6020526040808220805460ff19166002179055517feac6c7d5a1c157497119a5d4f661d5f23b844c415452ef440ed346bd127d885e9190a2600a5461111f90600163ffffffff6123df16565b600a5550565b6001600160a01b0381166000908152600c6020526040812081815460ff16600281111561114e57fe5b1415611193576040805162461bcd60e51b815260206004820152600f60248201526e32b93937b92fb737ba26b2b6b132b960891b604482015290519081900360640190fd5b6001815460ff1660028111156111a557fe5b146111b15760006111c8565b60028101546009546111c89163ffffffff6123df16565b6001909101540192915050565b6000546001600160a01b03163314611220576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b60005b81518110156112505761124882828151811061123b57fe5b60200260200101516116f9565b600101611223565b5050565b600061126286868685611a1c565b6112a8576040805162461bcd60e51b81526020600482015260126024820152716572726f725f6261645369676e617475726560701b604482015290519081900360640190fd5b6112b486868686612421565b9695505050505050565b60006112d3836112cd336112e0565b84611990565b9392505050565b60055481565b60006113036112ee83611c6a565b6112f784611125565b9063ffffffff6123df16565b92915050565b600254604080516370a0823160e01b8152306004820152905160009283926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561135957600080fd5b505afa15801561136d573d6000803e3d6000fd5b505050506040513d602081101561138357600080fd5b5051905060006113a1611394610fe6565b839063ffffffff6123df16565b90508015806113b05750600754155b156113c057600092505050611002565b60006113d76007548361273290919063ffffffff16565b6009549091506113ed908263ffffffff61277416565b600955600554611403908363ffffffff61277416565b6005556040805183815290517f41b06c6e0a1531dcb4b86d53ec6268666aa12d55775f8e5a63596fc935cdcc229181900360200190a160075460408051838152602081019290925280517f24a9873073eba764d17ef9fa7475b3b209c02e6e6f7ed991c9c80e09226a37a79281900390910190a15091505090565b6002546001600160a01b0316151590565b60085481565b600a5481565b60006112d3836114aa856112e0565b846122ee565b336001600160a01b03821614806114e457506001336000908152600d602052604090205460ff1660028111156114e257fe5b145b61152a576040805162461bcd60e51b8152602060048201526012602482015271195c9c9bdc97db9bdd14195c9b5a5d1d195960721b604482015290519081900360640190fd5b6001600160a01b0381166000908152600c602052604090206001815460ff16600281111561155457fe5b1461159e576040805162461bcd60e51b815260206004820152601560248201527432b93937b92fb737ba20b1ba34bb32a6b2b6b132b960591b604482015290519081900360640190fd5b6115a782611125565b600182810191909155815460ff191660021782556007546115c7916123df565b6007556008546115de90600163ffffffff61277416565b6008556040516001600160a01b038316907f7df2bff504799b36cafb9574b3fcfd8432ef4a1fa89d1ba9fe40324501adf5f590600090a25050565b6001546001600160a01b0316331461166b576040805162461bcd60e51b815260206004820152601060248201526f37b7363ca832b73234b733a7bbb732b960811b604482015290519081900360640190fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b604080516001600160a01b0392909216600560a21b18601483015260348201905290565b60075481565b6000546001600160a01b03163314611744576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b60016001600160a01b0382166000908152600d602052604090205460ff16600281111561176d57fe5b14156117c0576040805162461bcd60e51b815260206004820152601860248201527f6572726f725f616c72656164794163746976654167656e740000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000818152600d6020526040808220805460ff19166001179055517f10581818fb1ffbfd9ac8500cba931a30c3a57b5e9b7972f2fa0aef002b3fde2b9190a2600a5461111f90600163ffffffff61277416565b60095481565b6001336000908152600d602052604090205460ff16600281111561184357fe5b1461188f576040805162461bcd60e51b8152602060048201526017602482015276195c9c9bdc97dbdb9b1e529bda5b94185c9d1059d95b9d604a1b604482015290519081900360640190fd5b60005b8151811015611250576118b78282815181106118aa57fe5b6020026020010151611fc2565b600101611892565b806118c9336112e0565b1015611918576040805162461bcd60e51b81526020600482015260196024820152786572726f725f696e73756666696369656e7442616c616e636560381b604482015290519081900360640190fd5b336000908152600c60205260409020600381015461193c908363ffffffff61277416565b600382015561194b83836127ce565b6040805183815290516001600160a01b0385169133917f638ce96e87261f007ef5c0389bb59b90db3e19c42edee859d6b09739d8d79f7f9181900360200190a3505050565b600061199e33858585612421565b949350505050565b600b5481565b60005b8151811015611250576119d48282815181106119c757fe5b60200260200101516114b0565b6001016119af565b60065481565b6000546001600160a01b031681565b600c60205260009081526040902080546001820154600283015460039093015460ff90921692909184565b60008151604114611a74576040805162461bcd60e51b815260206004820152601860248201527f6572726f725f6261645369676e61747572654c656e6774680000000000000000604482015290519081900360640190fd5b60208201516040830151606084015160001a601b811015611a9357601b015b8060ff16601b1480611aa857508060ff16601c145b611af9576040805162461bcd60e51b815260206004820152601960248201527f6572726f725f6261645369676e617475726556657273696f6e00000000000000604482015290519081900360640190fd5b6000878730611b078c611c6a565b60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a313034000000815250601d01856001600160a01b03166001600160a01b031660601b8152601401848152602001836001600160a01b03166001600160a01b031660601b8152601401828152602001945050505050604051602081830303815290604052805190602001209050600060018284878760405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611bf5573d6000803e3d6000fd5b5050604051601f1901516001600160a01b038c81169116149650505050505050949350505050565b600080805b8451811015611c6257611c58611c4b868381518110611c3d57fe5b60200260200101518661149b565b839063ffffffff61277416565b9150600101611c22565b509392505050565b6001600160a01b0381166000908152600c6020526040812081815460ff166002811115611c9357fe5b1415611cd8576040805162461bcd60e51b815260206004820152600f60248201526e32b93937b92fb737ba26b2b6b132b960891b604482015290519081900360640190fd5b6003015492915050565b600254604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611d2d57600080fd5b505afa158015611d41573d6000803e3d6000fd5b505050506040513d6020811015611d5757600080fd5b5051600254604080516323b872dd60e01b81523360048201523060248201526044810186905290519293506001600160a01b03909116916323b872dd916064808201926020929091908290030181600087803b158015611db657600080fd5b505af1158015611dca573d6000803e3d6000fd5b505050506040513d6020811015611de057600080fd5b5051611e24576040805162461bcd60e51b815260206004820152600e60248201526d32b93937b92fba3930b739b332b960911b604482015290519081900360640190fd5b600254604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611e6f57600080fd5b505afa158015611e83573d6000803e3d6000fd5b505050506040513d6020811015611e9957600080fd5b5051905082611eae828463ffffffff6123df16565b1015611ef2576040805162461bcd60e51b815260206004820152600e60248201526d32b93937b92fba3930b739b332b960911b604482015290519081900360640190fd5b611efc84846127ce565b600554611f0f908463ffffffff61277416565b6005556040805184815290516001600160a01b0386169133917f4e018df3c92158645fcf45007db7029d3fa97d269866be2bd4360c5f5a6163e49181900360200190a350505050565b6004546001600160a01b031681565b600d6020526000908152604090205460ff1681565b611f84612935565b6040518060c0016040528060055481526020016006548152602001600754815260200160085481526020016009548152602001600a54815250905090565b6001336000908152600d602052604090205460ff166002811115611fe257fe5b1461202e576040805162461bcd60e51b8152602060048201526017602482015276195c9c9bdc97dbdb9b1e529bda5b94185c9d1059d95b9d604a1b604482015290519081900360640190fd5b6001600160a01b0381166000908152600c602052604090206001815460ff16600281111561205857fe5b14156120a1576040805162461bcd60e51b815260206004820152601360248201527232b93937b92fb0b63932b0b23ca6b2b6b132b960691b604482015290519081900360640190fd5b6002815460ff1660028111156120b357fe5b14156120d1576008546120cd90600163ffffffff6123df16565b6008555b600080825460ff1660028111156120e457fe5b1480156120f25750600b5415155b80156121005750600b544710155b825460ff19166001908117845560095460028501556007549192506121259190612774565b6007556040516001600160a01b038416907f0abf3b3f643594d958297062a019458e27d7766629590ac621aa1000fa1298ab90600090a280156121c357600b546040516001600160a01b0385169180156108fc02916000818181858888f19350505050156121c357600b5460408051918252517f55e2724f03f2711a94cf86d8b10c57130b103d6c2f1726076fbf9430340d41e79181900360200190a15b505050565b6003546001600160a01b031681565b60006121e68585600085611a1c565b61222c576040805162461bcd60e51b81526020600482015260126024820152716572726f725f6261645369676e617475726560701b604482015290519081900360640190fd5b612240858561223a886112e0565b86612421565b95945050505050565b6001546001600160a01b031681565b6000546001600160a01b031633146122a3576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b600b548114156122b2576122eb565b600b8190556040805182815290517f749d0aa4ca45d6142166deb1820b64a888996311bb9f74a88c081f5b041d949c9181900360200190a15b50565b6000336001600160a01b038516148061231157506000546001600160a01b031633145b612357576040805162461bcd60e51b8152602060048201526012602482015271195c9c9bdc97db9bdd14195c9b5a5d1d195960721b604482015290519081900360640190fd5b61199e84858585612421565b6000546001600160a01b031633146123ae576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b031681565b60006112d383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612839565b6000826124305750600061199e565b612439856112e0565b831115612489576040805162461bcd60e51b81526020600482015260196024820152786572726f725f696e73756666696369656e7442616c616e636560381b604482015290519081900360640190fd5b6001600160a01b0385166000908152600c6020526040902060038101546124b6908563ffffffff61277416565b60038201556006546124ce908563ffffffff61277416565b6006558215612625576002546003546001600160a01b0391821691634000aea09116866124fa896116cf565b6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561256457818101518382015260200161254c565b50505050905090810190601f1680156125915780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156125b257600080fd5b505af11580156125c6573d6000803e3d6000fd5b505050506040513d60208110156125dc57600080fd5b5051612620576040805162461bcd60e51b815260206004820152600e60248201526d32b93937b92fba3930b739b332b960911b604482015290519081900360640190fd5b6126e9565b6002546040805163a9059cbb60e01b81526001600160a01b038881166004830152602482018890529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561267b57600080fd5b505af115801561268f573d6000803e3d6000fd5b505050506040513d60208110156126a557600080fd5b50516126e9576040805162461bcd60e51b815260206004820152600e60248201526d32b93937b92fba3930b739b332b960911b604482015290519081900360640190fd5b6040805185815290516001600160a01b038816917f48dc35af7b45e2a81fffad55f6e2fafacdb1d3d0d50d24ebdc16324f5ba757f1919081900360200190a25091949350505050565b60006112d383836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506128d0565b6000828201838110156112d3576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b0382166000908152600c6020526040902060018101546127fb908363ffffffff61277416565b60018201556000815460ff16600281111561281257fe5b14156121c357805460ff19166002178155600854612831906001612774565b600855505050565b600081848411156128c85760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561288d578181015183820152602001612875565b50505050905090810190601f1680156128ba5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000818361291f5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561288d578181015183820152602001612875565b50600083858161292b57fe5b0495945050505050565b6040518060c00160405280600690602082028036833750919291505056fea26469706673582212201bc1ebe49687dbeb26b9f260d089c5aa418b9a9ef5e8f22bf1ce619e57f6f06c64736f6c63430006060033", + "deployedBytecode": "0x6080604052600436106102605760003560e01c806371cdfd6811610144578063bf1e42c0116100b6578063ce7b78641161007a578063ce7b786414610d5e578063e30c397814610e31578063e6018c3114610e46578063ead5d35914610e70578063f2fde38b14610eb1578063fc0c546a14610ee457610267565b8063bf1e42c014610c5d578063c44b73a314610c72578063c59d484714610cc9578063ca6d56dc14610d16578063cc77244014610d4957610267565b80638da5cb5b116101085780638da5cb5b146109d35780639107d08e14610a04578063a2d3cf4b14610a70578063a4d6ddc014610b41578063ae66d94814610bf1578063b274bcc714610c2457610267565b806371cdfd681461088157806373e2290c146108ba57806379049017146108fb5780637b30ed431461091057806385a21246146109be57610267565b8063392e53cd116101dd5780634e71e0c8116101a15780634e71e0c8146106b9578063593b79fe146106ce5780635fb6c6ed14610776578063662d45a21461078b5780636d8018b8146107be5780636f4d469b146107d357610267565b8063392e53cd146105f85780633d8e36a3146106215780633ebff90e146106365780634bee91371461064b5780634e40ea641461068657610267565b80631a79246c116102245780631a79246c146104885780632b94411f146105605780632df3eba41461059b5780632e0d4212146105b0578063331beb5f146105e357610267565b8063015c7f511461026c5780630600a8651461034d57806309a6400b14610374578063131b9c04146103a75780631796621a146103da57610267565b3661026757005b600080fd5b34801561027857600080fd5b5061034b600480360360c081101561028f57600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156102c257600080fd5b8201836020820111156102d457600080fd5b803590602001918460208302840111600160201b831117156102f557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550506001600160a01b0383358116945060208401351692604001359150610ef99050565b005b34801561035957600080fd5b50610362610fe6565b60408051918252519081900360200190f35b34801561038057600080fd5b5061034b6004803603602081101561039757600080fd5b50356001600160a01b0316611005565b3480156103b357600080fd5b50610362600480360360208110156103ca57600080fd5b50356001600160a01b0316611125565b3480156103e657600080fd5b5061034b600480360360208110156103fd57600080fd5b810190602081018135600160201b81111561041757600080fd5b82018360208201111561042957600080fd5b803590602001918460208302840111600160201b8311171561044a57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506111d5945050505050565b34801561049457600080fd5b50610362600480360360a08110156104ab57600080fd5b6001600160a01b038235811692602081013590911691604082013591606081013515159181019060a081016080820135600160201b8111156104ec57600080fd5b8201836020820111156104fe57600080fd5b803590602001918460018302840111600160201b8311171561051f57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611254945050505050565b34801561056c57600080fd5b506103626004803603604081101561058357600080fd5b506001600160a01b03813516906020013515156112be565b3480156105a757600080fd5b506103626112da565b3480156105bc57600080fd5b50610362600480360360208110156105d357600080fd5b50356001600160a01b03166112e0565b3480156105ef57600080fd5b50610362611309565b34801561060457600080fd5b5061060d61147e565b604080519115158252519081900360200190f35b34801561062d57600080fd5b5061036261148f565b34801561064257600080fd5b50610362611495565b34801561065757600080fd5b506103626004803603604081101561066e57600080fd5b506001600160a01b038135169060200135151561149b565b34801561069257600080fd5b5061034b600480360360208110156106a957600080fd5b50356001600160a01b03166114b0565b3480156106c557600080fd5b5061034b611619565b3480156106da57600080fd5b50610701600480360360208110156106f157600080fd5b50356001600160a01b03166116cf565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561073b578181015183820152602001610723565b50505050905090810190601f1680156107685780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561078257600080fd5b506103626116f3565b34801561079757600080fd5b5061034b600480360360208110156107ae57600080fd5b50356001600160a01b03166116f9565b3480156107ca57600080fd5b5061036261181d565b3480156107df57600080fd5b5061034b600480360360208110156107f657600080fd5b810190602081018135600160201b81111561081057600080fd5b82018360208201111561082257600080fd5b803590602001918460208302840111600160201b8311171561084357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611823945050505050565b34801561088d57600080fd5b5061034b600480360360408110156108a457600080fd5b506001600160a01b0381351690602001356118bf565b3480156108c657600080fd5b50610362600480360360608110156108dd57600080fd5b506001600160a01b0381351690602081013590604001351515611990565b34801561090757600080fd5b506103626119a6565b34801561091c57600080fd5b5061034b6004803603602081101561093357600080fd5b810190602081018135600160201b81111561094d57600080fd5b82018360208201111561095f57600080fd5b803590602001918460208302840111600160201b8311171561098057600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506119ac945050505050565b3480156109ca57600080fd5b506103626119dc565b3480156109df57600080fd5b506109e86119e2565b604080516001600160a01b039092168252519081900360200190f35b348015610a1057600080fd5b50610a3760048036036020811015610a2757600080fd5b50356001600160a01b03166119f1565b60405180856002811115610a4757fe5b60ff16815260200184815260200183815260200182815260200194505050505060405180910390f35b348015610a7c57600080fd5b5061060d60048036036080811015610a9357600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610acd57600080fd5b820183602082011115610adf57600080fd5b803590602001918460018302840111600160201b83111715610b0057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611a1c945050505050565b348015610b4d57600080fd5b5061036260048036036040811015610b6457600080fd5b810190602081018135600160201b811115610b7e57600080fd5b820183602082011115610b9057600080fd5b803590602001918460208302840111600160201b83111715610bb157600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505050503515159050611c1d565b348015610bfd57600080fd5b5061036260048036036020811015610c1457600080fd5b50356001600160a01b0316611c6a565b348015610c3057600080fd5b5061034b60048036036040811015610c4757600080fd5b506001600160a01b038135169060200135611ce2565b348015610c6957600080fd5b506109e8611f58565b348015610c7e57600080fd5b50610ca560048036036020811015610c9557600080fd5b50356001600160a01b0316611f67565b60405180826002811115610cb557fe5b60ff16815260200191505060405180910390f35b348015610cd557600080fd5b50610cde611f7c565b604051808260c080838360005b83811015610d03578181015183820152602001610ceb565b5050505090500191505060405180910390f35b348015610d2257600080fd5b5061034b60048036036020811015610d3957600080fd5b50356001600160a01b0316611fc2565b348015610d5557600080fd5b506109e86121c8565b348015610d6a57600080fd5b5061036260048036036080811015610d8157600080fd5b6001600160a01b038235811692602081013590911691604082013515159190810190608081016060820135600160201b811115610dbd57600080fd5b820183602082011115610dcf57600080fd5b803590602001918460018302840111600160201b83111715610df057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506121d7945050505050565b348015610e3d57600080fd5b506109e8612249565b348015610e5257600080fd5b5061034b60048036036020811015610e6957600080fd5b5035612258565b348015610e7c57600080fd5b5061036260048036036060811015610e9357600080fd5b506001600160a01b03813516906020810135906040013515156122ee565b348015610ebd57600080fd5b5061034b60048036036020811015610ed457600080fd5b50356001600160a01b0316612363565b348015610ef057600080fd5b506109e86123d0565b610f0161147e565b15610f53576040805162461bcd60e51b815260206004820152601860248201527f6572726f725f616c7265616479496e697469616c697a65640000000000000000604482015290519081900360640190fd5b60008054336001600160a01b031991821617909155600280549091166001600160a01b038716179055610f85846111d5565b600380546001600160a01b038086166001600160a01b0319928316179092556004805492851692909116919091179055610fbe81612258565b5050600080546001600160a01b0319166001600160a01b039590951694909417909355505050565b6000610fff6006546005546123df90919063ffffffff16565b90505b90565b6000546001600160a01b03163314611050576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b60016001600160a01b0382166000908152600d602052604090205460ff16600281111561107957fe5b146110c2576040805162461bcd60e51b8152602060048201526014602482015273195c9c9bdc97db9bdd1058dd1a5d995059d95b9d60621b604482015290519081900360640190fd5b6001600160a01b0381166000818152600d6020526040808220805460ff19166002179055517feac6c7d5a1c157497119a5d4f661d5f23b844c415452ef440ed346bd127d885e9190a2600a5461111f90600163ffffffff6123df16565b600a5550565b6001600160a01b0381166000908152600c6020526040812081815460ff16600281111561114e57fe5b1415611193576040805162461bcd60e51b815260206004820152600f60248201526e32b93937b92fb737ba26b2b6b132b960891b604482015290519081900360640190fd5b6001815460ff1660028111156111a557fe5b146111b15760006111c8565b60028101546009546111c89163ffffffff6123df16565b6001909101540192915050565b6000546001600160a01b03163314611220576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b60005b81518110156112505761124882828151811061123b57fe5b60200260200101516116f9565b600101611223565b5050565b600061126286868685611a1c565b6112a8576040805162461bcd60e51b81526020600482015260126024820152716572726f725f6261645369676e617475726560701b604482015290519081900360640190fd5b6112b486868686612421565b9695505050505050565b60006112d3836112cd336112e0565b84611990565b9392505050565b60055481565b60006113036112ee83611c6a565b6112f784611125565b9063ffffffff6123df16565b92915050565b600254604080516370a0823160e01b8152306004820152905160009283926001600160a01b03909116916370a0823191602480820192602092909190829003018186803b15801561135957600080fd5b505afa15801561136d573d6000803e3d6000fd5b505050506040513d602081101561138357600080fd5b5051905060006113a1611394610fe6565b839063ffffffff6123df16565b90508015806113b05750600754155b156113c057600092505050611002565b60006113d76007548361273290919063ffffffff16565b6009549091506113ed908263ffffffff61277416565b600955600554611403908363ffffffff61277416565b6005556040805183815290517f41b06c6e0a1531dcb4b86d53ec6268666aa12d55775f8e5a63596fc935cdcc229181900360200190a160075460408051838152602081019290925280517f24a9873073eba764d17ef9fa7475b3b209c02e6e6f7ed991c9c80e09226a37a79281900390910190a15091505090565b6002546001600160a01b0316151590565b60085481565b600a5481565b60006112d3836114aa856112e0565b846122ee565b336001600160a01b03821614806114e457506001336000908152600d602052604090205460ff1660028111156114e257fe5b145b61152a576040805162461bcd60e51b8152602060048201526012602482015271195c9c9bdc97db9bdd14195c9b5a5d1d195960721b604482015290519081900360640190fd5b6001600160a01b0381166000908152600c602052604090206001815460ff16600281111561155457fe5b1461159e576040805162461bcd60e51b815260206004820152601560248201527432b93937b92fb737ba20b1ba34bb32a6b2b6b132b960591b604482015290519081900360640190fd5b6115a782611125565b600182810191909155815460ff191660021782556007546115c7916123df565b6007556008546115de90600163ffffffff61277416565b6008556040516001600160a01b038316907f7df2bff504799b36cafb9574b3fcfd8432ef4a1fa89d1ba9fe40324501adf5f590600090a25050565b6001546001600160a01b0316331461166b576040805162461bcd60e51b815260206004820152601060248201526f37b7363ca832b73234b733a7bbb732b960811b604482015290519081900360640190fd5b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b604080516001600160a01b0392909216600560a21b18601483015260348201905290565b60075481565b6000546001600160a01b03163314611744576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b60016001600160a01b0382166000908152600d602052604090205460ff16600281111561176d57fe5b14156117c0576040805162461bcd60e51b815260206004820152601860248201527f6572726f725f616c72656164794163746976654167656e740000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000818152600d6020526040808220805460ff19166001179055517f10581818fb1ffbfd9ac8500cba931a30c3a57b5e9b7972f2fa0aef002b3fde2b9190a2600a5461111f90600163ffffffff61277416565b60095481565b6001336000908152600d602052604090205460ff16600281111561184357fe5b1461188f576040805162461bcd60e51b8152602060048201526017602482015276195c9c9bdc97dbdb9b1e529bda5b94185c9d1059d95b9d604a1b604482015290519081900360640190fd5b60005b8151811015611250576118b78282815181106118aa57fe5b6020026020010151611fc2565b600101611892565b806118c9336112e0565b1015611918576040805162461bcd60e51b81526020600482015260196024820152786572726f725f696e73756666696369656e7442616c616e636560381b604482015290519081900360640190fd5b336000908152600c60205260409020600381015461193c908363ffffffff61277416565b600382015561194b83836127ce565b6040805183815290516001600160a01b0385169133917f638ce96e87261f007ef5c0389bb59b90db3e19c42edee859d6b09739d8d79f7f9181900360200190a3505050565b600061199e33858585612421565b949350505050565b600b5481565b60005b8151811015611250576119d48282815181106119c757fe5b60200260200101516114b0565b6001016119af565b60065481565b6000546001600160a01b031681565b600c60205260009081526040902080546001820154600283015460039093015460ff90921692909184565b60008151604114611a74576040805162461bcd60e51b815260206004820152601860248201527f6572726f725f6261645369676e61747572654c656e6774680000000000000000604482015290519081900360640190fd5b60208201516040830151606084015160001a601b811015611a9357601b015b8060ff16601b1480611aa857508060ff16601c145b611af9576040805162461bcd60e51b815260206004820152601960248201527f6572726f725f6261645369676e617475726556657273696f6e00000000000000604482015290519081900360640190fd5b6000878730611b078c611c6a565b60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a313034000000815250601d01856001600160a01b03166001600160a01b031660601b8152601401848152602001836001600160a01b03166001600160a01b031660601b8152601401828152602001945050505050604051602081830303815290604052805190602001209050600060018284878760405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611bf5573d6000803e3d6000fd5b5050604051601f1901516001600160a01b038c81169116149650505050505050949350505050565b600080805b8451811015611c6257611c58611c4b868381518110611c3d57fe5b60200260200101518661149b565b839063ffffffff61277416565b9150600101611c22565b509392505050565b6001600160a01b0381166000908152600c6020526040812081815460ff166002811115611c9357fe5b1415611cd8576040805162461bcd60e51b815260206004820152600f60248201526e32b93937b92fb737ba26b2b6b132b960891b604482015290519081900360640190fd5b6003015492915050565b600254604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611d2d57600080fd5b505afa158015611d41573d6000803e3d6000fd5b505050506040513d6020811015611d5757600080fd5b5051600254604080516323b872dd60e01b81523360048201523060248201526044810186905290519293506001600160a01b03909116916323b872dd916064808201926020929091908290030181600087803b158015611db657600080fd5b505af1158015611dca573d6000803e3d6000fd5b505050506040513d6020811015611de057600080fd5b5051611e24576040805162461bcd60e51b815260206004820152600e60248201526d32b93937b92fba3930b739b332b960911b604482015290519081900360640190fd5b600254604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611e6f57600080fd5b505afa158015611e83573d6000803e3d6000fd5b505050506040513d6020811015611e9957600080fd5b5051905082611eae828463ffffffff6123df16565b1015611ef2576040805162461bcd60e51b815260206004820152600e60248201526d32b93937b92fba3930b739b332b960911b604482015290519081900360640190fd5b611efc84846127ce565b600554611f0f908463ffffffff61277416565b6005556040805184815290516001600160a01b0386169133917f4e018df3c92158645fcf45007db7029d3fa97d269866be2bd4360c5f5a6163e49181900360200190a350505050565b6004546001600160a01b031681565b600d6020526000908152604090205460ff1681565b611f84612935565b6040518060c0016040528060055481526020016006548152602001600754815260200160085481526020016009548152602001600a54815250905090565b6001336000908152600d602052604090205460ff166002811115611fe257fe5b1461202e576040805162461bcd60e51b8152602060048201526017602482015276195c9c9bdc97dbdb9b1e529bda5b94185c9d1059d95b9d604a1b604482015290519081900360640190fd5b6001600160a01b0381166000908152600c602052604090206001815460ff16600281111561205857fe5b14156120a1576040805162461bcd60e51b815260206004820152601360248201527232b93937b92fb0b63932b0b23ca6b2b6b132b960691b604482015290519081900360640190fd5b6002815460ff1660028111156120b357fe5b14156120d1576008546120cd90600163ffffffff6123df16565b6008555b600080825460ff1660028111156120e457fe5b1480156120f25750600b5415155b80156121005750600b544710155b825460ff19166001908117845560095460028501556007549192506121259190612774565b6007556040516001600160a01b038416907f0abf3b3f643594d958297062a019458e27d7766629590ac621aa1000fa1298ab90600090a280156121c357600b546040516001600160a01b0385169180156108fc02916000818181858888f19350505050156121c357600b5460408051918252517f55e2724f03f2711a94cf86d8b10c57130b103d6c2f1726076fbf9430340d41e79181900360200190a15b505050565b6003546001600160a01b031681565b60006121e68585600085611a1c565b61222c576040805162461bcd60e51b81526020600482015260126024820152716572726f725f6261645369676e617475726560701b604482015290519081900360640190fd5b612240858561223a886112e0565b86612421565b95945050505050565b6001546001600160a01b031681565b6000546001600160a01b031633146122a3576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b600b548114156122b2576122eb565b600b8190556040805182815290517f749d0aa4ca45d6142166deb1820b64a888996311bb9f74a88c081f5b041d949c9181900360200190a15b50565b6000336001600160a01b038516148061231157506000546001600160a01b031633145b612357576040805162461bcd60e51b8152602060048201526012602482015271195c9c9bdc97db9bdd14195c9b5a5d1d195960721b604482015290519081900360640190fd5b61199e84858585612421565b6000546001600160a01b031633146123ae576040805162461bcd60e51b815260206004820152600960248201526837b7363ca7bbb732b960b91b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b031681565b60006112d383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612839565b6000826124305750600061199e565b612439856112e0565b831115612489576040805162461bcd60e51b81526020600482015260196024820152786572726f725f696e73756666696369656e7442616c616e636560381b604482015290519081900360640190fd5b6001600160a01b0385166000908152600c6020526040902060038101546124b6908563ffffffff61277416565b60038201556006546124ce908563ffffffff61277416565b6006558215612625576002546003546001600160a01b0391821691634000aea09116866124fa896116cf565b6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561256457818101518382015260200161254c565b50505050905090810190601f1680156125915780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156125b257600080fd5b505af11580156125c6573d6000803e3d6000fd5b505050506040513d60208110156125dc57600080fd5b5051612620576040805162461bcd60e51b815260206004820152600e60248201526d32b93937b92fba3930b739b332b960911b604482015290519081900360640190fd5b6126e9565b6002546040805163a9059cbb60e01b81526001600160a01b038881166004830152602482018890529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561267b57600080fd5b505af115801561268f573d6000803e3d6000fd5b505050506040513d60208110156126a557600080fd5b50516126e9576040805162461bcd60e51b815260206004820152600e60248201526d32b93937b92fba3930b739b332b960911b604482015290519081900360640190fd5b6040805185815290516001600160a01b038816917f48dc35af7b45e2a81fffad55f6e2fafacdb1d3d0d50d24ebdc16324f5ba757f1919081900360200190a25091949350505050565b60006112d383836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506128d0565b6000828201838110156112d3576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b0382166000908152600c6020526040902060018101546127fb908363ffffffff61277416565b60018201556000815460ff16600281111561281257fe5b14156121c357805460ff19166002178155600854612831906001612774565b600855505050565b600081848411156128c85760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561288d578181015183820152602001612875565b50505050905090810190601f1680156128ba5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000818361291f5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561288d578181015183820152602001612875565b50600083858161292b57fe5b0495945050505050565b6040518060c00160405280600690602082028036833750919291505056fea26469706673582212201bc1ebe49687dbeb26b9f260d089c5aa418b9a9ef5e8f22bf1ce619e57f6f06c64736f6c63430006060033", + "immutableReferences": {}, + "sourceMap": "271:16899:4:-:0;;;2096:43;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;2133:1:4;577:14:12;;-1:-1:-1;;;;;;577:14:12;;;271:16899:4;;;;;;", + "deployedSourceMap": "271:16899:4:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;2180:713:4;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2180:713:4;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;2180:713:4;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;2180:713:4;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;2180:713:4;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;2180:713:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;2180:713:4;;-1:-1:-1;;;;;;;2180:713:4;;;;;-1:-1:-1;2180:713:4;;;;;;;;;;-1:-1:-1;2180:713:4;;-1:-1:-1;2180:713:4:i;:::-;;4469:124;;5:9:-1;2:2;;;27:1;24;17:12;2:2;4469:124:4;;;:::i;:::-;;;;;;;;;;;;;;;;5097:308;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5097:308:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;5097:308:4;-1:-1:-1;;;;;5097:308:4;;:::i;3641:424::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3641:424:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;3641:424:4;-1:-1:-1;;;;;3641:424:4;;:::i;4599:181::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;4599:181:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;4599:181:4;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;4599:181:4;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;4599:181:4;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;4599:181:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;4599:181:4;;-1:-1:-1;4599:181:4;;-1:-1:-1;;;;;4599:181:4:i;15415:377::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;15415:377:4;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;15415:377:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;15415:377:4;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;15415:377:4;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;15415:377:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;15415:377:4;;-1:-1:-1;15415:377:4;;-1:-1:-1;;;;;15415:377:4:i;10807:190::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;10807:190:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;10807:190:4;;;;;;;;;;:::i;1518:28::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1518:28:4;;;:::i;4315:148::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;4315:148:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;4315:148:4;-1:-1:-1;;;;;4315:148:4;;:::i;5555:593::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;5555:593:4;;;:::i;2899:103::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;2899:103:4;;;:::i;:::-;;;;;;;;;;;;;;;;;;1634:34;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1634:34:4;;;:::i;1718:33::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1718:33:4;;;:::i;10337:190::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;10337:190:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;10337:190:4;;;;;;;;;;:::i;6993:547::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;6993:547:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;6993:547:4;-1:-1:-1;;;;;6993:547:4;;:::i;1123:226:12:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1123:226:12;;;:::i;15798:389:4:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;15798:389:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;15798:389:4;-1:-1:-1;;;;;15798:389:4;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;15798:389:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1596:32;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1596:32:4;;;:::i;4786:305::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;4786:305:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;4786:305:4;-1:-1:-1;;;;;4786:305:4;;:::i;1674:37::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1674:37:4;;;:::i;7546:186::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;7546:186:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;7546:186:4;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;7546:186:4;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;7546:186:4;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;7546:186:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;7546:186:4;;-1:-1:-1;7546:186:4;;-1:-1:-1;;;;;7546:186:4:i;9012:470::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;9012:470:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;9012:470:4;;;;;;;;:::i;11003:182::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;11003:182:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;11003:182:4;;;;;;;;;;;;;;;:::i;1758:27::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1758:27:4;;;:::i;7773:162::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;7773:162:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;7773:162:4;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;7773:162:4;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;7773:162:4;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;7773:162:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;7773:162:4;;-1:-1:-1;7773:162:4;;-1:-1:-1;;;;;7773:162:4:i;1552:37::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1552:37:4;;;:::i;236:20:12:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;236:20:12;;;:::i;:::-;;;;-1:-1:-1;;;;;236:20:12;;;;;;;;;;;;;;1792:48:4;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1792:48:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;1792:48:4;-1:-1:-1;;;;;1792:48:4;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12403:1022;;5:9:-1;2:2;;;27:1;24;17:12;2:2;12403:1022:4;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;12403:1022:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;12403:1022:4;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;12403:1022:4;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;12403:1022:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;12403:1022:4;;-1:-1:-1;12403:1022:4;;-1:-1:-1;;;;;12403:1022:4:i;10007:324::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;10007:324:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;10007:324:4;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;10007:324:4;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;10007:324:4;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;10007:324:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;10007:324:4;;-1:-1:-1;;;;10007:324:4;;;;-1:-1:-1;10007:324:4;:::i;4071:238::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;4071:238:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;4071:238:4;-1:-1:-1;;;;;4071:238:4;;:::i;8044:530::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;8044:530:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;8044:530:4;;;;;;;;:::i;1480:31::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1480:31:4;;;:::i;1846:54::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1846:54:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;1846:54:4;-1:-1:-1;;;;;1846:54:4;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3175:289;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3175:289:4;;;:::i;:::-;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;3175:289:4;;;;;;;;;;;;;;;;6154:833;;5:9:-1;2:2;;;27:1;24;17:12;2:2;6154:833:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;6154:833:4;-1:-1:-1;;;;;6154:833:4;;:::i;1446:28::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1446:28:4;;;:::i;14296:383::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;14296:383:4;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;14296:383:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;11:28;;8:2;;;52:1;49;42:12;8:2;14296:383:4;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;14296:383:4;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;14296:383:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;14296:383:4;;-1:-1:-1;14296:383:4;;-1:-1:-1;;;;;14296:383:4:i;262:27:12:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;262:27:12;;;:::i;3470:165:4:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;3470:165:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;3470:165:4;;:::i;10533:268::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;10533:268:4;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;10533:268:4;;;;;;;;;;;;;;;:::i;929:102:12:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;929:102:12;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;929:102:12;-1:-1:-1;;;;;929:102:12;;:::i;1420:20:4:-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;1420:20:4;;;:::i;2180:713::-;2456:15;:13;:15::i;:::-;2455:16;2447:53;;;;;-1:-1:-1;;;2447:53:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;2510:5;:18;;2518:10;-1:-1:-1;;;;;;2510:18:4;;;;;;;2633:5;:29;;;;;-1:-1:-1;;;;;2633:29:4;;;;;2672:40;2690:21;2672:17;:40::i;:::-;2722:13;:36;;-1:-1:-1;;;;;2722:36:4;;;-1:-1:-1;;;;;;2722:36:4;;;;;;;2768:16;:42;;;;;;;;;;;;;;;2820:36;2836:19;2820:15;:36::i;:::-;-1:-1:-1;;2866:5:4;:20;;-1:-1:-1;;;;;;2866:20:4;-1:-1:-1;;;;;2866:20:4;;;;;;;;;;;-1:-1:-1;;;2180:713:4:o;4469:124::-;4519:7;4545:41;4563:22;;4545:13;;:17;;:41;;;;:::i;:::-;4538:48;;4469:124;;:::o;5097:308::-;739:5:12;;-1:-1:-1;;;;;739:5:12;725:10;:19;717:41;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;;;;5201:19:4::1;-1:-1:-1::0;;;;;5176:21:4;::::1;;::::0;;;:14:::1;:21;::::0;;;;;::::1;;:44;::::0;::::1;;;;;;;5168:77;;;::::0;;-1:-1:-1;;;5168:77:4;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;5168:77:4;;;;;;;;;;;;;::::1;;-1:-1:-1::0;;;;;5255:21:4;::::1;;::::0;;;:14:::1;:21;::::0;;;;;:45;;-1:-1:-1;;5255:45:4::1;5279:21;5255:45;::::0;;5315:27;::::1;::::0;5255:21;5315:27:::1;5373:18;::::0;:25:::1;::::0;5396:1:::1;5373:25;:22;:25;:::i;:::-;5352:18;:46:::0;-1:-1:-1;5097:308:4:o;3641:424::-;-1:-1:-1;;;;;3744:18:4;;3699:7;3744:18;;;:10;:18;;;;;3699:7;3780:11;;;;:32;;;;;;;;;;3772:60;;;;;-1:-1:-1;;;3772:60:4;;;;;;;;;;;;-1:-1:-1;;;3772:60:4;;;;;;;;;;;;;;;3936:19;3921:11;;;;:34;;;;;;;;;:123;;4043:1;3921:123;;;4005:14;;;;3978:22;;:42;;;:26;:42;:::i;:::-;3861:27;;;;;:197;;3641:424;-1:-1:-1;;3641:424:4:o;4599:181::-;739:5:12;;-1:-1:-1;;;;;739:5:12;725:10;:19;717:41;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;;;;4683:9:4::1;4678:96;4702:6;:13;4698:1;:17;4678:96;;;4736:27;4753:6;4760:1;4753:9;;;;;;;;;;;;;;4736:16;:27::i;:::-;4717:3;;4678:96;;;;4599:181:::0;:::o;15415:377::-;15608:14;15646:51;15663:10;15675:2;15679:6;15687:9;15646:16;:51::i;:::-;15638:82;;;;;-1:-1:-1;;;15638:82:4;;;;;;;;;;;;-1:-1:-1;;;15638:82:4;;;;;;;;;;;;;;;15737:48;15747:10;15759:2;15763:6;15771:13;15737:9;:48::i;:::-;15730:55;15415:377;-1:-1:-1;;;;;;15415:377:4:o;10807:190::-;10894:7;10924:66;10935:2;10939:35;10963:10;10939:23;:35::i;:::-;10976:13;10924:10;:66::i;:::-;10917:73;10807:190;-1:-1:-1;;;10807:190:4:o;1518:28::-;;;;:::o;4315:148::-;4385:7;4411:45;4435:20;4448:6;4435:12;:20::i;:::-;4411:19;4423:6;4411:11;:19::i;:::-;:23;:45;:23;:45;:::i;:::-;4404:52;4315:148;-1:-1:-1;;4315:148:4:o;5555:593::-;5634:5;;:30;;;-1:-1:-1;;;5634:30:4;;5658:4;5634:30;;;;;;5597:7;;;;-1:-1:-1;;;;;5634:5:4;;;;:15;;:30;;;;;;;;;;;;;;;:5;:30;;;2:2:-1;;;;27:1;24;17:12;2:2;5634:30:4;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5634:30:4;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;5634:30:4;;-1:-1:-1;5674:15:4;5692:32;5704:19;:17;:19::i;:::-;5692:7;;:32;:11;:32;:::i;:::-;5674:50;-1:-1:-1;5766:12:4;;;:38;;-1:-1:-1;5782:17:4;;:22;5766:38;5762:52;;;5813:1;5806:8;;;;;;5762:52;5824:25;5852:30;5864:17;;5852:7;:11;;:30;;;;:::i;:::-;5917:22;;5824:58;;-1:-1:-1;5917:45:4;;5824:58;5917:45;:26;:45;:::i;:::-;5892:22;:70;5988:13;;:26;;6006:7;5988:26;:17;:26;:::i;:::-;5972:13;:42;6029:24;;;;;;;;;;;;;;;;;6099:17;;6068:49;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6134:7:4;-1:-1:-1;;5555:593:4;:::o;2899:103::-;2975:5;;-1:-1:-1;;;;;2975:5:4;2967:28;;2899:103;:::o;1634:34::-;;;;:::o;1718:33::-;;;;:::o;10337:190::-;10426:7;10456:64;10465:6;10473:31;10497:6;10473:23;:31::i;:::-;10506:13;10456:8;:64::i;6993:547::-;7054:10;-1:-1:-1;;;;;7054:20:4;;;;:73;;-1:-1:-1;7108:19:4;7093:10;7078:26;;;;:14;:26;;;;;;;;:49;;;;;;;;;7054:73;7046:104;;;;;-1:-1:-1;;;7046:104:4;;;;;;;;;;;;-1:-1:-1;;;7046:104:4;;;;;;;;;;;;;;;-1:-1:-1;;;;;7186:18:4;;7160:23;7186:18;;;:10;:18;;;;;7237:19;7222:11;;;;:34;;;;;;;;;7214:68;;;;;-1:-1:-1;;;7214:68:4;;;;;;;;;;;;-1:-1:-1;;;7214:68:4;;;;;;;;;;;;;;;7322:19;7334:6;7322:11;:19::i;:::-;7292:27;;;;:49;;;;7351:35;;-1:-1:-1;;7351:35:4;7365:21;7351:35;;;7416:17;;:24;;:21;:24::i;:::-;7396:17;:44;7472:19;;:26;;7496:1;7472:26;:23;:26;:::i;:::-;7450:19;:48;7513:20;;-1:-1:-1;;;;;7513:20:4;;;;;;;;6993:547;;:::o;1123:226:12:-;1188:12;;-1:-1:-1;;;;;1188:12:12;1174:10;:26;1166:55;;;;;-1:-1:-1;;;1166:55:12;;;;;;;;;;;;-1:-1:-1;;;1166:55:12;;;;;;;;;;;;;;;1264:12;;;1257:5;;1236:41;;-1:-1:-1;;;;;1264:12:12;;;;1257:5;;;;1236:41;;;1295:12;;;;1287:20;;-1:-1:-1;;;;;;1287:20:12;;;-1:-1:-1;;;;;1295:12:12;;1287:20;;;;1317:25;;;1123:226::o;15798:389:4:-;15911:4;15905:11;;-1:-1:-1;;;;;15934:50:4;;;;-1:-1:-1;;;16049:52:4;16028:2;16021:10;;15997:118;16148:2;16141:10;;16128:24;;15905:11;15882:299::o;1596:32::-;;;;:::o;4786:305::-;739:5:12;;-1:-1:-1;;;;;739:5:12;725:10;:19;717:41;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;;;;4887:19:4::1;-1:-1:-1::0;;;;;4862:21:4;::::1;;::::0;;;:14:::1;:21;::::0;;;;;::::1;;:44;::::0;::::1;;;;;;;;4854:81;;;::::0;;-1:-1:-1;;;4854:81:4;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;-1:-1:-1::0;;;;;4945:21:4;::::1;;::::0;;;:14:::1;:21;::::0;;;;;:43;;-1:-1:-1;;4945:43:4::1;4969:19;4945:43;::::0;;5003:25;::::1;::::0;4945:21;5003:25:::1;5059:18;::::0;:25:::1;::::0;5082:1:::1;5059:25;:22;:25;:::i;1674:37::-:0;;;;:::o;7546:186::-;1984:19;1969:10;1954:26;;;;:14;:26;;;;;;;;:49;;;;;;;;;1946:85;;;;;-1:-1:-1;;;1946:85:4;;;;;;;;;;;;-1:-1:-1;;;1946:85:4;;;;;;;;;;;;;;;7640:9:::1;7635:91;7659:7;:14;7655:1;:18;7635:91;;;7694:21;7704:7;7712:1;7704:10;;;;;;;;;;;;;;7694:9;:21::i;:::-;7675:3;;7635:91;;9012:470:::0;9140:6;9101:35;9125:10;9101:23;:35::i;:::-;:45;;9093:83;;;;;-1:-1:-1;;;9093:83:4;;;;;;;;;;;;-1:-1:-1;;;9093:83:4;;;;;;;;;;;;;;;9282:10;9245:23;9271:22;;;:10;:22;;;;;9328;;;;:34;;9355:6;9328:34;:26;:34;:::i;:::-;9303:22;;;:59;9372:35;9389:9;9400:6;9372:16;:35::i;:::-;9422:53;;;;;;;;-1:-1:-1;;;;;9422:53:4;;;9445:10;;9422:53;;;;;;;;;9012:470;;;:::o;11003:182::-;11100:7;11130:48;11140:10;11152:2;11156:6;11164:13;11130:9;:48::i;:::-;11123:55;11003:182;-1:-1:-1;;;;11003:182:4:o;1758:27::-;;;;:::o;7773:162::-;7842:9;7837:92;7861:7;:14;7857:1;:18;7837:92;;;7896:22;7907:7;7915:1;7907:10;;;;;;;;;;;;;;7896;:22::i;:::-;7877:3;;7837:92;;1552:37;;;;:::o;236:20:12:-;;;-1:-1:-1;;;;;236:20:12;;:::o;1792:48:4:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;12403:1022::-;12576:12;12612:9;:16;12632:2;12612:22;12604:59;;;;;-1:-1:-1;;;12604:59:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;12818:2;12803:18;;12797:25;12861:2;12846:18;;12840:25;12912:2;12897:18;;12891:25;12674:9;12883:34;12944:2;12940:6;;12936:44;;;12967:2;12962:7;12936:44;12997:1;:7;;13002:2;12997:7;:18;;;;13008:1;:7;;13013:2;13008:7;12997:18;12989:56;;;;;-1:-1:-1;;;12989:56:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;13151:19;13250:9;13261:6;13277:4;13284:20;13297:6;13284:12;:20::i;:::-;13183:122;;;;;;;;;;;;;-1:-1:-1;;;;;13183:122:4;-1:-1:-1;;;;;13183:122:4;;;;;;;;;;;;;-1:-1:-1;;;;;13183:122:4;-1:-1:-1;;;;;13183:122:4;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;13183:122:4;;;13173:133;;;;;;13151:155;;13316:24;13343:31;13353:11;13366:1;13369;13372;13343:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;13343:31:4;;-1:-1:-1;;13343:31:4;;-1:-1:-1;;;;;13392:26:4;;;;;;;-1:-1:-1;;;;;;;12403:1022:4;;;;;;:::o;10007:324::-;10110:7;;;10164:135;10188:7;:14;10184:1;:18;10164:135;;;10235:53;10249:38;10261:7;10269:1;10261:10;;;;;;;;;;;;;;10273:13;10249:11;:38::i;:::-;10235:9;;:53;:13;:53;:::i;:::-;10223:65;-1:-1:-1;10204:3:4;;10164:135;;;-1:-1:-1;10315:9:4;10007:324;-1:-1:-1;;;10007:324:4:o;4071:238::-;-1:-1:-1;;;;;4175:18:4;;4130:7;4175:18;;;:10;:18;;;;;4130:7;4211:11;;;;:32;;;;;;;;;;4203:60;;;;;-1:-1:-1;;;4203:60:4;;;;;;;;;;;;-1:-1:-1;;;4203:60:4;;;;;;;;;;;;;;;4280:22;;;;4071:238;-1:-1:-1;;4071:238:4:o;8044:530::-;8147:5;;:30;;;-1:-1:-1;;;8147:30:4;;8171:4;8147:30;;;;;;8129:15;;-1:-1:-1;;;;;8147:5:4;;:15;;:30;;;;;;;;;;;;;;:5;:30;;;2:2:-1;;;;27:1;24;17:12;2:2;8147:30:4;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;8147:30:4;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;8147:30:4;8195:5;;:53;;;-1:-1:-1;;;8195:53:4;;8214:10;8195:53;;;;8234:4;8195:53;;;;;;;;;;;;8147:30;;-1:-1:-1;;;;;;8195:5:4;;;;:18;;:53;;;;;8147:30;;8195:53;;;;;;;;:5;;:53;;;2:2:-1;;;;27:1;24;17:12;2:2;8195:53:4;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;8195:53:4;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;8195:53:4;8187:80;;;;;-1:-1:-1;;;8187:80:4;;;;;;;;;;;;-1:-1:-1;;;8187:80:4;;;;;;;;;;;;;;;8294:5;;:30;;;-1:-1:-1;;;8294:30:4;;8318:4;8294:30;;;;;;8277:14;;-1:-1:-1;;;;;8294:5:4;;:15;;:30;;;;;;;;;;;;;;:5;:30;;;2:2:-1;;;;27:1;24;17:12;2:2;8294:30:4;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;8294:30:4;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;8294:30:4;;-1:-1:-1;8371:6:4;8342:25;8294:30;8356:10;8342:25;:13;:25;:::i;:::-;:35;;8334:62;;;;;-1:-1:-1;;;8334:62:4;;;;;;;;;;;;-1:-1:-1;;;8334:62:4;;;;;;;;;;;;;;;8407:35;8424:9;8435:6;8407:16;:35::i;:::-;8468:13;;:25;;8486:6;8468:25;:17;:25;:::i;:::-;8452:13;:41;8508:59;;;;;;;;-1:-1:-1;;;;;8508:59:4;;;8536:10;;8508:59;;;;;;;;;8044:530;;;;:::o;1480:31::-;;;-1:-1:-1;;;;;1480:31:4;;:::o;1846:54::-;;;;;;;;;;;;;;;:::o;3175:289::-;3216:17;;:::i;:::-;3245:212;;;;;;;;3266:13;;3245:212;;;;3293:22;;3245:212;;;;3329:17;;3245:212;;;;3360:19;;3245:212;;;;3393:22;;3245:212;;;;3429:18;;3245:212;;;;;3175:289;:::o;6154:833::-;1984:19;1969:10;1954:26;;;;:14;:26;;;;;;;;:49;;;;;;;;;1946:85;;;;;-1:-1:-1;;;1946:85:4;;;;;;;;;;;;-1:-1:-1;;;1946:85:4;;;;;;;;;;;;;;;-1:-1:-1;;;;;6258:18:4;::::1;6232:23;6258:18:::0;;;:10:::1;:18;::::0;;;;6309:19:::1;6294:11:::0;;::::1;;:34;::::0;::::1;;;;;;;;6286:66;;;::::0;;-1:-1:-1;;;6286:66:4;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;6286:66:4;;;;;;;;;;;;;::::1;;6380:21;6365:11:::0;;::::1;;:36;::::0;::::1;;;;;;;6362:113;;;6438:19;::::0;:26:::1;::::0;6462:1:::1;6438:26;:23;:26;:::i;:::-;6416:19;:48:::0;6362:113:::1;6484:12;::::0;6499:11;;::::1;;:32;::::0;::::1;;;;;;;:53;;;;-1:-1:-1::0;6535:12:4::1;::::0;:17;::::1;6499:53;:94;;;;;6581:12;;6556:21;:37;;6499:94;6603:33:::0;;-1:-1:-1;;6603:33:4::1;6617:19;6603:33:::0;;::::1;::::0;;6663:22:::1;::::0;6646:14:::1;::::0;::::1;:39:::0;6715:17:::1;::::0;6484:109;;-1:-1:-1;6715:24:4::1;::::0;:17;:21:::1;:24::i;:::-;6695:17;:44:::0;6754:20:::1;::::0;-1:-1:-1;;;;;6754:20:4;::::1;::::0;::::1;::::0;;;::::1;6854:7;6850:131;;;6893:12;::::0;6881:25:::1;::::0;-1:-1:-1;;;;;6881:11:4;::::1;::::0;:25;::::1;;;::::0;::::1;::::0;;;6893:12;6881:11;:25;::::1;;;;;;6877:94;;;6943:12;::::0;6926:30:::1;::::0;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;6877:94;2041:1;;6154:833:::0;:::o;1446:28::-;;;-1:-1:-1;;;;;1446:28:4;;:::o;14296:383::-;14471:14;14509:46;14526:10;14538:2;14542:1;14545:9;14509:16;:46::i;:::-;14501:77;;;;;-1:-1:-1;;;14501:77:4;;;;;;;;;;;;-1:-1:-1;;;14501:77:4;;;;;;;;;;;;;;;14595;14605:10;14617:2;14621:35;14645:10;14621:23;:35::i;:::-;14658:13;14595:9;:77::i;:::-;14588:84;14296:383;-1:-1:-1;;;;;14296:383:4:o;262:27:12:-;;;-1:-1:-1;;;;;262:27:12;;:::o;3470:165:4:-;739:5:12;;-1:-1:-1;;;;;739:5:12;725:10;:19;717:41;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;;;;3542:12:4::1;;3535:3;:19;3532:31;;;3556:7;;3532:31;3572:12;:18:::0;;;3605:23:::1;::::0;;;;;;;::::1;::::0;;;;::::1;::::0;;::::1;768:1:12;3470:165:4::0;:::o;10533:268::-;10632:7;10663:10;-1:-1:-1;;;;;10663:20:4;;;;:43;;-1:-1:-1;10701:5:4;;-1:-1:-1;;;;;10701:5:4;10687:10;:19;10663:43;10655:74;;;;;-1:-1:-1;;;10655:74:4;;;;;;;;;;;;-1:-1:-1;;;10655:74:4;;;;;;;;;;;;;;;10746:48;10756:6;10764;10772;10780:13;10746:9;:48::i;929:102:12:-;739:5;;-1:-1:-1;;;;;739:5:12;725:10;:19;717:41;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;-1:-1:-1;;;717:41:12;;;;;;;;;;;;;;;1001:12:::1;:23:::0;;-1:-1:-1;;;;;;1001:23:12::1;-1:-1:-1::0;;;;;1001:23:12;;;::::1;::::0;;;::::1;::::0;;929:102::o;1420:20:4:-;;;-1:-1:-1;;;;;1420:20:4;;:::o;1321:134:17:-;1379:7;1405:43;1409:1;1412;1405:43;;;;;;;;;;;;;;;;;:3;:43::i;16338:830:4:-;16450:7;16477:11;16473:25;;-1:-1:-1;16497:1:4;16490:8;;16473:25;16526:29;16550:4;16526:23;:29::i;:::-;16516:6;:39;;16508:77;;;;;-1:-1:-1;;;16508:77:4;;;;;;;;;;;;-1:-1:-1;;;16508:77:4;;;;;;;;;;;;;;;-1:-1:-1;;;;;16621:16:4;;16595:23;16621:16;;;:10;:16;;;;;16672:22;;;;:34;;16699:6;16672:34;:26;:34;:::i;:::-;16647:22;;;:59;16741:22;;:34;;16768:6;16741:34;:26;:34;:::i;:::-;16716:22;:59;16785:307;;;;16841:5;;16884:13;;-1:-1:-1;;;;;16841:5:4;;;;:21;;16884:13;16919:6;16947:11;16955:2;16947:7;:11::i;:::-;16841:135;;;;;;;;;;;;;-1:-1:-1;;;;;16841:135:4;-1:-1:-1;;;;;16841:135:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;16841:135:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;16841:135:4;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;16841:135:4;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;16841:135:4;16816:208;;;;;-1:-1:-1;;;16816:208:4;;;;;;;;;;;;-1:-1:-1;;;16816:208:4;;;;;;;;;;;;;;;16785:307;;;17047:5;;:26;;;-1:-1:-1;;;17047:26:4;;-1:-1:-1;;;;;17047:26:4;;;;;;;;;;;;;;;:5;;;;;:14;;:26;;;;;;;;;;;;;;:5;;:26;;;2:2:-1;;;;27:1;24;17:12;2:2;17047:26:4;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;17047:26:4;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;17047:26:4;17039:53;;;;;-1:-1:-1;;;17039:53:4;;;;;;;;;;;;-1:-1:-1;;;17039:53:4;;;;;;;;;;;;;;;17107:31;;;;;;;;-1:-1:-1;;;;;17107:31:4;;;;;;;;;;;;;-1:-1:-1;17155:6:4;;16338:830;-1:-1:-1;;;;16338:830:4:o;3101:130:17:-;3159:7;3185:39;3189:1;3192;3185:39;;;;;;;;;;;;;;;;;:3;:39::i;874:176::-;932:7;963:5;;;986:6;;;;978:46;;;;;-1:-1:-1;;;978:46:17;;;;;;;;;;;;;;;;;;;;;;;;;;;9578:423:4;-1:-1:-1;;;;;9678:18:4;;9652:23;9678:18;;;:10;:18;;;;;9736:27;;;;:39;;9768:6;9736:39;:31;:39;:::i;:::-;9706:27;;;:69;9854:17;9839:11;;;;:32;;;;;;;;;9835:160;;;9887:35;;-1:-1:-1;;9887:35:4;9901:21;9887:35;;;9958:19;;:26;;9887:35;9958:23;:26::i;:::-;9936:19;:48;9578:423;;;:::o;1746:187:17:-;1832:7;1867:12;1859:6;;;;1851:29;;;;-1:-1:-1;;;1851:29:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;1851:29:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1902:5:17;;;1746:187::o;3713:272::-;3799:7;3833:12;3826:5;3818:28;;;;-1:-1:-1;;;3818:28:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;3818:28:17;;3856:9;3872:1;3868;:5;;;;;;;3713:272;-1:-1:-1;;;;;3713:272:17:o;271:16899:4:-;;;;;;;;;;;29:2:-1;21:6;17:15;125:4;109:14;101:6;88:42;-1:-1;271:16899:4;;;-1:-1:-1;;271:16899:4:o", + "source": "pragma solidity 0.6.6;\n\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\nimport \"openzeppelin-solidity/contracts/token/ERC20/IERC20.sol\";\nimport \"./IERC677.sol\";\nimport \"./Ownable.sol\"; // TODO: switch to \"openzeppelin-solidity/contracts/access/Ownable.sol\";\n\ncontract DataUnionSidechain is Ownable {\n using SafeMath for uint256;\n\n //used to describe members and join part agents\n enum ActiveStatus {None, Active, Inactive}\n\n //emitted by joins/parts\n event MemberJoined(address indexed member);\n event MemberParted(address indexed member);\n event JoinPartAgentAdded(address indexed agent);\n event JoinPartAgentRemoved(address indexed agent);\n\n //emitted when revenue received\n event RevenueReceived(uint256 amount);\n event NewEarnings(uint256 earningsPerMember, uint256 activeMemberCount);\n\n //emitted by withdrawal\n event EarningsWithdrawn(address indexed member, uint256 amount);\n\n //in-contract transfers\n event TransferWithinContract(address indexed from, address indexed to, uint amount);\n event TransferToAddressInContract(address indexed from, address indexed to, uint amount);\n\n //new member eth\n event UpdateNewMemberEth(uint value);\n event NewMemberEthSent(uint amountWei);\n\n struct MemberInfo {\n ActiveStatus status;\n uint256 earningsBeforeLastJoin;\n uint256 lmeAtJoin;\n uint256 withdrawnEarnings;\n }\n\n IERC677 public token;\n address public tokenMediator;\n address public dataUnionMainnet;\n\n uint256 public totalEarnings;\n uint256 public totalEarningsWithdrawn;\n\n uint256 public activeMemberCount;\n uint256 public inactiveMemberCount;\n uint256 public lifetimeMemberEarnings;\n\n uint256 public joinPartAgentCount;\n\n uint256 public newMemberEth;\n\n mapping(address => MemberInfo) public memberData;\n mapping(address => ActiveStatus) public joinPartAgents;\n\n modifier onlyJoinPartAgent() {\n require(joinPartAgents[msg.sender] == ActiveStatus.Active, \"error_onlyJoinPartAgent\");\n _;\n }\n\n // owner will be set by initialize()\n constructor() public Ownable(address(0)) {}\n\n receive() external payable {}\n\n function initialize(\n address initialOwner,\n address tokenAddress,\n address[] memory initialJoinPartAgents,\n address tokenMediatorAddress,\n address mainnetDataUnionAddress,\n uint256 defaultNewMemberEth\n ) public {\n require(!isInitialized(), \"error_alreadyInitialized\");\n owner = msg.sender; // set real owner at the end. During initialize, addJoinPartAgents can be called by owner only\n token = IERC677(tokenAddress);\n addJoinPartAgents(initialJoinPartAgents);\n tokenMediator = tokenMediatorAddress;\n dataUnionMainnet = mainnetDataUnionAddress;\n setNewMemberEth(defaultNewMemberEth);\n owner = initialOwner;\n }\n\n function isInitialized() public view returns (bool){\n return address(token) != address(0);\n }\n\n /**\n * Atomic getter to get all state variables in one call\n * This alleviates the fact that JSON RPC batch requests aren't available in ethers.js\n */\n function getStats() public view returns (uint256[6] memory) {\n return [\n totalEarnings,\n totalEarningsWithdrawn,\n activeMemberCount,\n inactiveMemberCount,\n lifetimeMemberEarnings,\n joinPartAgentCount\n ];\n }\n\n function setNewMemberEth(uint val) public onlyOwner {\n if(val == newMemberEth) return;\n newMemberEth = val;\n emit UpdateNewMemberEth(val);\n }\n\n function getEarnings(address member) public view returns (uint256) {\n MemberInfo storage info = memberData[member];\n require(info.status != ActiveStatus.None, \"error_notMember\");\n return\n info.earningsBeforeLastJoin +\n (\n info.status == ActiveStatus.Active\n ? lifetimeMemberEarnings.sub(info.lmeAtJoin)\n : 0\n );\n }\n\n function getWithdrawn(address member) public view returns (uint256) {\n MemberInfo storage info = memberData[member];\n require(info.status != ActiveStatus.None, \"error_notMember\");\n return info.withdrawnEarnings;\n }\n\n function getWithdrawableEarnings(address member) public view returns (uint256) {\n return getEarnings(member).sub(getWithdrawn(member));\n }\n\n function totalWithdrawable() public view returns (uint256) {\n return totalEarnings.sub(totalEarningsWithdrawn);\n }\n\n function addJoinPartAgents(address[] memory agents) public onlyOwner {\n for (uint256 i = 0; i < agents.length; i++) {\n addJoinPartAgent(agents[i]);\n }\n }\n\n function addJoinPartAgent(address agent) public onlyOwner {\n require(joinPartAgents[agent] != ActiveStatus.Active, \"error_alreadyActiveAgent\");\n joinPartAgents[agent] = ActiveStatus.Active;\n emit JoinPartAgentAdded(agent);\n joinPartAgentCount = joinPartAgentCount.add(1);\n }\n\n function removeJoinPartAgent(address agent) public onlyOwner {\n require(joinPartAgents[agent] == ActiveStatus.Active, \"error_notActiveAgent\");\n joinPartAgents[agent] = ActiveStatus.Inactive;\n emit JoinPartAgentRemoved(agent);\n joinPartAgentCount = joinPartAgentCount.sub(1);\n }\n\n /**\n * Process unaccounted tokens that have been sent previously\n * Called by AMB (see DataUnionMainnet:sendTokensToBridge)\n */\n function refreshRevenue() public returns (uint256) {\n uint256 balance = token.balanceOf(address(this));\n uint256 revenue = balance.sub(totalWithdrawable()); // a.sub(b) errors if b > a\n if (revenue == 0 || activeMemberCount == 0) return 0;\n uint256 earningsPerMember = revenue.div(activeMemberCount);\n lifetimeMemberEarnings = lifetimeMemberEarnings.add(earningsPerMember);\n totalEarnings = totalEarnings.add(revenue);\n emit RevenueReceived(revenue);\n emit NewEarnings(earningsPerMember, activeMemberCount);\n return revenue;\n }\n\n function addMember(address payable member) public onlyJoinPartAgent {\n MemberInfo storage info = memberData[member];\n require(info.status != ActiveStatus.Active, \"error_alreadyMember\");\n if(info.status == ActiveStatus.Inactive){\n inactiveMemberCount = inactiveMemberCount.sub(1);\n }\n bool sendEth = info.status == ActiveStatus.None && newMemberEth != 0 && address(this).balance >= newMemberEth;\n info.status = ActiveStatus.Active;\n info.lmeAtJoin = lifetimeMemberEarnings;\n activeMemberCount = activeMemberCount.add(1);\n emit MemberJoined(member);\n\n // give new members ETH. continue even if transfer fails\n if (sendEth) {\n if (member.send(newMemberEth)) {\n NewMemberEthSent(newMemberEth);\n }\n }\n }\n\n function partMember(address member) public {\n require(msg.sender == member || joinPartAgents[msg.sender] == ActiveStatus.Active, \"error_notPermitted\");\n MemberInfo storage info = memberData[member];\n require(info.status == ActiveStatus.Active, \"error_notActiveMember\");\n info.earningsBeforeLastJoin = getEarnings(member);\n info.status = ActiveStatus.Inactive;\n activeMemberCount = activeMemberCount.sub(1);\n inactiveMemberCount = inactiveMemberCount.add(1);\n emit MemberParted(member);\n }\n\n function addMembers(address payable[] memory members) public onlyJoinPartAgent {\n for (uint256 i = 0; i < members.length; i++) {\n addMember(members[i]);\n }\n }\n\n //access checked in partMember\n function partMembers(address[] memory members) public {\n for (uint256 i = 0; i < members.length; i++) {\n partMember(members[i]);\n }\n }\n\n /**\n * Transfer tokens from outside contract, add to a recipient's in-contract balance\n */\n function transferToMemberInContract(address recipient, uint amount) public {\n uint bal_before = token.balanceOf(address(this));\n require(token.transferFrom(msg.sender, address(this), amount), \"error_transfer\");\n uint bal_after = token.balanceOf(address(this));\n require(bal_after.sub(bal_before) >= amount, \"error_transfer\");\n\n _increaseBalance(recipient, amount);\n totalEarnings = totalEarnings.add(amount);\n emit TransferToAddressInContract(msg.sender, recipient, amount);\n }\n\n /**\n * Transfer tokens from sender's in-contract balance to recipient's in-contract balance\n * This is done by \"withdrawing\" sender's earnings and crediting them to recipient's unwithdrawn earnings,\n * so withdrawnEarnings never decreases for anyone (within this function)\n * @param recipient whose withdrawable earnings will increase\n * @param amount how much withdrawable earnings is transferred\n */\n function transferWithinContract(address recipient, uint amount) public {\n require(getWithdrawableEarnings(msg.sender) >= amount, \"error_insufficientBalance\"); // reverts with \"error_notMember\" msg.sender not member\n MemberInfo storage info = memberData[msg.sender];\n info.withdrawnEarnings = info.withdrawnEarnings.add(amount);\n _increaseBalance(recipient, amount);\n emit TransferWithinContract(msg.sender, recipient, amount);\n }\n\n /**\n * Hack to add to single member's balance without affecting lmeAtJoin\n */\n function _increaseBalance(address member, uint amount) internal {\n MemberInfo storage info = memberData[member];\n info.earningsBeforeLastJoin = info.earningsBeforeLastJoin.add(amount);\n\n // allow seeing and withdrawing earnings\n if (info.status == ActiveStatus.None) {\n info.status = ActiveStatus.Inactive;\n inactiveMemberCount = inactiveMemberCount.add(1);\n }\n }\n\n function withdrawMembers(address[] memory members, bool sendToMainnet)\n public\n returns (uint256)\n {\n uint256 withdrawn = 0;\n for (uint256 i = 0; i < members.length; i++) {\n withdrawn = withdrawn.add(withdrawAll(members[i], sendToMainnet));\n }\n return withdrawn;\n }\n\n function withdrawAll(address member, bool sendToMainnet)\n public\n returns (uint256)\n {\n return withdraw(member, getWithdrawableEarnings(member), sendToMainnet);\n }\n\n function withdraw(address member, uint amount, bool sendToMainnet)\n public\n returns (uint256)\n {\n require(msg.sender == member || msg.sender == owner, \"error_notPermitted\");\n return _withdraw(member, member, amount, sendToMainnet);\n }\n\n function withdrawAllTo(address to, bool sendToMainnet)\n public\n returns (uint256)\n {\n return withdrawTo(to, getWithdrawableEarnings(msg.sender), sendToMainnet);\n }\n\n function withdrawTo(address to, uint amount, bool sendToMainnet)\n public\n returns (uint256)\n {\n return _withdraw(msg.sender, to, amount, sendToMainnet);\n }\n\n /**\n * Check signature from a member authorizing withdrawing its earnings to another account.\n * Throws if the signature is badly formatted or doesn't match the given signer and amount.\n * Signature has parts the act as replay protection:\n * 1) `address(this)`: signature can't be used for other contracts;\n * 2) `withdrawn[signer]`: signature only works once (for unspecified amount), and can be \"cancelled\" by sending a withdraw tx.\n * Generated in Javascript with: `web3.eth.accounts.sign(recipientAddress + amount.toString(16, 64) + contractAddress.slice(2) + withdrawnTokens.toString(16, 64), signerPrivateKey)`,\n * or for unlimited amount: `web3.eth.accounts.sign(recipientAddress + \"0\".repeat(64) + contractAddress.slice(2) + withdrawnTokens.toString(16, 64), signerPrivateKey)`.\n * @param signer whose earnings are being withdrawn\n * @param recipient of the tokens\n * @param amount how much is authorized for withdraw, or zero for unlimited (withdrawAll)\n * @param signature byte array from `web3.eth.accounts.sign`\n * @return isValid true iff signer of the authorization (member whose earnings are going to be withdrawn) matches the signature\n */\n function signatureIsValid(\n address signer,\n address recipient,\n uint amount,\n bytes memory signature\n )\n public view\n returns (bool isValid)\n {\n require(signature.length == 65, \"error_badSignatureLength\");\n\n bytes32 r; bytes32 s; uint8 v;\n assembly { // solium-disable-line security/no-inline-assembly\n r := mload(add(signature, 32))\n s := mload(add(signature, 64))\n v := byte(0, mload(add(signature, 96)))\n }\n if (v < 27) {\n v += 27;\n }\n require(v == 27 || v == 28, \"error_badSignatureVersion\");\n\n // When changing the message, remember to double-check that message length is correct!\n bytes32 messageHash = keccak256(abi.encodePacked(\n \"\\x19Ethereum Signed Message:\\n104\", recipient, amount, address(this), getWithdrawn(signer)));\n address calculatedSigner = ecrecover(messageHash, v, r, s);\n\n return calculatedSigner == signer;\n }\n\n /**\n * Do an \"unlimited donate withdraw\" on behalf of someone else, to an address they've specified.\n * Sponsored withdraw is paid by admin, but target account could be whatever the member specifies.\n * The signature gives a \"blank cheque\" for admin to withdraw all tokens to `recipient` in the future,\n * and it's valid until next withdraw (and so can be nullified by withdrawing any amount).\n * A new signature needs to be obtained for each subsequent future withdraw.\n * @param fromSigner whose earnings are being withdrawn\n * @param to the address the tokens will be sent to (instead of `msg.sender`)\n * @param sendToMainnet if the tokens should be sent to mainnet or only withdrawn into sidechain address\n * @param signature from the member, see `signatureIsValid` how signature generated for unlimited amount\n */\n function withdrawAllToSigned(\n address fromSigner,\n address to,\n bool sendToMainnet,\n bytes memory signature\n )\n public\n returns (uint withdrawn)\n {\n require(signatureIsValid(fromSigner, to, 0, signature), \"error_badSignature\");\n return _withdraw(fromSigner, to, getWithdrawableEarnings(fromSigner), sendToMainnet);\n }\n\n /**\n * Do a \"donate withdraw\" on behalf of someone else, to an address they've specified.\n * Sponsored withdraw is paid by admin, but target account could be whatever the member specifies.\n * The signature is valid only for given amount of tokens that may be different from maximum withdrawable tokens.\n * @param fromSigner whose earnings are being withdrawn\n * @param to the address the tokens will be sent to (instead of `msg.sender`)\n * @param amount of tokens to withdraw\n * @param sendToMainnet if the tokens should be sent to mainnet or only withdrawn into sidechain address\n * @param signature from the member, see `signatureIsValid` how signature generated for unlimited amount\n */\n function withdrawToSigned(\n address fromSigner,\n address to,\n uint amount,\n bool sendToMainnet,\n bytes memory signature\n )\n public\n returns (uint withdrawn)\n {\n require(signatureIsValid(fromSigner, to, amount, signature), \"error_badSignature\");\n return _withdraw(fromSigner, to, amount, sendToMainnet);\n }\n\n function toBytes(address a) public pure returns (bytes memory b) {\n assembly {\n let m := mload(0x40)\n a := and(a, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\n mstore(\n add(m, 20),\n xor(0x140000000000000000000000000000000000000000, a)\n )\n mstore(0x40, add(m, 52))\n b := m\n }\n }\n\n /**\n * Internal function common to all withdraw methods.\n * Does NOT check proper access, so all callers must do that first.\n */\n function _withdraw(address from, address to, uint amount, bool sendToMainnet)\n internal\n returns (uint256)\n {\n if (amount == 0) return 0;\n require(amount <= getWithdrawableEarnings(from), \"error_insufficientBalance\");\n MemberInfo storage info = memberData[from];\n info.withdrawnEarnings = info.withdrawnEarnings.add(amount);\n totalEarningsWithdrawn = totalEarningsWithdrawn.add(amount);\n if (sendToMainnet)\n require(\n token.transferAndCall(\n tokenMediator,\n amount,\n toBytes(to)\n ),\n \"error_transfer\"\n );\n else require(token.transfer(to, amount), \"error_transfer\");\n emit EarningsWithdrawn(from, amount);\n return amount;\n }\n}\n", + "sourcePath": "/home/heynow/streamr/data-union-solidity/contracts/DataUnionSidechain.sol", + "ast": { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/DataUnionSidechain.sol", + "exportedSymbols": { + "DataUnionSidechain": [ + 2432 + ] + }, + "id": 2433, + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 1167, + "literals": [ + "solidity", + "0.6", + ".6" + ], + "nodeType": "PragmaDirective", + "src": "0:22:4" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "file": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "id": 1168, + "nodeType": "ImportDirective", + "scope": 2433, + "sourceUnit": 3642, + "src": "24:59:4", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol", + "file": "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol", + "id": 1169, + "nodeType": "ImportDirective", + "scope": 2433, + "sourceUnit": 4283, + "src": "84:64:4", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/IERC677.sol", + "file": "./IERC677.sol", + "id": 1170, + "nodeType": "ImportDirective", + "scope": 2433, + "sourceUnit": 2940, + "src": "149:23:4", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/Ownable.sol", + "file": "./Ownable.sol", + "id": 1171, + "nodeType": "ImportDirective", + "scope": 2433, + "sourceUnit": 3181, + "src": "173:23:4", + "symbolAliases": [], + "unitAlias": "" + }, + { + "abstract": false, + "baseContracts": [ + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 1172, + "name": "Ownable", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 3180, + "src": "302:7:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_Ownable_$3180", + "typeString": "contract Ownable" + } + }, + "id": 1173, + "nodeType": "InheritanceSpecifier", + "src": "302:7:4" + } + ], + "contractDependencies": [ + 3180 + ], + "contractKind": "contract", + "documentation": null, + "fullyImplemented": true, + "id": 2432, + "linearizedBaseContracts": [ + 2432, + 3180 + ], + "name": "DataUnionSidechain", + "nodeType": "ContractDefinition", + "nodes": [ + { + "id": 1176, + "libraryName": { + "contractScope": null, + "id": 1174, + "name": "SafeMath", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 3641, + "src": "322:8:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_SafeMath_$3641", + "typeString": "library SafeMath" + } + }, + "nodeType": "UsingForDirective", + "src": "316:27:4", + "typeName": { + "id": 1175, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "335:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + }, + { + "canonicalName": "DataUnionSidechain.ActiveStatus", + "id": 1180, + "members": [ + { + "id": 1177, + "name": "None", + "nodeType": "EnumValue", + "src": "420:4:4" + }, + { + "id": 1178, + "name": "Active", + "nodeType": "EnumValue", + "src": "426:6:4" + }, + { + "id": 1179, + "name": "Inactive", + "nodeType": "EnumValue", + "src": "434:8:4" + } + ], + "name": "ActiveStatus", + "nodeType": "EnumDefinition", + "src": "401:42:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1184, + "name": "MemberJoined", + "nodeType": "EventDefinition", + "parameters": { + "id": 1183, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1182, + "indexed": true, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1184, + "src": "497:22:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1181, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "497:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "496:24:4" + }, + "src": "478:43:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1188, + "name": "MemberParted", + "nodeType": "EventDefinition", + "parameters": { + "id": 1187, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1186, + "indexed": true, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1188, + "src": "545:22:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1185, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "545:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "544:24:4" + }, + "src": "526:43:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1192, + "name": "JoinPartAgentAdded", + "nodeType": "EventDefinition", + "parameters": { + "id": 1191, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1190, + "indexed": true, + "mutability": "mutable", + "name": "agent", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1192, + "src": "599:21:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1189, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "599:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "598:23:4" + }, + "src": "574:48:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1196, + "name": "JoinPartAgentRemoved", + "nodeType": "EventDefinition", + "parameters": { + "id": 1195, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1194, + "indexed": true, + "mutability": "mutable", + "name": "agent", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1196, + "src": "654:21:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1193, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "654:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "653:23:4" + }, + "src": "627:50:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1200, + "name": "RevenueReceived", + "nodeType": "EventDefinition", + "parameters": { + "id": 1199, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1198, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1200, + "src": "741:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1197, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "741:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "740:16:4" + }, + "src": "719:38:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1206, + "name": "NewEarnings", + "nodeType": "EventDefinition", + "parameters": { + "id": 1205, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1202, + "indexed": false, + "mutability": "mutable", + "name": "earningsPerMember", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1206, + "src": "780:25:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1201, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "780:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1204, + "indexed": false, + "mutability": "mutable", + "name": "activeMemberCount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1206, + "src": "807:25:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1203, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "807:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "779:54:4" + }, + "src": "762:72:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1212, + "name": "EarningsWithdrawn", + "nodeType": "EventDefinition", + "parameters": { + "id": 1211, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1208, + "indexed": true, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1212, + "src": "892:22:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1207, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "892:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1210, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1212, + "src": "916:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1209, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "916:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "891:40:4" + }, + "src": "868:64:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1220, + "name": "TransferWithinContract", + "nodeType": "EventDefinition", + "parameters": { + "id": 1219, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1214, + "indexed": true, + "mutability": "mutable", + "name": "from", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1220, + "src": "995:20:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1213, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "995:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1216, + "indexed": true, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1220, + "src": "1017:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1215, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1017:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1218, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1220, + "src": "1037:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1217, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1037:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "994:55:4" + }, + "src": "966:84:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1228, + "name": "TransferToAddressInContract", + "nodeType": "EventDefinition", + "parameters": { + "id": 1227, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1222, + "indexed": true, + "mutability": "mutable", + "name": "from", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1228, + "src": "1089:20:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1221, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1089:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1224, + "indexed": true, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1228, + "src": "1111:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1223, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1111:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1226, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1228, + "src": "1131:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1225, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1131:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1088:55:4" + }, + "src": "1055:89:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1232, + "name": "UpdateNewMemberEth", + "nodeType": "EventDefinition", + "parameters": { + "id": 1231, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1230, + "indexed": false, + "mutability": "mutable", + "name": "value", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1232, + "src": "1196:10:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1229, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1196:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1195:12:4" + }, + "src": "1171:37:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1236, + "name": "NewMemberEthSent", + "nodeType": "EventDefinition", + "parameters": { + "id": 1235, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1234, + "indexed": false, + "mutability": "mutable", + "name": "amountWei", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1236, + "src": "1236:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1233, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1236:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1235:16:4" + }, + "src": "1213:39:4" + }, + { + "canonicalName": "DataUnionSidechain.MemberInfo", + "id": 1245, + "members": [ + { + "constant": false, + "id": 1238, + "mutability": "mutable", + "name": "status", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1245, + "src": "1286:19:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "typeName": { + "contractScope": null, + "id": 1237, + "name": "ActiveStatus", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1180, + "src": "1286:12:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1240, + "mutability": "mutable", + "name": "earningsBeforeLastJoin", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1245, + "src": "1315:30:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1239, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1315:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1242, + "mutability": "mutable", + "name": "lmeAtJoin", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1245, + "src": "1355:17:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1241, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1355:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1244, + "mutability": "mutable", + "name": "withdrawnEarnings", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1245, + "src": "1382:25:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1243, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1382:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "name": "MemberInfo", + "nodeType": "StructDefinition", + "scope": 2432, + "src": "1258:156:4", + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "fc0c546a", + "id": 1247, + "mutability": "mutable", + "name": "token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1420:20:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + }, + "typeName": { + "contractScope": null, + "id": 1246, + "name": "IERC677", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2939, + "src": "1420:7:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "cc772440", + "id": 1249, + "mutability": "mutable", + "name": "tokenMediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1446:28:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1248, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1446:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "bf1e42c0", + "id": 1251, + "mutability": "mutable", + "name": "dataUnionMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1480:31:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1250, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1480:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "2df3eba4", + "id": 1253, + "mutability": "mutable", + "name": "totalEarnings", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1518:28:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1252, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1518:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "85a21246", + "id": 1255, + "mutability": "mutable", + "name": "totalEarningsWithdrawn", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1552:37:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1254, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1552:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "5fb6c6ed", + "id": 1257, + "mutability": "mutable", + "name": "activeMemberCount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1596:32:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1256, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1596:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "3d8e36a3", + "id": 1259, + "mutability": "mutable", + "name": "inactiveMemberCount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1634:34:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1258, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1634:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "6d8018b8", + "id": 1261, + "mutability": "mutable", + "name": "lifetimeMemberEarnings", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1674:37:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1260, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1674:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "3ebff90e", + "id": 1263, + "mutability": "mutable", + "name": "joinPartAgentCount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1718:33:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1262, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1718:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "79049017", + "id": 1265, + "mutability": "mutable", + "name": "newMemberEth", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1758:27:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1264, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1758:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "9107d08e", + "id": 1269, + "mutability": "mutable", + "name": "memberData", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1792:48:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo)" + }, + "typeName": { + "id": 1268, + "keyType": { + "id": 1266, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1800:7:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Mapping", + "src": "1792:30:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo)" + }, + "valueType": { + "contractScope": null, + "id": 1267, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "1811:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "c44b73a3", + "id": 1273, + "mutability": "mutable", + "name": "joinPartAgents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1846:54:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + }, + "typeName": { + "id": 1272, + "keyType": { + "id": 1270, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1854:7:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Mapping", + "src": "1846:32:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + }, + "valueType": { + "contractScope": null, + "id": 1271, + "name": "ActiveStatus", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1180, + "src": "1865:12:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + } + }, + "value": null, + "visibility": "public" + }, + { + "body": { + "id": 1287, + "nodeType": "Block", + "src": "1936:113:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1282, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1276, + "name": "joinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1273, + "src": "1954:14:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1279, + "indexExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1277, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "1969:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1278, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "1969:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1954:26:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1280, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "1984:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1281, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "1984:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "1954:49:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6f6e6c794a6f696e506172744167656e74", + "id": 1283, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2005:25:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_956f78fcce2b1e1b69129df43faa6544de07d17c942f714c7b52da05de24f86e", + "typeString": "literal_string \"error_onlyJoinPartAgent\"" + }, + "value": "error_onlyJoinPartAgent" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_956f78fcce2b1e1b69129df43faa6544de07d17c942f714c7b52da05de24f86e", + "typeString": "literal_string \"error_onlyJoinPartAgent\"" + } + ], + "id": 1275, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "1946:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1284, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1946:85:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1285, + "nodeType": "ExpressionStatement", + "src": "1946:85:4" + }, + { + "id": 1286, + "nodeType": "PlaceholderStatement", + "src": "2041:1:4" + } + ] + }, + "documentation": null, + "id": 1288, + "name": "onlyJoinPartAgent", + "nodeType": "ModifierDefinition", + "overrides": null, + "parameters": { + "id": 1274, + "nodeType": "ParameterList", + "parameters": [], + "src": "1933:2:4" + }, + "src": "1907:142:4", + "virtual": false, + "visibility": "internal" + }, + { + "body": { + "id": 1297, + "nodeType": "Block", + "src": "2137:2:4", + "statements": [] + }, + "documentation": null, + "id": 1298, + "implemented": true, + "kind": "constructor", + "modifiers": [ + { + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "30", + "id": 1293, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2133:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "id": 1292, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2125:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1291, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2125:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1294, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2125:10:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "id": 1295, + "modifierName": { + "argumentTypes": null, + "id": 1290, + "name": "Ownable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3180, + "src": "2117:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_Ownable_$3180_$", + "typeString": "type(contract Ownable)" + } + }, + "nodeType": "ModifierInvocation", + "src": "2117:19:4" + } + ], + "name": "", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1289, + "nodeType": "ParameterList", + "parameters": [], + "src": "2107:2:4" + }, + "returnParameters": { + "id": 1296, + "nodeType": "ParameterList", + "parameters": [], + "src": "2137:0:4" + }, + "scope": 2432, + "src": "2096:43:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1301, + "nodeType": "Block", + "src": "2172:2:4", + "statements": [] + }, + "documentation": null, + "id": 1302, + "implemented": true, + "kind": "receive", + "modifiers": [], + "name": "", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1299, + "nodeType": "ParameterList", + "parameters": [], + "src": "2152:2:4" + }, + "returnParameters": { + "id": 1300, + "nodeType": "ParameterList", + "parameters": [], + "src": "2172:0:4" + }, + "scope": 2432, + "src": "2145:29:4", + "stateMutability": "payable", + "virtual": false, + "visibility": "external" + }, + { + "body": { + "id": 1356, + "nodeType": "Block", + "src": "2437:456:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1321, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "!", + "prefix": true, + "src": "2455:16:4", + "subExpression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1319, + "name": "isInitialized", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1373, + "src": "2456:13:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_bool_$", + "typeString": "function () view returns (bool)" + } + }, + "id": 1320, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2456:15:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f616c7265616479496e697469616c697a6564", + "id": 1322, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2473:26:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_845b975974cd10e32a9d060d8158a7b328a11a448ea3c75e0603113d3b173fd5", + "typeString": "literal_string \"error_alreadyInitialized\"" + }, + "value": "error_alreadyInitialized" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_845b975974cd10e32a9d060d8158a7b328a11a448ea3c75e0603113d3b173fd5", + "typeString": "literal_string \"error_alreadyInitialized\"" + } + ], + "id": 1318, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "2447:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1323, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2447:53:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1324, + "nodeType": "ExpressionStatement", + "src": "2447:53:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1328, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1325, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "2510:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1326, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "2518:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1327, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2518:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "src": "2510:18:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1329, + "nodeType": "ExpressionStatement", + "src": "2510:18:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1334, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1330, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "2633:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1332, + "name": "tokenAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1306, + "src": "2649:12:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1331, + "name": "IERC677", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2939, + "src": "2641:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_IERC677_$2939_$", + "typeString": "type(contract IERC677)" + } + }, + "id": 1333, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2641:21:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "src": "2633:29:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 1335, + "nodeType": "ExpressionStatement", + "src": "2633:29:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1337, + "name": "initialJoinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1309, + "src": "2690:21:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + ], + "id": 1336, + "name": "addJoinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1533, + "src": "2672:17:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_array$_t_address_$dyn_memory_ptr_$returns$__$", + "typeString": "function (address[] memory)" + } + }, + "id": 1338, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2672:40:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1339, + "nodeType": "ExpressionStatement", + "src": "2672:40:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1342, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1340, + "name": "tokenMediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1249, + "src": "2722:13:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 1341, + "name": "tokenMediatorAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1311, + "src": "2738:20:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2722:36:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1343, + "nodeType": "ExpressionStatement", + "src": "2722:36:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1346, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1344, + "name": "dataUnionMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1251, + "src": "2768:16:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 1345, + "name": "mainnetDataUnionAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1313, + "src": "2787:23:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2768:42:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1347, + "nodeType": "ExpressionStatement", + "src": "2768:42:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1349, + "name": "defaultNewMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1315, + "src": "2836:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1348, + "name": "setNewMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1411, + "src": "2820:15:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 1350, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2820:36:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1351, + "nodeType": "ExpressionStatement", + "src": "2820:36:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1354, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1352, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "2866:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 1353, + "name": "initialOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1304, + "src": "2874:12:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2866:20:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1355, + "nodeType": "ExpressionStatement", + "src": "2866:20:4" + } + ] + }, + "documentation": null, + "functionSelector": "015c7f51", + "id": 1357, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "initialize", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1316, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1304, + "mutability": "mutable", + "name": "initialOwner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1357, + "src": "2209:20:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1303, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2209:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1306, + "mutability": "mutable", + "name": "tokenAddress", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1357, + "src": "2239:20:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1305, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2239:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1309, + "mutability": "mutable", + "name": "initialJoinPartAgents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1357, + "src": "2269:38:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 1307, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2269:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1308, + "length": null, + "nodeType": "ArrayTypeName", + "src": "2269:9:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1311, + "mutability": "mutable", + "name": "tokenMediatorAddress", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1357, + "src": "2317:28:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1310, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2317:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1313, + "mutability": "mutable", + "name": "mainnetDataUnionAddress", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1357, + "src": "2355:31:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1312, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2355:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1315, + "mutability": "mutable", + "name": "defaultNewMemberEth", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1357, + "src": "2396:27:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1314, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2396:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2199:230:4" + }, + "returnParameters": { + "id": 1317, + "nodeType": "ParameterList", + "parameters": [], + "src": "2437:0:4" + }, + "scope": 2432, + "src": "2180:713:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1372, + "nodeType": "Block", + "src": "2950:52:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 1370, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1364, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "2975:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + ], + "id": 1363, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2967:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1362, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2967:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1365, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2967:14:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "30", + "id": 1368, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2993:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "id": 1367, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2985:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1366, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2985:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1369, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2985:10:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "src": "2967:28:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "functionReturnParameters": 1361, + "id": 1371, + "nodeType": "Return", + "src": "2960:35:4" + } + ] + }, + "documentation": null, + "functionSelector": "392e53cd", + "id": 1373, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "isInitialized", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1358, + "nodeType": "ParameterList", + "parameters": [], + "src": "2921:2:4" + }, + "returnParameters": { + "id": 1361, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1360, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1373, + "src": "2945:4:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 1359, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "2945:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2944:6:4" + }, + "scope": 2432, + "src": "2899:103:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1389, + "nodeType": "Block", + "src": "3235:229:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "components": [ + { + "argumentTypes": null, + "id": 1381, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1253, + "src": "3266:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 1382, + "name": "totalEarningsWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1255, + "src": "3293:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 1383, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "3329:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 1384, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "3360:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 1385, + "name": "lifetimeMemberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1261, + "src": "3393:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 1386, + "name": "joinPartAgentCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1263, + "src": "3429:18:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 1387, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "3252:205:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$6_memory_ptr", + "typeString": "uint256[6] memory" + } + }, + "functionReturnParameters": 1380, + "id": 1388, + "nodeType": "Return", + "src": "3245:212:4" + } + ] + }, + "documentation": { + "id": 1374, + "nodeType": "StructuredDocumentation", + "src": "3008:162:4", + "text": "Atomic getter to get all state variables in one call\nThis alleviates the fact that JSON RPC batch requests aren't available in ethers.js" + }, + "functionSelector": "c59d4847", + "id": 1390, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "getStats", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1375, + "nodeType": "ParameterList", + "parameters": [], + "src": "3192:2:4" + }, + "returnParameters": { + "id": 1380, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1379, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1390, + "src": "3216:17:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$6_memory_ptr", + "typeString": "uint256[6]" + }, + "typeName": { + "baseType": { + "id": 1376, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "3216:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1378, + "length": { + "argumentTypes": null, + "hexValue": "36", + "id": 1377, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3224:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_6_by_1", + "typeString": "int_const 6" + }, + "value": "6" + }, + "nodeType": "ArrayTypeName", + "src": "3216:10:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$6_storage_ptr", + "typeString": "uint256[6]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3215:19:4" + }, + "scope": 2432, + "src": "3175:289:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1410, + "nodeType": "Block", + "src": "3522:113:4", + "statements": [ + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1399, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1397, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1392, + "src": "3535:3:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 1398, + "name": "newMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1265, + "src": "3542:12:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "3535:19:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1401, + "nodeType": "IfStatement", + "src": "3532:31:4", + "trueBody": { + "expression": null, + "functionReturnParameters": 1396, + "id": 1400, + "nodeType": "Return", + "src": "3556:7:4" + } + }, + { + "expression": { + "argumentTypes": null, + "id": 1404, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1402, + "name": "newMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1265, + "src": "3572:12:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 1403, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1392, + "src": "3587:3:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "3572:18:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1405, + "nodeType": "ExpressionStatement", + "src": "3572:18:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1407, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1392, + "src": "3624:3:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1406, + "name": "UpdateNewMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1232, + "src": "3605:18:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 1408, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3605:23:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1409, + "nodeType": "EmitStatement", + "src": "3600:28:4" + } + ] + }, + "documentation": null, + "functionSelector": "e6018c31", + "id": 1411, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 1395, + "modifierName": { + "argumentTypes": null, + "id": 1394, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "3512:9:4", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "3512:9:4" + } + ], + "name": "setNewMemberEth", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1393, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1392, + "mutability": "mutable", + "name": "val", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1411, + "src": "3495:8:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1391, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "3495:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3494:10:4" + }, + "returnParameters": { + "id": 1396, + "nodeType": "ParameterList", + "parameters": [], + "src": "3522:0:4" + }, + "scope": 2432, + "src": "3470:165:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1450, + "nodeType": "Block", + "src": "3708:357:4", + "statements": [ + { + "assignments": [ + 1419 + ], + "declarations": [ + { + "constant": false, + "id": 1419, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1450, + "src": "3718:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 1418, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "3718:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1423, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1420, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "3744:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 1422, + "indexExpression": { + "argumentTypes": null, + "id": 1421, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1413, + "src": "3755:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "3744:18:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "3718:44:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1429, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1425, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1419, + "src": "3780:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1426, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "3780:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1427, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "3795:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1428, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "None", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3795:17:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "3780:32:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6e6f744d656d626572", + "id": 1430, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3814:17:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_d7a3e0a08d346fd90b7cdd70bcb3d747f808a83a9bae19592a90bf66cd6b4372", + "typeString": "literal_string \"error_notMember\"" + }, + "value": "error_notMember" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_d7a3e0a08d346fd90b7cdd70bcb3d747f808a83a9bae19592a90bf66cd6b4372", + "typeString": "literal_string \"error_notMember\"" + } + ], + "id": 1424, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "3772:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1431, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3772:60:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1432, + "nodeType": "ExpressionStatement", + "src": "3772:60:4" + }, + { + "expression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1448, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1433, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1419, + "src": "3861:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1434, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "earningsBeforeLastJoin", + "nodeType": "MemberAccess", + "referencedDeclaration": 1240, + "src": "3861:27:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "+", + "rightExpression": { + "argumentTypes": null, + "components": [ + { + "argumentTypes": null, + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1439, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1435, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1419, + "src": "3921:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1436, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "3921:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1437, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "3936:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1438, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3936:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "3921:34:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1445, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4043:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "id": 1446, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "Conditional", + "src": "3921:123:4", + "trueExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1442, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1419, + "src": "4005:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1443, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "lmeAtJoin", + "nodeType": "MemberAccess", + "referencedDeclaration": 1242, + "src": "4005:14:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1440, + "name": "lifetimeMemberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1261, + "src": "3978:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1441, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "3978:26:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1444, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3978:42:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 1447, + "isConstant": false, + "isInlineArray": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "3903:155:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "3861:197:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 1417, + "id": 1449, + "nodeType": "Return", + "src": "3842:216:4" + } + ] + }, + "documentation": null, + "functionSelector": "131b9c04", + "id": 1451, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "getEarnings", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1414, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1413, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1451, + "src": "3662:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1412, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3662:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3661:16:4" + }, + "returnParameters": { + "id": 1417, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1416, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1451, + "src": "3699:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1415, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "3699:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3698:9:4" + }, + "scope": 2432, + "src": "3641:424:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1476, + "nodeType": "Block", + "src": "4139:170:4", + "statements": [ + { + "assignments": [ + 1459 + ], + "declarations": [ + { + "constant": false, + "id": 1459, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1476, + "src": "4149:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 1458, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "4149:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1463, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1460, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "4175:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 1462, + "indexExpression": { + "argumentTypes": null, + "id": 1461, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1453, + "src": "4186:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "4175:18:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "4149:44:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1469, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1465, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1459, + "src": "4211:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1466, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "4211:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1467, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "4226:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1468, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "None", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "4226:17:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "4211:32:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6e6f744d656d626572", + "id": 1470, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4245:17:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_d7a3e0a08d346fd90b7cdd70bcb3d747f808a83a9bae19592a90bf66cd6b4372", + "typeString": "literal_string \"error_notMember\"" + }, + "value": "error_notMember" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_d7a3e0a08d346fd90b7cdd70bcb3d747f808a83a9bae19592a90bf66cd6b4372", + "typeString": "literal_string \"error_notMember\"" + } + ], + "id": 1464, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "4203:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1471, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4203:60:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1472, + "nodeType": "ExpressionStatement", + "src": "4203:60:4" + }, + { + "expression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1473, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1459, + "src": "4280:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1474, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "withdrawnEarnings", + "nodeType": "MemberAccess", + "referencedDeclaration": 1244, + "src": "4280:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 1457, + "id": 1475, + "nodeType": "Return", + "src": "4273:29:4" + } + ] + }, + "documentation": null, + "functionSelector": "ae66d948", + "id": 1477, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "getWithdrawn", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1454, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1453, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1477, + "src": "4093:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1452, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4093:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4092:16:4" + }, + "returnParameters": { + "id": 1457, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1456, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1477, + "src": "4130:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1455, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4130:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4129:9:4" + }, + "scope": 2432, + "src": "4071:238:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1493, + "nodeType": "Block", + "src": "4394:69:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1489, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1479, + "src": "4448:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1488, + "name": "getWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1477, + "src": "4435:12:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 1490, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4435:20:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1485, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1479, + "src": "4423:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1484, + "name": "getEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1451, + "src": "4411:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 1486, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4411:19:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1487, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "4411:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1491, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4411:45:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 1483, + "id": 1492, + "nodeType": "Return", + "src": "4404:52:4" + } + ] + }, + "documentation": null, + "functionSelector": "2e0d4212", + "id": 1494, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "getWithdrawableEarnings", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1480, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1479, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1494, + "src": "4348:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1478, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4348:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4347:16:4" + }, + "returnParameters": { + "id": 1483, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1482, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1494, + "src": "4385:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1481, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4385:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4384:9:4" + }, + "scope": 2432, + "src": "4315:148:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1504, + "nodeType": "Block", + "src": "4528:65:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1501, + "name": "totalEarningsWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1255, + "src": "4563:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1499, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1253, + "src": "4545:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1500, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "4545:17:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1502, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4545:41:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 1498, + "id": 1503, + "nodeType": "Return", + "src": "4538:48:4" + } + ] + }, + "documentation": null, + "functionSelector": "0600a865", + "id": 1505, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "totalWithdrawable", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1495, + "nodeType": "ParameterList", + "parameters": [], + "src": "4495:2:4" + }, + "returnParameters": { + "id": 1498, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1497, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1505, + "src": "4519:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1496, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4519:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4518:9:4" + }, + "scope": 2432, + "src": "4469:124:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1532, + "nodeType": "Block", + "src": "4668:112:4", + "statements": [ + { + "body": { + "id": 1530, + "nodeType": "Block", + "src": "4722:52:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1525, + "name": "agents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1508, + "src": "4753:6:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + "id": 1527, + "indexExpression": { + "argumentTypes": null, + "id": 1526, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1514, + "src": "4760:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "4753:9:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1524, + "name": "addJoinPartAgent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1569, + "src": "4736:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 1528, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4736:27:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1529, + "nodeType": "ExpressionStatement", + "src": "4736:27:4" + } + ] + }, + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1520, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1517, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1514, + "src": "4698:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "<", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1518, + "name": "agents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1508, + "src": "4702:6:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + "id": 1519, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "length", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "4702:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "4698:17:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 1531, + "initializationExpression": { + "assignments": [ + 1514 + ], + "declarations": [ + { + "constant": false, + "id": 1514, + "mutability": "mutable", + "name": "i", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1531, + "src": "4683:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1513, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4683:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1516, + "initialValue": { + "argumentTypes": null, + "hexValue": "30", + "id": 1515, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4695:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "nodeType": "VariableDeclarationStatement", + "src": "4683:13:4" + }, + "loopExpression": { + "expression": { + "argumentTypes": null, + "id": 1522, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "++", + "prefix": false, + "src": "4717:3:4", + "subExpression": { + "argumentTypes": null, + "id": 1521, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1514, + "src": "4717:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1523, + "nodeType": "ExpressionStatement", + "src": "4717:3:4" + }, + "nodeType": "ForStatement", + "src": "4678:96:4" + } + ] + }, + "documentation": null, + "functionSelector": "1796621a", + "id": 1533, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 1511, + "modifierName": { + "argumentTypes": null, + "id": 1510, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "4658:9:4", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "4658:9:4" + } + ], + "name": "addJoinPartAgents", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1509, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1508, + "mutability": "mutable", + "name": "agents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1533, + "src": "4626:23:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 1506, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4626:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1507, + "length": null, + "nodeType": "ArrayTypeName", + "src": "4626:9:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4625:25:4" + }, + "returnParameters": { + "id": 1512, + "nodeType": "ParameterList", + "parameters": [], + "src": "4668:0:4" + }, + "scope": 2432, + "src": "4599:181:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1568, + "nodeType": "Block", + "src": "4844:247:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1546, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1541, + "name": "joinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1273, + "src": "4862:14:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1543, + "indexExpression": { + "argumentTypes": null, + "id": 1542, + "name": "agent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1535, + "src": "4877:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "4862:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1544, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "4887:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1545, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "4887:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "4862:44:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f616c72656164794163746976654167656e74", + "id": 1547, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4908:26:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_bb39e853702abde1810741d4774a63438edaeee888b9b2a936f664fafe2a45b8", + "typeString": "literal_string \"error_alreadyActiveAgent\"" + }, + "value": "error_alreadyActiveAgent" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_bb39e853702abde1810741d4774a63438edaeee888b9b2a936f664fafe2a45b8", + "typeString": "literal_string \"error_alreadyActiveAgent\"" + } + ], + "id": 1540, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "4854:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1548, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4854:81:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1549, + "nodeType": "ExpressionStatement", + "src": "4854:81:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1555, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1550, + "name": "joinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1273, + "src": "4945:14:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1552, + "indexExpression": { + "argumentTypes": null, + "id": 1551, + "name": "agent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1535, + "src": "4960:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "nodeType": "IndexAccess", + "src": "4945:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1553, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "4969:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1554, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "4969:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "4945:43:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "id": 1556, + "nodeType": "ExpressionStatement", + "src": "4945:43:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1558, + "name": "agent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1535, + "src": "5022:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1557, + "name": "JoinPartAgentAdded", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1192, + "src": "5003:18:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 1559, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5003:25:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1560, + "nodeType": "EmitStatement", + "src": "4998:30:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1566, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1561, + "name": "joinPartAgentCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1263, + "src": "5038:18:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 1564, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5082:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 1562, + "name": "joinPartAgentCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1263, + "src": "5059:18:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1563, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "5059:22:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1565, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5059:25:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "5038:46:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1567, + "nodeType": "ExpressionStatement", + "src": "5038:46:4" + } + ] + }, + "documentation": null, + "functionSelector": "662d45a2", + "id": 1569, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 1538, + "modifierName": { + "argumentTypes": null, + "id": 1537, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "4834:9:4", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "4834:9:4" + } + ], + "name": "addJoinPartAgent", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1536, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1535, + "mutability": "mutable", + "name": "agent", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1569, + "src": "4812:13:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1534, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4812:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4811:15:4" + }, + "returnParameters": { + "id": 1539, + "nodeType": "ParameterList", + "parameters": [], + "src": "4844:0:4" + }, + "scope": 2432, + "src": "4786:305:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1604, + "nodeType": "Block", + "src": "5158:247:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1582, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1577, + "name": "joinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1273, + "src": "5176:14:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1579, + "indexExpression": { + "argumentTypes": null, + "id": 1578, + "name": "agent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1571, + "src": "5191:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "5176:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1580, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "5201:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1581, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "5201:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "5176:44:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6e6f744163746976654167656e74", + "id": 1583, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5222:22:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_7374b1c602a903c4ee0ecf07cf7d2bb5da07e6616a0fd70b600a11d82b670e51", + "typeString": "literal_string \"error_notActiveAgent\"" + }, + "value": "error_notActiveAgent" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_7374b1c602a903c4ee0ecf07cf7d2bb5da07e6616a0fd70b600a11d82b670e51", + "typeString": "literal_string \"error_notActiveAgent\"" + } + ], + "id": 1576, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "5168:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1584, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5168:77:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1585, + "nodeType": "ExpressionStatement", + "src": "5168:77:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1591, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1586, + "name": "joinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1273, + "src": "5255:14:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1588, + "indexExpression": { + "argumentTypes": null, + "id": 1587, + "name": "agent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1571, + "src": "5270:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "nodeType": "IndexAccess", + "src": "5255:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1589, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "5279:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1590, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Inactive", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "5279:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "5255:45:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "id": 1592, + "nodeType": "ExpressionStatement", + "src": "5255:45:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1594, + "name": "agent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1571, + "src": "5336:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1593, + "name": "JoinPartAgentRemoved", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1196, + "src": "5315:20:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 1595, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5315:27:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1596, + "nodeType": "EmitStatement", + "src": "5310:32:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1602, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1597, + "name": "joinPartAgentCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1263, + "src": "5352:18:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 1600, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5396:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 1598, + "name": "joinPartAgentCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1263, + "src": "5373:18:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1599, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "5373:22:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1601, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5373:25:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "5352:46:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1603, + "nodeType": "ExpressionStatement", + "src": "5352:46:4" + } + ] + }, + "documentation": null, + "functionSelector": "09a6400b", + "id": 1605, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 1574, + "modifierName": { + "argumentTypes": null, + "id": 1573, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "5148:9:4", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "5148:9:4" + } + ], + "name": "removeJoinPartAgent", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1572, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1571, + "mutability": "mutable", + "name": "agent", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1605, + "src": "5126:13:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1570, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "5126:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "5125:15:4" + }, + "returnParameters": { + "id": 1575, + "nodeType": "ParameterList", + "parameters": [], + "src": "5158:0:4" + }, + "scope": 2432, + "src": "5097:308:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1671, + "nodeType": "Block", + "src": "5606:542:4", + "statements": [ + { + "assignments": [ + 1612 + ], + "declarations": [ + { + "constant": false, + "id": 1612, + "mutability": "mutable", + "name": "balance", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1671, + "src": "5616:15:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1611, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "5616:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1620, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1617, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "5658:4:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + ], + "id": 1616, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "5650:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1615, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "5650:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1618, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5650:13:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "expression": { + "argumentTypes": null, + "id": 1613, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "5634:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 1614, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balanceOf", + "nodeType": "MemberAccess", + "referencedDeclaration": 4221, + "src": "5634:15:4", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view external returns (uint256)" + } + }, + "id": 1619, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5634:30:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "5616:48:4" + }, + { + "assignments": [ + 1622 + ], + "declarations": [ + { + "constant": false, + "id": 1622, + "mutability": "mutable", + "name": "revenue", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1671, + "src": "5674:15:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1621, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "5674:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1628, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1625, + "name": "totalWithdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1505, + "src": "5704:17:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 1626, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5704:19:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1623, + "name": "balance", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1612, + "src": "5692:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1624, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "5692:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1627, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5692:32:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "5674:50:4" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 1635, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1631, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1629, + "name": "revenue", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1622, + "src": "5766:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1630, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5777:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "5766:12:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "||", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1634, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1632, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "5782:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1633, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5803:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "5782:22:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "5766:38:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1638, + "nodeType": "IfStatement", + "src": "5762:52:4", + "trueBody": { + "expression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1636, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5813:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "functionReturnParameters": 1610, + "id": 1637, + "nodeType": "Return", + "src": "5806:8:4" + } + }, + { + "assignments": [ + 1640 + ], + "declarations": [ + { + "constant": false, + "id": 1640, + "mutability": "mutable", + "name": "earningsPerMember", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1671, + "src": "5824:25:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1639, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "5824:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1645, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1643, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "5864:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1641, + "name": "revenue", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1622, + "src": "5852:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1642, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "div", + "nodeType": "MemberAccess", + "referencedDeclaration": 3571, + "src": "5852:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1644, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5852:30:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "5824:58:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1651, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1646, + "name": "lifetimeMemberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1261, + "src": "5892:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1649, + "name": "earningsPerMember", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1640, + "src": "5944:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1647, + "name": "lifetimeMemberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1261, + "src": "5917:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1648, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "5917:26:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1650, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5917:45:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "5892:70:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1652, + "nodeType": "ExpressionStatement", + "src": "5892:70:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1658, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1653, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1253, + "src": "5972:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1656, + "name": "revenue", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1622, + "src": "6006:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1654, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1253, + "src": "5988:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1655, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "5988:17:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1657, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5988:26:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "5972:42:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1659, + "nodeType": "ExpressionStatement", + "src": "5972:42:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1661, + "name": "revenue", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1622, + "src": "6045:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1660, + "name": "RevenueReceived", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1200, + "src": "6029:15:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 1662, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6029:24:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1663, + "nodeType": "EmitStatement", + "src": "6024:29:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1665, + "name": "earningsPerMember", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1640, + "src": "6080:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 1666, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "6099:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1664, + "name": "NewEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1206, + "src": "6068:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$_t_uint256_$returns$__$", + "typeString": "function (uint256,uint256)" + } + }, + "id": 1667, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6068:49:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1668, + "nodeType": "EmitStatement", + "src": "6063:54:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1669, + "name": "revenue", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1622, + "src": "6134:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 1610, + "id": 1670, + "nodeType": "Return", + "src": "6127:14:4" + } + ] + }, + "documentation": { + "id": 1606, + "nodeType": "StructuredDocumentation", + "src": "5411:139:4", + "text": "Process unaccounted tokens that have been sent previously\nCalled by AMB (see DataUnionMainnet:sendTokensToBridge)" + }, + "functionSelector": "331beb5f", + "id": 1672, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "refreshRevenue", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1607, + "nodeType": "ParameterList", + "parameters": [], + "src": "5578:2:4" + }, + "returnParameters": { + "id": 1610, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1609, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1672, + "src": "5597:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1608, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "5597:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "5596:9:4" + }, + "scope": 2432, + "src": "5555:593:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1765, + "nodeType": "Block", + "src": "6222:765:4", + "statements": [ + { + "assignments": [ + 1680 + ], + "declarations": [ + { + "constant": false, + "id": 1680, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1765, + "src": "6232:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 1679, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "6232:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1684, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1681, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "6258:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 1683, + "indexExpression": { + "argumentTypes": null, + "id": 1682, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1674, + "src": "6269:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "6258:18:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "6232:44:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1690, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1686, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1680, + "src": "6294:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1687, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "6294:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1688, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "6309:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1689, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "6309:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "6294:34:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f616c72656164794d656d626572", + "id": 1691, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6330:21:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_0cd731b7251f7a1d03a588db9c28b82c775f5ea903082a5ec49eb1fc1ac0eb1f", + "typeString": "literal_string \"error_alreadyMember\"" + }, + "value": "error_alreadyMember" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_0cd731b7251f7a1d03a588db9c28b82c775f5ea903082a5ec49eb1fc1ac0eb1f", + "typeString": "literal_string \"error_alreadyMember\"" + } + ], + "id": 1685, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "6286:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1692, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6286:66:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1693, + "nodeType": "ExpressionStatement", + "src": "6286:66:4" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1698, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1694, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1680, + "src": "6365:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1695, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "6365:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1696, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "6380:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1697, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Inactive", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "6380:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "6365:36:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1707, + "nodeType": "IfStatement", + "src": "6362:113:4", + "trueBody": { + "id": 1706, + "nodeType": "Block", + "src": "6402:73:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 1704, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1699, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "6416:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 1702, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6462:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 1700, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "6438:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1701, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "6438:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1703, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6438:26:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6416:48:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1705, + "nodeType": "ExpressionStatement", + "src": "6416:48:4" + } + ] + } + }, + { + "assignments": [ + 1709 + ], + "declarations": [ + { + "constant": false, + "id": 1709, + "mutability": "mutable", + "name": "sendEth", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1765, + "src": "6484:12:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 1708, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "6484:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1727, + "initialValue": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 1726, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 1718, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1714, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1710, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1680, + "src": "6499:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1711, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "6499:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1712, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "6514:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1713, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "None", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "6514:17:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "6499:32:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "&&", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1717, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1715, + "name": "newMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1265, + "src": "6535:12:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1716, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6551:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "6535:17:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "6499:53:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "&&", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1725, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1721, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "6564:4:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + ], + "id": 1720, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "6556:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1719, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "6556:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1722, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6556:13:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 1723, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balance", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "6556:21:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": ">=", + "rightExpression": { + "argumentTypes": null, + "id": 1724, + "name": "newMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1265, + "src": "6581:12:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6556:37:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "6499:94:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "6484:109:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1733, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1728, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1680, + "src": "6603:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1730, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "6603:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1731, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "6617:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1732, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "6617:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "6603:33:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "id": 1734, + "nodeType": "ExpressionStatement", + "src": "6603:33:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1739, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1735, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1680, + "src": "6646:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1737, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "lmeAtJoin", + "nodeType": "MemberAccess", + "referencedDeclaration": 1242, + "src": "6646:14:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 1738, + "name": "lifetimeMemberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1261, + "src": "6663:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6646:39:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1740, + "nodeType": "ExpressionStatement", + "src": "6646:39:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1746, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1741, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "6695:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 1744, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6737:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 1742, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "6715:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1743, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "6715:21:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1745, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6715:24:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6695:44:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1747, + "nodeType": "ExpressionStatement", + "src": "6695:44:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1749, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1674, + "src": "6767:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "id": 1748, + "name": "MemberJoined", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1184, + "src": "6754:12:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 1750, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6754:20:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1751, + "nodeType": "EmitStatement", + "src": "6749:25:4" + }, + { + "condition": { + "argumentTypes": null, + "id": 1752, + "name": "sendEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1709, + "src": "6854:7:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1764, + "nodeType": "IfStatement", + "src": "6850:131:4", + "trueBody": { + "id": 1763, + "nodeType": "Block", + "src": "6863:118:4", + "statements": [ + { + "condition": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1755, + "name": "newMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1265, + "src": "6893:12:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1753, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1674, + "src": "6881:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 1754, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "send", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "6881:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_send_nonpayable$_t_uint256_$returns$_t_bool_$", + "typeString": "function (uint256) returns (bool)" + } + }, + "id": 1756, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6881:25:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1762, + "nodeType": "IfStatement", + "src": "6877:94:4", + "trueBody": { + "id": 1761, + "nodeType": "Block", + "src": "6908:63:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1758, + "name": "newMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1265, + "src": "6943:12:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1757, + "name": "NewMemberEthSent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1236, + "src": "6926:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 1759, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6926:30:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1760, + "nodeType": "ExpressionStatement", + "src": "6926:30:4" + } + ] + } + } + ] + } + } + ] + }, + "documentation": null, + "functionSelector": "ca6d56dc", + "id": 1766, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 1677, + "modifierName": { + "argumentTypes": null, + "id": 1676, + "name": "onlyJoinPartAgent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1288, + "src": "6204:17:4", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "6204:17:4" + } + ], + "name": "addMember", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1675, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1674, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1766, + "src": "6173:22:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + "typeName": { + "id": 1673, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "6173:15:4", + "stateMutability": "payable", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "6172:24:4" + }, + "returnParameters": { + "id": 1678, + "nodeType": "ParameterList", + "parameters": [], + "src": "6222:0:4" + }, + "scope": 2432, + "src": "6154:833:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1835, + "nodeType": "Block", + "src": "7036:504:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 1783, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 1775, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1772, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "7054:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1773, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7054:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 1774, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1768, + "src": "7068:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "7054:20:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "||", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1782, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1776, + "name": "joinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1273, + "src": "7078:14:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1779, + "indexExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1777, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "7093:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1778, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7093:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7078:26:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1780, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "7108:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1781, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7108:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "7078:49:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "7054:73:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6e6f745065726d6974746564", + "id": 1784, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7129:20:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_81fcea6533090d67b5d2d1910c87832a3a952f4bfc10eedbdaba5b028593bde1", + "typeString": "literal_string \"error_notPermitted\"" + }, + "value": "error_notPermitted" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_81fcea6533090d67b5d2d1910c87832a3a952f4bfc10eedbdaba5b028593bde1", + "typeString": "literal_string \"error_notPermitted\"" + } + ], + "id": 1771, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "7046:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1785, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7046:104:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1786, + "nodeType": "ExpressionStatement", + "src": "7046:104:4" + }, + { + "assignments": [ + 1788 + ], + "declarations": [ + { + "constant": false, + "id": 1788, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1835, + "src": "7160:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 1787, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "7160:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1792, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1789, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "7186:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 1791, + "indexExpression": { + "argumentTypes": null, + "id": 1790, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1768, + "src": "7197:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7186:18:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "7160:44:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1798, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1794, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1788, + "src": "7222:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1795, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "7222:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1796, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "7237:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1797, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7237:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "7222:34:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6e6f744163746976654d656d626572", + "id": 1799, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7258:23:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_bc4828de8fccb67618bdc2462d405754421b1e879aff6628f11ddb63528355b9", + "typeString": "literal_string \"error_notActiveMember\"" + }, + "value": "error_notActiveMember" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_bc4828de8fccb67618bdc2462d405754421b1e879aff6628f11ddb63528355b9", + "typeString": "literal_string \"error_notActiveMember\"" + } + ], + "id": 1793, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "7214:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1800, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7214:68:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1801, + "nodeType": "ExpressionStatement", + "src": "7214:68:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1808, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1802, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1788, + "src": "7292:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1804, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "earningsBeforeLastJoin", + "nodeType": "MemberAccess", + "referencedDeclaration": 1240, + "src": "7292:27:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1806, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1768, + "src": "7334:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1805, + "name": "getEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1451, + "src": "7322:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 1807, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7322:19:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7292:49:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1809, + "nodeType": "ExpressionStatement", + "src": "7292:49:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1815, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1810, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1788, + "src": "7351:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1812, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "7351:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1813, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "7365:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1814, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Inactive", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7365:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "7351:35:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "id": 1816, + "nodeType": "ExpressionStatement", + "src": "7351:35:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1822, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1817, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "7396:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 1820, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7438:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 1818, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "7416:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1819, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "7416:21:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1821, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7416:24:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7396:44:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1823, + "nodeType": "ExpressionStatement", + "src": "7396:44:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1829, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1824, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "7450:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 1827, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7496:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 1825, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "7472:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1826, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "7472:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1828, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7472:26:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7450:48:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1830, + "nodeType": "ExpressionStatement", + "src": "7450:48:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1832, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1768, + "src": "7526:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1831, + "name": "MemberParted", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1188, + "src": "7513:12:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 1833, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7513:20:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1834, + "nodeType": "EmitStatement", + "src": "7508:25:4" + } + ] + }, + "documentation": null, + "functionSelector": "4e40ea64", + "id": 1836, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "partMember", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1769, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1768, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1836, + "src": "7013:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1767, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "7013:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "7012:16:4" + }, + "returnParameters": { + "id": 1770, + "nodeType": "ParameterList", + "parameters": [], + "src": "7036:0:4" + }, + "scope": 2432, + "src": "6993:547:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1863, + "nodeType": "Block", + "src": "7625:107:4", + "statements": [ + { + "body": { + "id": 1861, + "nodeType": "Block", + "src": "7680:46:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1856, + "name": "members", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1839, + "src": "7704:7:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_payable_$dyn_memory_ptr", + "typeString": "address payable[] memory" + } + }, + "id": 1858, + "indexExpression": { + "argumentTypes": null, + "id": 1857, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1845, + "src": "7712:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7704:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "id": 1855, + "name": "addMember", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1766, + "src": "7694:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_payable_$returns$__$", + "typeString": "function (address payable)" + } + }, + "id": 1859, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7694:21:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1860, + "nodeType": "ExpressionStatement", + "src": "7694:21:4" + } + ] + }, + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1851, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1848, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1845, + "src": "7655:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "<", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1849, + "name": "members", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1839, + "src": "7659:7:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_payable_$dyn_memory_ptr", + "typeString": "address payable[] memory" + } + }, + "id": 1850, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "length", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7659:14:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7655:18:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 1862, + "initializationExpression": { + "assignments": [ + 1845 + ], + "declarations": [ + { + "constant": false, + "id": 1845, + "mutability": "mutable", + "name": "i", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1862, + "src": "7640:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1844, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "7640:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1847, + "initialValue": { + "argumentTypes": null, + "hexValue": "30", + "id": 1846, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7652:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "nodeType": "VariableDeclarationStatement", + "src": "7640:13:4" + }, + "loopExpression": { + "expression": { + "argumentTypes": null, + "id": 1853, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "++", + "prefix": false, + "src": "7675:3:4", + "subExpression": { + "argumentTypes": null, + "id": 1852, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1845, + "src": "7675:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1854, + "nodeType": "ExpressionStatement", + "src": "7675:3:4" + }, + "nodeType": "ForStatement", + "src": "7635:91:4" + } + ] + }, + "documentation": null, + "functionSelector": "6f4d469b", + "id": 1864, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 1842, + "modifierName": { + "argumentTypes": null, + "id": 1841, + "name": "onlyJoinPartAgent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1288, + "src": "7607:17:4", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "7607:17:4" + } + ], + "name": "addMembers", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1840, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1839, + "mutability": "mutable", + "name": "members", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1864, + "src": "7566:32:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_payable_$dyn_memory_ptr", + "typeString": "address payable[]" + }, + "typeName": { + "baseType": { + "id": 1837, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "7566:15:4", + "stateMutability": "payable", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 1838, + "length": null, + "nodeType": "ArrayTypeName", + "src": "7566:17:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_payable_$dyn_storage_ptr", + "typeString": "address payable[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "7565:34:4" + }, + "returnParameters": { + "id": 1843, + "nodeType": "ParameterList", + "parameters": [], + "src": "7625:0:4" + }, + "scope": 2432, + "src": "7546:186:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1889, + "nodeType": "Block", + "src": "7827:108:4", + "statements": [ + { + "body": { + "id": 1887, + "nodeType": "Block", + "src": "7882:47:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1882, + "name": "members", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1867, + "src": "7907:7:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + "id": 1884, + "indexExpression": { + "argumentTypes": null, + "id": 1883, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1871, + "src": "7915:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7907:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1881, + "name": "partMember", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1836, + "src": "7896:10:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 1885, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7896:22:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1886, + "nodeType": "ExpressionStatement", + "src": "7896:22:4" + } + ] + }, + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1877, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1874, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1871, + "src": "7857:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "<", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1875, + "name": "members", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1867, + "src": "7861:7:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + "id": 1876, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "length", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7861:14:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7857:18:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 1888, + "initializationExpression": { + "assignments": [ + 1871 + ], + "declarations": [ + { + "constant": false, + "id": 1871, + "mutability": "mutable", + "name": "i", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1888, + "src": "7842:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1870, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "7842:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1873, + "initialValue": { + "argumentTypes": null, + "hexValue": "30", + "id": 1872, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7854:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "nodeType": "VariableDeclarationStatement", + "src": "7842:13:4" + }, + "loopExpression": { + "expression": { + "argumentTypes": null, + "id": 1879, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "++", + "prefix": false, + "src": "7877:3:4", + "subExpression": { + "argumentTypes": null, + "id": 1878, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1871, + "src": "7877:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1880, + "nodeType": "ExpressionStatement", + "src": "7877:3:4" + }, + "nodeType": "ForStatement", + "src": "7837:92:4" + } + ] + }, + "documentation": null, + "functionSelector": "7b30ed43", + "id": 1890, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "partMembers", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1868, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1867, + "mutability": "mutable", + "name": "members", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1890, + "src": "7794:24:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 1865, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "7794:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1866, + "length": null, + "nodeType": "ArrayTypeName", + "src": "7794:9:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "7793:26:4" + }, + "returnParameters": { + "id": 1869, + "nodeType": "ParameterList", + "parameters": [], + "src": "7827:0:4" + }, + "scope": 2432, + "src": "7773:162:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1961, + "nodeType": "Block", + "src": "8119:455:4", + "statements": [ + { + "assignments": [ + 1899 + ], + "declarations": [ + { + "constant": false, + "id": 1899, + "mutability": "mutable", + "name": "bal_before", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1961, + "src": "8129:15:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1898, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "8129:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1907, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1904, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "8171:4:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + ], + "id": 1903, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "8163:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1902, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "8163:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1905, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8163:13:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "expression": { + "argumentTypes": null, + "id": 1900, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "8147:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 1901, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balanceOf", + "nodeType": "MemberAccess", + "referencedDeclaration": 4221, + "src": "8147:15:4", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view external returns (uint256)" + } + }, + "id": 1906, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8147:30:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "8129:48:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1911, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "8214:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1912, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "8214:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1915, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "8234:4:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + ], + "id": 1914, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "8226:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1913, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "8226:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1916, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8226:13:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 1917, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1895, + "src": "8241:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1909, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "8195:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 1910, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "transferFrom", + "nodeType": "MemberAccess", + "referencedDeclaration": 4263, + "src": "8195:18:4", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$_t_bool_$", + "typeString": "function (address,address,uint256) external returns (bool)" + } + }, + "id": 1918, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8195:53:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f7472616e73666572", + "id": 1919, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "8250:16:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + }, + "value": "error_transfer" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + } + ], + "id": 1908, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "8187:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1920, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8187:80:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1921, + "nodeType": "ExpressionStatement", + "src": "8187:80:4" + }, + { + "assignments": [ + 1923 + ], + "declarations": [ + { + "constant": false, + "id": 1923, + "mutability": "mutable", + "name": "bal_after", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1961, + "src": "8277:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1922, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "8277:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1931, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1928, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "8318:4:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + ], + "id": 1927, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "8310:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1926, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "8310:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1929, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8310:13:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "expression": { + "argumentTypes": null, + "id": 1924, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "8294:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 1925, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balanceOf", + "nodeType": "MemberAccess", + "referencedDeclaration": 4221, + "src": "8294:15:4", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view external returns (uint256)" + } + }, + "id": 1930, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8294:30:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "8277:47:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1938, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1935, + "name": "bal_before", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1899, + "src": "8356:10:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1933, + "name": "bal_after", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1923, + "src": "8342:9:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1934, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "8342:13:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1936, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8342:25:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": ">=", + "rightExpression": { + "argumentTypes": null, + "id": 1937, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1895, + "src": "8371:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "8342:35:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f7472616e73666572", + "id": 1939, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "8379:16:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + }, + "value": "error_transfer" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + } + ], + "id": 1932, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "8334:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1940, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8334:62:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1941, + "nodeType": "ExpressionStatement", + "src": "8334:62:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1943, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1893, + "src": "8424:9:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1944, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1895, + "src": "8435:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1942, + "name": "_increaseBalance", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2056, + "src": "8407:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256)" + } + }, + "id": 1945, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8407:35:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1946, + "nodeType": "ExpressionStatement", + "src": "8407:35:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1952, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1947, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1253, + "src": "8452:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1950, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1895, + "src": "8486:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1948, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1253, + "src": "8468:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1949, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "8468:17:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1951, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8468:25:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "8452:41:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1953, + "nodeType": "ExpressionStatement", + "src": "8452:41:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1955, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "8536:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1956, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "8536:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 1957, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1893, + "src": "8548:9:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1958, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1895, + "src": "8560:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1954, + "name": "TransferToAddressInContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1228, + "src": "8508:27:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,address,uint256)" + } + }, + "id": 1959, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8508:59:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1960, + "nodeType": "EmitStatement", + "src": "8503:64:4" + } + ] + }, + "documentation": { + "id": 1891, + "nodeType": "StructuredDocumentation", + "src": "7941:98:4", + "text": "Transfer tokens from outside contract, add to a recipient's in-contract balance" + }, + "functionSelector": "b274bcc7", + "id": 1962, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "transferToMemberInContract", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1896, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1893, + "mutability": "mutable", + "name": "recipient", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1962, + "src": "8080:17:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1892, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "8080:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1895, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1962, + "src": "8099:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1894, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "8099:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "8079:32:4" + }, + "returnParameters": { + "id": 1897, + "nodeType": "ParameterList", + "parameters": [], + "src": "8119:0:4" + }, + "scope": 2432, + "src": "8044:530:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2009, + "nodeType": "Block", + "src": "9083:399:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1976, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1972, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "9125:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1973, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "9125:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "id": 1971, + "name": "getWithdrawableEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1494, + "src": "9101:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 1974, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9101:35:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": ">=", + "rightExpression": { + "argumentTypes": null, + "id": 1975, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1967, + "src": "9140:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "9101:45:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f696e73756666696369656e7442616c616e6365", + "id": 1977, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "9148:27:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_74799d65376d943bac023262731d6421d2e6b6332748a55385eb85a0683327fc", + "typeString": "literal_string \"error_insufficientBalance\"" + }, + "value": "error_insufficientBalance" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_74799d65376d943bac023262731d6421d2e6b6332748a55385eb85a0683327fc", + "typeString": "literal_string \"error_insufficientBalance\"" + } + ], + "id": 1970, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "9093:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1978, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9093:83:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1979, + "nodeType": "ExpressionStatement", + "src": "9093:83:4" + }, + { + "assignments": [ + 1981 + ], + "declarations": [ + { + "constant": false, + "id": 1981, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2009, + "src": "9245:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 1980, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "9245:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1986, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1982, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "9271:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 1985, + "indexExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1983, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "9282:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1984, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "9282:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "9271:22:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "9245:48:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1995, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1987, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1981, + "src": "9303:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1989, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "withdrawnEarnings", + "nodeType": "MemberAccess", + "referencedDeclaration": 1244, + "src": "9303:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1993, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1967, + "src": "9355:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1990, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1981, + "src": "9328:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1991, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "withdrawnEarnings", + "nodeType": "MemberAccess", + "referencedDeclaration": 1244, + "src": "9328:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1992, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "9328:26:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1994, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9328:34:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "9303:59:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1996, + "nodeType": "ExpressionStatement", + "src": "9303:59:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1998, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1965, + "src": "9389:9:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1999, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1967, + "src": "9400:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1997, + "name": "_increaseBalance", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2056, + "src": "9372:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256)" + } + }, + "id": 2000, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9372:35:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2001, + "nodeType": "ExpressionStatement", + "src": "9372:35:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2003, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "9445:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 2004, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "9445:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 2005, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1965, + "src": "9457:9:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2006, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1967, + "src": "9468:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 2002, + "name": "TransferWithinContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1220, + "src": "9422:22:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,address,uint256)" + } + }, + "id": 2007, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9422:53:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2008, + "nodeType": "EmitStatement", + "src": "9417:58:4" + } + ] + }, + "documentation": { + "id": 1963, + "nodeType": "StructuredDocumentation", + "src": "8580:427:4", + "text": "Transfer tokens from sender's in-contract balance to recipient's in-contract balance\nThis is done by \"withdrawing\" sender's earnings and crediting them to recipient's unwithdrawn earnings,\n so withdrawnEarnings never decreases for anyone (within this function)\n@param recipient whose withdrawable earnings will increase\n@param amount how much withdrawable earnings is transferred" + }, + "functionSelector": "71cdfd68", + "id": 2010, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "transferWithinContract", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1968, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1965, + "mutability": "mutable", + "name": "recipient", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2010, + "src": "9044:17:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1964, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "9044:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1967, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2010, + "src": "9063:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1966, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "9063:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "9043:32:4" + }, + "returnParameters": { + "id": 1969, + "nodeType": "ParameterList", + "parameters": [], + "src": "9083:0:4" + }, + "scope": 2432, + "src": "9012:470:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2055, + "nodeType": "Block", + "src": "9642:359:4", + "statements": [ + { + "assignments": [ + 2019 + ], + "declarations": [ + { + "constant": false, + "id": 2019, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2055, + "src": "9652:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 2018, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "9652:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2023, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 2020, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "9678:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 2022, + "indexExpression": { + "argumentTypes": null, + "id": 2021, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2013, + "src": "9689:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "9678:18:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "9652:44:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 2032, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2024, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2019, + "src": "9706:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 2026, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "earningsBeforeLastJoin", + "nodeType": "MemberAccess", + "referencedDeclaration": 1240, + "src": "9706:27:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2030, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2015, + "src": "9768:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2027, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2019, + "src": "9736:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 2028, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "earningsBeforeLastJoin", + "nodeType": "MemberAccess", + "referencedDeclaration": 1240, + "src": "9736:27:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2029, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "9736:31:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 2031, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9736:39:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "9706:69:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2033, + "nodeType": "ExpressionStatement", + "src": "9706:69:4" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 2038, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2034, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2019, + "src": "9839:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 2035, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "9839:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2036, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "9854:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 2037, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "None", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "9854:17:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "9839:32:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 2054, + "nodeType": "IfStatement", + "src": "9835:160:4", + "trueBody": { + "id": 2053, + "nodeType": "Block", + "src": "9873:122:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 2044, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2039, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2019, + "src": "9887:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 2041, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "9887:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2042, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "9901:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 2043, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Inactive", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "9901:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "9887:35:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "id": 2045, + "nodeType": "ExpressionStatement", + "src": "9887:35:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 2051, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 2046, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "9936:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 2049, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "9982:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 2047, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "9958:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2048, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "9958:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 2050, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9958:26:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "9936:48:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2052, + "nodeType": "ExpressionStatement", + "src": "9936:48:4" + } + ] + } + } + ] + }, + "documentation": { + "id": 2011, + "nodeType": "StructuredDocumentation", + "src": "9488:85:4", + "text": "Hack to add to single member's balance without affecting lmeAtJoin" + }, + "id": 2056, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "_increaseBalance", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2016, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2013, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2056, + "src": "9604:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2012, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "9604:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2015, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2056, + "src": "9620:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2014, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "9620:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "9603:29:4" + }, + "returnParameters": { + "id": 2017, + "nodeType": "ParameterList", + "parameters": [], + "src": "9642:0:4" + }, + "scope": 2432, + "src": "9578:423:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "internal" + }, + { + "body": { + "id": 2097, + "nodeType": "Block", + "src": "10123:208:4", + "statements": [ + { + "assignments": [ + 2067 + ], + "declarations": [ + { + "constant": false, + "id": 2067, + "mutability": "mutable", + "name": "withdrawn", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2097, + "src": "10133:17:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2066, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "10133:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2069, + "initialValue": { + "argumentTypes": null, + "hexValue": "30", + "id": 2068, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "10153:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "nodeType": "VariableDeclarationStatement", + "src": "10133:21:4" + }, + { + "body": { + "id": 2093, + "nodeType": "Block", + "src": "10209:90:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 2091, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 2081, + "name": "withdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2067, + "src": "10223:9:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 2085, + "name": "members", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2059, + "src": "10261:7:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + "id": 2087, + "indexExpression": { + "argumentTypes": null, + "id": 2086, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2071, + "src": "10269:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "10261:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2088, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2061, + "src": "10273:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2084, + "name": "withdrawAll", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2116, + "src": "10249:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,bool) returns (uint256)" + } + }, + "id": 2089, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10249:38:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 2082, + "name": "withdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2067, + "src": "10235:9:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2083, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "10235:13:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 2090, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10235:53:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "10223:65:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2092, + "nodeType": "ExpressionStatement", + "src": "10223:65:4" + } + ] + }, + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 2077, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2074, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2071, + "src": "10184:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "<", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2075, + "name": "members", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2059, + "src": "10188:7:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + "id": 2076, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "length", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "10188:14:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "10184:18:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 2094, + "initializationExpression": { + "assignments": [ + 2071 + ], + "declarations": [ + { + "constant": false, + "id": 2071, + "mutability": "mutable", + "name": "i", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2094, + "src": "10169:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2070, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "10169:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2073, + "initialValue": { + "argumentTypes": null, + "hexValue": "30", + "id": 2072, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "10181:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "nodeType": "VariableDeclarationStatement", + "src": "10169:13:4" + }, + "loopExpression": { + "expression": { + "argumentTypes": null, + "id": 2079, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "++", + "prefix": false, + "src": "10204:3:4", + "subExpression": { + "argumentTypes": null, + "id": 2078, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2071, + "src": "10204:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2080, + "nodeType": "ExpressionStatement", + "src": "10204:3:4" + }, + "nodeType": "ForStatement", + "src": "10164:135:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 2095, + "name": "withdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2067, + "src": "10315:9:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2065, + "id": 2096, + "nodeType": "Return", + "src": "10308:16:4" + } + ] + }, + "documentation": null, + "functionSelector": "a4d6ddc0", + "id": 2098, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawMembers", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2062, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2059, + "mutability": "mutable", + "name": "members", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2098, + "src": "10032:24:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 2057, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "10032:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 2058, + "length": null, + "nodeType": "ArrayTypeName", + "src": "10032:9:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2061, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2098, + "src": "10058:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2060, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "10058:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10031:46:4" + }, + "returnParameters": { + "id": 2065, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2064, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2098, + "src": "10110:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2063, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "10110:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10109:9:4" + }, + "scope": 2432, + "src": "10007:324:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2115, + "nodeType": "Block", + "src": "10439:88:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2108, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2100, + "src": "10465:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2110, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2100, + "src": "10497:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 2109, + "name": "getWithdrawableEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1494, + "src": "10473:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 2111, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10473:31:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2112, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2102, + "src": "10506:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2107, + "name": "withdraw", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2148, + "src": "10456:8:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_uint256_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,uint256,bool) returns (uint256)" + } + }, + "id": 2113, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10456:64:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2106, + "id": 2114, + "nodeType": "Return", + "src": "10449:71:4" + } + ] + }, + "documentation": null, + "functionSelector": "4bee9137", + "id": 2116, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawAll", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2103, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2100, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2116, + "src": "10358:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2099, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "10358:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2102, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2116, + "src": "10374:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2101, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "10374:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10357:36:4" + }, + "returnParameters": { + "id": 2106, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2105, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2116, + "src": "10426:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2104, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "10426:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10425:9:4" + }, + "scope": 2432, + "src": "10337:190:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2147, + "nodeType": "Block", + "src": "10645:156:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 2136, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 2131, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2128, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "10663:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 2129, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "10663:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 2130, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2118, + "src": "10677:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "10663:20:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "||", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 2135, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2132, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "10687:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 2133, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "10687:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 2134, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "10701:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "10687:19:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "10663:43:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6e6f745065726d6974746564", + "id": 2137, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "10708:20:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_81fcea6533090d67b5d2d1910c87832a3a952f4bfc10eedbdaba5b028593bde1", + "typeString": "literal_string \"error_notPermitted\"" + }, + "value": "error_notPermitted" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_81fcea6533090d67b5d2d1910c87832a3a952f4bfc10eedbdaba5b028593bde1", + "typeString": "literal_string \"error_notPermitted\"" + } + ], + "id": 2127, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "10655:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2138, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10655:74:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2139, + "nodeType": "ExpressionStatement", + "src": "10655:74:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2141, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2118, + "src": "10756:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2142, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2118, + "src": "10764:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2143, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2120, + "src": "10772:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2144, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2122, + "src": "10780:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2140, + "name": "_withdraw", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2431, + "src": "10746:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_address_$_t_uint256_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,address,uint256,bool) returns (uint256)" + } + }, + "id": 2145, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10746:48:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2126, + "id": 2146, + "nodeType": "Return", + "src": "10739:55:4" + } + ] + }, + "documentation": null, + "functionSelector": "ead5d359", + "id": 2148, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdraw", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2123, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2118, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2148, + "src": "10551:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2117, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "10551:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2120, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2148, + "src": "10567:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2119, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "10567:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2122, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2148, + "src": "10580:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2121, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "10580:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10550:49:4" + }, + "returnParameters": { + "id": 2126, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2125, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2148, + "src": "10632:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2124, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "10632:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10631:9:4" + }, + "scope": 2432, + "src": "10533:268:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2166, + "nodeType": "Block", + "src": "10907:90:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2158, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2150, + "src": "10935:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2160, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "10963:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 2161, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "10963:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "id": 2159, + "name": "getWithdrawableEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1494, + "src": "10939:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 2162, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10939:35:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2163, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2152, + "src": "10976:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2157, + "name": "withdrawTo", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2187, + "src": "10924:10:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_uint256_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,uint256,bool) returns (uint256)" + } + }, + "id": 2164, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10924:66:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2156, + "id": 2165, + "nodeType": "Return", + "src": "10917:73:4" + } + ] + }, + "documentation": null, + "functionSelector": "2b94411f", + "id": 2167, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawAllTo", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2153, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2150, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2167, + "src": "10830:10:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2149, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "10830:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2152, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2167, + "src": "10842:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2151, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "10842:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10829:32:4" + }, + "returnParameters": { + "id": 2156, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2155, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2167, + "src": "10894:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2154, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "10894:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10893:9:4" + }, + "scope": 2432, + "src": "10807:190:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2186, + "nodeType": "Block", + "src": "11113:72:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2179, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "11140:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 2180, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "11140:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 2181, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2169, + "src": "11152:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2182, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2171, + "src": "11156:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2183, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2173, + "src": "11164:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2178, + "name": "_withdraw", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2431, + "src": "11130:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_address_$_t_uint256_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,address,uint256,bool) returns (uint256)" + } + }, + "id": 2184, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "11130:48:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2177, + "id": 2185, + "nodeType": "Return", + "src": "11123:55:4" + } + ] + }, + "documentation": null, + "functionSelector": "73e2290c", + "id": 2187, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawTo", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2174, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2169, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2187, + "src": "11023:10:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2168, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "11023:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2171, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2187, + "src": "11035:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2170, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "11035:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2173, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2187, + "src": "11048:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2172, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "11048:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "11022:45:4" + }, + "returnParameters": { + "id": 2177, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2176, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2187, + "src": "11100:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2175, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "11100:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "11099:9:4" + }, + "scope": 2432, + "src": "11003:182:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2270, + "nodeType": "Block", + "src": "12594:831:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 2205, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2202, + "name": "signature", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2196, + "src": "12612:9:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + "id": 2203, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "length", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "12612:16:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "3635", + "id": 2204, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "12632:2:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_65_by_1", + "typeString": "int_const 65" + }, + "value": "65" + }, + "src": "12612:22:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6261645369676e61747572654c656e677468", + "id": 2206, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "12636:26:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_4077da77d01843e066cb3ce202dcb5c333f11623972b2a584316e75b72c622e0", + "typeString": "literal_string \"error_badSignatureLength\"" + }, + "value": "error_badSignatureLength" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_4077da77d01843e066cb3ce202dcb5c333f11623972b2a584316e75b72c622e0", + "typeString": "literal_string \"error_badSignatureLength\"" + } + ], + "id": 2201, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "12604:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2207, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "12604:59:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2208, + "nodeType": "ExpressionStatement", + "src": "12604:59:4" + }, + { + "assignments": [ + 2210 + ], + "declarations": [ + { + "constant": false, + "id": 2210, + "mutability": "mutable", + "name": "r", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2270, + "src": "12674:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 2209, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "12674:7:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2211, + "initialValue": null, + "nodeType": "VariableDeclarationStatement", + "src": "12674:9:4" + }, + { + "assignments": [ + 2213 + ], + "declarations": [ + { + "constant": false, + "id": 2213, + "mutability": "mutable", + "name": "s", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2270, + "src": "12685:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 2212, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "12685:7:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2214, + "initialValue": null, + "nodeType": "VariableDeclarationStatement", + "src": "12685:9:4" + }, + { + "assignments": [ + 2216 + ], + "declarations": [ + { + "constant": false, + "id": 2216, + "mutability": "mutable", + "name": "v", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2270, + "src": "12696:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "typeName": { + "id": 2215, + "name": "uint8", + "nodeType": "ElementaryTypeName", + "src": "12696:5:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2217, + "initialValue": null, + "nodeType": "VariableDeclarationStatement", + "src": "12696:7:4" + }, + { + "AST": { + "nodeType": "YulBlock", + "src": "12722:205:4", + "statements": [ + { + "nodeType": "YulAssignment", + "src": "12792:30:4", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "signature", + "nodeType": "YulIdentifier", + "src": "12807:9:4" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "12818:2:4", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "12803:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "12803:18:4" + } + ], + "functionName": { + "name": "mload", + "nodeType": "YulIdentifier", + "src": "12797:5:4" + }, + "nodeType": "YulFunctionCall", + "src": "12797:25:4" + }, + "variableNames": [ + { + "name": "r", + "nodeType": "YulIdentifier", + "src": "12792:1:4" + } + ] + }, + { + "nodeType": "YulAssignment", + "src": "12835:30:4", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "signature", + "nodeType": "YulIdentifier", + "src": "12850:9:4" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "12861:2:4", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "12846:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "12846:18:4" + } + ], + "functionName": { + "name": "mload", + "nodeType": "YulIdentifier", + "src": "12840:5:4" + }, + "nodeType": "YulFunctionCall", + "src": "12840:25:4" + }, + "variableNames": [ + { + "name": "s", + "nodeType": "YulIdentifier", + "src": "12835:1:4" + } + ] + }, + { + "nodeType": "YulAssignment", + "src": "12878:39:4", + "value": { + "arguments": [ + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "12888:1:4", + "type": "", + "value": "0" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "signature", + "nodeType": "YulIdentifier", + "src": "12901:9:4" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "12912:2:4", + "type": "", + "value": "96" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "12897:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "12897:18:4" + } + ], + "functionName": { + "name": "mload", + "nodeType": "YulIdentifier", + "src": "12891:5:4" + }, + "nodeType": "YulFunctionCall", + "src": "12891:25:4" + } + ], + "functionName": { + "name": "byte", + "nodeType": "YulIdentifier", + "src": "12883:4:4" + }, + "nodeType": "YulFunctionCall", + "src": "12883:34:4" + }, + "variableNames": [ + { + "name": "v", + "nodeType": "YulIdentifier", + "src": "12878:1:4" + } + ] + } + ] + }, + "evmVersion": "istanbul", + "externalReferences": [ + { + "declaration": 2210, + "isOffset": false, + "isSlot": false, + "src": "12792:1:4", + "valueSize": 1 + }, + { + "declaration": 2213, + "isOffset": false, + "isSlot": false, + "src": "12835:1:4", + "valueSize": 1 + }, + { + "declaration": 2196, + "isOffset": false, + "isSlot": false, + "src": "12807:9:4", + "valueSize": 1 + }, + { + "declaration": 2196, + "isOffset": false, + "isSlot": false, + "src": "12850:9:4", + "valueSize": 1 + }, + { + "declaration": 2196, + "isOffset": false, + "isSlot": false, + "src": "12901:9:4", + "valueSize": 1 + }, + { + "declaration": 2216, + "isOffset": false, + "isSlot": false, + "src": "12878:1:4", + "valueSize": 1 + } + ], + "id": 2218, + "nodeType": "InlineAssembly", + "src": "12713:214:4" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "id": 2221, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2219, + "name": "v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2216, + "src": "12940:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "nodeType": "BinaryOperation", + "operator": "<", + "rightExpression": { + "argumentTypes": null, + "hexValue": "3237", + "id": 2220, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "12944:2:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_27_by_1", + "typeString": "int_const 27" + }, + "value": "27" + }, + "src": "12940:6:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 2227, + "nodeType": "IfStatement", + "src": "12936:44:4", + "trueBody": { + "id": 2226, + "nodeType": "Block", + "src": "12948:32:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 2224, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 2222, + "name": "v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2216, + "src": "12962:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "nodeType": "Assignment", + "operator": "+=", + "rightHandSide": { + "argumentTypes": null, + "hexValue": "3237", + "id": 2223, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "12967:2:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_27_by_1", + "typeString": "int_const 27" + }, + "value": "27" + }, + "src": "12962:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "id": 2225, + "nodeType": "ExpressionStatement", + "src": "12962:7:4" + } + ] + } + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 2235, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "id": 2231, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2229, + "name": "v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2216, + "src": "12997:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "3237", + "id": 2230, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "13002:2:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_27_by_1", + "typeString": "int_const 27" + }, + "value": "27" + }, + "src": "12997:7:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "||", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "id": 2234, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2232, + "name": "v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2216, + "src": "13008:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "3238", + "id": 2233, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "13013:2:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_28_by_1", + "typeString": "int_const 28" + }, + "value": "28" + }, + "src": "13008:7:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "12997:18:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6261645369676e617475726556657273696f6e", + "id": 2236, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "13017:27:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_8fa0eae5d18986979b1a6399b1aa7a4d8b3c5537b79b5808266bd780a9c464db", + "typeString": "literal_string \"error_badSignatureVersion\"" + }, + "value": "error_badSignatureVersion" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_8fa0eae5d18986979b1a6399b1aa7a4d8b3c5537b79b5808266bd780a9c464db", + "typeString": "literal_string \"error_badSignatureVersion\"" + } + ], + "id": 2228, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "12989:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2237, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "12989:56:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2238, + "nodeType": "ExpressionStatement", + "src": "12989:56:4" + }, + { + "assignments": [ + 2240 + ], + "declarations": [ + { + "constant": false, + "id": 2240, + "mutability": "mutable", + "name": "messageHash", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2270, + "src": "13151:19:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 2239, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "13151:7:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2256, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "19457468657265756d205369676e6564204d6573736167653a0a313034", + "id": 2244, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "13213:35:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_8d960065d1d57999e7234857e6a0652c524bb2aeb2c4d7c6b962ce1fe99d1ca0", + "typeString": "literal_string \"\u0019Ethereum Signed Message:\n104\"" + }, + "value": "\u0019Ethereum Signed Message:\n104" + }, + { + "argumentTypes": null, + "id": 2245, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2192, + "src": "13250:9:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2246, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2194, + "src": "13261:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2249, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "13277:4:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + ], + "id": 2248, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "13269:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 2247, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "13269:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 2250, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "13269:13:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2252, + "name": "signer", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2190, + "src": "13297:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 2251, + "name": "getWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1477, + "src": "13284:12:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 2253, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "13284:20:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_8d960065d1d57999e7234857e6a0652c524bb2aeb2c4d7c6b962ce1fe99d1ca0", + "typeString": "literal_string \"\u0019Ethereum Signed Message:\n104\"" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 2242, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "13183:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 2243, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encodePacked", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "13183:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodepacked_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 2254, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "13183:122:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 2241, + "name": "keccak256", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -8, + "src": "13173:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", + "typeString": "function (bytes memory) pure returns (bytes32)" + } + }, + "id": 2255, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "13173:133:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "13151:155:4" + }, + { + "assignments": [ + 2258 + ], + "declarations": [ + { + "constant": false, + "id": 2258, + "mutability": "mutable", + "name": "calculatedSigner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2270, + "src": "13316:24:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2257, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "13316:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2265, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2260, + "name": "messageHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2240, + "src": "13353:11:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + { + "argumentTypes": null, + "id": 2261, + "name": "v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2216, + "src": "13366:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + { + "argumentTypes": null, + "id": 2262, + "name": "r", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2210, + "src": "13369:1:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + { + "argumentTypes": null, + "id": 2263, + "name": "s", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2213, + "src": "13372:1:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "id": 2259, + "name": "ecrecover", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -6, + "src": "13343:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_ecrecover_pure$_t_bytes32_$_t_uint8_$_t_bytes32_$_t_bytes32_$returns$_t_address_$", + "typeString": "function (bytes32,uint8,bytes32,bytes32) pure returns (address)" + } + }, + "id": 2264, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "13343:31:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "13316:58:4" + }, + { + "expression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 2268, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2266, + "name": "calculatedSigner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2258, + "src": "13392:16:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 2267, + "name": "signer", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2190, + "src": "13412:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "13392:26:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "functionReturnParameters": 2200, + "id": 2269, + "nodeType": "Return", + "src": "13385:33:4" + } + ] + }, + "documentation": { + "id": 2188, + "nodeType": "StructuredDocumentation", + "src": "11191:1207:4", + "text": "Check signature from a member authorizing withdrawing its earnings to another account.\nThrows if the signature is badly formatted or doesn't match the given signer and amount.\nSignature has parts the act as replay protection:\n1) `address(this)`: signature can't be used for other contracts;\n2) `withdrawn[signer]`: signature only works once (for unspecified amount), and can be \"cancelled\" by sending a withdraw tx.\nGenerated in Javascript with: `web3.eth.accounts.sign(recipientAddress + amount.toString(16, 64) + contractAddress.slice(2) + withdrawnTokens.toString(16, 64), signerPrivateKey)`,\nor for unlimited amount: `web3.eth.accounts.sign(recipientAddress + \"0\".repeat(64) + contractAddress.slice(2) + withdrawnTokens.toString(16, 64), signerPrivateKey)`.\n@param signer whose earnings are being withdrawn\n@param recipient of the tokens\n@param amount how much is authorized for withdraw, or zero for unlimited (withdrawAll)\n@param signature byte array from `web3.eth.accounts.sign`\n@return isValid true iff signer of the authorization (member whose earnings are going to be withdrawn) matches the signature" + }, + "functionSelector": "a2d3cf4b", + "id": 2271, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "signatureIsValid", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2197, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2190, + "mutability": "mutable", + "name": "signer", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2271, + "src": "12438:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2189, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "12438:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2192, + "mutability": "mutable", + "name": "recipient", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2271, + "src": "12462:17:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2191, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "12462:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2194, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2271, + "src": "12489:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2193, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "12489:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2196, + "mutability": "mutable", + "name": "signature", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2271, + "src": "12510:22:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 2195, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "12510:5:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "12428:110:4" + }, + "returnParameters": { + "id": 2200, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2199, + "mutability": "mutable", + "name": "isValid", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2271, + "src": "12576:12:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2198, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "12576:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "12575:14:4" + }, + "scope": 2432, + "src": "12403:1022:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2304, + "nodeType": "Block", + "src": "14491:188:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2287, + "name": "fromSigner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2274, + "src": "14526:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2288, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2276, + "src": "14538:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "hexValue": "30", + "id": 2289, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "14542:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + { + "argumentTypes": null, + "id": 2290, + "name": "signature", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2280, + "src": "14545:9:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 2286, + "name": "signatureIsValid", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2271, + "src": "14509:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$_t_address_$_t_uint256_$_t_bytes_memory_ptr_$returns$_t_bool_$", + "typeString": "function (address,address,uint256,bytes memory) view returns (bool)" + } + }, + "id": 2291, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "14509:46:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6261645369676e6174757265", + "id": 2292, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "14557:20:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_2ec4ea0e2156213061c2a099c127d1a6548cdd3e5b4bf1f695ceebe1aeb9d2b2", + "typeString": "literal_string \"error_badSignature\"" + }, + "value": "error_badSignature" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_2ec4ea0e2156213061c2a099c127d1a6548cdd3e5b4bf1f695ceebe1aeb9d2b2", + "typeString": "literal_string \"error_badSignature\"" + } + ], + "id": 2285, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "14501:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2293, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "14501:77:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2294, + "nodeType": "ExpressionStatement", + "src": "14501:77:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2296, + "name": "fromSigner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2274, + "src": "14605:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2297, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2276, + "src": "14617:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2299, + "name": "fromSigner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2274, + "src": "14645:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 2298, + "name": "getWithdrawableEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1494, + "src": "14621:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 2300, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "14621:35:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2301, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2278, + "src": "14658:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2295, + "name": "_withdraw", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2431, + "src": "14595:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_address_$_t_uint256_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,address,uint256,bool) returns (uint256)" + } + }, + "id": 2302, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "14595:77:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2284, + "id": 2303, + "nodeType": "Return", + "src": "14588:84:4" + } + ] + }, + "documentation": { + "id": 2272, + "nodeType": "StructuredDocumentation", + "src": "13431:860:4", + "text": "Do an \"unlimited donate withdraw\" on behalf of someone else, to an address they've specified.\nSponsored withdraw is paid by admin, but target account could be whatever the member specifies.\nThe signature gives a \"blank cheque\" for admin to withdraw all tokens to `recipient` in the future,\n and it's valid until next withdraw (and so can be nullified by withdrawing any amount).\nA new signature needs to be obtained for each subsequent future withdraw.\n@param fromSigner whose earnings are being withdrawn\n@param to the address the tokens will be sent to (instead of `msg.sender`)\n@param sendToMainnet if the tokens should be sent to mainnet or only withdrawn into sidechain address\n@param signature from the member, see `signatureIsValid` how signature generated for unlimited amount" + }, + "functionSelector": "ce7b7864", + "id": 2305, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawAllToSigned", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2281, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2274, + "mutability": "mutable", + "name": "fromSigner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2305, + "src": "14334:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2273, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "14334:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2276, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2305, + "src": "14362:10:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2275, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "14362:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2278, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2305, + "src": "14382:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2277, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "14382:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2280, + "mutability": "mutable", + "name": "signature", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2305, + "src": "14410:22:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 2279, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "14410:5:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "14324:114:4" + }, + "returnParameters": { + "id": 2284, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2283, + "mutability": "mutable", + "name": "withdrawn", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2305, + "src": "14471:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2282, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "14471:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "14470:16:4" + }, + "scope": 2432, + "src": "14296:383:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2338, + "nodeType": "Block", + "src": "15628:164:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2323, + "name": "fromSigner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2308, + "src": "15663:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2324, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2310, + "src": "15675:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2325, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2312, + "src": "15679:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2326, + "name": "signature", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2316, + "src": "15687:9:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 2322, + "name": "signatureIsValid", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2271, + "src": "15646:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$_t_address_$_t_uint256_$_t_bytes_memory_ptr_$returns$_t_bool_$", + "typeString": "function (address,address,uint256,bytes memory) view returns (bool)" + } + }, + "id": 2327, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "15646:51:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6261645369676e6174757265", + "id": 2328, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "15699:20:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_2ec4ea0e2156213061c2a099c127d1a6548cdd3e5b4bf1f695ceebe1aeb9d2b2", + "typeString": "literal_string \"error_badSignature\"" + }, + "value": "error_badSignature" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_2ec4ea0e2156213061c2a099c127d1a6548cdd3e5b4bf1f695ceebe1aeb9d2b2", + "typeString": "literal_string \"error_badSignature\"" + } + ], + "id": 2321, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "15638:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2329, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "15638:82:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2330, + "nodeType": "ExpressionStatement", + "src": "15638:82:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2332, + "name": "fromSigner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2308, + "src": "15747:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2333, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2310, + "src": "15759:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2334, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2312, + "src": "15763:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2335, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2314, + "src": "15771:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2331, + "name": "_withdraw", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2431, + "src": "15737:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_address_$_t_uint256_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,address,uint256,bool) returns (uint256)" + } + }, + "id": 2336, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "15737:48:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2320, + "id": 2337, + "nodeType": "Return", + "src": "15730:55:4" + } + ] + }, + "documentation": { + "id": 2306, + "nodeType": "StructuredDocumentation", + "src": "14685:725:4", + "text": "Do a \"donate withdraw\" on behalf of someone else, to an address they've specified.\nSponsored withdraw is paid by admin, but target account could be whatever the member specifies.\nThe signature is valid only for given amount of tokens that may be different from maximum withdrawable tokens.\n@param fromSigner whose earnings are being withdrawn\n@param to the address the tokens will be sent to (instead of `msg.sender`)\n@param amount of tokens to withdraw\n@param sendToMainnet if the tokens should be sent to mainnet or only withdrawn into sidechain address\n@param signature from the member, see `signatureIsValid` how signature generated for unlimited amount" + }, + "functionSelector": "1a79246c", + "id": 2339, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawToSigned", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2317, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2308, + "mutability": "mutable", + "name": "fromSigner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2339, + "src": "15450:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2307, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "15450:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2310, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2339, + "src": "15478:10:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2309, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "15478:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2312, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2339, + "src": "15498:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2311, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "15498:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2314, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2339, + "src": "15519:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2313, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "15519:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2316, + "mutability": "mutable", + "name": "signature", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2339, + "src": "15547:22:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 2315, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "15547:5:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "15440:135:4" + }, + "returnParameters": { + "id": 2320, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2319, + "mutability": "mutable", + "name": "withdrawn", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2339, + "src": "15608:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2318, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "15608:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "15607:16:4" + }, + "scope": 2432, + "src": "15415:377:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2347, + "nodeType": "Block", + "src": "15863:324:4", + "statements": [ + { + "AST": { + "nodeType": "YulBlock", + "src": "15882:299:4", + "statements": [ + { + "nodeType": "YulVariableDeclaration", + "src": "15896:20:4", + "value": { + "arguments": [ + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "15911:4:4", + "type": "", + "value": "0x40" + } + ], + "functionName": { + "name": "mload", + "nodeType": "YulIdentifier", + "src": "15905:5:4" + }, + "nodeType": "YulFunctionCall", + "src": "15905:11:4" + }, + "variables": [ + { + "name": "m", + "nodeType": "YulTypedName", + "src": "15900:1:4", + "type": "" + } + ] + }, + { + "nodeType": "YulAssignment", + "src": "15929:55:4", + "value": { + "arguments": [ + { + "name": "a", + "nodeType": "YulIdentifier", + "src": "15938:1:4" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "15941:42:4", + "type": "", + "value": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + } + ], + "functionName": { + "name": "and", + "nodeType": "YulIdentifier", + "src": "15934:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "15934:50:4" + }, + "variableNames": [ + { + "name": "a", + "nodeType": "YulIdentifier", + "src": "15929:1:4" + } + ] + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "m", + "nodeType": "YulIdentifier", + "src": "16025:1:4" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "16028:2:4", + "type": "", + "value": "20" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "16021:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "16021:10:4" + }, + { + "arguments": [ + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "16053:44:4", + "type": "", + "value": "0x140000000000000000000000000000000000000000" + }, + { + "name": "a", + "nodeType": "YulIdentifier", + "src": "16099:1:4" + } + ], + "functionName": { + "name": "xor", + "nodeType": "YulIdentifier", + "src": "16049:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "16049:52:4" + } + ], + "functionName": { + "name": "mstore", + "nodeType": "YulIdentifier", + "src": "15997:6:4" + }, + "nodeType": "YulFunctionCall", + "src": "15997:118:4" + }, + "nodeType": "YulExpressionStatement", + "src": "15997:118:4" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "16135:4:4", + "type": "", + "value": "0x40" + }, + { + "arguments": [ + { + "name": "m", + "nodeType": "YulIdentifier", + "src": "16145:1:4" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "16148:2:4", + "type": "", + "value": "52" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "16141:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "16141:10:4" + } + ], + "functionName": { + "name": "mstore", + "nodeType": "YulIdentifier", + "src": "16128:6:4" + }, + "nodeType": "YulFunctionCall", + "src": "16128:24:4" + }, + "nodeType": "YulExpressionStatement", + "src": "16128:24:4" + }, + { + "nodeType": "YulAssignment", + "src": "16165:6:4", + "value": { + "name": "m", + "nodeType": "YulIdentifier", + "src": "16170:1:4" + }, + "variableNames": [ + { + "name": "b", + "nodeType": "YulIdentifier", + "src": "16165:1:4" + } + ] + } + ] + }, + "evmVersion": "istanbul", + "externalReferences": [ + { + "declaration": 2341, + "isOffset": false, + "isSlot": false, + "src": "15929:1:4", + "valueSize": 1 + }, + { + "declaration": 2341, + "isOffset": false, + "isSlot": false, + "src": "15938:1:4", + "valueSize": 1 + }, + { + "declaration": 2341, + "isOffset": false, + "isSlot": false, + "src": "16099:1:4", + "valueSize": 1 + }, + { + "declaration": 2344, + "isOffset": false, + "isSlot": false, + "src": "16165:1:4", + "valueSize": 1 + } + ], + "id": 2346, + "nodeType": "InlineAssembly", + "src": "15873:308:4" + } + ] + }, + "documentation": null, + "functionSelector": "593b79fe", + "id": 2348, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "toBytes", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2342, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2341, + "mutability": "mutable", + "name": "a", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2348, + "src": "15815:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2340, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "15815:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "15814:11:4" + }, + "returnParameters": { + "id": 2345, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2344, + "mutability": "mutable", + "name": "b", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2348, + "src": "15847:14:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 2343, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "15847:5:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "15846:16:4" + }, + "scope": 2432, + "src": "15798:389:4", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2430, + "nodeType": "Block", + "src": "16463:705:4", + "statements": [ + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 2364, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2362, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "16477:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 2363, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "16487:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "16477:11:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 2367, + "nodeType": "IfStatement", + "src": "16473:25:4", + "trueBody": { + "expression": { + "argumentTypes": null, + "hexValue": "30", + "id": 2365, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "16497:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "functionReturnParameters": 2361, + "id": 2366, + "nodeType": "Return", + "src": "16490:8:4" + } + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 2373, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2369, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "16516:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "<=", + "rightExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2371, + "name": "from", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2351, + "src": "16550:4:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 2370, + "name": "getWithdrawableEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1494, + "src": "16526:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 2372, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16526:29:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "16516:39:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f696e73756666696369656e7442616c616e6365", + "id": 2374, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "16557:27:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_74799d65376d943bac023262731d6421d2e6b6332748a55385eb85a0683327fc", + "typeString": "literal_string \"error_insufficientBalance\"" + }, + "value": "error_insufficientBalance" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_74799d65376d943bac023262731d6421d2e6b6332748a55385eb85a0683327fc", + "typeString": "literal_string \"error_insufficientBalance\"" + } + ], + "id": 2368, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "16508:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2375, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16508:77:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2376, + "nodeType": "ExpressionStatement", + "src": "16508:77:4" + }, + { + "assignments": [ + 2378 + ], + "declarations": [ + { + "constant": false, + "id": 2378, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2430, + "src": "16595:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 2377, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "16595:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2382, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 2379, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "16621:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 2381, + "indexExpression": { + "argumentTypes": null, + "id": 2380, + "name": "from", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2351, + "src": "16632:4:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "16621:16:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "16595:42:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 2391, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2383, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2378, + "src": "16647:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 2385, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "withdrawnEarnings", + "nodeType": "MemberAccess", + "referencedDeclaration": 1244, + "src": "16647:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2389, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "16699:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2386, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2378, + "src": "16672:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 2387, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "withdrawnEarnings", + "nodeType": "MemberAccess", + "referencedDeclaration": 1244, + "src": "16672:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2388, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "16672:26:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 2390, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16672:34:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "16647:59:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2392, + "nodeType": "ExpressionStatement", + "src": "16647:59:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 2398, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 2393, + "name": "totalEarningsWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1255, + "src": "16716:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2396, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "16768:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 2394, + "name": "totalEarningsWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1255, + "src": "16741:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2395, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "16741:26:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 2397, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16741:34:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "16716:59:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2399, + "nodeType": "ExpressionStatement", + "src": "16716:59:4" + }, + { + "condition": { + "argumentTypes": null, + "id": 2400, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2357, + "src": "16789:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2416, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2353, + "src": "17062:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2417, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "17066:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 2414, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "17047:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 2415, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "transfer", + "nodeType": "MemberAccess", + "referencedDeclaration": 4231, + "src": "17047:14:4", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_uint256_$returns$_t_bool_$", + "typeString": "function (address,uint256) external returns (bool)" + } + }, + "id": 2418, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "17047:26:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f7472616e73666572", + "id": 2419, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "17075:16:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + }, + "value": "error_transfer" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + } + ], + "id": 2413, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "17039:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2420, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "17039:53:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2421, + "nodeType": "ExpressionStatement", + "src": "17039:53:4" + }, + "id": 2422, + "nodeType": "IfStatement", + "src": "16785:307:4", + "trueBody": { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2404, + "name": "tokenMediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1249, + "src": "16884:13:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2405, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "16919:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2407, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2353, + "src": "16955:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 2406, + "name": "toBytes", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2348, + "src": "16947:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (address) pure returns (bytes memory)" + } + }, + "id": 2408, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16947:11:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "expression": { + "argumentTypes": null, + "id": 2402, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "16841:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 2403, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "transferAndCall", + "nodeType": "MemberAccess", + "referencedDeclaration": 2938, + "src": "16841:21:4", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_uint256_$_t_bytes_memory_ptr_$returns$_t_bool_$", + "typeString": "function (address,uint256,bytes memory) external returns (bool)" + } + }, + "id": 2409, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16841:135:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f7472616e73666572", + "id": 2410, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "16994:16:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + }, + "value": "error_transfer" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + } + ], + "id": 2401, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "16816:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2411, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16816:208:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2412, + "nodeType": "ExpressionStatement", + "src": "16816:208:4" + } + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2424, + "name": "from", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2351, + "src": "17125:4:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2425, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "17131:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 2423, + "name": "EarningsWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1212, + "src": "17107:17:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256)" + } + }, + "id": 2426, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "17107:31:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2427, + "nodeType": "EmitStatement", + "src": "17102:36:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 2428, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "17155:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2361, + "id": 2429, + "nodeType": "Return", + "src": "17148:13:4" + } + ] + }, + "documentation": { + "id": 2349, + "nodeType": "StructuredDocumentation", + "src": "16193:140:4", + "text": "Internal function common to all withdraw methods.\nDoes NOT check proper access, so all callers must do that first." + }, + "id": 2431, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "_withdraw", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2358, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2351, + "mutability": "mutable", + "name": "from", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2431, + "src": "16357:12:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2350, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "16357:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2353, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2431, + "src": "16371:10:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2352, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "16371:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2355, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2431, + "src": "16383:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2354, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "16383:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2357, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2431, + "src": "16396:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2356, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "16396:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "16356:59:4" + }, + "returnParameters": { + "id": 2361, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2360, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2431, + "src": "16450:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2359, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "16450:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "16449:9:4" + }, + "scope": 2432, + "src": "16338:830:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "internal" + } + ], + "scope": 2433, + "src": "271:16899:4" + } + ], + "src": "0:17171:4" + }, + "legacyAST": { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/DataUnionSidechain.sol", + "exportedSymbols": { + "DataUnionSidechain": [ + 2432 + ] + }, + "id": 2433, + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 1167, + "literals": [ + "solidity", + "0.6", + ".6" + ], + "nodeType": "PragmaDirective", + "src": "0:22:4" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "file": "openzeppelin-solidity/contracts/math/SafeMath.sol", + "id": 1168, + "nodeType": "ImportDirective", + "scope": 2433, + "sourceUnit": 3642, + "src": "24:59:4", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol", + "file": "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol", + "id": 1169, + "nodeType": "ImportDirective", + "scope": 2433, + "sourceUnit": 4283, + "src": "84:64:4", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/IERC677.sol", + "file": "./IERC677.sol", + "id": 1170, + "nodeType": "ImportDirective", + "scope": 2433, + "sourceUnit": 2940, + "src": "149:23:4", + "symbolAliases": [], + "unitAlias": "" + }, + { + "absolutePath": "/home/heynow/streamr/data-union-solidity/contracts/Ownable.sol", + "file": "./Ownable.sol", + "id": 1171, + "nodeType": "ImportDirective", + "scope": 2433, + "sourceUnit": 3181, + "src": "173:23:4", + "symbolAliases": [], + "unitAlias": "" + }, + { + "abstract": false, + "baseContracts": [ + { + "arguments": null, + "baseName": { + "contractScope": null, + "id": 1172, + "name": "Ownable", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 3180, + "src": "302:7:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_Ownable_$3180", + "typeString": "contract Ownable" + } + }, + "id": 1173, + "nodeType": "InheritanceSpecifier", + "src": "302:7:4" + } + ], + "contractDependencies": [ + 3180 + ], + "contractKind": "contract", + "documentation": null, + "fullyImplemented": true, + "id": 2432, + "linearizedBaseContracts": [ + 2432, + 3180 + ], + "name": "DataUnionSidechain", + "nodeType": "ContractDefinition", + "nodes": [ + { + "id": 1176, + "libraryName": { + "contractScope": null, + "id": 1174, + "name": "SafeMath", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 3641, + "src": "322:8:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_SafeMath_$3641", + "typeString": "library SafeMath" + } + }, + "nodeType": "UsingForDirective", + "src": "316:27:4", + "typeName": { + "id": 1175, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "335:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + }, + { + "canonicalName": "DataUnionSidechain.ActiveStatus", + "id": 1180, + "members": [ + { + "id": 1177, + "name": "None", + "nodeType": "EnumValue", + "src": "420:4:4" + }, + { + "id": 1178, + "name": "Active", + "nodeType": "EnumValue", + "src": "426:6:4" + }, + { + "id": 1179, + "name": "Inactive", + "nodeType": "EnumValue", + "src": "434:8:4" + } + ], + "name": "ActiveStatus", + "nodeType": "EnumDefinition", + "src": "401:42:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1184, + "name": "MemberJoined", + "nodeType": "EventDefinition", + "parameters": { + "id": 1183, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1182, + "indexed": true, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1184, + "src": "497:22:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1181, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "497:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "496:24:4" + }, + "src": "478:43:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1188, + "name": "MemberParted", + "nodeType": "EventDefinition", + "parameters": { + "id": 1187, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1186, + "indexed": true, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1188, + "src": "545:22:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1185, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "545:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "544:24:4" + }, + "src": "526:43:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1192, + "name": "JoinPartAgentAdded", + "nodeType": "EventDefinition", + "parameters": { + "id": 1191, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1190, + "indexed": true, + "mutability": "mutable", + "name": "agent", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1192, + "src": "599:21:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1189, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "599:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "598:23:4" + }, + "src": "574:48:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1196, + "name": "JoinPartAgentRemoved", + "nodeType": "EventDefinition", + "parameters": { + "id": 1195, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1194, + "indexed": true, + "mutability": "mutable", + "name": "agent", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1196, + "src": "654:21:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1193, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "654:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "653:23:4" + }, + "src": "627:50:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1200, + "name": "RevenueReceived", + "nodeType": "EventDefinition", + "parameters": { + "id": 1199, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1198, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1200, + "src": "741:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1197, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "741:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "740:16:4" + }, + "src": "719:38:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1206, + "name": "NewEarnings", + "nodeType": "EventDefinition", + "parameters": { + "id": 1205, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1202, + "indexed": false, + "mutability": "mutable", + "name": "earningsPerMember", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1206, + "src": "780:25:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1201, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "780:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1204, + "indexed": false, + "mutability": "mutable", + "name": "activeMemberCount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1206, + "src": "807:25:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1203, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "807:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "779:54:4" + }, + "src": "762:72:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1212, + "name": "EarningsWithdrawn", + "nodeType": "EventDefinition", + "parameters": { + "id": 1211, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1208, + "indexed": true, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1212, + "src": "892:22:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1207, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "892:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1210, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1212, + "src": "916:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1209, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "916:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "891:40:4" + }, + "src": "868:64:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1220, + "name": "TransferWithinContract", + "nodeType": "EventDefinition", + "parameters": { + "id": 1219, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1214, + "indexed": true, + "mutability": "mutable", + "name": "from", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1220, + "src": "995:20:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1213, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "995:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1216, + "indexed": true, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1220, + "src": "1017:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1215, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1017:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1218, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1220, + "src": "1037:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1217, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1037:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "994:55:4" + }, + "src": "966:84:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1228, + "name": "TransferToAddressInContract", + "nodeType": "EventDefinition", + "parameters": { + "id": 1227, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1222, + "indexed": true, + "mutability": "mutable", + "name": "from", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1228, + "src": "1089:20:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1221, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1089:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1224, + "indexed": true, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1228, + "src": "1111:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1223, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1111:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1226, + "indexed": false, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1228, + "src": "1131:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1225, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1131:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1088:55:4" + }, + "src": "1055:89:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1232, + "name": "UpdateNewMemberEth", + "nodeType": "EventDefinition", + "parameters": { + "id": 1231, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1230, + "indexed": false, + "mutability": "mutable", + "name": "value", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1232, + "src": "1196:10:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1229, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1196:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1195:12:4" + }, + "src": "1171:37:4" + }, + { + "anonymous": false, + "documentation": null, + "id": 1236, + "name": "NewMemberEthSent", + "nodeType": "EventDefinition", + "parameters": { + "id": 1235, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1234, + "indexed": false, + "mutability": "mutable", + "name": "amountWei", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1236, + "src": "1236:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1233, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "1236:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "1235:16:4" + }, + "src": "1213:39:4" + }, + { + "canonicalName": "DataUnionSidechain.MemberInfo", + "id": 1245, + "members": [ + { + "constant": false, + "id": 1238, + "mutability": "mutable", + "name": "status", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1245, + "src": "1286:19:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "typeName": { + "contractScope": null, + "id": 1237, + "name": "ActiveStatus", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1180, + "src": "1286:12:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1240, + "mutability": "mutable", + "name": "earningsBeforeLastJoin", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1245, + "src": "1315:30:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1239, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1315:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1242, + "mutability": "mutable", + "name": "lmeAtJoin", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1245, + "src": "1355:17:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1241, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1355:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1244, + "mutability": "mutable", + "name": "withdrawnEarnings", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1245, + "src": "1382:25:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1243, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1382:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "name": "MemberInfo", + "nodeType": "StructDefinition", + "scope": 2432, + "src": "1258:156:4", + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "fc0c546a", + "id": 1247, + "mutability": "mutable", + "name": "token", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1420:20:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + }, + "typeName": { + "contractScope": null, + "id": 1246, + "name": "IERC677", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 2939, + "src": "1420:7:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "cc772440", + "id": 1249, + "mutability": "mutable", + "name": "tokenMediator", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1446:28:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1248, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1446:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "bf1e42c0", + "id": 1251, + "mutability": "mutable", + "name": "dataUnionMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1480:31:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1250, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1480:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "2df3eba4", + "id": 1253, + "mutability": "mutable", + "name": "totalEarnings", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1518:28:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1252, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1518:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "85a21246", + "id": 1255, + "mutability": "mutable", + "name": "totalEarningsWithdrawn", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1552:37:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1254, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1552:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "5fb6c6ed", + "id": 1257, + "mutability": "mutable", + "name": "activeMemberCount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1596:32:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1256, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1596:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "3d8e36a3", + "id": 1259, + "mutability": "mutable", + "name": "inactiveMemberCount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1634:34:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1258, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1634:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "6d8018b8", + "id": 1261, + "mutability": "mutable", + "name": "lifetimeMemberEarnings", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1674:37:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1260, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1674:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "3ebff90e", + "id": 1263, + "mutability": "mutable", + "name": "joinPartAgentCount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1718:33:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1262, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1718:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "79049017", + "id": 1265, + "mutability": "mutable", + "name": "newMemberEth", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1758:27:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1264, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1758:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "9107d08e", + "id": 1269, + "mutability": "mutable", + "name": "memberData", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1792:48:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo)" + }, + "typeName": { + "id": 1268, + "keyType": { + "id": 1266, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1800:7:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Mapping", + "src": "1792:30:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo)" + }, + "valueType": { + "contractScope": null, + "id": 1267, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "1811:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + } + }, + "value": null, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "c44b73a3", + "id": 1273, + "mutability": "mutable", + "name": "joinPartAgents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2432, + "src": "1846:54:4", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + }, + "typeName": { + "id": 1272, + "keyType": { + "id": 1270, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1854:7:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Mapping", + "src": "1846:32:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + }, + "valueType": { + "contractScope": null, + "id": 1271, + "name": "ActiveStatus", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1180, + "src": "1865:12:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + } + }, + "value": null, + "visibility": "public" + }, + { + "body": { + "id": 1287, + "nodeType": "Block", + "src": "1936:113:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1282, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1276, + "name": "joinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1273, + "src": "1954:14:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1279, + "indexExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1277, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "1969:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1278, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "1969:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "1954:26:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1280, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "1984:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1281, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "1984:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "1954:49:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6f6e6c794a6f696e506172744167656e74", + "id": 1283, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2005:25:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_956f78fcce2b1e1b69129df43faa6544de07d17c942f714c7b52da05de24f86e", + "typeString": "literal_string \"error_onlyJoinPartAgent\"" + }, + "value": "error_onlyJoinPartAgent" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_956f78fcce2b1e1b69129df43faa6544de07d17c942f714c7b52da05de24f86e", + "typeString": "literal_string \"error_onlyJoinPartAgent\"" + } + ], + "id": 1275, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "1946:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1284, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "1946:85:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1285, + "nodeType": "ExpressionStatement", + "src": "1946:85:4" + }, + { + "id": 1286, + "nodeType": "PlaceholderStatement", + "src": "2041:1:4" + } + ] + }, + "documentation": null, + "id": 1288, + "name": "onlyJoinPartAgent", + "nodeType": "ModifierDefinition", + "overrides": null, + "parameters": { + "id": 1274, + "nodeType": "ParameterList", + "parameters": [], + "src": "1933:2:4" + }, + "src": "1907:142:4", + "virtual": false, + "visibility": "internal" + }, + { + "body": { + "id": 1297, + "nodeType": "Block", + "src": "2137:2:4", + "statements": [] + }, + "documentation": null, + "id": 1298, + "implemented": true, + "kind": "constructor", + "modifiers": [ + { + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "30", + "id": 1293, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2133:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "id": 1292, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2125:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1291, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2125:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1294, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2125:10:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "id": 1295, + "modifierName": { + "argumentTypes": null, + "id": 1290, + "name": "Ownable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3180, + "src": "2117:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_Ownable_$3180_$", + "typeString": "type(contract Ownable)" + } + }, + "nodeType": "ModifierInvocation", + "src": "2117:19:4" + } + ], + "name": "", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1289, + "nodeType": "ParameterList", + "parameters": [], + "src": "2107:2:4" + }, + "returnParameters": { + "id": 1296, + "nodeType": "ParameterList", + "parameters": [], + "src": "2137:0:4" + }, + "scope": 2432, + "src": "2096:43:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1301, + "nodeType": "Block", + "src": "2172:2:4", + "statements": [] + }, + "documentation": null, + "id": 1302, + "implemented": true, + "kind": "receive", + "modifiers": [], + "name": "", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1299, + "nodeType": "ParameterList", + "parameters": [], + "src": "2152:2:4" + }, + "returnParameters": { + "id": 1300, + "nodeType": "ParameterList", + "parameters": [], + "src": "2172:0:4" + }, + "scope": 2432, + "src": "2145:29:4", + "stateMutability": "payable", + "virtual": false, + "visibility": "external" + }, + { + "body": { + "id": 1356, + "nodeType": "Block", + "src": "2437:456:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1321, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "!", + "prefix": true, + "src": "2455:16:4", + "subExpression": { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1319, + "name": "isInitialized", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1373, + "src": "2456:13:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_bool_$", + "typeString": "function () view returns (bool)" + } + }, + "id": 1320, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2456:15:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f616c7265616479496e697469616c697a6564", + "id": 1322, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2473:26:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_845b975974cd10e32a9d060d8158a7b328a11a448ea3c75e0603113d3b173fd5", + "typeString": "literal_string \"error_alreadyInitialized\"" + }, + "value": "error_alreadyInitialized" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_845b975974cd10e32a9d060d8158a7b328a11a448ea3c75e0603113d3b173fd5", + "typeString": "literal_string \"error_alreadyInitialized\"" + } + ], + "id": 1318, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "2447:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1323, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2447:53:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1324, + "nodeType": "ExpressionStatement", + "src": "2447:53:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1328, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1325, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "2510:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1326, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "2518:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1327, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "2518:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "src": "2510:18:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1329, + "nodeType": "ExpressionStatement", + "src": "2510:18:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1334, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1330, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "2633:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1332, + "name": "tokenAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1306, + "src": "2649:12:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1331, + "name": "IERC677", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2939, + "src": "2641:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_IERC677_$2939_$", + "typeString": "type(contract IERC677)" + } + }, + "id": 1333, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2641:21:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "src": "2633:29:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 1335, + "nodeType": "ExpressionStatement", + "src": "2633:29:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1337, + "name": "initialJoinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1309, + "src": "2690:21:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + ], + "id": 1336, + "name": "addJoinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1533, + "src": "2672:17:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_array$_t_address_$dyn_memory_ptr_$returns$__$", + "typeString": "function (address[] memory)" + } + }, + "id": 1338, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2672:40:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1339, + "nodeType": "ExpressionStatement", + "src": "2672:40:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1342, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1340, + "name": "tokenMediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1249, + "src": "2722:13:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 1341, + "name": "tokenMediatorAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1311, + "src": "2738:20:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2722:36:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1343, + "nodeType": "ExpressionStatement", + "src": "2722:36:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1346, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1344, + "name": "dataUnionMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1251, + "src": "2768:16:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 1345, + "name": "mainnetDataUnionAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1313, + "src": "2787:23:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2768:42:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1347, + "nodeType": "ExpressionStatement", + "src": "2768:42:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1349, + "name": "defaultNewMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1315, + "src": "2836:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1348, + "name": "setNewMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1411, + "src": "2820:15:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 1350, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2820:36:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1351, + "nodeType": "ExpressionStatement", + "src": "2820:36:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1354, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1352, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "2866:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 1353, + "name": "initialOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1304, + "src": "2874:12:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2866:20:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1355, + "nodeType": "ExpressionStatement", + "src": "2866:20:4" + } + ] + }, + "documentation": null, + "functionSelector": "015c7f51", + "id": 1357, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "initialize", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1316, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1304, + "mutability": "mutable", + "name": "initialOwner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1357, + "src": "2209:20:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1303, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2209:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1306, + "mutability": "mutable", + "name": "tokenAddress", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1357, + "src": "2239:20:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1305, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2239:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1309, + "mutability": "mutable", + "name": "initialJoinPartAgents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1357, + "src": "2269:38:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 1307, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2269:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1308, + "length": null, + "nodeType": "ArrayTypeName", + "src": "2269:9:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1311, + "mutability": "mutable", + "name": "tokenMediatorAddress", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1357, + "src": "2317:28:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1310, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2317:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1313, + "mutability": "mutable", + "name": "mainnetDataUnionAddress", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1357, + "src": "2355:31:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1312, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2355:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1315, + "mutability": "mutable", + "name": "defaultNewMemberEth", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1357, + "src": "2396:27:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1314, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2396:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2199:230:4" + }, + "returnParameters": { + "id": 1317, + "nodeType": "ParameterList", + "parameters": [], + "src": "2437:0:4" + }, + "scope": 2432, + "src": "2180:713:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1372, + "nodeType": "Block", + "src": "2950:52:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 1370, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1364, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "2975:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + ], + "id": 1363, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2967:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1362, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2967:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1365, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2967:14:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "30", + "id": 1368, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2993:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "id": 1367, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2985:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1366, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2985:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1369, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "2985:10:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "src": "2967:28:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "functionReturnParameters": 1361, + "id": 1371, + "nodeType": "Return", + "src": "2960:35:4" + } + ] + }, + "documentation": null, + "functionSelector": "392e53cd", + "id": 1373, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "isInitialized", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1358, + "nodeType": "ParameterList", + "parameters": [], + "src": "2921:2:4" + }, + "returnParameters": { + "id": 1361, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1360, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1373, + "src": "2945:4:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 1359, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "2945:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "2944:6:4" + }, + "scope": 2432, + "src": "2899:103:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1389, + "nodeType": "Block", + "src": "3235:229:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "components": [ + { + "argumentTypes": null, + "id": 1381, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1253, + "src": "3266:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 1382, + "name": "totalEarningsWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1255, + "src": "3293:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 1383, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "3329:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 1384, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "3360:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 1385, + "name": "lifetimeMemberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1261, + "src": "3393:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 1386, + "name": "joinPartAgentCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1263, + "src": "3429:18:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 1387, + "isConstant": false, + "isInlineArray": true, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "3252:205:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$6_memory_ptr", + "typeString": "uint256[6] memory" + } + }, + "functionReturnParameters": 1380, + "id": 1388, + "nodeType": "Return", + "src": "3245:212:4" + } + ] + }, + "documentation": { + "id": 1374, + "nodeType": "StructuredDocumentation", + "src": "3008:162:4", + "text": "Atomic getter to get all state variables in one call\nThis alleviates the fact that JSON RPC batch requests aren't available in ethers.js" + }, + "functionSelector": "c59d4847", + "id": 1390, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "getStats", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1375, + "nodeType": "ParameterList", + "parameters": [], + "src": "3192:2:4" + }, + "returnParameters": { + "id": 1380, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1379, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1390, + "src": "3216:17:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$6_memory_ptr", + "typeString": "uint256[6]" + }, + "typeName": { + "baseType": { + "id": 1376, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "3216:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1378, + "length": { + "argumentTypes": null, + "hexValue": "36", + "id": 1377, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3224:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_6_by_1", + "typeString": "int_const 6" + }, + "value": "6" + }, + "nodeType": "ArrayTypeName", + "src": "3216:10:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$6_storage_ptr", + "typeString": "uint256[6]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3215:19:4" + }, + "scope": 2432, + "src": "3175:289:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1410, + "nodeType": "Block", + "src": "3522:113:4", + "statements": [ + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1399, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1397, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1392, + "src": "3535:3:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 1398, + "name": "newMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1265, + "src": "3542:12:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "3535:19:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1401, + "nodeType": "IfStatement", + "src": "3532:31:4", + "trueBody": { + "expression": null, + "functionReturnParameters": 1396, + "id": 1400, + "nodeType": "Return", + "src": "3556:7:4" + } + }, + { + "expression": { + "argumentTypes": null, + "id": 1404, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1402, + "name": "newMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1265, + "src": "3572:12:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 1403, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1392, + "src": "3587:3:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "3572:18:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1405, + "nodeType": "ExpressionStatement", + "src": "3572:18:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1407, + "name": "val", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1392, + "src": "3624:3:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1406, + "name": "UpdateNewMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1232, + "src": "3605:18:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 1408, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3605:23:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1409, + "nodeType": "EmitStatement", + "src": "3600:28:4" + } + ] + }, + "documentation": null, + "functionSelector": "e6018c31", + "id": 1411, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 1395, + "modifierName": { + "argumentTypes": null, + "id": 1394, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "3512:9:4", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "3512:9:4" + } + ], + "name": "setNewMemberEth", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1393, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1392, + "mutability": "mutable", + "name": "val", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1411, + "src": "3495:8:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1391, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "3495:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3494:10:4" + }, + "returnParameters": { + "id": 1396, + "nodeType": "ParameterList", + "parameters": [], + "src": "3522:0:4" + }, + "scope": 2432, + "src": "3470:165:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1450, + "nodeType": "Block", + "src": "3708:357:4", + "statements": [ + { + "assignments": [ + 1419 + ], + "declarations": [ + { + "constant": false, + "id": 1419, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1450, + "src": "3718:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 1418, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "3718:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1423, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1420, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "3744:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 1422, + "indexExpression": { + "argumentTypes": null, + "id": 1421, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1413, + "src": "3755:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "3744:18:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "3718:44:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1429, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1425, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1419, + "src": "3780:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1426, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "3780:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1427, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "3795:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1428, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "None", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3795:17:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "3780:32:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6e6f744d656d626572", + "id": 1430, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3814:17:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_d7a3e0a08d346fd90b7cdd70bcb3d747f808a83a9bae19592a90bf66cd6b4372", + "typeString": "literal_string \"error_notMember\"" + }, + "value": "error_notMember" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_d7a3e0a08d346fd90b7cdd70bcb3d747f808a83a9bae19592a90bf66cd6b4372", + "typeString": "literal_string \"error_notMember\"" + } + ], + "id": 1424, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "3772:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1431, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3772:60:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1432, + "nodeType": "ExpressionStatement", + "src": "3772:60:4" + }, + { + "expression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1448, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1433, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1419, + "src": "3861:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1434, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "earningsBeforeLastJoin", + "nodeType": "MemberAccess", + "referencedDeclaration": 1240, + "src": "3861:27:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "+", + "rightExpression": { + "argumentTypes": null, + "components": [ + { + "argumentTypes": null, + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1439, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1435, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1419, + "src": "3921:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1436, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "3921:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1437, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "3936:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1438, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "3936:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "3921:34:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1445, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4043:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "id": 1446, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "Conditional", + "src": "3921:123:4", + "trueExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1442, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1419, + "src": "4005:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1443, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "lmeAtJoin", + "nodeType": "MemberAccess", + "referencedDeclaration": 1242, + "src": "4005:14:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1440, + "name": "lifetimeMemberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1261, + "src": "3978:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1441, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "3978:26:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1444, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "3978:42:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "id": 1447, + "isConstant": false, + "isInlineArray": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "3903:155:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "3861:197:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 1417, + "id": 1449, + "nodeType": "Return", + "src": "3842:216:4" + } + ] + }, + "documentation": null, + "functionSelector": "131b9c04", + "id": 1451, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "getEarnings", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1414, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1413, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1451, + "src": "3662:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1412, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "3662:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3661:16:4" + }, + "returnParameters": { + "id": 1417, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1416, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1451, + "src": "3699:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1415, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "3699:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "3698:9:4" + }, + "scope": 2432, + "src": "3641:424:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1476, + "nodeType": "Block", + "src": "4139:170:4", + "statements": [ + { + "assignments": [ + 1459 + ], + "declarations": [ + { + "constant": false, + "id": 1459, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1476, + "src": "4149:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 1458, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "4149:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1463, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1460, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "4175:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 1462, + "indexExpression": { + "argumentTypes": null, + "id": 1461, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1453, + "src": "4186:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "4175:18:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "4149:44:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1469, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1465, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1459, + "src": "4211:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1466, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "4211:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1467, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "4226:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1468, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "None", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "4226:17:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "4211:32:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6e6f744d656d626572", + "id": 1470, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4245:17:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_d7a3e0a08d346fd90b7cdd70bcb3d747f808a83a9bae19592a90bf66cd6b4372", + "typeString": "literal_string \"error_notMember\"" + }, + "value": "error_notMember" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_d7a3e0a08d346fd90b7cdd70bcb3d747f808a83a9bae19592a90bf66cd6b4372", + "typeString": "literal_string \"error_notMember\"" + } + ], + "id": 1464, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "4203:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1471, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4203:60:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1472, + "nodeType": "ExpressionStatement", + "src": "4203:60:4" + }, + { + "expression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1473, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1459, + "src": "4280:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1474, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "withdrawnEarnings", + "nodeType": "MemberAccess", + "referencedDeclaration": 1244, + "src": "4280:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 1457, + "id": 1475, + "nodeType": "Return", + "src": "4273:29:4" + } + ] + }, + "documentation": null, + "functionSelector": "ae66d948", + "id": 1477, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "getWithdrawn", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1454, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1453, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1477, + "src": "4093:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1452, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4093:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4092:16:4" + }, + "returnParameters": { + "id": 1457, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1456, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1477, + "src": "4130:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1455, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4130:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4129:9:4" + }, + "scope": 2432, + "src": "4071:238:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1493, + "nodeType": "Block", + "src": "4394:69:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1489, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1479, + "src": "4448:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1488, + "name": "getWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1477, + "src": "4435:12:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 1490, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4435:20:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1485, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1479, + "src": "4423:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1484, + "name": "getEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1451, + "src": "4411:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 1486, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4411:19:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1487, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "4411:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1491, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4411:45:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 1483, + "id": 1492, + "nodeType": "Return", + "src": "4404:52:4" + } + ] + }, + "documentation": null, + "functionSelector": "2e0d4212", + "id": 1494, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "getWithdrawableEarnings", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1480, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1479, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1494, + "src": "4348:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1478, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4348:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4347:16:4" + }, + "returnParameters": { + "id": 1483, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1482, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1494, + "src": "4385:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1481, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4385:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4384:9:4" + }, + "scope": 2432, + "src": "4315:148:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1504, + "nodeType": "Block", + "src": "4528:65:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1501, + "name": "totalEarningsWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1255, + "src": "4563:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1499, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1253, + "src": "4545:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1500, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "4545:17:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1502, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4545:41:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 1498, + "id": 1503, + "nodeType": "Return", + "src": "4538:48:4" + } + ] + }, + "documentation": null, + "functionSelector": "0600a865", + "id": 1505, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "totalWithdrawable", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1495, + "nodeType": "ParameterList", + "parameters": [], + "src": "4495:2:4" + }, + "returnParameters": { + "id": 1498, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1497, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1505, + "src": "4519:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1496, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4519:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4518:9:4" + }, + "scope": 2432, + "src": "4469:124:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1532, + "nodeType": "Block", + "src": "4668:112:4", + "statements": [ + { + "body": { + "id": 1530, + "nodeType": "Block", + "src": "4722:52:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1525, + "name": "agents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1508, + "src": "4753:6:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + "id": 1527, + "indexExpression": { + "argumentTypes": null, + "id": 1526, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1514, + "src": "4760:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "4753:9:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1524, + "name": "addJoinPartAgent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1569, + "src": "4736:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 1528, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4736:27:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1529, + "nodeType": "ExpressionStatement", + "src": "4736:27:4" + } + ] + }, + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1520, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1517, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1514, + "src": "4698:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "<", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1518, + "name": "agents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1508, + "src": "4702:6:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + "id": 1519, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "length", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "4702:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "4698:17:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 1531, + "initializationExpression": { + "assignments": [ + 1514 + ], + "declarations": [ + { + "constant": false, + "id": 1514, + "mutability": "mutable", + "name": "i", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1531, + "src": "4683:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1513, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "4683:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1516, + "initialValue": { + "argumentTypes": null, + "hexValue": "30", + "id": 1515, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4695:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "nodeType": "VariableDeclarationStatement", + "src": "4683:13:4" + }, + "loopExpression": { + "expression": { + "argumentTypes": null, + "id": 1522, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "++", + "prefix": false, + "src": "4717:3:4", + "subExpression": { + "argumentTypes": null, + "id": 1521, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1514, + "src": "4717:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1523, + "nodeType": "ExpressionStatement", + "src": "4717:3:4" + }, + "nodeType": "ForStatement", + "src": "4678:96:4" + } + ] + }, + "documentation": null, + "functionSelector": "1796621a", + "id": 1533, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 1511, + "modifierName": { + "argumentTypes": null, + "id": 1510, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "4658:9:4", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "4658:9:4" + } + ], + "name": "addJoinPartAgents", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1509, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1508, + "mutability": "mutable", + "name": "agents", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1533, + "src": "4626:23:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 1506, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4626:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1507, + "length": null, + "nodeType": "ArrayTypeName", + "src": "4626:9:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4625:25:4" + }, + "returnParameters": { + "id": 1512, + "nodeType": "ParameterList", + "parameters": [], + "src": "4668:0:4" + }, + "scope": 2432, + "src": "4599:181:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1568, + "nodeType": "Block", + "src": "4844:247:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1546, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1541, + "name": "joinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1273, + "src": "4862:14:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1543, + "indexExpression": { + "argumentTypes": null, + "id": 1542, + "name": "agent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1535, + "src": "4877:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "4862:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1544, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "4887:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1545, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "4887:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "4862:44:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f616c72656164794163746976654167656e74", + "id": 1547, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "4908:26:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_bb39e853702abde1810741d4774a63438edaeee888b9b2a936f664fafe2a45b8", + "typeString": "literal_string \"error_alreadyActiveAgent\"" + }, + "value": "error_alreadyActiveAgent" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_bb39e853702abde1810741d4774a63438edaeee888b9b2a936f664fafe2a45b8", + "typeString": "literal_string \"error_alreadyActiveAgent\"" + } + ], + "id": 1540, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "4854:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1548, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "4854:81:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1549, + "nodeType": "ExpressionStatement", + "src": "4854:81:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1555, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1550, + "name": "joinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1273, + "src": "4945:14:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1552, + "indexExpression": { + "argumentTypes": null, + "id": 1551, + "name": "agent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1535, + "src": "4960:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "nodeType": "IndexAccess", + "src": "4945:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1553, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "4969:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1554, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "4969:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "4945:43:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "id": 1556, + "nodeType": "ExpressionStatement", + "src": "4945:43:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1558, + "name": "agent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1535, + "src": "5022:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1557, + "name": "JoinPartAgentAdded", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1192, + "src": "5003:18:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 1559, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5003:25:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1560, + "nodeType": "EmitStatement", + "src": "4998:30:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1566, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1561, + "name": "joinPartAgentCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1263, + "src": "5038:18:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 1564, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5082:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 1562, + "name": "joinPartAgentCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1263, + "src": "5059:18:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1563, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "5059:22:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1565, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5059:25:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "5038:46:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1567, + "nodeType": "ExpressionStatement", + "src": "5038:46:4" + } + ] + }, + "documentation": null, + "functionSelector": "662d45a2", + "id": 1569, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 1538, + "modifierName": { + "argumentTypes": null, + "id": 1537, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "4834:9:4", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "4834:9:4" + } + ], + "name": "addJoinPartAgent", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1536, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1535, + "mutability": "mutable", + "name": "agent", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1569, + "src": "4812:13:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1534, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "4812:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "4811:15:4" + }, + "returnParameters": { + "id": 1539, + "nodeType": "ParameterList", + "parameters": [], + "src": "4844:0:4" + }, + "scope": 2432, + "src": "4786:305:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1604, + "nodeType": "Block", + "src": "5158:247:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1582, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1577, + "name": "joinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1273, + "src": "5176:14:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1579, + "indexExpression": { + "argumentTypes": null, + "id": 1578, + "name": "agent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1571, + "src": "5191:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "5176:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1580, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "5201:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1581, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "5201:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "5176:44:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6e6f744163746976654167656e74", + "id": 1583, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5222:22:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_7374b1c602a903c4ee0ecf07cf7d2bb5da07e6616a0fd70b600a11d82b670e51", + "typeString": "literal_string \"error_notActiveAgent\"" + }, + "value": "error_notActiveAgent" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_7374b1c602a903c4ee0ecf07cf7d2bb5da07e6616a0fd70b600a11d82b670e51", + "typeString": "literal_string \"error_notActiveAgent\"" + } + ], + "id": 1576, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "5168:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1584, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5168:77:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1585, + "nodeType": "ExpressionStatement", + "src": "5168:77:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1591, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1586, + "name": "joinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1273, + "src": "5255:14:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1588, + "indexExpression": { + "argumentTypes": null, + "id": 1587, + "name": "agent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1571, + "src": "5270:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "nodeType": "IndexAccess", + "src": "5255:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1589, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "5279:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1590, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Inactive", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "5279:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "5255:45:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "id": 1592, + "nodeType": "ExpressionStatement", + "src": "5255:45:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1594, + "name": "agent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1571, + "src": "5336:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1593, + "name": "JoinPartAgentRemoved", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1196, + "src": "5315:20:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 1595, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5315:27:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1596, + "nodeType": "EmitStatement", + "src": "5310:32:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1602, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1597, + "name": "joinPartAgentCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1263, + "src": "5352:18:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 1600, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5396:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 1598, + "name": "joinPartAgentCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1263, + "src": "5373:18:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1599, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "5373:22:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1601, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5373:25:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "5352:46:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1603, + "nodeType": "ExpressionStatement", + "src": "5352:46:4" + } + ] + }, + "documentation": null, + "functionSelector": "09a6400b", + "id": 1605, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 1574, + "modifierName": { + "argumentTypes": null, + "id": 1573, + "name": "onlyOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3137, + "src": "5148:9:4", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "5148:9:4" + } + ], + "name": "removeJoinPartAgent", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1572, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1571, + "mutability": "mutable", + "name": "agent", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1605, + "src": "5126:13:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1570, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "5126:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "5125:15:4" + }, + "returnParameters": { + "id": 1575, + "nodeType": "ParameterList", + "parameters": [], + "src": "5158:0:4" + }, + "scope": 2432, + "src": "5097:308:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1671, + "nodeType": "Block", + "src": "5606:542:4", + "statements": [ + { + "assignments": [ + 1612 + ], + "declarations": [ + { + "constant": false, + "id": 1612, + "mutability": "mutable", + "name": "balance", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1671, + "src": "5616:15:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1611, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "5616:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1620, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1617, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "5658:4:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + ], + "id": 1616, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "5650:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1615, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "5650:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1618, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5650:13:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "expression": { + "argumentTypes": null, + "id": 1613, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "5634:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 1614, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balanceOf", + "nodeType": "MemberAccess", + "referencedDeclaration": 4221, + "src": "5634:15:4", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view external returns (uint256)" + } + }, + "id": 1619, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5634:30:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "5616:48:4" + }, + { + "assignments": [ + 1622 + ], + "declarations": [ + { + "constant": false, + "id": 1622, + "mutability": "mutable", + "name": "revenue", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1671, + "src": "5674:15:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1621, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "5674:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1628, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [], + "expression": { + "argumentTypes": [], + "id": 1625, + "name": "totalWithdrawable", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1505, + "src": "5704:17:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$__$returns$_t_uint256_$", + "typeString": "function () view returns (uint256)" + } + }, + "id": 1626, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5704:19:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1623, + "name": "balance", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1612, + "src": "5692:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1624, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "5692:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1627, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5692:32:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "5674:50:4" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 1635, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1631, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1629, + "name": "revenue", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1622, + "src": "5766:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1630, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5777:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "5766:12:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "||", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1634, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1632, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "5782:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1633, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5803:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "5782:22:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "5766:38:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1638, + "nodeType": "IfStatement", + "src": "5762:52:4", + "trueBody": { + "expression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1636, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "5813:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "functionReturnParameters": 1610, + "id": 1637, + "nodeType": "Return", + "src": "5806:8:4" + } + }, + { + "assignments": [ + 1640 + ], + "declarations": [ + { + "constant": false, + "id": 1640, + "mutability": "mutable", + "name": "earningsPerMember", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1671, + "src": "5824:25:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1639, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "5824:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1645, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1643, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "5864:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1641, + "name": "revenue", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1622, + "src": "5852:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1642, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "div", + "nodeType": "MemberAccess", + "referencedDeclaration": 3571, + "src": "5852:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1644, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5852:30:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "5824:58:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1651, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1646, + "name": "lifetimeMemberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1261, + "src": "5892:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1649, + "name": "earningsPerMember", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1640, + "src": "5944:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1647, + "name": "lifetimeMemberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1261, + "src": "5917:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1648, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "5917:26:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1650, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5917:45:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "5892:70:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1652, + "nodeType": "ExpressionStatement", + "src": "5892:70:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1658, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1653, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1253, + "src": "5972:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1656, + "name": "revenue", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1622, + "src": "6006:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1654, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1253, + "src": "5988:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1655, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "5988:17:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1657, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "5988:26:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "5972:42:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1659, + "nodeType": "ExpressionStatement", + "src": "5972:42:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1661, + "name": "revenue", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1622, + "src": "6045:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1660, + "name": "RevenueReceived", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1200, + "src": "6029:15:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 1662, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6029:24:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1663, + "nodeType": "EmitStatement", + "src": "6024:29:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1665, + "name": "earningsPerMember", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1640, + "src": "6080:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 1666, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "6099:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1664, + "name": "NewEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1206, + "src": "6068:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$_t_uint256_$returns$__$", + "typeString": "function (uint256,uint256)" + } + }, + "id": 1667, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6068:49:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1668, + "nodeType": "EmitStatement", + "src": "6063:54:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1669, + "name": "revenue", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1622, + "src": "6134:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 1610, + "id": 1670, + "nodeType": "Return", + "src": "6127:14:4" + } + ] + }, + "documentation": { + "id": 1606, + "nodeType": "StructuredDocumentation", + "src": "5411:139:4", + "text": "Process unaccounted tokens that have been sent previously\nCalled by AMB (see DataUnionMainnet:sendTokensToBridge)" + }, + "functionSelector": "331beb5f", + "id": 1672, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "refreshRevenue", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1607, + "nodeType": "ParameterList", + "parameters": [], + "src": "5578:2:4" + }, + "returnParameters": { + "id": 1610, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1609, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1672, + "src": "5597:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1608, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "5597:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "5596:9:4" + }, + "scope": 2432, + "src": "5555:593:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1765, + "nodeType": "Block", + "src": "6222:765:4", + "statements": [ + { + "assignments": [ + 1680 + ], + "declarations": [ + { + "constant": false, + "id": 1680, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1765, + "src": "6232:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 1679, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "6232:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1684, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1681, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "6258:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 1683, + "indexExpression": { + "argumentTypes": null, + "id": 1682, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1674, + "src": "6269:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "6258:18:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "6232:44:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1690, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1686, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1680, + "src": "6294:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1687, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "6294:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1688, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "6309:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1689, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "6309:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "6294:34:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f616c72656164794d656d626572", + "id": 1691, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6330:21:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_0cd731b7251f7a1d03a588db9c28b82c775f5ea903082a5ec49eb1fc1ac0eb1f", + "typeString": "literal_string \"error_alreadyMember\"" + }, + "value": "error_alreadyMember" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_0cd731b7251f7a1d03a588db9c28b82c775f5ea903082a5ec49eb1fc1ac0eb1f", + "typeString": "literal_string \"error_alreadyMember\"" + } + ], + "id": 1685, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "6286:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1692, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6286:66:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1693, + "nodeType": "ExpressionStatement", + "src": "6286:66:4" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1698, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1694, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1680, + "src": "6365:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1695, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "6365:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1696, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "6380:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1697, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Inactive", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "6380:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "6365:36:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1707, + "nodeType": "IfStatement", + "src": "6362:113:4", + "trueBody": { + "id": 1706, + "nodeType": "Block", + "src": "6402:73:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 1704, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1699, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "6416:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 1702, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6462:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 1700, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "6438:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1701, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "6438:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1703, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6438:26:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6416:48:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1705, + "nodeType": "ExpressionStatement", + "src": "6416:48:4" + } + ] + } + }, + { + "assignments": [ + 1709 + ], + "declarations": [ + { + "constant": false, + "id": 1709, + "mutability": "mutable", + "name": "sendEth", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1765, + "src": "6484:12:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 1708, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "6484:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1727, + "initialValue": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 1726, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 1718, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1714, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1710, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1680, + "src": "6499:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1711, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "6499:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1712, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "6514:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1713, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "None", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "6514:17:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "6499:32:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "&&", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1717, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1715, + "name": "newMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1265, + "src": "6535:12:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 1716, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6551:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "6535:17:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "6499:53:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "&&", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1725, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1721, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "6564:4:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + ], + "id": 1720, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "6556:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1719, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "6556:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1722, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6556:13:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 1723, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balance", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "6556:21:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": ">=", + "rightExpression": { + "argumentTypes": null, + "id": 1724, + "name": "newMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1265, + "src": "6581:12:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6556:37:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "6499:94:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "6484:109:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1733, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1728, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1680, + "src": "6603:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1730, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "6603:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1731, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "6617:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1732, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "6617:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "6603:33:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "id": 1734, + "nodeType": "ExpressionStatement", + "src": "6603:33:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1739, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1735, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1680, + "src": "6646:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1737, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "lmeAtJoin", + "nodeType": "MemberAccess", + "referencedDeclaration": 1242, + "src": "6646:14:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "id": 1738, + "name": "lifetimeMemberEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1261, + "src": "6663:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6646:39:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1740, + "nodeType": "ExpressionStatement", + "src": "6646:39:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1746, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1741, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "6695:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 1744, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "6737:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 1742, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "6715:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1743, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "6715:21:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1745, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6715:24:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "6695:44:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1747, + "nodeType": "ExpressionStatement", + "src": "6695:44:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1749, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1674, + "src": "6767:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "id": 1748, + "name": "MemberJoined", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1184, + "src": "6754:12:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 1750, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6754:20:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1751, + "nodeType": "EmitStatement", + "src": "6749:25:4" + }, + { + "condition": { + "argumentTypes": null, + "id": 1752, + "name": "sendEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1709, + "src": "6854:7:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1764, + "nodeType": "IfStatement", + "src": "6850:131:4", + "trueBody": { + "id": 1763, + "nodeType": "Block", + "src": "6863:118:4", + "statements": [ + { + "condition": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1755, + "name": "newMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1265, + "src": "6893:12:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1753, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1674, + "src": "6881:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 1754, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "send", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "6881:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_send_nonpayable$_t_uint256_$returns$_t_bool_$", + "typeString": "function (uint256) returns (bool)" + } + }, + "id": 1756, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6881:25:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 1762, + "nodeType": "IfStatement", + "src": "6877:94:4", + "trueBody": { + "id": 1761, + "nodeType": "Block", + "src": "6908:63:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1758, + "name": "newMemberEth", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1265, + "src": "6943:12:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1757, + "name": "NewMemberEthSent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1236, + "src": "6926:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$returns$__$", + "typeString": "function (uint256)" + } + }, + "id": 1759, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "6926:30:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1760, + "nodeType": "ExpressionStatement", + "src": "6926:30:4" + } + ] + } + } + ] + } + } + ] + }, + "documentation": null, + "functionSelector": "ca6d56dc", + "id": 1766, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 1677, + "modifierName": { + "argumentTypes": null, + "id": 1676, + "name": "onlyJoinPartAgent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1288, + "src": "6204:17:4", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "6204:17:4" + } + ], + "name": "addMember", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1675, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1674, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1766, + "src": "6173:22:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + "typeName": { + "id": 1673, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "6173:15:4", + "stateMutability": "payable", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "6172:24:4" + }, + "returnParameters": { + "id": 1678, + "nodeType": "ParameterList", + "parameters": [], + "src": "6222:0:4" + }, + "scope": 2432, + "src": "6154:833:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1835, + "nodeType": "Block", + "src": "7036:504:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 1783, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 1775, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1772, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "7054:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1773, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7054:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 1774, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1768, + "src": "7068:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "7054:20:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "||", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1782, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1776, + "name": "joinPartAgents", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1273, + "src": "7078:14:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_enum$_ActiveStatus_$1180_$", + "typeString": "mapping(address => enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1779, + "indexExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1777, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "7093:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1778, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7093:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7078:26:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1780, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "7108:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1781, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7108:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "7078:49:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "7054:73:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6e6f745065726d6974746564", + "id": 1784, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7129:20:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_81fcea6533090d67b5d2d1910c87832a3a952f4bfc10eedbdaba5b028593bde1", + "typeString": "literal_string \"error_notPermitted\"" + }, + "value": "error_notPermitted" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_81fcea6533090d67b5d2d1910c87832a3a952f4bfc10eedbdaba5b028593bde1", + "typeString": "literal_string \"error_notPermitted\"" + } + ], + "id": 1771, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "7046:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1785, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7046:104:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1786, + "nodeType": "ExpressionStatement", + "src": "7046:104:4" + }, + { + "assignments": [ + 1788 + ], + "declarations": [ + { + "constant": false, + "id": 1788, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1835, + "src": "7160:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 1787, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "7160:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1792, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1789, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "7186:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 1791, + "indexExpression": { + "argumentTypes": null, + "id": 1790, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1768, + "src": "7197:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7186:18:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "7160:44:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 1798, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1794, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1788, + "src": "7222:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1795, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "7222:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1796, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "7237:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1797, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Active", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7237:19:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "7222:34:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6e6f744163746976654d656d626572", + "id": 1799, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7258:23:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_bc4828de8fccb67618bdc2462d405754421b1e879aff6628f11ddb63528355b9", + "typeString": "literal_string \"error_notActiveMember\"" + }, + "value": "error_notActiveMember" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_bc4828de8fccb67618bdc2462d405754421b1e879aff6628f11ddb63528355b9", + "typeString": "literal_string \"error_notActiveMember\"" + } + ], + "id": 1793, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "7214:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1800, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7214:68:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1801, + "nodeType": "ExpressionStatement", + "src": "7214:68:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1808, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1802, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1788, + "src": "7292:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1804, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "earningsBeforeLastJoin", + "nodeType": "MemberAccess", + "referencedDeclaration": 1240, + "src": "7292:27:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1806, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1768, + "src": "7334:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1805, + "name": "getEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1451, + "src": "7322:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 1807, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7322:19:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7292:49:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1809, + "nodeType": "ExpressionStatement", + "src": "7292:49:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1815, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1810, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1788, + "src": "7351:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1812, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "7351:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1813, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "7365:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 1814, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Inactive", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7365:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "7351:35:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "id": 1816, + "nodeType": "ExpressionStatement", + "src": "7351:35:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1822, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1817, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "7396:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 1820, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7438:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 1818, + "name": "activeMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1257, + "src": "7416:17:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1819, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "7416:21:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1821, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7416:24:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7396:44:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1823, + "nodeType": "ExpressionStatement", + "src": "7396:44:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1829, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1824, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "7450:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 1827, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7496:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 1825, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "7472:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1826, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "7472:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1828, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7472:26:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7450:48:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1830, + "nodeType": "ExpressionStatement", + "src": "7450:48:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1832, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1768, + "src": "7526:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1831, + "name": "MemberParted", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1188, + "src": "7513:12:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 1833, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7513:20:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1834, + "nodeType": "EmitStatement", + "src": "7508:25:4" + } + ] + }, + "documentation": null, + "functionSelector": "4e40ea64", + "id": 1836, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "partMember", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1769, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1768, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1836, + "src": "7013:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1767, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "7013:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "7012:16:4" + }, + "returnParameters": { + "id": 1770, + "nodeType": "ParameterList", + "parameters": [], + "src": "7036:0:4" + }, + "scope": 2432, + "src": "6993:547:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1863, + "nodeType": "Block", + "src": "7625:107:4", + "statements": [ + { + "body": { + "id": 1861, + "nodeType": "Block", + "src": "7680:46:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1856, + "name": "members", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1839, + "src": "7704:7:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_payable_$dyn_memory_ptr", + "typeString": "address payable[] memory" + } + }, + "id": 1858, + "indexExpression": { + "argumentTypes": null, + "id": 1857, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1845, + "src": "7712:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7704:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "id": 1855, + "name": "addMember", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1766, + "src": "7694:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_payable_$returns$__$", + "typeString": "function (address payable)" + } + }, + "id": 1859, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7694:21:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1860, + "nodeType": "ExpressionStatement", + "src": "7694:21:4" + } + ] + }, + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1851, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1848, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1845, + "src": "7655:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "<", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1849, + "name": "members", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1839, + "src": "7659:7:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_payable_$dyn_memory_ptr", + "typeString": "address payable[] memory" + } + }, + "id": 1850, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "length", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7659:14:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7655:18:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 1862, + "initializationExpression": { + "assignments": [ + 1845 + ], + "declarations": [ + { + "constant": false, + "id": 1845, + "mutability": "mutable", + "name": "i", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1862, + "src": "7640:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1844, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "7640:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1847, + "initialValue": { + "argumentTypes": null, + "hexValue": "30", + "id": 1846, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7652:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "nodeType": "VariableDeclarationStatement", + "src": "7640:13:4" + }, + "loopExpression": { + "expression": { + "argumentTypes": null, + "id": 1853, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "++", + "prefix": false, + "src": "7675:3:4", + "subExpression": { + "argumentTypes": null, + "id": 1852, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1845, + "src": "7675:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1854, + "nodeType": "ExpressionStatement", + "src": "7675:3:4" + }, + "nodeType": "ForStatement", + "src": "7635:91:4" + } + ] + }, + "documentation": null, + "functionSelector": "6f4d469b", + "id": 1864, + "implemented": true, + "kind": "function", + "modifiers": [ + { + "arguments": null, + "id": 1842, + "modifierName": { + "argumentTypes": null, + "id": 1841, + "name": "onlyJoinPartAgent", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1288, + "src": "7607:17:4", + "typeDescriptions": { + "typeIdentifier": "t_modifier$__$", + "typeString": "modifier ()" + } + }, + "nodeType": "ModifierInvocation", + "src": "7607:17:4" + } + ], + "name": "addMembers", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1840, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1839, + "mutability": "mutable", + "name": "members", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1864, + "src": "7566:32:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_payable_$dyn_memory_ptr", + "typeString": "address payable[]" + }, + "typeName": { + "baseType": { + "id": 1837, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "7566:15:4", + "stateMutability": "payable", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "id": 1838, + "length": null, + "nodeType": "ArrayTypeName", + "src": "7566:17:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_payable_$dyn_storage_ptr", + "typeString": "address payable[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "7565:34:4" + }, + "returnParameters": { + "id": 1843, + "nodeType": "ParameterList", + "parameters": [], + "src": "7625:0:4" + }, + "scope": 2432, + "src": "7546:186:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1889, + "nodeType": "Block", + "src": "7827:108:4", + "statements": [ + { + "body": { + "id": 1887, + "nodeType": "Block", + "src": "7882:47:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1882, + "name": "members", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1867, + "src": "7907:7:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + "id": 1884, + "indexExpression": { + "argumentTypes": null, + "id": 1883, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1871, + "src": "7915:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "7907:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 1881, + "name": "partMember", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1836, + "src": "7896:10:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$returns$__$", + "typeString": "function (address)" + } + }, + "id": 1885, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "7896:22:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1886, + "nodeType": "ExpressionStatement", + "src": "7896:22:4" + } + ] + }, + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1877, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 1874, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1871, + "src": "7857:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "<", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1875, + "name": "members", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1867, + "src": "7861:7:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + "id": 1876, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "length", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "7861:14:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "7857:18:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 1888, + "initializationExpression": { + "assignments": [ + 1871 + ], + "declarations": [ + { + "constant": false, + "id": 1871, + "mutability": "mutable", + "name": "i", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1888, + "src": "7842:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1870, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "7842:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1873, + "initialValue": { + "argumentTypes": null, + "hexValue": "30", + "id": 1872, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "7854:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "nodeType": "VariableDeclarationStatement", + "src": "7842:13:4" + }, + "loopExpression": { + "expression": { + "argumentTypes": null, + "id": 1879, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "++", + "prefix": false, + "src": "7877:3:4", + "subExpression": { + "argumentTypes": null, + "id": 1878, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1871, + "src": "7877:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1880, + "nodeType": "ExpressionStatement", + "src": "7877:3:4" + }, + "nodeType": "ForStatement", + "src": "7837:92:4" + } + ] + }, + "documentation": null, + "functionSelector": "7b30ed43", + "id": 1890, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "partMembers", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1868, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1867, + "mutability": "mutable", + "name": "members", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1890, + "src": "7794:24:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 1865, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "7794:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 1866, + "length": null, + "nodeType": "ArrayTypeName", + "src": "7794:9:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "7793:26:4" + }, + "returnParameters": { + "id": 1869, + "nodeType": "ParameterList", + "parameters": [], + "src": "7827:0:4" + }, + "scope": 2432, + "src": "7773:162:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 1961, + "nodeType": "Block", + "src": "8119:455:4", + "statements": [ + { + "assignments": [ + 1899 + ], + "declarations": [ + { + "constant": false, + "id": 1899, + "mutability": "mutable", + "name": "bal_before", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1961, + "src": "8129:15:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1898, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "8129:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1907, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1904, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "8171:4:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + ], + "id": 1903, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "8163:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1902, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "8163:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1905, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8163:13:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "expression": { + "argumentTypes": null, + "id": 1900, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "8147:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 1901, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balanceOf", + "nodeType": "MemberAccess", + "referencedDeclaration": 4221, + "src": "8147:15:4", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view external returns (uint256)" + } + }, + "id": 1906, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8147:30:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "8129:48:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1911, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "8214:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1912, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "8214:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1915, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "8234:4:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + ], + "id": 1914, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "8226:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1913, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "8226:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1916, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8226:13:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 1917, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1895, + "src": "8241:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1909, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "8195:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 1910, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "transferFrom", + "nodeType": "MemberAccess", + "referencedDeclaration": 4263, + "src": "8195:18:4", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$_t_bool_$", + "typeString": "function (address,address,uint256) external returns (bool)" + } + }, + "id": 1918, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8195:53:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f7472616e73666572", + "id": 1919, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "8250:16:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + }, + "value": "error_transfer" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + } + ], + "id": 1908, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "8187:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1920, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8187:80:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1921, + "nodeType": "ExpressionStatement", + "src": "8187:80:4" + }, + { + "assignments": [ + 1923 + ], + "declarations": [ + { + "constant": false, + "id": 1923, + "mutability": "mutable", + "name": "bal_after", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1961, + "src": "8277:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1922, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "8277:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1931, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1928, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "8318:4:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + ], + "id": 1927, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "8310:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 1926, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "8310:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 1929, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8310:13:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "expression": { + "argumentTypes": null, + "id": 1924, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "8294:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 1925, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "balanceOf", + "nodeType": "MemberAccess", + "referencedDeclaration": 4221, + "src": "8294:15:4", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view external returns (uint256)" + } + }, + "id": 1930, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8294:30:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "8277:47:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1938, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1935, + "name": "bal_before", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1899, + "src": "8356:10:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1933, + "name": "bal_after", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1923, + "src": "8342:9:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1934, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sub", + "nodeType": "MemberAccess", + "referencedDeclaration": 3491, + "src": "8342:13:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1936, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8342:25:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": ">=", + "rightExpression": { + "argumentTypes": null, + "id": 1937, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1895, + "src": "8371:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "8342:35:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f7472616e73666572", + "id": 1939, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "8379:16:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + }, + "value": "error_transfer" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + } + ], + "id": 1932, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "8334:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1940, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8334:62:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1941, + "nodeType": "ExpressionStatement", + "src": "8334:62:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1943, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1893, + "src": "8424:9:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1944, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1895, + "src": "8435:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1942, + "name": "_increaseBalance", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2056, + "src": "8407:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256)" + } + }, + "id": 1945, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8407:35:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1946, + "nodeType": "ExpressionStatement", + "src": "8407:35:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1952, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 1947, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1253, + "src": "8452:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1950, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1895, + "src": "8486:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 1948, + "name": "totalEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1253, + "src": "8468:13:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1949, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "8468:17:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1951, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8468:25:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "8452:41:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1953, + "nodeType": "ExpressionStatement", + "src": "8452:41:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1955, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "8536:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1956, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "8536:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 1957, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1893, + "src": "8548:9:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1958, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1895, + "src": "8560:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1954, + "name": "TransferToAddressInContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1228, + "src": "8508:27:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,address,uint256)" + } + }, + "id": 1959, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "8508:59:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1960, + "nodeType": "EmitStatement", + "src": "8503:64:4" + } + ] + }, + "documentation": { + "id": 1891, + "nodeType": "StructuredDocumentation", + "src": "7941:98:4", + "text": "Transfer tokens from outside contract, add to a recipient's in-contract balance" + }, + "functionSelector": "b274bcc7", + "id": 1962, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "transferToMemberInContract", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1896, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1893, + "mutability": "mutable", + "name": "recipient", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1962, + "src": "8080:17:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1892, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "8080:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1895, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 1962, + "src": "8099:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1894, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "8099:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "8079:32:4" + }, + "returnParameters": { + "id": 1897, + "nodeType": "ParameterList", + "parameters": [], + "src": "8119:0:4" + }, + "scope": 2432, + "src": "8044:530:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2009, + "nodeType": "Block", + "src": "9083:399:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 1976, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1972, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "9125:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1973, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "9125:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "id": 1971, + "name": "getWithdrawableEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1494, + "src": "9101:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 1974, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9101:35:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": ">=", + "rightExpression": { + "argumentTypes": null, + "id": 1975, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1967, + "src": "9140:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "9101:45:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f696e73756666696369656e7442616c616e6365", + "id": 1977, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "9148:27:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_74799d65376d943bac023262731d6421d2e6b6332748a55385eb85a0683327fc", + "typeString": "literal_string \"error_insufficientBalance\"" + }, + "value": "error_insufficientBalance" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_74799d65376d943bac023262731d6421d2e6b6332748a55385eb85a0683327fc", + "typeString": "literal_string \"error_insufficientBalance\"" + } + ], + "id": 1970, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "9093:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 1978, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9093:83:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 1979, + "nodeType": "ExpressionStatement", + "src": "9093:83:4" + }, + { + "assignments": [ + 1981 + ], + "declarations": [ + { + "constant": false, + "id": 1981, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2009, + "src": "9245:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 1980, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "9245:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 1986, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 1982, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "9271:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 1985, + "indexExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1983, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "9282:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 1984, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "9282:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "9271:22:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "9245:48:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 1995, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1987, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1981, + "src": "9303:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1989, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "withdrawnEarnings", + "nodeType": "MemberAccess", + "referencedDeclaration": 1244, + "src": "9303:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1993, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1967, + "src": "9355:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 1990, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1981, + "src": "9328:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 1991, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "withdrawnEarnings", + "nodeType": "MemberAccess", + "referencedDeclaration": 1244, + "src": "9328:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1992, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "9328:26:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 1994, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9328:34:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "9303:59:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 1996, + "nodeType": "ExpressionStatement", + "src": "9303:59:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 1998, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1965, + "src": "9389:9:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 1999, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1967, + "src": "9400:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 1997, + "name": "_increaseBalance", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2056, + "src": "9372:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256)" + } + }, + "id": 2000, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9372:35:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2001, + "nodeType": "ExpressionStatement", + "src": "9372:35:4" + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2003, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "9445:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 2004, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "9445:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 2005, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1965, + "src": "9457:9:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2006, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1967, + "src": "9468:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 2002, + "name": "TransferWithinContract", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1220, + "src": "9422:22:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,address,uint256)" + } + }, + "id": 2007, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9422:53:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2008, + "nodeType": "EmitStatement", + "src": "9417:58:4" + } + ] + }, + "documentation": { + "id": 1963, + "nodeType": "StructuredDocumentation", + "src": "8580:427:4", + "text": "Transfer tokens from sender's in-contract balance to recipient's in-contract balance\nThis is done by \"withdrawing\" sender's earnings and crediting them to recipient's unwithdrawn earnings,\n so withdrawnEarnings never decreases for anyone (within this function)\n@param recipient whose withdrawable earnings will increase\n@param amount how much withdrawable earnings is transferred" + }, + "functionSelector": "71cdfd68", + "id": 2010, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "transferWithinContract", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 1968, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 1965, + "mutability": "mutable", + "name": "recipient", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2010, + "src": "9044:17:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 1964, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "9044:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 1967, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2010, + "src": "9063:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 1966, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "9063:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "9043:32:4" + }, + "returnParameters": { + "id": 1969, + "nodeType": "ParameterList", + "parameters": [], + "src": "9083:0:4" + }, + "scope": 2432, + "src": "9012:470:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2055, + "nodeType": "Block", + "src": "9642:359:4", + "statements": [ + { + "assignments": [ + 2019 + ], + "declarations": [ + { + "constant": false, + "id": 2019, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2055, + "src": "9652:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 2018, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "9652:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2023, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 2020, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "9678:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 2022, + "indexExpression": { + "argumentTypes": null, + "id": 2021, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2013, + "src": "9689:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "9678:18:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "9652:44:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 2032, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2024, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2019, + "src": "9706:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 2026, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "earningsBeforeLastJoin", + "nodeType": "MemberAccess", + "referencedDeclaration": 1240, + "src": "9706:27:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2030, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2015, + "src": "9768:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2027, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2019, + "src": "9736:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 2028, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "earningsBeforeLastJoin", + "nodeType": "MemberAccess", + "referencedDeclaration": 1240, + "src": "9736:27:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2029, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "9736:31:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 2031, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9736:39:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "9706:69:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2033, + "nodeType": "ExpressionStatement", + "src": "9706:69:4" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + }, + "id": 2038, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2034, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2019, + "src": "9839:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 2035, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "9839:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2036, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "9854:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 2037, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "None", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "9854:17:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "9839:32:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 2054, + "nodeType": "IfStatement", + "src": "9835:160:4", + "trueBody": { + "id": 2053, + "nodeType": "Block", + "src": "9873:122:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 2044, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2039, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2019, + "src": "9887:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 2041, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "status", + "nodeType": "MemberAccess", + "referencedDeclaration": 1238, + "src": "9887:11:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2042, + "name": "ActiveStatus", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1180, + "src": "9901:12:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_enum$_ActiveStatus_$1180_$", + "typeString": "type(enum DataUnionSidechain.ActiveStatus)" + } + }, + "id": 2043, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "Inactive", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "9901:21:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "src": "9887:35:4", + "typeDescriptions": { + "typeIdentifier": "t_enum$_ActiveStatus_$1180", + "typeString": "enum DataUnionSidechain.ActiveStatus" + } + }, + "id": 2045, + "nodeType": "ExpressionStatement", + "src": "9887:35:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 2051, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 2046, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "9936:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "31", + "id": 2049, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "9982:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + }, + "value": "1" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_1_by_1", + "typeString": "int_const 1" + } + ], + "expression": { + "argumentTypes": null, + "id": 2047, + "name": "inactiveMemberCount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1259, + "src": "9958:19:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2048, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "9958:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 2050, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "9958:26:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "9936:48:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2052, + "nodeType": "ExpressionStatement", + "src": "9936:48:4" + } + ] + } + } + ] + }, + "documentation": { + "id": 2011, + "nodeType": "StructuredDocumentation", + "src": "9488:85:4", + "text": "Hack to add to single member's balance without affecting lmeAtJoin" + }, + "id": 2056, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "_increaseBalance", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2016, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2013, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2056, + "src": "9604:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2012, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "9604:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2015, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2056, + "src": "9620:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2014, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "9620:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "9603:29:4" + }, + "returnParameters": { + "id": 2017, + "nodeType": "ParameterList", + "parameters": [], + "src": "9642:0:4" + }, + "scope": 2432, + "src": "9578:423:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "internal" + }, + { + "body": { + "id": 2097, + "nodeType": "Block", + "src": "10123:208:4", + "statements": [ + { + "assignments": [ + 2067 + ], + "declarations": [ + { + "constant": false, + "id": 2067, + "mutability": "mutable", + "name": "withdrawn", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2097, + "src": "10133:17:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2066, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "10133:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2069, + "initialValue": { + "argumentTypes": null, + "hexValue": "30", + "id": 2068, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "10153:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "nodeType": "VariableDeclarationStatement", + "src": "10133:21:4" + }, + { + "body": { + "id": 2093, + "nodeType": "Block", + "src": "10209:90:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 2091, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 2081, + "name": "withdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2067, + "src": "10223:9:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 2085, + "name": "members", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2059, + "src": "10261:7:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + "id": 2087, + "indexExpression": { + "argumentTypes": null, + "id": 2086, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2071, + "src": "10269:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "10261:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2088, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2061, + "src": "10273:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2084, + "name": "withdrawAll", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2116, + "src": "10249:11:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,bool) returns (uint256)" + } + }, + "id": 2089, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10249:38:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 2082, + "name": "withdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2067, + "src": "10235:9:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2083, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "10235:13:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 2090, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10235:53:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "10223:65:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2092, + "nodeType": "ExpressionStatement", + "src": "10223:65:4" + } + ] + }, + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 2077, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2074, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2071, + "src": "10184:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "<", + "rightExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2075, + "name": "members", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2059, + "src": "10188:7:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[] memory" + } + }, + "id": 2076, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "length", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "10188:14:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "10184:18:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 2094, + "initializationExpression": { + "assignments": [ + 2071 + ], + "declarations": [ + { + "constant": false, + "id": 2071, + "mutability": "mutable", + "name": "i", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2094, + "src": "10169:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2070, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "10169:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2073, + "initialValue": { + "argumentTypes": null, + "hexValue": "30", + "id": 2072, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "10181:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "nodeType": "VariableDeclarationStatement", + "src": "10169:13:4" + }, + "loopExpression": { + "expression": { + "argumentTypes": null, + "id": 2079, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "++", + "prefix": false, + "src": "10204:3:4", + "subExpression": { + "argumentTypes": null, + "id": 2078, + "name": "i", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2071, + "src": "10204:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2080, + "nodeType": "ExpressionStatement", + "src": "10204:3:4" + }, + "nodeType": "ForStatement", + "src": "10164:135:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 2095, + "name": "withdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2067, + "src": "10315:9:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2065, + "id": 2096, + "nodeType": "Return", + "src": "10308:16:4" + } + ] + }, + "documentation": null, + "functionSelector": "a4d6ddc0", + "id": 2098, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawMembers", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2062, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2059, + "mutability": "mutable", + "name": "members", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2098, + "src": "10032:24:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_memory_ptr", + "typeString": "address[]" + }, + "typeName": { + "baseType": { + "id": 2057, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "10032:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 2058, + "length": null, + "nodeType": "ArrayTypeName", + "src": "10032:9:4", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_address_$dyn_storage_ptr", + "typeString": "address[]" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2061, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2098, + "src": "10058:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2060, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "10058:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10031:46:4" + }, + "returnParameters": { + "id": 2065, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2064, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2098, + "src": "10110:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2063, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "10110:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10109:9:4" + }, + "scope": 2432, + "src": "10007:324:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2115, + "nodeType": "Block", + "src": "10439:88:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2108, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2100, + "src": "10465:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2110, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2100, + "src": "10497:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 2109, + "name": "getWithdrawableEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1494, + "src": "10473:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 2111, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10473:31:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2112, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2102, + "src": "10506:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2107, + "name": "withdraw", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2148, + "src": "10456:8:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_uint256_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,uint256,bool) returns (uint256)" + } + }, + "id": 2113, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10456:64:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2106, + "id": 2114, + "nodeType": "Return", + "src": "10449:71:4" + } + ] + }, + "documentation": null, + "functionSelector": "4bee9137", + "id": 2116, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawAll", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2103, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2100, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2116, + "src": "10358:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2099, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "10358:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2102, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2116, + "src": "10374:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2101, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "10374:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10357:36:4" + }, + "returnParameters": { + "id": 2106, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2105, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2116, + "src": "10426:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2104, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "10426:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10425:9:4" + }, + "scope": 2432, + "src": "10337:190:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2147, + "nodeType": "Block", + "src": "10645:156:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 2136, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 2131, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2128, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "10663:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 2129, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "10663:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 2130, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2118, + "src": "10677:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "10663:20:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "||", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 2135, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2132, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "10687:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 2133, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "10687:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 2134, + "name": "owner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3105, + "src": "10701:5:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "10687:19:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "10663:43:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6e6f745065726d6974746564", + "id": 2137, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "10708:20:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_81fcea6533090d67b5d2d1910c87832a3a952f4bfc10eedbdaba5b028593bde1", + "typeString": "literal_string \"error_notPermitted\"" + }, + "value": "error_notPermitted" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_81fcea6533090d67b5d2d1910c87832a3a952f4bfc10eedbdaba5b028593bde1", + "typeString": "literal_string \"error_notPermitted\"" + } + ], + "id": 2127, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "10655:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2138, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10655:74:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2139, + "nodeType": "ExpressionStatement", + "src": "10655:74:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2141, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2118, + "src": "10756:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2142, + "name": "member", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2118, + "src": "10764:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2143, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2120, + "src": "10772:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2144, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2122, + "src": "10780:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2140, + "name": "_withdraw", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2431, + "src": "10746:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_address_$_t_uint256_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,address,uint256,bool) returns (uint256)" + } + }, + "id": 2145, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10746:48:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2126, + "id": 2146, + "nodeType": "Return", + "src": "10739:55:4" + } + ] + }, + "documentation": null, + "functionSelector": "ead5d359", + "id": 2148, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdraw", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2123, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2118, + "mutability": "mutable", + "name": "member", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2148, + "src": "10551:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2117, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "10551:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2120, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2148, + "src": "10567:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2119, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "10567:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2122, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2148, + "src": "10580:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2121, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "10580:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10550:49:4" + }, + "returnParameters": { + "id": 2126, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2125, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2148, + "src": "10632:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2124, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "10632:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10631:9:4" + }, + "scope": 2432, + "src": "10533:268:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2166, + "nodeType": "Block", + "src": "10907:90:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2158, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2150, + "src": "10935:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2160, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "10963:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 2161, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "10963:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + ], + "id": 2159, + "name": "getWithdrawableEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1494, + "src": "10939:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 2162, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10939:35:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2163, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2152, + "src": "10976:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2157, + "name": "withdrawTo", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2187, + "src": "10924:10:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_uint256_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,uint256,bool) returns (uint256)" + } + }, + "id": 2164, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "10924:66:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2156, + "id": 2165, + "nodeType": "Return", + "src": "10917:73:4" + } + ] + }, + "documentation": null, + "functionSelector": "2b94411f", + "id": 2167, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawAllTo", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2153, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2150, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2167, + "src": "10830:10:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2149, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "10830:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2152, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2167, + "src": "10842:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2151, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "10842:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10829:32:4" + }, + "returnParameters": { + "id": 2156, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2155, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2167, + "src": "10894:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2154, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "10894:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "10893:9:4" + }, + "scope": 2432, + "src": "10807:190:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2186, + "nodeType": "Block", + "src": "11113:72:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2179, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "11140:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 2180, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "sender", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "11140:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "id": 2181, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2169, + "src": "11152:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2182, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2171, + "src": "11156:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2183, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2173, + "src": "11164:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2178, + "name": "_withdraw", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2431, + "src": "11130:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_address_$_t_uint256_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,address,uint256,bool) returns (uint256)" + } + }, + "id": 2184, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "11130:48:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2177, + "id": 2185, + "nodeType": "Return", + "src": "11123:55:4" + } + ] + }, + "documentation": null, + "functionSelector": "73e2290c", + "id": 2187, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawTo", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2174, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2169, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2187, + "src": "11023:10:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2168, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "11023:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2171, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2187, + "src": "11035:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2170, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "11035:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2173, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2187, + "src": "11048:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2172, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "11048:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "11022:45:4" + }, + "returnParameters": { + "id": 2177, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2176, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2187, + "src": "11100:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2175, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "11100:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "11099:9:4" + }, + "scope": 2432, + "src": "11003:182:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2270, + "nodeType": "Block", + "src": "12594:831:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 2205, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2202, + "name": "signature", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2196, + "src": "12612:9:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + "id": 2203, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "length", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "12612:16:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "3635", + "id": 2204, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "12632:2:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_65_by_1", + "typeString": "int_const 65" + }, + "value": "65" + }, + "src": "12612:22:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6261645369676e61747572654c656e677468", + "id": 2206, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "12636:26:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_4077da77d01843e066cb3ce202dcb5c333f11623972b2a584316e75b72c622e0", + "typeString": "literal_string \"error_badSignatureLength\"" + }, + "value": "error_badSignatureLength" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_4077da77d01843e066cb3ce202dcb5c333f11623972b2a584316e75b72c622e0", + "typeString": "literal_string \"error_badSignatureLength\"" + } + ], + "id": 2201, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "12604:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2207, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "12604:59:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2208, + "nodeType": "ExpressionStatement", + "src": "12604:59:4" + }, + { + "assignments": [ + 2210 + ], + "declarations": [ + { + "constant": false, + "id": 2210, + "mutability": "mutable", + "name": "r", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2270, + "src": "12674:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 2209, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "12674:7:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2211, + "initialValue": null, + "nodeType": "VariableDeclarationStatement", + "src": "12674:9:4" + }, + { + "assignments": [ + 2213 + ], + "declarations": [ + { + "constant": false, + "id": 2213, + "mutability": "mutable", + "name": "s", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2270, + "src": "12685:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 2212, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "12685:7:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2214, + "initialValue": null, + "nodeType": "VariableDeclarationStatement", + "src": "12685:9:4" + }, + { + "assignments": [ + 2216 + ], + "declarations": [ + { + "constant": false, + "id": 2216, + "mutability": "mutable", + "name": "v", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2270, + "src": "12696:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "typeName": { + "id": 2215, + "name": "uint8", + "nodeType": "ElementaryTypeName", + "src": "12696:5:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2217, + "initialValue": null, + "nodeType": "VariableDeclarationStatement", + "src": "12696:7:4" + }, + { + "AST": { + "nodeType": "YulBlock", + "src": "12722:205:4", + "statements": [ + { + "nodeType": "YulAssignment", + "src": "12792:30:4", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "signature", + "nodeType": "YulIdentifier", + "src": "12807:9:4" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "12818:2:4", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "12803:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "12803:18:4" + } + ], + "functionName": { + "name": "mload", + "nodeType": "YulIdentifier", + "src": "12797:5:4" + }, + "nodeType": "YulFunctionCall", + "src": "12797:25:4" + }, + "variableNames": [ + { + "name": "r", + "nodeType": "YulIdentifier", + "src": "12792:1:4" + } + ] + }, + { + "nodeType": "YulAssignment", + "src": "12835:30:4", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "signature", + "nodeType": "YulIdentifier", + "src": "12850:9:4" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "12861:2:4", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "12846:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "12846:18:4" + } + ], + "functionName": { + "name": "mload", + "nodeType": "YulIdentifier", + "src": "12840:5:4" + }, + "nodeType": "YulFunctionCall", + "src": "12840:25:4" + }, + "variableNames": [ + { + "name": "s", + "nodeType": "YulIdentifier", + "src": "12835:1:4" + } + ] + }, + { + "nodeType": "YulAssignment", + "src": "12878:39:4", + "value": { + "arguments": [ + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "12888:1:4", + "type": "", + "value": "0" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "signature", + "nodeType": "YulIdentifier", + "src": "12901:9:4" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "12912:2:4", + "type": "", + "value": "96" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "12897:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "12897:18:4" + } + ], + "functionName": { + "name": "mload", + "nodeType": "YulIdentifier", + "src": "12891:5:4" + }, + "nodeType": "YulFunctionCall", + "src": "12891:25:4" + } + ], + "functionName": { + "name": "byte", + "nodeType": "YulIdentifier", + "src": "12883:4:4" + }, + "nodeType": "YulFunctionCall", + "src": "12883:34:4" + }, + "variableNames": [ + { + "name": "v", + "nodeType": "YulIdentifier", + "src": "12878:1:4" + } + ] + } + ] + }, + "evmVersion": "istanbul", + "externalReferences": [ + { + "declaration": 2210, + "isOffset": false, + "isSlot": false, + "src": "12792:1:4", + "valueSize": 1 + }, + { + "declaration": 2213, + "isOffset": false, + "isSlot": false, + "src": "12835:1:4", + "valueSize": 1 + }, + { + "declaration": 2196, + "isOffset": false, + "isSlot": false, + "src": "12807:9:4", + "valueSize": 1 + }, + { + "declaration": 2196, + "isOffset": false, + "isSlot": false, + "src": "12850:9:4", + "valueSize": 1 + }, + { + "declaration": 2196, + "isOffset": false, + "isSlot": false, + "src": "12901:9:4", + "valueSize": 1 + }, + { + "declaration": 2216, + "isOffset": false, + "isSlot": false, + "src": "12878:1:4", + "valueSize": 1 + } + ], + "id": 2218, + "nodeType": "InlineAssembly", + "src": "12713:214:4" + }, + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "id": 2221, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2219, + "name": "v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2216, + "src": "12940:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "nodeType": "BinaryOperation", + "operator": "<", + "rightExpression": { + "argumentTypes": null, + "hexValue": "3237", + "id": 2220, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "12944:2:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_27_by_1", + "typeString": "int_const 27" + }, + "value": "27" + }, + "src": "12940:6:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 2227, + "nodeType": "IfStatement", + "src": "12936:44:4", + "trueBody": { + "id": 2226, + "nodeType": "Block", + "src": "12948:32:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "id": 2224, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 2222, + "name": "v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2216, + "src": "12962:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "nodeType": "Assignment", + "operator": "+=", + "rightHandSide": { + "argumentTypes": null, + "hexValue": "3237", + "id": 2223, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "12967:2:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_27_by_1", + "typeString": "int_const 27" + }, + "value": "27" + }, + "src": "12962:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "id": 2225, + "nodeType": "ExpressionStatement", + "src": "12962:7:4" + } + ] + } + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "id": 2235, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "id": 2231, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2229, + "name": "v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2216, + "src": "12997:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "3237", + "id": 2230, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "13002:2:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_27_by_1", + "typeString": "int_const 27" + }, + "value": "27" + }, + "src": "12997:7:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "nodeType": "BinaryOperation", + "operator": "||", + "rightExpression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "id": 2234, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2232, + "name": "v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2216, + "src": "13008:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "3238", + "id": 2233, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "13013:2:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_28_by_1", + "typeString": "int_const 28" + }, + "value": "28" + }, + "src": "13008:7:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "src": "12997:18:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6261645369676e617475726556657273696f6e", + "id": 2236, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "13017:27:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_8fa0eae5d18986979b1a6399b1aa7a4d8b3c5537b79b5808266bd780a9c464db", + "typeString": "literal_string \"error_badSignatureVersion\"" + }, + "value": "error_badSignatureVersion" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_8fa0eae5d18986979b1a6399b1aa7a4d8b3c5537b79b5808266bd780a9c464db", + "typeString": "literal_string \"error_badSignatureVersion\"" + } + ], + "id": 2228, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "12989:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2237, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "12989:56:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2238, + "nodeType": "ExpressionStatement", + "src": "12989:56:4" + }, + { + "assignments": [ + 2240 + ], + "declarations": [ + { + "constant": false, + "id": 2240, + "mutability": "mutable", + "name": "messageHash", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2270, + "src": "13151:19:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 2239, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "13151:7:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2256, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "hexValue": "19457468657265756d205369676e6564204d6573736167653a0a313034", + "id": 2244, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "13213:35:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_8d960065d1d57999e7234857e6a0652c524bb2aeb2c4d7c6b962ce1fe99d1ca0", + "typeString": "literal_string \"\u0019Ethereum Signed Message:\n104\"" + }, + "value": "\u0019Ethereum Signed Message:\n104" + }, + { + "argumentTypes": null, + "id": 2245, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2192, + "src": "13250:9:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2246, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2194, + "src": "13261:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2249, + "name": "this", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -28, + "src": "13277:4:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_contract$_DataUnionSidechain_$2432", + "typeString": "contract DataUnionSidechain" + } + ], + "id": 2248, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "13269:7:4", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 2247, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "13269:7:4", + "typeDescriptions": { + "typeIdentifier": null, + "typeString": null + } + } + }, + "id": 2250, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "13269:13:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2252, + "name": "signer", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2190, + "src": "13297:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 2251, + "name": "getWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1477, + "src": "13284:12:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 2253, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "13284:20:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_8d960065d1d57999e7234857e6a0652c524bb2aeb2c4d7c6b962ce1fe99d1ca0", + "typeString": "literal_string \"\u0019Ethereum Signed Message:\n104\"" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_address_payable", + "typeString": "address payable" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 2242, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "13183:3:4", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 2243, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberName": "encodePacked", + "nodeType": "MemberAccess", + "referencedDeclaration": null, + "src": "13183:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodepacked_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 2254, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "13183:122:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 2241, + "name": "keccak256", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -8, + "src": "13173:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", + "typeString": "function (bytes memory) pure returns (bytes32)" + } + }, + "id": 2255, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "13173:133:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "13151:155:4" + }, + { + "assignments": [ + 2258 + ], + "declarations": [ + { + "constant": false, + "id": 2258, + "mutability": "mutable", + "name": "calculatedSigner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2270, + "src": "13316:24:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2257, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "13316:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2265, + "initialValue": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2260, + "name": "messageHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2240, + "src": "13353:11:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + { + "argumentTypes": null, + "id": 2261, + "name": "v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2216, + "src": "13366:1:4", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + { + "argumentTypes": null, + "id": 2262, + "name": "r", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2210, + "src": "13369:1:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + { + "argumentTypes": null, + "id": 2263, + "name": "s", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2213, + "src": "13372:1:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "id": 2259, + "name": "ecrecover", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -6, + "src": "13343:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_ecrecover_pure$_t_bytes32_$_t_uint8_$_t_bytes32_$_t_bytes32_$returns$_t_address_$", + "typeString": "function (bytes32,uint8,bytes32,bytes32) pure returns (address)" + } + }, + "id": 2264, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "13343:31:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "13316:58:4" + }, + { + "expression": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 2268, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2266, + "name": "calculatedSigner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2258, + "src": "13392:16:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "id": 2267, + "name": "signer", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2190, + "src": "13412:6:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "13392:26:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "functionReturnParameters": 2200, + "id": 2269, + "nodeType": "Return", + "src": "13385:33:4" + } + ] + }, + "documentation": { + "id": 2188, + "nodeType": "StructuredDocumentation", + "src": "11191:1207:4", + "text": "Check signature from a member authorizing withdrawing its earnings to another account.\nThrows if the signature is badly formatted or doesn't match the given signer and amount.\nSignature has parts the act as replay protection:\n1) `address(this)`: signature can't be used for other contracts;\n2) `withdrawn[signer]`: signature only works once (for unspecified amount), and can be \"cancelled\" by sending a withdraw tx.\nGenerated in Javascript with: `web3.eth.accounts.sign(recipientAddress + amount.toString(16, 64) + contractAddress.slice(2) + withdrawnTokens.toString(16, 64), signerPrivateKey)`,\nor for unlimited amount: `web3.eth.accounts.sign(recipientAddress + \"0\".repeat(64) + contractAddress.slice(2) + withdrawnTokens.toString(16, 64), signerPrivateKey)`.\n@param signer whose earnings are being withdrawn\n@param recipient of the tokens\n@param amount how much is authorized for withdraw, or zero for unlimited (withdrawAll)\n@param signature byte array from `web3.eth.accounts.sign`\n@return isValid true iff signer of the authorization (member whose earnings are going to be withdrawn) matches the signature" + }, + "functionSelector": "a2d3cf4b", + "id": 2271, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "signatureIsValid", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2197, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2190, + "mutability": "mutable", + "name": "signer", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2271, + "src": "12438:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2189, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "12438:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2192, + "mutability": "mutable", + "name": "recipient", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2271, + "src": "12462:17:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2191, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "12462:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2194, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2271, + "src": "12489:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2193, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "12489:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2196, + "mutability": "mutable", + "name": "signature", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2271, + "src": "12510:22:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 2195, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "12510:5:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "12428:110:4" + }, + "returnParameters": { + "id": 2200, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2199, + "mutability": "mutable", + "name": "isValid", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2271, + "src": "12576:12:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2198, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "12576:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "12575:14:4" + }, + "scope": 2432, + "src": "12403:1022:4", + "stateMutability": "view", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2304, + "nodeType": "Block", + "src": "14491:188:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2287, + "name": "fromSigner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2274, + "src": "14526:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2288, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2276, + "src": "14538:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "hexValue": "30", + "id": 2289, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "14542:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + { + "argumentTypes": null, + "id": 2290, + "name": "signature", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2280, + "src": "14545:9:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 2286, + "name": "signatureIsValid", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2271, + "src": "14509:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$_t_address_$_t_uint256_$_t_bytes_memory_ptr_$returns$_t_bool_$", + "typeString": "function (address,address,uint256,bytes memory) view returns (bool)" + } + }, + "id": 2291, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "14509:46:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6261645369676e6174757265", + "id": 2292, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "14557:20:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_2ec4ea0e2156213061c2a099c127d1a6548cdd3e5b4bf1f695ceebe1aeb9d2b2", + "typeString": "literal_string \"error_badSignature\"" + }, + "value": "error_badSignature" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_2ec4ea0e2156213061c2a099c127d1a6548cdd3e5b4bf1f695ceebe1aeb9d2b2", + "typeString": "literal_string \"error_badSignature\"" + } + ], + "id": 2285, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "14501:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2293, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "14501:77:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2294, + "nodeType": "ExpressionStatement", + "src": "14501:77:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2296, + "name": "fromSigner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2274, + "src": "14605:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2297, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2276, + "src": "14617:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2299, + "name": "fromSigner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2274, + "src": "14645:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 2298, + "name": "getWithdrawableEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1494, + "src": "14621:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 2300, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "14621:35:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2301, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2278, + "src": "14658:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2295, + "name": "_withdraw", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2431, + "src": "14595:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_address_$_t_uint256_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,address,uint256,bool) returns (uint256)" + } + }, + "id": 2302, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "14595:77:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2284, + "id": 2303, + "nodeType": "Return", + "src": "14588:84:4" + } + ] + }, + "documentation": { + "id": 2272, + "nodeType": "StructuredDocumentation", + "src": "13431:860:4", + "text": "Do an \"unlimited donate withdraw\" on behalf of someone else, to an address they've specified.\nSponsored withdraw is paid by admin, but target account could be whatever the member specifies.\nThe signature gives a \"blank cheque\" for admin to withdraw all tokens to `recipient` in the future,\n and it's valid until next withdraw (and so can be nullified by withdrawing any amount).\nA new signature needs to be obtained for each subsequent future withdraw.\n@param fromSigner whose earnings are being withdrawn\n@param to the address the tokens will be sent to (instead of `msg.sender`)\n@param sendToMainnet if the tokens should be sent to mainnet or only withdrawn into sidechain address\n@param signature from the member, see `signatureIsValid` how signature generated for unlimited amount" + }, + "functionSelector": "ce7b7864", + "id": 2305, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawAllToSigned", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2281, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2274, + "mutability": "mutable", + "name": "fromSigner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2305, + "src": "14334:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2273, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "14334:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2276, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2305, + "src": "14362:10:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2275, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "14362:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2278, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2305, + "src": "14382:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2277, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "14382:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2280, + "mutability": "mutable", + "name": "signature", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2305, + "src": "14410:22:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 2279, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "14410:5:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "14324:114:4" + }, + "returnParameters": { + "id": 2284, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2283, + "mutability": "mutable", + "name": "withdrawn", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2305, + "src": "14471:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2282, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "14471:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "14470:16:4" + }, + "scope": 2432, + "src": "14296:383:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2338, + "nodeType": "Block", + "src": "15628:164:4", + "statements": [ + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2323, + "name": "fromSigner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2308, + "src": "15663:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2324, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2310, + "src": "15675:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2325, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2312, + "src": "15679:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2326, + "name": "signature", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2316, + "src": "15687:9:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 2322, + "name": "signatureIsValid", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2271, + "src": "15646:16:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$_t_address_$_t_uint256_$_t_bytes_memory_ptr_$returns$_t_bool_$", + "typeString": "function (address,address,uint256,bytes memory) view returns (bool)" + } + }, + "id": 2327, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "15646:51:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f6261645369676e6174757265", + "id": 2328, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "15699:20:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_2ec4ea0e2156213061c2a099c127d1a6548cdd3e5b4bf1f695ceebe1aeb9d2b2", + "typeString": "literal_string \"error_badSignature\"" + }, + "value": "error_badSignature" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_2ec4ea0e2156213061c2a099c127d1a6548cdd3e5b4bf1f695ceebe1aeb9d2b2", + "typeString": "literal_string \"error_badSignature\"" + } + ], + "id": 2321, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "15638:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2329, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "15638:82:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2330, + "nodeType": "ExpressionStatement", + "src": "15638:82:4" + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2332, + "name": "fromSigner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2308, + "src": "15747:10:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2333, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2310, + "src": "15759:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2334, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2312, + "src": "15763:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "id": 2335, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2314, + "src": "15771:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "id": 2331, + "name": "_withdraw", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2431, + "src": "15737:9:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_address_$_t_uint256_$_t_bool_$returns$_t_uint256_$", + "typeString": "function (address,address,uint256,bool) returns (uint256)" + } + }, + "id": 2336, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "15737:48:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2320, + "id": 2337, + "nodeType": "Return", + "src": "15730:55:4" + } + ] + }, + "documentation": { + "id": 2306, + "nodeType": "StructuredDocumentation", + "src": "14685:725:4", + "text": "Do a \"donate withdraw\" on behalf of someone else, to an address they've specified.\nSponsored withdraw is paid by admin, but target account could be whatever the member specifies.\nThe signature is valid only for given amount of tokens that may be different from maximum withdrawable tokens.\n@param fromSigner whose earnings are being withdrawn\n@param to the address the tokens will be sent to (instead of `msg.sender`)\n@param amount of tokens to withdraw\n@param sendToMainnet if the tokens should be sent to mainnet or only withdrawn into sidechain address\n@param signature from the member, see `signatureIsValid` how signature generated for unlimited amount" + }, + "functionSelector": "1a79246c", + "id": 2339, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "withdrawToSigned", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2317, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2308, + "mutability": "mutable", + "name": "fromSigner", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2339, + "src": "15450:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2307, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "15450:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2310, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2339, + "src": "15478:10:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2309, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "15478:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2312, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2339, + "src": "15498:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2311, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "15498:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2314, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2339, + "src": "15519:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2313, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "15519:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2316, + "mutability": "mutable", + "name": "signature", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2339, + "src": "15547:22:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 2315, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "15547:5:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "15440:135:4" + }, + "returnParameters": { + "id": 2320, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2319, + "mutability": "mutable", + "name": "withdrawn", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2339, + "src": "15608:14:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2318, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "15608:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "15607:16:4" + }, + "scope": 2432, + "src": "15415:377:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2347, + "nodeType": "Block", + "src": "15863:324:4", + "statements": [ + { + "AST": { + "nodeType": "YulBlock", + "src": "15882:299:4", + "statements": [ + { + "nodeType": "YulVariableDeclaration", + "src": "15896:20:4", + "value": { + "arguments": [ + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "15911:4:4", + "type": "", + "value": "0x40" + } + ], + "functionName": { + "name": "mload", + "nodeType": "YulIdentifier", + "src": "15905:5:4" + }, + "nodeType": "YulFunctionCall", + "src": "15905:11:4" + }, + "variables": [ + { + "name": "m", + "nodeType": "YulTypedName", + "src": "15900:1:4", + "type": "" + } + ] + }, + { + "nodeType": "YulAssignment", + "src": "15929:55:4", + "value": { + "arguments": [ + { + "name": "a", + "nodeType": "YulIdentifier", + "src": "15938:1:4" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "15941:42:4", + "type": "", + "value": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + } + ], + "functionName": { + "name": "and", + "nodeType": "YulIdentifier", + "src": "15934:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "15934:50:4" + }, + "variableNames": [ + { + "name": "a", + "nodeType": "YulIdentifier", + "src": "15929:1:4" + } + ] + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "m", + "nodeType": "YulIdentifier", + "src": "16025:1:4" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "16028:2:4", + "type": "", + "value": "20" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "16021:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "16021:10:4" + }, + { + "arguments": [ + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "16053:44:4", + "type": "", + "value": "0x140000000000000000000000000000000000000000" + }, + { + "name": "a", + "nodeType": "YulIdentifier", + "src": "16099:1:4" + } + ], + "functionName": { + "name": "xor", + "nodeType": "YulIdentifier", + "src": "16049:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "16049:52:4" + } + ], + "functionName": { + "name": "mstore", + "nodeType": "YulIdentifier", + "src": "15997:6:4" + }, + "nodeType": "YulFunctionCall", + "src": "15997:118:4" + }, + "nodeType": "YulExpressionStatement", + "src": "15997:118:4" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "16135:4:4", + "type": "", + "value": "0x40" + }, + { + "arguments": [ + { + "name": "m", + "nodeType": "YulIdentifier", + "src": "16145:1:4" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "16148:2:4", + "type": "", + "value": "52" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "16141:3:4" + }, + "nodeType": "YulFunctionCall", + "src": "16141:10:4" + } + ], + "functionName": { + "name": "mstore", + "nodeType": "YulIdentifier", + "src": "16128:6:4" + }, + "nodeType": "YulFunctionCall", + "src": "16128:24:4" + }, + "nodeType": "YulExpressionStatement", + "src": "16128:24:4" + }, + { + "nodeType": "YulAssignment", + "src": "16165:6:4", + "value": { + "name": "m", + "nodeType": "YulIdentifier", + "src": "16170:1:4" + }, + "variableNames": [ + { + "name": "b", + "nodeType": "YulIdentifier", + "src": "16165:1:4" + } + ] + } + ] + }, + "evmVersion": "istanbul", + "externalReferences": [ + { + "declaration": 2341, + "isOffset": false, + "isSlot": false, + "src": "15929:1:4", + "valueSize": 1 + }, + { + "declaration": 2341, + "isOffset": false, + "isSlot": false, + "src": "15938:1:4", + "valueSize": 1 + }, + { + "declaration": 2341, + "isOffset": false, + "isSlot": false, + "src": "16099:1:4", + "valueSize": 1 + }, + { + "declaration": 2344, + "isOffset": false, + "isSlot": false, + "src": "16165:1:4", + "valueSize": 1 + } + ], + "id": 2346, + "nodeType": "InlineAssembly", + "src": "15873:308:4" + } + ] + }, + "documentation": null, + "functionSelector": "593b79fe", + "id": 2348, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "toBytes", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2342, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2341, + "mutability": "mutable", + "name": "a", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2348, + "src": "15815:9:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2340, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "15815:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "15814:11:4" + }, + "returnParameters": { + "id": 2345, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2344, + "mutability": "mutable", + "name": "b", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2348, + "src": "15847:14:4", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 2343, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "15847:5:4", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "15846:16:4" + }, + "scope": 2432, + "src": "15798:389:4", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 2430, + "nodeType": "Block", + "src": "16463:705:4", + "statements": [ + { + "condition": { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 2364, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2362, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "16477:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "argumentTypes": null, + "hexValue": "30", + "id": 2363, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "16487:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "src": "16477:11:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": null, + "id": 2367, + "nodeType": "IfStatement", + "src": "16473:25:4", + "trueBody": { + "expression": { + "argumentTypes": null, + "hexValue": "30", + "id": 2365, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "16497:1:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + }, + "functionReturnParameters": 2361, + "id": 2366, + "nodeType": "Return", + "src": "16490:8:4" + } + }, + { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 2373, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "argumentTypes": null, + "id": 2369, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "16516:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "<=", + "rightExpression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2371, + "name": "from", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2351, + "src": "16550:4:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 2370, + "name": "getWithdrawableEarnings", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1494, + "src": "16526:23:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_address_$returns$_t_uint256_$", + "typeString": "function (address) view returns (uint256)" + } + }, + "id": 2372, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16526:29:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "16516:39:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f696e73756666696369656e7442616c616e6365", + "id": 2374, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "16557:27:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_74799d65376d943bac023262731d6421d2e6b6332748a55385eb85a0683327fc", + "typeString": "literal_string \"error_insufficientBalance\"" + }, + "value": "error_insufficientBalance" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_74799d65376d943bac023262731d6421d2e6b6332748a55385eb85a0683327fc", + "typeString": "literal_string \"error_insufficientBalance\"" + } + ], + "id": 2368, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "16508:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2375, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16508:77:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2376, + "nodeType": "ExpressionStatement", + "src": "16508:77:4" + }, + { + "assignments": [ + 2378 + ], + "declarations": [ + { + "constant": false, + "id": 2378, + "mutability": "mutable", + "name": "info", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2430, + "src": "16595:23:4", + "stateVariable": false, + "storageLocation": "storage", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + }, + "typeName": { + "contractScope": null, + "id": 2377, + "name": "MemberInfo", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 1245, + "src": "16595:10:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo" + } + }, + "value": null, + "visibility": "internal" + } + ], + "id": 2382, + "initialValue": { + "argumentTypes": null, + "baseExpression": { + "argumentTypes": null, + "id": 2379, + "name": "memberData", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1269, + "src": "16621:10:4", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_address_$_t_struct$_MemberInfo_$1245_storage_$", + "typeString": "mapping(address => struct DataUnionSidechain.MemberInfo storage ref)" + } + }, + "id": 2381, + "indexExpression": { + "argumentTypes": null, + "id": 2380, + "name": "from", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2351, + "src": "16632:4:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "16621:16:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage", + "typeString": "struct DataUnionSidechain.MemberInfo storage ref" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "16595:42:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 2391, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2383, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2378, + "src": "16647:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 2385, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "memberName": "withdrawnEarnings", + "nodeType": "MemberAccess", + "referencedDeclaration": 1244, + "src": "16647:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2389, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "16699:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "expression": { + "argumentTypes": null, + "id": 2386, + "name": "info", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2378, + "src": "16672:4:4", + "typeDescriptions": { + "typeIdentifier": "t_struct$_MemberInfo_$1245_storage_ptr", + "typeString": "struct DataUnionSidechain.MemberInfo storage pointer" + } + }, + "id": 2387, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberName": "withdrawnEarnings", + "nodeType": "MemberAccess", + "referencedDeclaration": 1244, + "src": "16672:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2388, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "16672:26:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 2390, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16672:34:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "16647:59:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2392, + "nodeType": "ExpressionStatement", + "src": "16647:59:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 2398, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "argumentTypes": null, + "id": 2393, + "name": "totalEarningsWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1255, + "src": "16716:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2396, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "16768:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 2394, + "name": "totalEarningsWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1255, + "src": "16741:22:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2395, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "add", + "nodeType": "MemberAccess", + "referencedDeclaration": 3474, + "src": "16741:26:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$bound_to$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 2397, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16741:34:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "16716:59:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 2399, + "nodeType": "ExpressionStatement", + "src": "16716:59:4" + }, + { + "condition": { + "argumentTypes": null, + "id": 2400, + "name": "sendToMainnet", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2357, + "src": "16789:13:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "falseBody": { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2416, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2353, + "src": "17062:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2417, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "17066:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "argumentTypes": null, + "id": 2414, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "17047:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 2415, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "transfer", + "nodeType": "MemberAccess", + "referencedDeclaration": 4231, + "src": "17047:14:4", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_uint256_$returns$_t_bool_$", + "typeString": "function (address,uint256) external returns (bool)" + } + }, + "id": 2418, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "17047:26:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f7472616e73666572", + "id": 2419, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "17075:16:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + }, + "value": "error_transfer" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + } + ], + "id": 2413, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "17039:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2420, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "17039:53:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2421, + "nodeType": "ExpressionStatement", + "src": "17039:53:4" + }, + "id": 2422, + "nodeType": "IfStatement", + "src": "16785:307:4", + "trueBody": { + "expression": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2404, + "name": "tokenMediator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1249, + "src": "16884:13:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2405, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "16919:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2407, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2353, + "src": "16955:2:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 2406, + "name": "toBytes", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2348, + "src": "16947:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_address_$returns$_t_bytes_memory_ptr_$", + "typeString": "function (address) pure returns (bytes memory)" + } + }, + "id": 2408, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16947:11:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "expression": { + "argumentTypes": null, + "id": 2402, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1247, + "src": "16841:5:4", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC677_$2939", + "typeString": "contract IERC677" + } + }, + "id": 2403, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "transferAndCall", + "nodeType": "MemberAccess", + "referencedDeclaration": 2938, + "src": "16841:21:4", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_uint256_$_t_bytes_memory_ptr_$returns$_t_bool_$", + "typeString": "function (address,uint256,bytes memory) external returns (bool)" + } + }, + "id": 2409, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16841:135:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "argumentTypes": null, + "hexValue": "6572726f725f7472616e73666572", + "id": 2410, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "16994:16:4", + "subdenomination": null, + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + }, + "value": "error_transfer" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_a79228fd2655f5e702d118a716d23aa1202e4ee8105c5cccde34ce1d470bb9af", + "typeString": "literal_string \"error_transfer\"" + } + ], + "id": 2401, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "16816:7:4", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 2411, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "16816:208:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2412, + "nodeType": "ExpressionStatement", + "src": "16816:208:4" + } + }, + { + "eventCall": { + "argumentTypes": null, + "arguments": [ + { + "argumentTypes": null, + "id": 2424, + "name": "from", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2351, + "src": "17125:4:4", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "argumentTypes": null, + "id": 2425, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "17131:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 2423, + "name": "EarningsWithdrawn", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 1212, + "src": "17107:17:4", + "typeDescriptions": { + "typeIdentifier": "t_function_event_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256)" + } + }, + "id": 2426, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "names": [], + "nodeType": "FunctionCall", + "src": "17107:31:4", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 2427, + "nodeType": "EmitStatement", + "src": "17102:36:4" + }, + { + "expression": { + "argumentTypes": null, + "id": 2428, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2355, + "src": "17155:6:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 2361, + "id": 2429, + "nodeType": "Return", + "src": "17148:13:4" + } + ] + }, + "documentation": { + "id": 2349, + "nodeType": "StructuredDocumentation", + "src": "16193:140:4", + "text": "Internal function common to all withdraw methods.\nDoes NOT check proper access, so all callers must do that first." + }, + "id": 2431, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "_withdraw", + "nodeType": "FunctionDefinition", + "overrides": null, + "parameters": { + "id": 2358, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2351, + "mutability": "mutable", + "name": "from", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2431, + "src": "16357:12:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2350, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "16357:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2353, + "mutability": "mutable", + "name": "to", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2431, + "src": "16371:10:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 2352, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "16371:7:4", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2355, + "mutability": "mutable", + "name": "amount", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2431, + "src": "16383:11:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2354, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "16383:4:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + }, + { + "constant": false, + "id": 2357, + "mutability": "mutable", + "name": "sendToMainnet", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2431, + "src": "16396:18:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 2356, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "16396:4:4", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "16356:59:4" + }, + "returnParameters": { + "id": 2361, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 2360, + "mutability": "mutable", + "name": "", + "nodeType": "VariableDeclaration", + "overrides": null, + "scope": 2431, + "src": "16450:7:4", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2359, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "16450:7:4", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "value": null, + "visibility": "internal" + } + ], + "src": "16449:9:4" + }, + "scope": 2432, + "src": "16338:830:4", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "internal" + } + ], + "scope": 2433, + "src": "271:16899:4" + } + ], + "src": "0:17171:4" + }, + "compiler": { + "name": "solc", + "version": "0.6.6+commit.6c089d02.Emscripten.clang" + }, + "networks": {}, + "schemaVersion": "3.2.3", + "updatedAt": "2020-12-07T14:56:26.133Z", + "devdoc": { + "methods": { + "claimOwnership()": { + "details": "Allows the pendingOwner address to finalize the transfer." + }, + "signatureIsValid(address,address,uint256,bytes)": { + "params": { + "amount": "how much is authorized for withdraw, or zero for unlimited (withdrawAll)", + "recipient": "of the tokens", + "signature": "byte array from `web3.eth.accounts.sign`", + "signer": "whose earnings are being withdrawn" + }, + "returns": { + "isValid": "true iff signer of the authorization (member whose earnings are going to be withdrawn) matches the signature" + } + }, + "transferOwnership(address)": { + "details": "Allows the current owner to set the pendingOwner address.", + "params": { + "newOwner": "The address to transfer ownership to." + } + }, + "transferWithinContract(address,uint256)": { + "params": { + "amount": "how much withdrawable earnings is transferred", + "recipient": "whose withdrawable earnings will increase" + } + }, + "withdrawAllToSigned(address,address,bool,bytes)": { + "params": { + "fromSigner": "whose earnings are being withdrawn", + "sendToMainnet": "if the tokens should be sent to mainnet or only withdrawn into sidechain address", + "signature": "from the member, see `signatureIsValid` how signature generated for unlimited amount", + "to": "the address the tokens will be sent to (instead of `msg.sender`)" + } + }, + "withdrawToSigned(address,address,uint256,bool,bytes)": { + "params": { + "amount": "of tokens to withdraw", + "fromSigner": "whose earnings are being withdrawn", + "sendToMainnet": "if the tokens should be sent to mainnet or only withdrawn into sidechain address", + "signature": "from the member, see `signatureIsValid` how signature generated for unlimited amount", + "to": "the address the tokens will be sent to (instead of `msg.sender`)" + } + } + } + }, + "userdoc": { + "methods": { + "getStats()": { + "notice": "Atomic getter to get all state variables in one call This alleviates the fact that JSON RPC batch requests aren't available in ethers.js" + }, + "refreshRevenue()": { + "notice": "Process unaccounted tokens that have been sent previously Called by AMB (see DataUnionMainnet:sendTokensToBridge)" + }, + "signatureIsValid(address,address,uint256,bytes)": { + "notice": "Check signature from a member authorizing withdrawing its earnings to another account. Throws if the signature is badly formatted or doesn't match the given signer and amount. Signature has parts the act as replay protection: 1) `address(this)`: signature can't be used for other contracts; 2) `withdrawn[signer]`: signature only works once (for unspecified amount), and can be \"cancelled\" by sending a withdraw tx. Generated in Javascript with: `web3.eth.accounts.sign(recipientAddress + amount.toString(16, 64) + contractAddress.slice(2) + withdrawnTokens.toString(16, 64), signerPrivateKey)`, or for unlimited amount: `web3.eth.accounts.sign(recipientAddress + \"0\".repeat(64) + contractAddress.slice(2) + withdrawnTokens.toString(16, 64), signerPrivateKey)`." + }, + "transferToMemberInContract(address,uint256)": { + "notice": "Transfer tokens from outside contract, add to a recipient's in-contract balance" + }, + "transferWithinContract(address,uint256)": { + "notice": "Transfer tokens from sender's in-contract balance to recipient's in-contract balance This is done by \"withdrawing\" sender's earnings and crediting them to recipient's unwithdrawn earnings, so withdrawnEarnings never decreases for anyone (within this function)" + }, + "withdrawAllToSigned(address,address,bool,bytes)": { + "notice": "Do an \"unlimited donate withdraw\" on behalf of someone else, to an address they've specified. Sponsored withdraw is paid by admin, but target account could be whatever the member specifies. The signature gives a \"blank cheque\" for admin to withdraw all tokens to `recipient` in the future, and it's valid until next withdraw (and so can be nullified by withdrawing any amount). A new signature needs to be obtained for each subsequent future withdraw." + }, + "withdrawToSigned(address,address,uint256,bool,bytes)": { + "notice": "Do a \"donate withdraw\" on behalf of someone else, to an address they've specified. Sponsored withdraw is paid by admin, but target account could be whatever the member specifies. The signature is valid only for given amount of tokens that may be different from maximum withdrawable tokens." + } + } + } +} \ No newline at end of file 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/examples/node/package-lock.json b/examples/node/package-lock.json index 2da623db7..03917af90 100644 --- a/examples/node/package-lock.json +++ b/examples/node/package-lock.json @@ -742,7 +742,7 @@ "qs": "^6.9.4", "randomstring": "^1.1.5", "receptacle": "^1.3.2", - "streamr-client-protocol": "^5.0.0-beta.9", + "streamr-client-protocol": "^5.0.0-beta.10", "uuid": "^8.2.0", "webpack-node-externals": "^1.7.2", "ws": "^7.3.0" diff --git a/examples/web/web-example-metamask.html b/examples/web/web-example-metamask.html index 76777b8d9..8798ba341 100644 --- a/examples/web/web-example-metamask.html +++ b/examples/web/web-example-metamask.html @@ -1,46 +1,47 @@ - diff --git a/examples/web/web-example-subscribe.html b/examples/web/web-example-subscribe.html index 7192ce43c..cfd90ebea 100644 --- a/examples/web/web-example-subscribe.html +++ b/examples/web/web-example-subscribe.html @@ -2,52 +2,124 @@ + + + + +

Real-time telemetrics from trams running in Helsinki, Finland.

+

Provided by the local public transport authority (HSL) over MQTT protocol.

+
+
+
+
+ - - -

Real-time telemetrics from trams running in Helsinki, Finland. Provided by the local public transport authority (HSL) over MQTT protocol.

+ } + + start() + diff --git a/examples/webpack/package-lock.json b/examples/webpack/package-lock.json index 4bf6faf70..88cefd538 100644 --- a/examples/webpack/package-lock.json +++ b/examples/webpack/package-lock.json @@ -5035,7 +5035,7 @@ "qs": "^6.9.4", "randomstring": "^1.1.5", "receptacle": "^1.3.2", - "streamr-client-protocol": "^5.0.0-beta.9", + "streamr-client-protocol": "^5.0.0-beta.10", "uuid": "^8.2.0", "webpack-node-externals": "^1.7.2", "ws": "^7.3.0" diff --git a/jest.config.js b/jest.config.js index 067acaedd..d5ece98e6 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,3 +1,5 @@ +const path = require('path') + // For a detailed explanation regarding each configuration property, visit: // https://jestjs.io/docs/en/configuration.html @@ -18,7 +20,7 @@ module.exports = { clearMocks: true, // Indicates whether the coverage information should be collected while executing the test - collectCoverage: true, + collectCoverage: false, // An array of glob patterns indicating a set of files for which coverage information should be collected collectCoverageFrom: ['src/**'], @@ -49,7 +51,7 @@ module.exports = { // forceCoverageMatch: [], // A path to a module which exports an async function that is triggered once before all test suites - // globalSetup: null, + globalSetup: './jest.setup.js', // A path to a module which exports an async function that is triggered once after all test suites // globalTeardown: null, @@ -58,10 +60,10 @@ module.exports = { // globals: {}, // An array of directory names to be searched recursively up from the requiring module's location - // moduleDirectories: [ - // "node_modules" - // ], - + moduleDirectories: [ + 'node_modules', + path.resolve('./node_modules'), // makes npm link work. + ], // An array of file extensions your modules use // moduleFileExtensions: [ // "js", @@ -74,7 +76,9 @@ module.exports = { // moduleNameMapper: {}, // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader - // modulePathIgnorePatterns: [], + modulePathIgnorePatterns: [ + '/dist', + ], // Activates notifications for test results // notify: false, @@ -83,7 +87,7 @@ module.exports = { // notifyMode: "always", // A preset that is used as a base for Jest's configuration - // preset: null, + preset: 'ts-jest', // Run tests from one or more projects // projects: null, @@ -112,13 +116,14 @@ module.exports = { // ], // Allows you to use a custom runner instead of Jest's default test runner - // runner: "jest-runner", + testRunner: 'jest-circus/runner', // The paths to modules that run some code to configure or set up the testing environment before each test // setupFiles: [], // The path to a module that runs some code to configure or set up the testing framework before each test // setupTestFrameworkScriptFile: null, + // setupFilesAfterEnv: [], // A list of paths to snapshot serializer modules Jest should use for snapshot testing // snapshotSerializers: [], @@ -150,7 +155,7 @@ module.exports = { // testResultsProcessor: null, // This option allows use of a custom test runner - // testRunner: "jasmine2", + // testRunner: 'jest-circus/runner', // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href // testURL: "about:blank", @@ -159,12 +164,17 @@ module.exports = { // timers: "real", // A map from regular expressions to paths to transformers - // transform: null, + transform: { + '\\.(js|ts)$': ['babel-jest', { + configFile: path.resolve(__dirname, '.babel.node.config.js'), + babelrc: false, + }] + }, // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation - // transformIgnorePatterns: [ - // "/node_modules/" - // ], + transformIgnorePatterns: [ + '/node_modules/(?!quick-lru)', // quick-lru is esm + ], // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them // unmockedModulePathPatterns: undefined, diff --git a/jest.setup.js b/jest.setup.js new file mode 100644 index 000000000..5592139d6 --- /dev/null +++ b/jest.setup.js @@ -0,0 +1,28 @@ +import GitRevisionPlugin from 'git-revision-webpack-plugin' +import Debug from 'debug' + +const pkg = require('./package.json') + +export default async () => { + if (process.env.DEBUG_CONSOLE) { + // Use debug as console log + // This prevents jest messing with console output + // Ensuring debug messages are printed alongside console messages, in the correct order + console.log = Debug('Streamr::CONSOLE') // eslint-disable-line no-console + } + + if (!process.env.GIT_VERSION) { + const gitRevisionPlugin = new GitRevisionPlugin() + const [GIT_VERSION, GIT_COMMITHASH, GIT_BRANCH] = await Promise.all([ + gitRevisionPlugin.version(), + gitRevisionPlugin.commithash(), + gitRevisionPlugin.branch(), + ]) + Object.assign(process.env, { + version: pkg.version, + GIT_VERSION, + GIT_COMMITHASH, + GIT_BRANCH, + }, process.env) // don't override whatever is in process.env + } +} diff --git a/package-lock.json b/package-lock.json index 25ce21448..420847bd7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { "name": "streamr-client", - "version": "4.1.6", + "version": "5.0.0-beta.10", "lockfileVersion": 1, "requires": true, "dependencies": { "@babel/cli": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.12.10.tgz", - "integrity": "sha512-+y4ZnePpvWs1fc/LhZRTHkTesbXkyBYuOB+5CyodZqrEuETXi3zOVfpAQIdgC3lXbHLTDG9dQosxR9BhvLKDLQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.13.0.tgz", + "integrity": "sha512-y5AohgeVhU+wO5kU1WGMLdocFj83xCxVjsVFa2ilII8NEwmBZvx7Ambq621FbFIK68loYJ9p43nfoi6es+rzSA==", "dev": true, "requires": { "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents", @@ -23,237 +23,278 @@ } }, "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", "dev": true, "requires": { - "@babel/highlight": "^7.10.4" + "@babel/highlight": "^7.12.13" } }, "@babel/compat-data": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz", - "integrity": "sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw==", + "version": "7.13.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.6.tgz", + "integrity": "sha512-VhgqKOWYVm7lQXlvbJnWOzwfAQATd2nV52koT0HZ/LdDH0m4DUDwkKYsH+IwpXb+bKPyBJzawA4I6nBKqZcpQw==", "dev": true }, "@babel/core": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", - "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.10", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.10", - "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.10", - "@babel/types": "^7.12.10", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.1.tgz", + "integrity": "sha512-FzeKfFBG2rmFtGiiMdXZPFt/5R5DXubVi82uYhjGX4Msf+pgYQMCFIqFXZWs5vbIYbf14VeBIgdGI03CDOOM1w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.0", + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-transforms": "^7.13.0", + "@babel/helpers": "^7.13.0", + "@babel/parser": "^7.13.0", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", + "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", "lodash": "^4.17.19", - "semver": "^5.4.1", + "semver": "7.0.0", "source-map": "^0.5.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } } }, "@babel/generator": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", - "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.0.tgz", + "integrity": "sha512-zBZfgvBB/ywjx0Rgc2+BwoH/3H+lDtlgD4hBOpEv5LxRnYsm/753iRuLepqnYlynpjC3AdQxtxsoeHJoEEwOAw==", "dev": true, "requires": { - "@babel/types": "^7.12.11", + "@babel/types": "^7.13.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" } }, "@babel/helper-annotate-as-pure": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz", - "integrity": "sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz", + "integrity": "sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw==", "dev": true, "requires": { - "@babel/types": "^7.12.10" + "@babel/types": "^7.12.13" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", - "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.12.13.tgz", + "integrity": "sha512-CZOv9tGphhDRlVjVkAgm8Nhklm9RzSmWpX2my+t7Ua/KT616pEzXsQCjinzvkRvHWJ9itO4f296efroX23XCMA==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.12.13", + "@babel/types": "^7.12.13" + } + }, + "@babel/helper-call-delegate": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.12.13.tgz", + "integrity": "sha512-K1kF0RXK/GpdS9OZDlBllG0+RQQtyzG/TC+nk0VkrUry4l4Xh2T7HdDsDOVlXQY/KcqvE/JQ84pKjKucdrg3FQ==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.10.4", - "@babel/types": "^7.10.4" + "@babel/helper-hoist-variables": "^7.12.13", + "@babel/types": "^7.12.13" } }, "@babel/helper-compilation-targets": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz", - "integrity": "sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.0.tgz", + "integrity": "sha512-SOWD0JK9+MMIhTQiUVd4ng8f3NXhPVQvTv7D3UN4wbp/6cAHnB2EmMaU1zZA2Hh1gwme+THBrVSqTFxHczTh0Q==", "dev": true, "requires": { - "@babel/compat-data": "^7.12.5", - "@babel/helper-validator-option": "^7.12.1", + "@babel/compat-data": "^7.13.0", + "@babel/helper-validator-option": "^7.12.17", "browserslist": "^4.14.5", - "semver": "^5.5.0" + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } } }, "@babel/helper-create-class-features-plugin": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz", - "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.0.tgz", + "integrity": "sha512-twwzhthM4/+6o9766AW2ZBHpIHPSGrPGk1+WfHiu13u/lBnggXGNYCpeAyVfNwGDKfkhEDp+WOD/xafoJ2iLjA==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-member-expression-to-functions": "^7.12.1", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-replace-supers": "^7.12.1", - "@babel/helper-split-export-declaration": "^7.10.4" + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-member-expression-to-functions": "^7.13.0", + "@babel/helper-optimise-call-expression": "^7.12.13", + "@babel/helper-replace-supers": "^7.13.0", + "@babel/helper-split-export-declaration": "^7.12.13" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz", - "integrity": "sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ==", + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.17.tgz", + "integrity": "sha512-p2VGmBu9oefLZ2nQpgnEnG0ZlRPvL8gAGvPUMQwUdaE8k49rOMuZpOwdQoy5qJf6K8jL3bcAMhVUlHAjIgJHUg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-annotate-as-pure": "^7.12.13", "regexpu-core": "^4.7.1" } }, - "@babel/helper-define-map": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", - "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", + "@babel/helper-define-polyfill-provider": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.2.tgz", + "integrity": "sha512-hWeolZJivTNGHXHzJjQz/NwDaG4mGXf22ZroOP8bQYgvHNzaQ5tylsVbAcAS2oDjXBwpu8qH2I/654QFS2rDpw==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/types": "^7.10.5", - "lodash": "^4.17.19" + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "@babel/helper-explode-assignable-expression": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz", - "integrity": "sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz", + "integrity": "sha512-qS0peLTDP8kOisG1blKbaoBg/o9OSa1qoumMjTK5pM+KDTtpxpsiubnCGP34vK8BXGcb2M9eigwgvoJryrzwWA==", "dev": true, "requires": { - "@babel/types": "^7.12.1" + "@babel/types": "^7.13.0" } }, "@babel/helper-function-name": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz", - "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", + "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.12.10", - "@babel/template": "^7.12.7", - "@babel/types": "^7.12.11" + "@babel/helper-get-function-arity": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/types": "^7.12.13" } }, "@babel/helper-get-function-arity": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz", - "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", + "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", "dev": true, "requires": { - "@babel/types": "^7.12.10" + "@babel/types": "^7.12.13" } }, "@babel/helper-hoist-variables": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", - "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.0.tgz", + "integrity": "sha512-0kBzvXiIKfsCA0y6cFEIJf4OdzfpRuNk4+YTeHZpGGc666SATFKTz6sRncwFnQk7/ugJ4dSrCj6iJuvW4Qwr2g==", "dev": true, "requires": { - "@babel/types": "^7.10.4" + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz", - "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.0.tgz", + "integrity": "sha512-yvRf8Ivk62JwisqV1rFRMxiSMDGnN6KH1/mDMmIrij4jztpQNRoHqqMG3U6apYbGRPJpgPalhva9Yd06HlUxJQ==", "dev": true, "requires": { - "@babel/types": "^7.12.7" + "@babel/types": "^7.13.0" } }, "@babel/helper-module-imports": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", - "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz", + "integrity": "sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g==", "dev": true, "requires": { - "@babel/types": "^7.12.5" + "@babel/types": "^7.12.13" } }, "@babel/helper-module-transforms": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", - "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-replace-supers": "^7.12.1", - "@babel/helper-simple-access": "^7.12.1", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/helper-validator-identifier": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.0.tgz", + "integrity": "sha512-Ls8/VBwH577+pw7Ku1QkUWIyRRNHpYlts7+qSqBBFCW3I8QteB9DxfcZ5YJpOwH6Ihe/wn8ch7fMGOP1OhEIvw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-replace-supers": "^7.13.0", + "@babel/helper-simple-access": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/helper-validator-identifier": "^7.12.11", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0", "lodash": "^4.17.19" } }, "@babel/helper-optimise-call-expression": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz", - "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz", + "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==", "dev": true, "requires": { - "@babel/types": "^7.12.10" + "@babel/types": "^7.12.13" } }, "@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", + "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", "dev": true }, "@babel/helper-remap-async-to-generator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz", - "integrity": "sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.13.0.tgz", + "integrity": "sha512-pUQpFBE9JvC9lrQbpX0TmeNIy5s7GnZjna2lhhcHC7DzgBs6fWn722Y5cfwgrtrqc7NAJwMvOa0mKhq6XaE4jg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-wrap-function": "^7.10.4", - "@babel/types": "^7.12.1" + "@babel/helper-annotate-as-pure": "^7.12.13", + "@babel/helper-wrap-function": "^7.13.0", + "@babel/types": "^7.13.0" } }, "@babel/helper-replace-supers": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz", - "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.0.tgz", + "integrity": "sha512-Segd5me1+Pz+rmN/NFBOplMbZG3SqRJOBlY+mA0SxAv6rjj7zJqr1AVr3SfzUVTLCv7ZLU5FycOM/SBGuLPbZw==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.12.7", - "@babel/helper-optimise-call-expression": "^7.12.10", - "@babel/traverse": "^7.12.10", - "@babel/types": "^7.12.11" + "@babel/helper-member-expression-to-functions": "^7.13.0", + "@babel/helper-optimise-call-expression": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" } }, "@babel/helper-simple-access": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", - "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.13.tgz", + "integrity": "sha512-0ski5dyYIHEfwpWGx5GPWhH35j342JaflmCeQmsPWcrOQDtCN6C1zKAVRFVbK53lPW2c9TsuLLSUDf0tIGJ5hA==", "dev": true, "requires": { - "@babel/types": "^7.12.1" + "@babel/types": "^7.12.13" } }, "@babel/helper-skip-transparent-expression-wrappers": { @@ -266,12 +307,12 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz", - "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", + "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", "dev": true, "requires": { - "@babel/types": "^7.12.11" + "@babel/types": "^7.12.13" } }, "@babel/helper-validator-identifier": { @@ -281,182 +322,182 @@ "dev": true }, "@babel/helper-validator-option": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz", - "integrity": "sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw==", + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz", + "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==", "dev": true }, "@babel/helper-wrap-function": { - "version": "7.12.3", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz", - "integrity": "sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.13.0.tgz", + "integrity": "sha512-1UX9F7K3BS42fI6qd2A4BjKzgGjToscyZTdp1DjknHLCIvpgne6918io+aL5LXFcER/8QWiwpoY902pVEqgTXA==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" + "@babel/helper-function-name": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" } }, "@babel/helpers": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz", - "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.0.tgz", + "integrity": "sha512-aan1MeFPxFacZeSz6Ld7YZo5aPuqnKlD7+HZY75xQsueczFccP9A7V05+oe0XpLwHK3oLorPe9eaAUljL7WEaQ==", "dev": true, "requires": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.5", - "@babel/types": "^7.12.5" + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" } }, "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz", + "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.12.11", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, "@babel/parser": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", - "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==", + "version": "7.13.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.4.tgz", + "integrity": "sha512-uvoOulWHhI+0+1f9L4BoozY7U5cIkZ9PgJqvb041d6vypgUmtVPG4vmGm4pSggjl8BELzvHyUeJSUyEMY6b+qA==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.12.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz", - "integrity": "sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A==", + "version": "7.13.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.13.5.tgz", + "integrity": "sha512-8cErJEDzhZgNKzYyjCKsHuyPqtWxG8gc9h4OFSUDJu0vCAOsObPU2LcECnW0kJwh/b+uUz46lObVzIXw0fzAbA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.12.1", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-remap-async-to-generator": "^7.13.0", "@babel/plugin-syntax-async-generators": "^7.8.0" } }, "@babel/plugin-proposal-class-properties": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz", - "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.13.0.tgz", + "integrity": "sha512-KnTDjFNC1g+45ka0myZNvSBFLhNCLN+GeGYLDEA8Oq7MZ6yMgfLoIRh86GRT0FjtJhZw8JyUskP9uvj5pHM9Zg==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-create-class-features-plugin": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0" } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz", - "integrity": "sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ==", + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.17.tgz", + "integrity": "sha512-ZNGoFZqrnuy9H2izB2jLlnNDAfVPlGl5NhFEiFe4D84ix9GQGygF+CWMGHKuE+bpyS/AOuDQCnkiRNqW2IzS1Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-plugin-utils": "^7.12.13", "@babel/plugin-syntax-dynamic-import": "^7.8.0" } }, "@babel/plugin-proposal-export-namespace-from": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz", - "integrity": "sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.13.tgz", + "integrity": "sha512-INAgtFo4OnLN3Y/j0VwAgw3HDXcDtX+C/erMvWzuV9v71r7urb6iyMXu7eM9IgLr1ElLlOkaHjJ0SbCmdOQ3Iw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-plugin-utils": "^7.12.13", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz", - "integrity": "sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.13.tgz", + "integrity": "sha512-v9eEi4GiORDg8x+Dmi5r8ibOe0VXoKDeNPYcTTxdGN4eOWikrJfDJCJrr1l5gKGvsNyGJbrfMftC2dTL6oz7pg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-plugin-utils": "^7.12.13", "@babel/plugin-syntax-json-strings": "^7.8.0" } }, "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz", - "integrity": "sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.13.tgz", + "integrity": "sha512-fqmiD3Lz7jVdK6kabeSr1PZlWSUVqSitmHEe3Z00dtGTKieWnX9beafvavc32kjORa5Bai4QNHgFDwWJP+WtSQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-plugin-utils": "^7.12.13", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" } }, "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz", - "integrity": "sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.0.tgz", + "integrity": "sha512-UkAvFA/9+lBBL015gjA68NvKiCReNxqFLm3SdNKaM3XXoDisA7tMAIX4PmIwatFoFqMxxT3WyG9sK3MO0Kting==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" } }, "@babel/plugin-proposal-numeric-separator": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz", - "integrity": "sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.13.tgz", + "integrity": "sha512-O1jFia9R8BUCl3ZGB7eitaAPu62TXJRHn7rh+ojNERCFyqRwJMTmhz+tJ+k0CwI6CLjX/ee4qW74FSqlq9I35w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-plugin-utils": "^7.12.13", "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", - "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.0.tgz", + "integrity": "sha512-B4qphdSTp0nLsWcuei07JPKeZej4+Hd22MdnulJXQa1nCcGSBlk8FiqenGERaPZ+PuYhz4Li2Wjc8yfJvHgUMw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-transform-parameters": "^7.12.1" + "@babel/plugin-transform-parameters": "^7.13.0" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz", - "integrity": "sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.13.tgz", + "integrity": "sha512-9+MIm6msl9sHWg58NvqpNpLtuFbmpFYk37x8kgnGzAHvX35E1FyAwSUt5hIkSoWJFSAH+iwU8bJ4fcD1zKXOzg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-plugin-utils": "^7.12.13", "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz", - "integrity": "sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.0.tgz", + "integrity": "sha512-OVRQOZEBP2luZrvEbNSX5FfWDousthhdEoAOpej+Tpe58HFLvqRClT89RauIvBuCDFEip7GW1eT86/5lMy2RNA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", "@babel/plugin-syntax-optional-chaining": "^7.8.0" } }, "@babel/plugin-proposal-private-methods": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz", - "integrity": "sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.13.0.tgz", + "integrity": "sha512-MXyyKQd9inhx1kDYPkFRVOBXQ20ES8Pto3T7UZ92xj2mY0EVD8oAVzeyYuVfy/mxAdTSIayOvg+aVzcHV2bn6Q==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-create-class-features-plugin": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0" } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz", - "integrity": "sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.13.tgz", + "integrity": "sha512-XyJmZidNfofEkqFV5VC/bLabGmO5QzenPO/YOfGuEbgU+2sSwMmio3YLb4WtBgcmmdwZHyVyv8on77IUjQ5Gvg==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-create-regexp-features-plugin": "^7.12.13", + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-syntax-async-generators": { @@ -478,12 +519,12 @@ } }, "@babel/plugin-syntax-class-properties": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz", - "integrity": "sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-syntax-dynamic-import": { @@ -577,364 +618,393 @@ } }, "@babel/plugin-syntax-top-level-await": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz", - "integrity": "sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz", + "integrity": "sha512-A81F9pDwyS7yM//KwbCSDqy3Uj4NMIurtplxphWxoYtNPov7cJsDkAFNNyVlIZ3jwGycVsurZ+LtOA8gZ376iQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.13.tgz", + "integrity": "sha512-cHP3u1JiUiG2LFDKbXnwVad81GvfyIOmCD6HIEId6ojrY0Drfy2q1jw7BwN7dE84+kTnBjLkXoL3IEy/3JPu2w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz", - "integrity": "sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.13.0.tgz", + "integrity": "sha512-96lgJagobeVmazXFaDrbmCLQxBysKu7U6Do3mLsx27gf5Dk85ezysrs2BZUpXD703U/Su1xTBDxxar2oa4jAGg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.13.0" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz", - "integrity": "sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.13.0.tgz", + "integrity": "sha512-3j6E004Dx0K3eGmhxVJxwwI89CTJrce7lg3UrtFuDAVQ/2+SJ/h/aSFOeE6/n0WB1GsOffsJp6MnPQNQ8nmwhg==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.12.1" + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-remap-async-to-generator": "^7.13.0" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz", - "integrity": "sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.13.tgz", + "integrity": "sha512-zNyFqbc3kI/fVpqwfqkg6RvBgFpC4J18aKKMmv7KdQ/1GgREapSJAykLMVNwfRGO3BtHj3YQZl8kxCXPcVMVeg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.12.12", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz", - "integrity": "sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.13.tgz", + "integrity": "sha512-Pxwe0iqWJX4fOOM2kEZeUuAxHMWb9nK+9oh5d11bsLoB0xMg+mkDpt0eYuDZB7ETrY9bbcVlKUGTOGWy7BHsMQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-classes": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz", - "integrity": "sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.13.0.tgz", + "integrity": "sha512-9BtHCPUARyVH1oXGcSJD3YpsqRLROJx5ZNP6tN5vnk17N0SVf9WCtf8Nuh1CFmgByKKAIMstitKduoCmsaDK5g==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-define-map": "^7.10.4", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.12.1", - "@babel/helper-split-export-declaration": "^7.10.4", + "@babel/helper-annotate-as-pure": "^7.12.13", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-optimise-call-expression": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-replace-supers": "^7.13.0", + "@babel/helper-split-export-declaration": "^7.12.13", "globals": "^11.1.0" } }, "@babel/plugin-transform-computed-properties": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz", - "integrity": "sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.13.0.tgz", + "integrity": "sha512-RRqTYTeZkZAz8WbieLTvKUEUxZlUTdmL5KGMyZj7FnMfLNKV4+r5549aORG/mgojRmFlQMJDUupwAMiF2Q7OUg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.13.0" } }, "@babel/plugin-transform-destructuring": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz", - "integrity": "sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.0.tgz", + "integrity": "sha512-zym5em7tePoNT9s964c0/KU3JPPnuq7VhIxPRefJ4/s82cD+q1mgKfuGRDMCPL0HTyKz4dISuQlCusfgCJ86HA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.13.0" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz", - "integrity": "sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.13.tgz", + "integrity": "sha512-foDrozE65ZFdUC2OfgeOCrEPTxdB3yjqxpXh8CH+ipd9CHd4s/iq81kcUpyH8ACGNEPdFqbtzfgzbT/ZGlbDeQ==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-create-regexp-features-plugin": "^7.12.13", + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz", - "integrity": "sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.13.tgz", + "integrity": "sha512-NfADJiiHdhLBW3pulJlJI2NB0t4cci4WTZ8FtdIuNc2+8pslXdPtRRAEWqUY+m9kNOk2eRYbTAOipAxlrOcwwQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz", - "integrity": "sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.13.tgz", + "integrity": "sha512-fbUelkM1apvqez/yYx1/oICVnGo2KM5s63mhGylrmXUxK/IAXSIf87QIxVfZldWf4QsOafY6vV3bX8aMHSvNrA==", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.12.13", + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-for-of": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz", - "integrity": "sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.13.0.tgz", + "integrity": "sha512-IHKT00mwUVYE0zzbkDgNRP6SRzvfGCYsOxIRz8KsiaaHCcT9BWIkO+H9QRJseHBLOGBZkHUdHiqj6r0POsdytg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.13.0" } }, "@babel/plugin-transform-function-name": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz", - "integrity": "sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.13.tgz", + "integrity": "sha512-6K7gZycG0cmIwwF7uMK/ZqeCikCGVBdyP2J5SKNCXO5EOHcqi+z7Jwf8AmyDNcBgxET8DrEtCt/mPKPyAzXyqQ==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-literals": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz", - "integrity": "sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.13.tgz", + "integrity": "sha512-FW+WPjSR7hiUxMcKqyNjP05tQ2kmBCdpEpZHY1ARm96tGQCCBvXKnpjILtDplUnJ/eHZ0lALLM+d2lMFSpYJrQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz", - "integrity": "sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.13.tgz", + "integrity": "sha512-kxLkOsg8yir4YeEPHLuO2tXP9R/gTjpuTOjshqSpELUN3ZAg2jfDnKUvzzJxObun38sw3wm4Uu69sX/zA7iRvg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz", - "integrity": "sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.13.0.tgz", + "integrity": "sha512-EKy/E2NHhY/6Vw5d1k3rgoobftcNUmp9fGjb9XZwQLtTctsRBOTRO7RHHxfIky1ogMN5BxN7p9uMA3SzPfotMQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-module-transforms": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz", - "integrity": "sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.0.tgz", + "integrity": "sha512-j7397PkIB4lcn25U2dClK6VLC6pr2s3q+wbE8R3vJvY6U1UTBBj0n6F+5v6+Fd/UwfDPAorMOs2TV+T4M+owpQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-simple-access": "^7.12.1", + "@babel/helper-module-transforms": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-simple-access": "^7.12.13", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz", - "integrity": "sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.13.tgz", + "integrity": "sha512-aHfVjhZ8QekaNF/5aNdStCGzwTbU7SI5hUybBKlMzqIMC7w7Ho8hx5a4R/DkTHfRfLwHGGxSpFt9BfxKCoXKoA==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.10.4", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-hoist-variables": "^7.12.13", + "@babel/helper-module-transforms": "^7.12.13", + "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-validator-identifier": "^7.12.11", "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz", - "integrity": "sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.13.0.tgz", + "integrity": "sha512-D/ILzAh6uyvkWjKKyFE/W0FzWwasv6vPTSqPcjxFqn6QpX3u8DjRVliq4F2BamO2Wee/om06Vyy+vPkNrd4wxw==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-module-transforms": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz", - "integrity": "sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.13.tgz", + "integrity": "sha512-Xsm8P2hr5hAxyYblrfACXpQKdQbx4m2df9/ZZSQ8MAhsadw06+jW7s9zsSw6he+mJZXRlVMyEnVktJo4zjk1WA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.1" + "@babel/helper-create-regexp-features-plugin": "^7.12.13" } }, "@babel/plugin-transform-new-target": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz", - "integrity": "sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.13.tgz", + "integrity": "sha512-/KY2hbLxrG5GTQ9zzZSc3xWiOy379pIETEhbtzwZcw9rvuaVV4Fqy7BYGYOWZnaoXIQYbbJ0ziXLa/sKcGCYEQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-object-super": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz", - "integrity": "sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.13.tgz", + "integrity": "sha512-JzYIcj3XtYspZDV8j9ulnoMPZZnF/Cj0LUxPOjR89BdBVx+zYJI9MdMIlUZjbXDX+6YVeS6I3e8op+qQ3BYBoQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.12.1" + "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-replace-supers": "^7.12.13" } }, "@babel/plugin-transform-parameters": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz", - "integrity": "sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.13.0.tgz", + "integrity": "sha512-Jt8k/h/mIwE2JFEOb3lURoY5C85ETcYPnbuAJ96zRBzh1XHtQZfs62ChZ6EP22QlC8c7Xqr9q+e1SU5qttwwjw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.13.0" } }, "@babel/plugin-transform-property-literals": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz", - "integrity": "sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.13.tgz", + "integrity": "sha512-nqVigwVan+lR+g8Fj8Exl0UQX2kymtjcWfMOYM1vTYEKujeyv2SkMgazf2qNcK7l4SDiKyTA/nHCPqL4e2zo1A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-regenerator": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz", - "integrity": "sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.13.tgz", + "integrity": "sha512-lxb2ZAvSLyJ2PEe47hoGWPmW22v7CtSl9jW8mingV4H2sEX/JOcrAj2nPuGWi56ERUm2bUpjKzONAuT6HCn2EA==", "dev": true, "requires": { "regenerator-transform": "^0.14.2" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz", - "integrity": "sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.13.tgz", + "integrity": "sha512-xhUPzDXxZN1QfiOy/I5tyye+TRz6lA7z6xaT4CLOjPRMVg1ldRf0LHw0TDBpYL4vG78556WuHdyO9oi5UmzZBg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-runtime": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz", - "integrity": "sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA==", + "version": "7.13.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.13.6.tgz", + "integrity": "sha512-QsTomUTIeOdYrNsOMJRSp2QzGvB1KYD4ePCC8Mei2SuoHScncYS3h1E9PR5gDL7buJmcqIHrWyH6B5GZMgDrRg==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.12.5", - "@babel/helper-plugin-utils": "^7.10.4", - "semver": "^5.5.1" + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "babel-plugin-polyfill-corejs2": "^0.1.4", + "babel-plugin-polyfill-corejs3": "^0.1.3", + "babel-plugin-polyfill-regenerator": "^0.1.2", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz", - "integrity": "sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.13.tgz", + "integrity": "sha512-xpL49pqPnLtf0tVluuqvzWIgLEhuPpZzvs2yabUHSKRNlN7ScYU7aMlmavOeyXJZKgZKQRBlh8rHbKiJDraTSw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-spread": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz", - "integrity": "sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.13.0.tgz", + "integrity": "sha512-V6vkiXijjzYeFmQTr3dBxPtZYLPcUfY34DebOU27jIl2M/Y8Egm52Hw82CSjjPqd54GTlJs5x+CR7HeNr24ckg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz", - "integrity": "sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.13.tgz", + "integrity": "sha512-Jc3JSaaWT8+fr7GRvQP02fKDsYk4K/lYwWq38r/UGfaxo89ajud321NH28KRQ7xy1Ybc0VUE5Pz8psjNNDUglg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-template-literals": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz", - "integrity": "sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.13.0.tgz", + "integrity": "sha512-d67umW6nlfmr1iehCcBv69eSUSySk1EsIS8aTDX4Xo9qajAh6mYtcl4kJrBkGXuxZPEgVr7RVfAvNW6YQkd4Mw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.13.0" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz", - "integrity": "sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.13.tgz", + "integrity": "sha512-eKv/LmUJpMnu4npgfvs3LiHhJua5fo/CysENxa45YCQXZwKnGCQKAg87bvoqSW1fFT+HA32l03Qxsm8ouTY3ZQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.13.0.tgz", + "integrity": "sha512-elQEwluzaU8R8dbVuW2Q2Y8Nznf7hnjM7+DSCd14Lo5fF63C9qNLbwZYbmZrtV9/ySpSUpkRpQXvJb6xyu4hCQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/plugin-syntax-typescript": "^7.12.13" } }, "@babel/plugin-transform-unicode-escapes": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz", - "integrity": "sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.13.tgz", + "integrity": "sha512-0bHEkdwJ/sN/ikBHfSmOXPypN/beiGqjo+o4/5K+vxEFNPRPdImhviPakMKG4x96l85emoa0Z6cDflsdBusZbw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz", - "integrity": "sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.13.tgz", + "integrity": "sha512-mDRzSNY7/zopwisPZ5kM9XKCfhchqIYwAKRERtEnhYscZB79VRekuRSoYbN0+KVe3y8+q1h6A4svXtP7N+UoCA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.12.1", - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-create-regexp-features-plugin": "^7.12.13", + "@babel/helper-plugin-utils": "^7.12.13" } }, "@babel/preset-env": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz", - "integrity": "sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.12.7", - "@babel/helper-compilation-targets": "^7.12.5", - "@babel/helper-module-imports": "^7.12.5", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-validator-option": "^7.12.11", - "@babel/plugin-proposal-async-generator-functions": "^7.12.1", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-dynamic-import": "^7.12.1", - "@babel/plugin-proposal-export-namespace-from": "^7.12.1", - "@babel/plugin-proposal-json-strings": "^7.12.1", - "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-numeric-separator": "^7.12.7", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-catch-binding": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.7", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-unicode-property-regex": "^7.12.1", + "version": "7.13.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.13.5.tgz", + "integrity": "sha512-xUeKBIIcbwxGevyWMSWZOW98W1lp7toITvVsMxSddCEQy932yYiF4fCB+CG3E/MXzFX3KbefgvCqEQ7TDoE6UQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.5", + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-validator-option": "^7.12.17", + "@babel/plugin-proposal-async-generator-functions": "^7.13.5", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-dynamic-import": "^7.12.17", + "@babel/plugin-proposal-export-namespace-from": "^7.12.13", + "@babel/plugin-proposal-json-strings": "^7.12.13", + "@babel/plugin-proposal-logical-assignment-operators": "^7.12.13", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.0", + "@babel/plugin-proposal-numeric-separator": "^7.12.13", + "@babel/plugin-proposal-object-rest-spread": "^7.13.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.12.13", + "@babel/plugin-proposal-optional-chaining": "^7.13.0", + "@babel/plugin-proposal-private-methods": "^7.13.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.12.13", "@babel/plugin-syntax-async-generators": "^7.8.0", - "@babel/plugin-syntax-class-properties": "^7.12.1", + "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-dynamic-import": "^7.8.0", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.0", @@ -944,43 +1014,54 @@ "@babel/plugin-syntax-object-rest-spread": "^7.8.0", "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.12.1", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-async-to-generator": "^7.12.1", - "@babel/plugin-transform-block-scoped-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.11", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-computed-properties": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-dotall-regex": "^7.12.1", - "@babel/plugin-transform-duplicate-keys": "^7.12.1", - "@babel/plugin-transform-exponentiation-operator": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-function-name": "^7.12.1", - "@babel/plugin-transform-literals": "^7.12.1", - "@babel/plugin-transform-member-expression-literals": "^7.12.1", - "@babel/plugin-transform-modules-amd": "^7.12.1", - "@babel/plugin-transform-modules-commonjs": "^7.12.1", - "@babel/plugin-transform-modules-systemjs": "^7.12.1", - "@babel/plugin-transform-modules-umd": "^7.12.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.1", - "@babel/plugin-transform-new-target": "^7.12.1", - "@babel/plugin-transform-object-super": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-property-literals": "^7.12.1", - "@babel/plugin-transform-regenerator": "^7.12.1", - "@babel/plugin-transform-reserved-words": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/plugin-transform-sticky-regex": "^7.12.7", - "@babel/plugin-transform-template-literals": "^7.12.1", - "@babel/plugin-transform-typeof-symbol": "^7.12.10", - "@babel/plugin-transform-unicode-escapes": "^7.12.1", - "@babel/plugin-transform-unicode-regex": "^7.12.1", + "@babel/plugin-syntax-top-level-await": "^7.12.13", + "@babel/plugin-transform-arrow-functions": "^7.13.0", + "@babel/plugin-transform-async-to-generator": "^7.13.0", + "@babel/plugin-transform-block-scoped-functions": "^7.12.13", + "@babel/plugin-transform-block-scoping": "^7.12.13", + "@babel/plugin-transform-classes": "^7.13.0", + "@babel/plugin-transform-computed-properties": "^7.13.0", + "@babel/plugin-transform-destructuring": "^7.13.0", + "@babel/plugin-transform-dotall-regex": "^7.12.13", + "@babel/plugin-transform-duplicate-keys": "^7.12.13", + "@babel/plugin-transform-exponentiation-operator": "^7.12.13", + "@babel/plugin-transform-for-of": "^7.13.0", + "@babel/plugin-transform-function-name": "^7.12.13", + "@babel/plugin-transform-literals": "^7.12.13", + "@babel/plugin-transform-member-expression-literals": "^7.12.13", + "@babel/plugin-transform-modules-amd": "^7.13.0", + "@babel/plugin-transform-modules-commonjs": "^7.13.0", + "@babel/plugin-transform-modules-systemjs": "^7.12.13", + "@babel/plugin-transform-modules-umd": "^7.13.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.13", + "@babel/plugin-transform-new-target": "^7.12.13", + "@babel/plugin-transform-object-super": "^7.12.13", + "@babel/plugin-transform-parameters": "^7.13.0", + "@babel/plugin-transform-property-literals": "^7.12.13", + "@babel/plugin-transform-regenerator": "^7.12.13", + "@babel/plugin-transform-reserved-words": "^7.12.13", + "@babel/plugin-transform-shorthand-properties": "^7.12.13", + "@babel/plugin-transform-spread": "^7.13.0", + "@babel/plugin-transform-sticky-regex": "^7.12.13", + "@babel/plugin-transform-template-literals": "^7.13.0", + "@babel/plugin-transform-typeof-symbol": "^7.12.13", + "@babel/plugin-transform-unicode-escapes": "^7.12.13", + "@babel/plugin-transform-unicode-regex": "^7.12.13", "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.12.11", - "core-js-compat": "^3.8.0", - "semver": "^5.5.0" + "@babel/types": "^7.13.0", + "babel-plugin-polyfill-corejs2": "^0.1.4", + "babel-plugin-polyfill-corejs3": "^0.1.3", + "babel-plugin-polyfill-regenerator": "^0.1.2", + "core-js-compat": "^3.9.0", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } } }, "@babel/preset-modules": { @@ -996,55 +1077,66 @@ "esutils": "^2.0.2" } }, + "@babel/preset-typescript": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.13.0.tgz", + "integrity": "sha512-LXJwxrHy0N3f6gIJlYbLta1D9BDtHpQeqwzM0LIfjDlr6UE/D5Mc7W4iDiQzaE+ks0sTjT26ArcHWnJVt0QiHw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/helper-validator-option": "^7.12.17", + "@babel/plugin-transform-typescript": "^7.13.0" + } + }, "@babel/runtime": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", - "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "version": "7.13.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.6.tgz", + "integrity": "sha512-Y/DEVhSQ91u27rxq7D0EH/sewS6+x06p/MgO1VppbDHMzYXLZrAR5cFjCom78e9RUw1BQAq6qJg6fXc/ep7glA==", "requires": { "regenerator-runtime": "^0.13.4" } }, "@babel/runtime-corejs3": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.12.5.tgz", - "integrity": "sha512-roGr54CsTmNPPzZoCP1AmDXuBoNao7tnSA83TXTwt+UK5QVyh1DIJnrgYRPWKCF2flqZQXwa7Yr8v7VmLzF0YQ==", + "version": "7.13.6", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.13.6.tgz", + "integrity": "sha512-wSbWQEOD7tk8zjRJVy41L85v+ctDk6AIv72hzVOyOhAeRSkzxKhamBP2jLPBYLYvLNgiJqa4gnpiYAIeedf/sA==", "requires": { "core-js-pure": "^3.0.0", "regenerator-runtime": "^0.13.4" } }, "@babel/template": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", - "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", "dev": true, "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.12.7", - "@babel/types": "^7.12.7" + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" } }, "@babel/traverse": { - "version": "7.12.12", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", - "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.0.tgz", + "integrity": "sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.12.11", - "@babel/generator": "^7.12.11", - "@babel/helper-function-name": "^7.12.11", - "@babel/helper-split-export-declaration": "^7.12.11", - "@babel/parser": "^7.12.11", - "@babel/types": "^7.12.12", + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.0", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.0", + "@babel/types": "^7.13.0", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.19" } }, "@babel/types": { - "version": "7.12.12", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", - "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.0.tgz", + "integrity": "sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", @@ -1068,6 +1160,12 @@ "minimist": "^1.2.0" } }, + "@discoveryjs/json-ext": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", + "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", + "dev": true + }, "@eslint/eslintrc": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", @@ -1104,9 +1202,9 @@ } }, "@ethersproject/abi": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.10.tgz", - "integrity": "sha512-cfC3lGgotfxX3SMri4+CisOPwignoj/QGHW9J29spC4R4Qqcnk/SYuVkPFBMdLbvBp3f/pGiVqPNwont0TSXhg==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.12.tgz", + "integrity": "sha512-Ujr/3bwyYYjXLDQfebeiiTuvOw9XtUKM8av6YkoBeMXyGQM9GkjrQlwJMNwGTmqjATH/ZNbRgCh98GjOLiIB1Q==", "requires": { "@ethersproject/address": "^5.0.9", "@ethersproject/bignumber": "^5.0.13", @@ -1120,9 +1218,9 @@ } }, "@ethersproject/abstract-provider": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.8.tgz", - "integrity": "sha512-fqJXkewcGdi8LogKMgRyzc/Ls2js07yor7+g9KfPs09uPOcQLg7cc34JN+lk34HH9gg2HU0DIA5797ZR8znkfw==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.9.tgz", + "integrity": "sha512-X9fMkqpeu9ayC3JyBkeeZhn35P4xQkpGX/l+FrxDtEW9tybf/UWXSMi8bGThpPtfJ6q6U2LDetXSpSwK4TfYQQ==", "requires": { "@ethersproject/bignumber": "^5.0.13", "@ethersproject/bytes": "^5.0.9", @@ -1134,9 +1232,9 @@ } }, "@ethersproject/abstract-signer": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.11.tgz", - "integrity": "sha512-RKOgPSEYafknA62SrD3OCK42AllHE4YBfKYXyQeM+sBP7Nq3X5FpzeoY4uzC43P4wIhmNoTHCKQuwnX7fBqb6Q==", + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.13.tgz", + "integrity": "sha512-VBIZEI5OK0TURoCYyw0t3w+TEO4kdwnI9wvt4kqUwyxSn3YCRpXYVl0Xoe7XBR/e5+nYOi2MyFGJ3tsFwONecQ==", "requires": { "@ethersproject/abstract-provider": "^5.0.8", "@ethersproject/bignumber": "^5.0.13", @@ -1146,9 +1244,9 @@ } }, "@ethersproject/address": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.9.tgz", - "integrity": "sha512-gKkmbZDMyGbVjr8nA5P0md1GgESqSGH7ILIrDidPdNXBl4adqbuA3OAuZx/O2oGpL6PtJ9BDa0kHheZ1ToHU3w==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.10.tgz", + "integrity": "sha512-70vqESmW5Srua1kMDIN6uVfdneZMaMyRYH4qPvkAXGkbicrCOsA9m01vIloA4wYiiF+HLEfL1ENKdn5jb9xiAw==", "requires": { "@ethersproject/bignumber": "^5.0.13", "@ethersproject/bytes": "^5.0.9", @@ -1158,26 +1256,26 @@ } }, "@ethersproject/base64": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.7.tgz", - "integrity": "sha512-S5oh5DVfCo06xwJXT8fQC68mvJfgScTl2AXvbYMsHNfIBTDb084Wx4iA9MNlEReOv6HulkS+gyrUM/j3514rSw==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.8.tgz", + "integrity": "sha512-PNbpHOMgZpZ1skvQl119pV2YkCPXmZTxw+T92qX0z7zaMFPypXWTZBzim+hUceb//zx4DFjeGT4aSjZRTOYThg==", "requires": { "@ethersproject/bytes": "^5.0.9" } }, "@ethersproject/basex": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.0.7.tgz", - "integrity": "sha512-OsXnRsujGmYD9LYyJlX+cVe5KfwgLUbUJrJMWdzRWogrygXd5HvGd7ygX1AYjlu1z8W/+t2FoQnczDR/H2iBjA==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.0.8.tgz", + "integrity": "sha512-PCVKZIShBQUqAXjJSvaCidThPvL0jaaQZcewJc0sf8Xx05BizaOS8r3jdPdpNdY+/qZtRDqwHTSKjvR/xssyLQ==", "requires": { "@ethersproject/bytes": "^5.0.9", "@ethersproject/properties": "^5.0.7" } }, "@ethersproject/bignumber": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.13.tgz", - "integrity": "sha512-b89bX5li6aK492yuPP5mPgRVgIxxBP7ksaBtKX5QQBsrZTpNOjf/MR4CjcUrAw8g+RQuD6kap9lPjFgY4U1/5A==", + "version": "5.0.14", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.14.tgz", + "integrity": "sha512-Q4TjMq9Gg3Xzj0aeJWqJgI3tdEiPiET7Y5OtNtjTAODZ2kp4y9jMNg97zVcvPedFvGROdpGDyCI77JDFodUzOw==", "requires": { "@ethersproject/bytes": "^5.0.9", "@ethersproject/logger": "^5.0.8", @@ -1185,25 +1283,25 @@ } }, "@ethersproject/bytes": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.9.tgz", - "integrity": "sha512-k+17ZViDtAugC0s7HM6rdsTWEdIYII4RPCDkPEuxKc6i40Bs+m6tjRAtCECX06wKZnrEoR9pjOJRXHJ/VLoOcA==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.10.tgz", + "integrity": "sha512-vpu0v1LZ1j1s9kERQIMnVU69MyHEzUff7nqK9XuCU4vx+AM8n9lU2gj7jtJIvGSt9HzatK/6I6bWusI5nyuaTA==", "requires": { "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/constants": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.8.tgz", - "integrity": "sha512-sCc73pFBsl59eDfoQR5OCEZCRv5b0iywadunti6MQIr5lt3XpwxK1Iuzd8XSFO02N9jUifvuZRrt0cY0+NBgTg==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.9.tgz", + "integrity": "sha512-2uAKH89UcaJP/Sc+54u92BtJtZ4cPgcS1p0YbB1L3tlkavwNvth+kNCUplIB1Becqs7BOZr0B/3dMNjhJDy4Dg==", "requires": { "@ethersproject/bignumber": "^5.0.13" } }, "@ethersproject/contracts": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.0.9.tgz", - "integrity": "sha512-CCTxVeDh6sjdSEbjzONhtwPjECvaHE62oGkY8M7kP0CHmgLD2SEGel0HZib8e5oQKRKGly9AKcUFW4g3rQ0AQw==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.0.11.tgz", + "integrity": "sha512-FTUUd/6x00dYL2VufE2VowZ7h3mAyBfCQMGwI3tKDIWka+C0CunllFiKrlYCdiHFuVeMotR65dIcnzbLn72MCw==", "requires": { "@ethersproject/abi": "^5.0.10", "@ethersproject/abstract-provider": "^5.0.8", @@ -1217,9 +1315,9 @@ } }, "@ethersproject/hash": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.10.tgz", - "integrity": "sha512-Tf0bvs6YFhw28LuHnhlDWyr0xfcDxSXdwM4TcskeBbmXVSKLv3bJQEEEBFUcRX0fJuslR3gCVySEaSh7vuMx5w==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.11.tgz", + "integrity": "sha512-H3KJ9fk33XWJ2djAW03IL7fg3DsDMYjO1XijiUb1hJ85vYfhvxu0OmsU7d3tg2Uv1H1kFSo8ghr3WFQ8c+NL3g==", "requires": { "@ethersproject/abstract-signer": "^5.0.10", "@ethersproject/address": "^5.0.9", @@ -1232,9 +1330,9 @@ } }, "@ethersproject/hdnode": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.0.8.tgz", - "integrity": "sha512-Mscpjd7BBjxYSWghaNMwV0xrBBkOoCq6YEPRm9MgE24CiBlzzbfEB5DGq6hiZqhQaxPkdCUtKKqZi3nt9hx43g==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.0.9.tgz", + "integrity": "sha512-S5UMmIC6XfFtqhUK4uTjD8GPNzSbE+sZ/0VMqFnA3zAJ+cEFZuEyhZDYnl2ItGJzjT4jsy+uEy1SIl3baYK1PQ==", "requires": { "@ethersproject/abstract-signer": "^5.0.10", "@ethersproject/basex": "^5.0.7", @@ -1251,9 +1349,9 @@ } }, "@ethersproject/json-wallets": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.0.10.tgz", - "integrity": "sha512-Ux36u+d7Dm0M5AQ+mWuHdvfGPMN8K1aaLQgwzrsD4ELTWlwRuHuQbmn7/GqeOpbfaV6POLwdYcBk2TXjlGp/IQ==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.0.11.tgz", + "integrity": "sha512-0GhWScWUlXXb4qJNp0wmkU95QS3YdN9UMOfMSEl76CRANWWrmyzxcBVSXSBu5iQ0/W8wO+xGlJJ3tpA6v3mbIw==", "requires": { "@ethersproject/abstract-signer": "^5.0.10", "@ethersproject/address": "^5.0.9", @@ -1271,48 +1369,48 @@ } }, "@ethersproject/keccak256": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.7.tgz", - "integrity": "sha512-zpUBmofWvx9PGfc7IICobgFQSgNmTOGTGLUxSYqZzY/T+b4y/2o5eqf/GGmD7qnTGzKQ42YlLNo+LeDP2qe55g==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.8.tgz", + "integrity": "sha512-zoGbwXcWWs9MX4NOAZ7N0hhgIRl4Q/IO/u9c/RHRY4WqDy3Ywm0OLamEV53QDwhjwn3YiiVwU1Ve5j7yJ0a/KQ==", "requires": { "@ethersproject/bytes": "^5.0.9", "js-sha3": "0.5.7" } }, "@ethersproject/logger": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.8.tgz", - "integrity": "sha512-SkJCTaVTnaZ3/ieLF5pVftxGEFX56pTH+f2Slrpv7cU0TNpUZNib84QQdukd++sWUp/S7j5t5NW+WegbXd4U/A==" + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.9.tgz", + "integrity": "sha512-kV3Uamv3XOH99Xf3kpIG3ZkS7mBNYcLDM00JSDtNgNB4BihuyxpQzIZPRIDmRi+95Z/R1Bb0X2kUNHa/kJoVrw==" }, "@ethersproject/networks": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.7.tgz", - "integrity": "sha512-dI14QATndIcUgcCBL1c5vUr/YsI5cCHLN81rF7PU+yS7Xgp2/Rzbr9+YqpC6NBXHFUASjh6GpKqsVMpufAL0BQ==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.8.tgz", + "integrity": "sha512-PYpptlO2Tu5f/JEBI5hdlMds5k1DY1QwVbh3LKPb3un9dQA2bC51vd2/gRWAgSBpF3kkmZOj4FhD7ATLX4H+DA==", "requires": { "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/pbkdf2": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.0.7.tgz", - "integrity": "sha512-0SNLNixPMqnosH6pyc4yPiUu/C9/Jbu+f6I8GJW9U2qNpMBddmRJviwseoha5Zw1V+Aw0Z/yvYyzIIE8yPXqLA==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.0.8.tgz", + "integrity": "sha512-UlmAMGbIPaS2xXsI38FbePVTfJMuU9jnwcqVn3p88HxPF4kD897ha+l3TNsBqJqf32UbQL5GImnf1oJkSKq4vQ==", "requires": { "@ethersproject/bytes": "^5.0.9", "@ethersproject/sha2": "^5.0.7" } }, "@ethersproject/properties": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.7.tgz", - "integrity": "sha512-812H1Rus2vjw0zbasfDI1GLNPDsoyX1pYqiCgaR1BuyKxUTbwcH1B+214l6VGe1v+F6iEVb7WjIwMjKhb4EUsg==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.8.tgz", + "integrity": "sha512-zEnLMze2Eu2VDPj/05QwCwMKHh506gpT9PP9KPVd4dDB+5d6AcROUYVLoIIQgBYK7X/Gw0UJmG3oVtnxOQafAw==", "requires": { "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/providers": { - "version": "5.0.19", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.0.19.tgz", - "integrity": "sha512-G+flo1jK1y/rvQy6b71+Nu7qOlkOKz+XqpgqFMZslkCzGuzQRmk9Qp7Ln4soK8RSyP1e5TCujaRf1H+EZahoaw==", + "version": "5.0.23", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.0.23.tgz", + "integrity": "sha512-eJ94z2tgPaUgUmxwd3BVkIzkgkbNIkY6wRPVas04LVaBTycObQbgj794aaUu2bfk7+Bn2B/gjUZtJW1ybxh9/A==", "requires": { "@ethersproject/abstract-provider": "^5.0.8", "@ethersproject/abstract-signer": "^5.0.10", @@ -1343,27 +1441,27 @@ } }, "@ethersproject/random": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.0.7.tgz", - "integrity": "sha512-PxSRWwN3s+FH9AWMZU6AcWJsNQ9KzqKV6NgdeKPtxahdDjCuXxTAuzTZNXNRK+qj+Il351UnweAGd+VuZcOAlQ==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.0.8.tgz", + "integrity": "sha512-4rHtotmd9NjklW0eDvByicEkL+qareIyFSbG1ShC8tPJJSAC0g55oQWzw+3nfdRCgBHRuEE7S8EcPcTVPvZ9cA==", "requires": { "@ethersproject/bytes": "^5.0.9", "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/rlp": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.7.tgz", - "integrity": "sha512-ulUTVEuV7PT4jJTPpfhRHK57tkLEDEY9XSYJtrSNHOqdwMvH0z7BM2AKIMq4LVDlnu4YZASdKrkFGEIO712V9w==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.8.tgz", + "integrity": "sha512-E4wdFs8xRNJfzNHmnkC8w5fPeT4Wd1U2cust3YeT16/46iSkLT8nn8ilidC6KhR7hfuSZE4UqSPzyk76p7cdZg==", "requires": { "@ethersproject/bytes": "^5.0.9", "@ethersproject/logger": "^5.0.8" } }, "@ethersproject/sha2": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.0.7.tgz", - "integrity": "sha512-MbUqz68hhp5RsaZdqi1eg1rrtiqt5wmhRYqdA7MX8swBkzW2KiLgK+Oh25UcWhUhdi1ImU9qrV6if5j0cC7Bxg==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.0.8.tgz", + "integrity": "sha512-ILP1ZgyvDj4rrdE+AXrTv9V88m7x87uga2VZ/FeULKPumOEw/4bGnJz/oQ8zDnDvVYRCJ+48VaQBS2CFLbk1ww==", "requires": { "@ethersproject/bytes": "^5.0.9", "@ethersproject/logger": "^5.0.8", @@ -1382,20 +1480,20 @@ } }, "@ethersproject/signing-key": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.8.tgz", - "integrity": "sha512-YKxQM45eDa6WAD+s3QZPdm1uW1MutzVuyoepdRRVmMJ8qkk7iOiIhUkZwqKLNxKzEJijt/82ycuOREc9WBNAKg==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.10.tgz", + "integrity": "sha512-w5it3GbFOvN6e0mTd5gDNj+bwSe6L9jqqYjU+uaYS8/hAEp4qYLk5p8ZjbJJkNn7u1p0iwocp8X9oH/OdK8apA==", "requires": { "@ethersproject/bytes": "^5.0.9", "@ethersproject/logger": "^5.0.8", "@ethersproject/properties": "^5.0.7", - "elliptic": "6.5.3" + "elliptic": "6.5.4" } }, "@ethersproject/solidity": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.0.8.tgz", - "integrity": "sha512-OJkyBq9KaoGsi8E8mYn6LX+vKyCURvxSp0yuGBcOqEFM3vkn9PsCiXsHdOXdNBvlHG5evJXwAYC2UR0TzgJeKA==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.0.9.tgz", + "integrity": "sha512-LIxSAYEQgLRXE3mRPCq39ou61kqP8fDrGqEeNcaNJS3aLbmAOS8MZp56uK++WsdI9hj8sNsFh78hrAa6zR9Jag==", "requires": { "@ethersproject/bignumber": "^5.0.13", "@ethersproject/bytes": "^5.0.9", @@ -1405,9 +1503,9 @@ } }, "@ethersproject/strings": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.8.tgz", - "integrity": "sha512-5IsdXf8tMY8QuHl8vTLnk9ehXDDm6x9FB9S9Og5IA1GYhLe5ZewydXSjlJlsqU2t9HRbfv97OJZV/pX8DVA/Hw==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.9.tgz", + "integrity": "sha512-ogxBpcUpdO524CYs841MoJHgHxEPUy0bJFDS4Ezg8My+WYVMfVAOlZSLss0Rurbeeam8CpUVDzM4zUn09SU66Q==", "requires": { "@ethersproject/bytes": "^5.0.9", "@ethersproject/constants": "^5.0.8", @@ -1415,9 +1513,9 @@ } }, "@ethersproject/transactions": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.9.tgz", - "integrity": "sha512-0Fu1yhdFBkrbMjenEr+39tmDxuHmaw0pe9Jb18XuKoItj7Z3p7+UzdHLr2S/okvHDHYPbZE5gtANDdQ3ZL1nBA==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.10.tgz", + "integrity": "sha512-Tqpp+vKYQyQdJQQk4M73tDzO7ODf2D42/sJOcKlDAAbdSni13v6a+31hUdo02qYXhVYwIs+ZjHnO4zKv5BNk8w==", "requires": { "@ethersproject/address": "^5.0.9", "@ethersproject/bignumber": "^5.0.13", @@ -1431,9 +1529,9 @@ } }, "@ethersproject/units": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.0.9.tgz", - "integrity": "sha512-4jIkcMVrJ3lCgXMO4M/2ww0/T/IN08vJTZld7FIAwa6aoBDTAy71+sby3sShl1SG3HEeKYbI3fBWauCUgPRUpQ==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.0.10.tgz", + "integrity": "sha512-eaiHi9ham5lbC7qpqxpae7OY/nHJUnRUnFFuEwi2VB5Nwe3Np468OAV+e+HR+jAK4fHXQE6PFBTxWGtnZuO37g==", "requires": { "@ethersproject/bignumber": "^5.0.13", "@ethersproject/constants": "^5.0.8", @@ -1441,9 +1539,9 @@ } }, "@ethersproject/wallet": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.0.10.tgz", - "integrity": "sha512-5siYr38NhqZKH6DUr6u4PdhgOKur8Q6sw+JID2TitEUmW0tOl8f6rpxAe77tw6SJT60D2UcvgsyLtl32+Nl+ig==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.0.11.tgz", + "integrity": "sha512-2Fg/DOvUltR7aZTOyWWlQhru+SKvq2UE3uEhXSyCFgMqDQNuc2nHXh1SHJtN65jsEbjVIppOe1Q7EQMvhmeeRw==", "requires": { "@ethersproject/abstract-provider": "^5.0.8", "@ethersproject/abstract-signer": "^5.0.10", @@ -1463,9 +1561,9 @@ } }, "@ethersproject/web": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.12.tgz", - "integrity": "sha512-gVxS5iW0bgidZ76kr7LsTxj4uzN5XpCLzvZrLp8TP+4YgxHfCeetFyQkRPgBEAJdNrexdSBayvyJvzGvOq0O8g==", + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.13.tgz", + "integrity": "sha512-G3x/Ns7pQm21ALnWLbdBI5XkW/jrsbXXffI9hKNPHqf59mTxHYtlNiSwxdoTSwCef3Hn7uvGZpaSgTyxs7IufQ==", "requires": { "@ethersproject/base64": "^5.0.7", "@ethersproject/bytes": "^5.0.9", @@ -1475,9 +1573,9 @@ } }, "@ethersproject/wordlists": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.0.8.tgz", - "integrity": "sha512-px2mloc1wAcdTbzv0ZotTx+Uh/dfnDO22D9Rx8xr7+/PUwAhZQjoJ9t7Hn72nsaN83rWBXsLvFcIRZju4GIaEQ==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.0.9.tgz", + "integrity": "sha512-Sn6MTjZkfbriod6GG6+p43W09HOXT4gwcDVNj0YoPYlo4Zq2Fk6b1CU9KUX3c6aI17PrgYb4qwZm5BMuORyqyQ==", "requires": { "@ethersproject/bytes": "^5.0.9", "@ethersproject/hash": "^5.0.10", @@ -1508,9 +1606,9 @@ } }, "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, "@jest/console": { @@ -1620,12 +1718,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2151,27 +2243,6 @@ "fastq": "^1.6.0" } }, - "@npmcli/move-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.0.tgz", - "integrity": "sha512-Iv2iq0JuyYjKeFkSR4LPaCdDZwlGK9X2cP/01nJcp3yMJ1FjNd9vpiEYvLUgzBxKPg2SFmaOhizoQsPc0LWeOQ==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^2.7.1" - }, - "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "@peculiar/asn1-schema": { "version": "2.0.27", "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.0.27.tgz", @@ -2191,6 +2262,12 @@ "tslib": "^2.0.0" } }, + "@polka/url": { + "version": "1.0.0-next.11", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.11.tgz", + "integrity": "sha512-3NsZsJIA/22P3QUyrEDNA2D133H4j224twJrdipXN38dpnIOzAbUDtOwkcJ5pXmn75w7LSQDjA4tO9dm1XlqlA==", + "dev": true + }, "@sinonjs/commons": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", @@ -2232,6 +2309,12 @@ "integrity": "sha512-8UT/J+xqCYfn3fKtOznAibsHpiuDshCb0fwgWxRazTT19Igp9ovoXMPhXyLD6m3CKQGTMHgqoxaFfMWaL40Rnw==", "dev": true }, + "@tsconfig/node14": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.0.tgz", + "integrity": "sha512-RKkL8eTdPv6t5EHgFKIVQgsDapugbuOptNd9OOunN/HAkzmmTnZELx1kNCK0rSdUYGmiFMM3rRQMAWiyp023LQ==", + "dev": true + }, "@types/asn1js": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/asn1js/-/asn1js-2.0.0.tgz", @@ -2278,57 +2361,185 @@ "@babel/types": "^7.3.0" } }, - "@types/graceful-fs": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.4.tgz", - "integrity": "sha512-mWA/4zFQhfvOA8zWkXobwJvBD7vzcxgrOQ0J5CH1votGqdq9m7+FwtGaqyCZqC3NyyBkc9z4m+iry4LlqcMWJg==", + "@types/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", "dev": true, "requires": { + "@types/connect": "*", "@types/node": "*" } }, - "@types/istanbul-lib-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", - "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", + "@types/connect": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz", + "integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/debug": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", + "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==", "dev": true }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "@types/eslint": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz", + "integrity": "sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "*" + "@types/estree": "*", + "@types/json-schema": "*" } }, - "@types/istanbul-reports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", - "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", + "@types/eslint-scope": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz", + "integrity": "sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==", "dev": true, "requires": { - "@types/istanbul-lib-report": "*" + "@types/eslint": "*", + "@types/estree": "*" } }, - "@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "@types/estree": { + "version": "0.0.46", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", + "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", "dev": true }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "@types/express": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.11.tgz", + "integrity": "sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.18", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz", + "integrity": "sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", + "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "26.0.20", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.20.tgz", + "integrity": "sha512-9zi2Y+5USJRxd0FsahERhBwlcvFh6D2GLQnY2FH2BzK8J9s9omvNHIbvABwIluXa0fD8XVKMLTO0aOEuUfACAA==", + "dev": true, + "requires": { + "jest-diff": "^26.0.0", + "pretty-format": "^26.0.0" + } + }, + "@types/json-schema": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "@types/lodash": { + "version": "4.14.168", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz", + "integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==", + "dev": true + }, + "@types/lodash.uniqueid": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/lodash.uniqueid/-/lodash.uniqueid-4.0.6.tgz", + "integrity": "sha512-WXXsDm7Q1SiAeCG9ubCiDxOuLEDi5x+Crx8SgwTFgBtofATwK1jAeSbGz2bHlfqWezi7mcjynenlBFCeDLhHlw==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", "dev": true }, "@types/node": { - "version": "14.14.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.21.tgz", - "integrity": "sha512-cHYfKsnwllYhjOzuC5q1VpguABBeecUp24yFluHpn/BQaVxB1CuQ1FSRZCzrPxrkIfWISXV2LbeoBthLWg0+0A==", + "version": "14.14.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz", + "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==", "dev": true }, + "@types/node-fetch": { + "version": "2.5.8", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz", + "integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -2336,9 +2547,46 @@ "dev": true }, "@types/prettier": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.6.tgz", - "integrity": "sha512-6gOkRe7OIioWAXfnO/2lFiv+SJichKVSys1mSsgyrYHSEjk8Ctv4tSR/Odvnu+HWlH2C8j53dahU03XmQdd5fA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-DxZZbyMAM9GWEzXL+BMZROWz9oo6A9EilwwOMET2UVu2uZTqMWS5S69KVtuVKaRjCUpcrOXRalet86/OpG4kqw==", + "dev": true + }, + "@types/qs": { + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", + "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.9", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz", + "integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/sinon": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.10.tgz", + "integrity": "sha512-/faDC0erR06wMdybwI/uR8wEKV/E83T0k4sepIpB7gXuy2gzx2xiOjmztq6a2Y6rIGJ04D+6UU0VBmWy+4HEMA==", + "dev": true, + "requires": { + "@types/sinonjs__fake-timers": "*" + } + }, + "@types/sinonjs__fake-timers": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", + "integrity": "sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==", "dev": true }, "@types/stack-utils": { @@ -2347,10 +2595,25 @@ "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", "dev": true }, + "@types/uuid": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz", + "integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==", + "dev": true + }, + "@types/ws": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.0.tgz", + "integrity": "sha512-Y29uQ3Uy+58bZrFLhX36hcI3Np37nqWE7ky5tjiDoy1GDZnIwVxS0CgF+s+1bXMzjKBFy+fqaRfb708iNzdinw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/yargs": { - "version": "15.0.12", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.12.tgz", - "integrity": "sha512-f+fD/fQAo3BCbCDlrUpznF1A5Zp9rB0noS5vnoormHSIPFKL0Z2DcUJ3Gxp5ytH4uLRNxy7AwYUC9exZzqGMAw==", + "version": "15.0.13", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz", + "integrity": "sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -2372,181 +2635,278 @@ "@types/node": "*" } }, - "@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "@typescript-eslint/eslint-plugin": { + "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": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" + "@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", + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } } }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", - "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", - "dev": true + "@typescript-eslint/experimental-utils": { + "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.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" + } }, - "@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", - "dev": true + "@typescript-eslint/parser": { + "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.17.0", + "@typescript-eslint/types": "4.17.0", + "@typescript-eslint/typescript-estree": "4.17.0", + "debug": "^4.1.1" + } }, - "@webassemblyjs/helper-buffer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", - "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "@typescript-eslint/scope-manager": { + "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.17.0", + "@typescript-eslint/visitor-keys": "4.17.0" + } + }, + "@typescript-eslint/types": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.17.0.tgz", + "integrity": "sha512-RN5z8qYpJ+kXwnLlyzZkiJwfW2AY458Bf8WqllkondQIcN2ZxQowAToGSd9BlAUZDB5Ea8I6mqL2quGYCLT+2g==", "dev": true }, - "@webassemblyjs/helper-code-frame": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", - "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "@typescript-eslint/typescript-estree": { + "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.17.0", + "@typescript-eslint/visitor-keys": "4.17.0", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "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": { - "@webassemblyjs/wast-printer": "1.9.0" + "@typescript-eslint/types": "4.17.0", + "eslint-visitor-keys": "^2.0.0" } }, - "@webassemblyjs/helper-fsm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", - "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "@webassemblyjs/ast": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", + "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", + "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", "dev": true }, - "@webassemblyjs/helper-module-context": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", - "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "@webassemblyjs/helper-api-error": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", + "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", + "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", + "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0" + "@webassemblyjs/floating-point-hex-parser": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@xtuc/long": "4.2.2" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", + "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", - "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", + "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0" + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0" } }, "@webassemblyjs/ieee754": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", - "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", + "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", - "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", + "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", "dev": true, "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", - "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", + "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", - "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", + "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/helper-wasm-section": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-opt": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "@webassemblyjs/wast-printer": "1.9.0" + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/helper-wasm-section": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-opt": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "@webassemblyjs/wast-printer": "1.11.0" } }, "@webassemblyjs/wasm-gen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", - "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", + "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" } }, "@webassemblyjs/wasm-opt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", - "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", + "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0" + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0" } }, "@webassemblyjs/wasm-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", - "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", + "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" } }, - "@webassemblyjs/wast-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", - "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "@webassemblyjs/wast-printer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", + "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/floating-point-hex-parser": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-code-frame": "1.9.0", - "@webassemblyjs/helper-fsm": "1.9.0", + "@webassemblyjs/ast": "1.11.0", "@xtuc/long": "4.2.2" } }, - "@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "@webpack-cli/configtest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.1.tgz", + "integrity": "sha512-B+4uBUYhpzDXmwuo3V9yBH6cISwxEI4J+NO5ggDaGEEHb0osY/R7MzeKc0bHURXQuZjMM4qD+bSJCKIuI3eNBQ==", + "dev": true + }, + "@webpack-cli/info": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.2.tgz", + "integrity": "sha512-5U9kUJHnwU+FhKH4PWGZuBC1hTEPYyxGSL5jjoBI96Gx8qcYJGOikpiIpFoTq8mmgX3im2zAo2wanv/alD74KQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" + "envinfo": "^7.7.3" } }, + "@webpack-cli/serve": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.0.tgz", + "integrity": "sha512-k2p2VrONcYVX1wRRrf0f3X2VGltLWcv+JzXRBDmvCxGlCeESx4OXw91TsWeKOkp784uNoVQo313vxJFHXPPwfw==", + "dev": true + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -2645,12 +3005,6 @@ "uri-js": "^4.2.2" } }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true - }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -2681,9 +3035,9 @@ } }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "ansi-styles": { @@ -2716,12 +3070,6 @@ } } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -2749,6 +3097,12 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", + "dev": true + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -2756,15 +3110,15 @@ "dev": true }, "array-includes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", - "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "get-intrinsic": "^1.0.1", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", "is-string": "^1.0.5" } }, @@ -2774,11 +3128,6 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, - "array-uniq": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz", - "integrity": "sha1-X8w3OSB3VyPP1k1lxkvvU7+eum0=" - }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -2825,33 +3174,6 @@ "pvutils": "^1.0.17" } }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -2904,6 +3226,15 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "available-typed-arrays": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", + "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", + "dev": true, + "requires": { + "array-filter": "^1.0.0" + } + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -3143,23 +3474,61 @@ "@types/babel__traverse": "^7.0.6" } }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true - }, - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "babel-plugin-polyfill-corejs2": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.1.5.tgz", + "integrity": "sha512-5IzdFIjYWqlOFVr/hMYUpc+5fbfuvJTAISwIY58jhH++ZtawtNlcJnxAixlk8ahVwHCz1ipW/kpXYliEBp66wg==", "dev": true, "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-plugin-syntax-class-properties": "^6.8.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "@babel/compat-data": "^7.13.0", + "@babel/helper-define-polyfill-provider": "^0.1.2", + "semver": "^6.1.1" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.4.tgz", + "integrity": "sha512-ysSzFn/qM8bvcDAn4mC7pKk85Y5dVaoa9h4u0mHxOEpDzabsseONhUpR7kHxpUinfj1bjU7mUZqD23rMZBoeSg==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.1.2", + "core-js-compat": "^3.8.1" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.1.3.tgz", + "integrity": "sha512-hRjTJQiOYt/wBKEc+8V8p9OJ9799blAJcuKzn1JXh3pApHoWl1Emxh2BHc6MC7Qt6bbr3uDpNxaYQnATLIudEg==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.1.2" + } + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", + "dev": true + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-plugin-syntax-class-properties": "^6.8.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } }, "babel-preset-current-node-syntax": { "version": "1.0.1", @@ -3397,16 +3766,6 @@ "dev": true, "optional": true }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -3592,46 +3951,29 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true } } }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "browserslist": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz", + "integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==", "dev": true, "requires": { - "pako": "~1.0.5" + "caniuse-lite": "^1.0.30001181", + "colorette": "^1.2.1", + "electron-to-chromium": "^1.3.649", + "escalade": "^3.1.1", + "node-releases": "^1.1.70" } }, - "browserslist": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz", - "integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==", + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001173", - "colorette": "^1.2.1", - "electron-to-chromium": "^1.3.634", - "escalade": "^3.1.1", - "node-releases": "^1.1.69" + "fast-json-stable-stringify": "2.x" } }, "bser": { @@ -3647,7 +3989,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -3671,11 +4012,14 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true + "bufferutil": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz", + "integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==", + "optional": true, + "requires": { + "node-gyp-build": "^4.2.0" + } }, "bytes": { "version": "3.1.0", @@ -3683,42 +4027,6 @@ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", "dev": true }, - "cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "dev": true, - "requires": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "dependencies": { - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - } - } - }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -3759,9 +4067,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001178", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001178.tgz", - "integrity": "sha512-VtdZLC0vsXykKni8Uztx45xynytOi71Ufx9T8kHptSw9AL4dpqailUJJHavttuzUe1KYuBYtChiWv+BAb7mPmQ==", + "version": "1.0.30001191", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001191.tgz", + "integrity": "sha512-xJJqzyd+7GCJXkcoBiQ1GuxEiOBCLQ0aVW9HMekifZsAVGdj5eJ4mFB9fEhSHipq9IOk/QXFJUiIr9lZT+EsGw==", "dev": true }, "capture-exit": { @@ -4040,12 +4348,6 @@ "wrap-ansi": "^6.2.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -4150,41 +4452,12 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, "confusing-browser-globals": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", "dev": true }, - "connection-parse": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/connection-parse/-/connection-parse-0.0.7.tgz", - "integrity": "sha1-GOcxiqsGppkmc3KxDFIm0locmmk=" - }, - "console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", - "dev": true - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, "contains-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", @@ -4198,6 +4471,14 @@ "dev": true, "requires": { "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } } }, "content-type": { @@ -4213,6 +4494,14 @@ "dev": true, "requires": { "safe-buffer": "~5.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } } }, "cookie": { @@ -4227,40 +4516,6 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -4268,17 +4523,18 @@ "dev": true }, "core-js": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.2.tgz", - "integrity": "sha512-FfApuSRgrR6G5s58casCBd9M2k+4ikuu4wbW6pJyYU7bd9zvFc9qf7vr5xmrZOhT9nn+8uwlH1oRR9jTnFoA3A==" + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.9.0.tgz", + "integrity": "sha512-PyFBJaLq93FlyYdsndE5VaueA9K5cNB7CGzeCj191YYLhkQM0gdZR2SKihM70oF0wdqKSKClv/tEBOpoRmdOVQ==", + "dev": true }, "core-js-compat": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.2.tgz", - "integrity": "sha512-LO8uL9lOIyRRrQmZxHZFl1RV+ZbcsAkFWTktn5SmH40WgLtSNYN4m4W2v9ONT147PxBY/XrRhrWq8TlvObyUjQ==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.9.0.tgz", + "integrity": "sha512-YK6fwFjCOKWwGnjFUR3c544YsnA/7DoLL0ysncuOJ4pwbriAtOpvM2bygdlcXbvQCQZ7bBU9CL4t7tGl7ETRpQ==", "dev": true, "requires": { - "browserslist": "^4.16.0", + "browserslist": "^4.16.3", "semver": "7.0.0" }, "dependencies": { @@ -4291,9 +4547,9 @@ } }, "core-js-pure": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.8.2.tgz", - "integrity": "sha512-v6zfIQqL/pzTVAbZvYUozsxNfxcFb6Ks3ZfEbuneJl3FW9Jb8F6vLWB6f+qTmAu72msUdyb84V8d/yBFf7FNnw==" + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.9.0.tgz", + "integrity": "sha512-3pEcmMZC9Cq0D4ZBh3pe2HLtqxpGNJBLXF/kZ2YzK17RbKp94w0HFbdbSx8H8kAlZG5k76hvLrkPm57Uyef+kg==" }, "core-util-is": { "version": "1.0.2", @@ -4400,12 +4656,6 @@ } } }, - "cyclist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", - "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", - "dev": true - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -4433,9 +4683,9 @@ } }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "requires": { "ms": "2.1.2" } @@ -4458,6 +4708,12 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, "deep-eql": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", @@ -4617,12 +4873,6 @@ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", "dev": true }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -4670,12 +4920,6 @@ "esutils": "^2.0.2" } }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, "domexception": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", @@ -4699,6 +4943,12 @@ "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", "dev": true }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -4706,18 +4956,38 @@ "dev": true, "requires": { "readable-stream": "^2.0.2" - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "ecc-jsbn": { @@ -4743,23 +5013,23 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.641", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.641.tgz", - "integrity": "sha512-b0DLhsHSHESC1I+Nx6n4w4Lr61chMd3m/av1rZQhS2IXTzaS5BMM5N+ldWdMIlni9CITMRM09m8He4+YV/92TA==", + "version": "1.3.672", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.672.tgz", + "integrity": "sha512-gFQe7HBb0lbOMqK2GAS5/1F+B0IMdYiAgB9OT/w1F4M7lgJK2aNOMNOM622aEax+nS1cTMytkiT0uMOkbtFmHw==", "dev": true }, "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "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" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" } }, "emittery": { @@ -4804,18 +5074,6 @@ "graceful-fs": "^4.1.2", "memory-fs": "^0.5.0", "tapable": "^1.0.0" - }, - "dependencies": { - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - } } }, "enquirer": { @@ -4828,9 +5086,9 @@ } }, "envinfo": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.3.tgz", - "integrity": "sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", + "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", "dev": true }, "errno": { @@ -4852,25 +5110,33 @@ } }, "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "version": "1.18.0-next.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz", + "integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==", "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2", "has": "^1.0.3", "has-symbols": "^1.0.1", "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", + "is-negative-zero": "^2.0.1", "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "object-inspect": "^1.9.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.3", + "string.prototype.trimstart": "^1.0.3" } }, + "es-module-lexer": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.0.tgz", + "integrity": "sha512-iuEGihqqhKWFgh72Q/Jtch7V2t/ft8w8IPP2aEN8ArYKO+IWyo6hsi96hCdgyeEDQIV3InhYQ9BlwUFPGXrbEQ==", + "dev": true + }, "es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -4977,12 +5243,12 @@ } }, "eslint": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.18.0.tgz", - "integrity": "sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.20.0.tgz", + "integrity": "sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", + "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.3.0", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -4994,7 +5260,7 @@ "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", "espree": "^7.3.1", - "esquery": "^1.2.0", + "esquery": "^1.4.0", "esutils": "^2.0.2", "file-entry-cache": "^6.0.0", "functional-red-black-tree": "^1.0.1", @@ -5021,11 +5287,14 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } }, "ansi-styles": { "version": "4.3.0", @@ -5335,9 +5604,9 @@ } }, "eslint-plugin-promise": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", - "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz", + "integrity": "sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ==", "dev": true }, "eslint-scope": { @@ -5399,9 +5668,9 @@ "dev": true }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -5451,40 +5720,40 @@ "dev": true }, "ethers": { - "version": "5.0.26", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.0.26.tgz", - "integrity": "sha512-MqA8Fvutn3qEW0yBJOHeV6KZmRpF2rqlL2B5058AGkUFsuu6j5Ns/FRlMsbGeQwBz801IB23jQp7vjRfFsKSkg==", - "requires": { - "@ethersproject/abi": "5.0.10", - "@ethersproject/abstract-provider": "5.0.8", - "@ethersproject/abstract-signer": "5.0.11", - "@ethersproject/address": "5.0.9", - "@ethersproject/base64": "5.0.7", - "@ethersproject/basex": "5.0.7", - "@ethersproject/bignumber": "5.0.13", - "@ethersproject/bytes": "5.0.9", - "@ethersproject/constants": "5.0.8", - "@ethersproject/contracts": "5.0.9", - "@ethersproject/hash": "5.0.10", - "@ethersproject/hdnode": "5.0.8", - "@ethersproject/json-wallets": "5.0.10", - "@ethersproject/keccak256": "5.0.7", - "@ethersproject/logger": "5.0.8", - "@ethersproject/networks": "5.0.7", - "@ethersproject/pbkdf2": "5.0.7", - "@ethersproject/properties": "5.0.7", - "@ethersproject/providers": "5.0.19", - "@ethersproject/random": "5.0.7", - "@ethersproject/rlp": "5.0.7", - "@ethersproject/sha2": "5.0.7", - "@ethersproject/signing-key": "5.0.8", - "@ethersproject/solidity": "5.0.8", - "@ethersproject/strings": "5.0.8", - "@ethersproject/transactions": "5.0.9", - "@ethersproject/units": "5.0.9", - "@ethersproject/wallet": "5.0.10", - "@ethersproject/web": "5.0.12", - "@ethersproject/wordlists": "5.0.8" + "version": "5.0.31", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.0.31.tgz", + "integrity": "sha512-zpq0YbNFLFn+t+ibS8UkVWFeK5w6rVMSvbSHrHAQslfazovLnQ/mc2gdN5+6P45/k8fPgHrfHrYvJ4XvyK/S1A==", + "requires": { + "@ethersproject/abi": "5.0.12", + "@ethersproject/abstract-provider": "5.0.9", + "@ethersproject/abstract-signer": "5.0.13", + "@ethersproject/address": "5.0.10", + "@ethersproject/base64": "5.0.8", + "@ethersproject/basex": "5.0.8", + "@ethersproject/bignumber": "5.0.14", + "@ethersproject/bytes": "5.0.10", + "@ethersproject/constants": "5.0.9", + "@ethersproject/contracts": "5.0.11", + "@ethersproject/hash": "5.0.11", + "@ethersproject/hdnode": "5.0.9", + "@ethersproject/json-wallets": "5.0.11", + "@ethersproject/keccak256": "5.0.8", + "@ethersproject/logger": "5.0.9", + "@ethersproject/networks": "5.0.8", + "@ethersproject/pbkdf2": "5.0.8", + "@ethersproject/properties": "5.0.8", + "@ethersproject/providers": "5.0.23", + "@ethersproject/random": "5.0.8", + "@ethersproject/rlp": "5.0.8", + "@ethersproject/sha2": "5.0.8", + "@ethersproject/signing-key": "5.0.10", + "@ethersproject/solidity": "5.0.9", + "@ethersproject/strings": "5.0.9", + "@ethersproject/transactions": "5.0.10", + "@ethersproject/units": "5.0.10", + "@ethersproject/wallet": "5.0.11", + "@ethersproject/web": "5.0.13", + "@ethersproject/wordlists": "5.0.9" } }, "eventemitter3": { @@ -5639,15 +5908,6 @@ } } }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, "expect": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz", @@ -5746,6 +6006,12 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, @@ -5945,6 +6211,12 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, "fastq": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", @@ -5972,16 +6244,10 @@ "pend": "~1.2.0" } }, - "figgy-pudding": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", - "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", - "dev": true - }, "file-entry-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", - "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "requires": { "flat-cache": "^3.0.4" @@ -6086,18 +6352,6 @@ "path-exists": "^4.0.0" } }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, "flat": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", @@ -6126,21 +6380,11 @@ } }, "flatted": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz", - "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", "dev": true }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, "follow-redirects": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz", @@ -6153,6 +6397,12 @@ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -6191,16 +6441,6 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, "fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -6227,18 +6467,6 @@ "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", "dev": true }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -6246,9 +6474,9 @@ "dev": true }, "fsevents": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz", - "integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, @@ -6301,9 +6529,9 @@ "dev": true }, "geckodriver": { - "version": "1.21.1", - "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-1.21.1.tgz", - "integrity": "sha512-i5pYkYFEjTMkSCWh8agNFJPCUxVPr9I3JsRQ+bAypt73urXFnB73GQxDbJPKzELUeLhbQybhNKNlKjxfgS1yAA==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-1.22.1.tgz", + "integrity": "sha512-pT5Wf3AVszsvu0I8XWQT6VX7GzVYtASxzluVMlMXb3wb+jlmE0IFNQ7VGfjpdDrwF/MraukmdFtVQLpSJH0M2A==", "dev": true, "requires": { "adm-zip": "0.4.16", @@ -6326,9 +6554,9 @@ "dev": true }, "get-intrinsic": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", - "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "dev": true, "requires": { "function-bind": "^1.1.1", @@ -6379,16 +6607,46 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true - } - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "getpass": { + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", @@ -6397,6 +6655,12 @@ "assert-plus": "^1.0.0" } }, + "git-revision-webpack-plugin": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/git-revision-webpack-plugin/-/git-revision-webpack-plugin-3.0.6.tgz", + "integrity": "sha512-vW/9dBahGbpKPcccy3xKkHgdWoH/cAPPc3lQw+3edl7b4j29JfNGVrja0a1d8ZoRe4nTN8GCPrF9aBErDnzx5Q==", + "dev": true + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -6434,60 +6698,11 @@ } } }, - "global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "requires": { - "global-prefix": "^3.0.0" - }, - "dependencies": { - "global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "requires": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true }, "globals": { "version": "11.12.0", @@ -6539,12 +6754,44 @@ "timed-out": "^2.0.0", "unzip-response": "^1.0.0", "url-parse-lax": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "dev": true }, "growl": { @@ -6560,6 +6807,15 @@ "dev": true, "optional": true }, + "gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dev": true, + "requires": { + "duplexer": "^0.1.2" + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -6592,6 +6848,14 @@ "dev": true, "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, "has-flag": { @@ -6647,25 +6911,6 @@ "inherits": "^2.0.4", "readable-stream": "^3.6.0", "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } } }, "hash.js": { @@ -6677,15 +6922,6 @@ "minimalistic-assert": "^1.0.1" } }, - "hashring": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/hashring/-/hashring-3.2.0.tgz", - "integrity": "sha1-/aTv3oqiLNuX+x0qZeiEAeHBRM4=", - "requires": { - "connection-parse": "0.0.x", - "simple-lru-cache": "0.0.x" - } - }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -6707,15 +6943,6 @@ "minimalistic-crypto-utils": "^1.0.1" } }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, "hosted-git-info": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", @@ -6805,12 +7032,6 @@ "sshpk": "^1.7.0" } }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, "https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", @@ -6841,12 +7062,6 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, "ignore": { "version": "5.1.8", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", @@ -6885,12 +7100,6 @@ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -6906,16 +7115,10 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", "dev": true }, "invariant": { @@ -6965,6 +7168,15 @@ } } }, + "is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -6988,9 +7200,9 @@ "dev": true }, "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", "dev": true }, "is-ci": { @@ -7087,6 +7299,12 @@ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true }, + "is-generator-function": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz", + "integrity": "sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ==", + "dev": true + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -7168,11 +7386,12 @@ "dev": true }, "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", "dev": true, "requires": { + "call-bind": "^1.0.2", "has-symbols": "^1.0.1" } }, @@ -7203,6 +7422,19 @@ "has-symbols": "^1.0.1" } }, + "is-typed-array": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", + "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.0-next.2", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -7492,6 +7724,86 @@ } } }, + "jest-circus": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-26.6.3.tgz", + "integrity": "sha512-ACrpWZGcQMpbv13XbzRzpytEJlilP/Su0JtNCi5r/xLpOUhnaIJr8leYYpLEMgPFURZISEHrnnpmB54Q/UziPw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/babel__traverse": "^7.0.4", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^26.6.2", + "is-generator-fn": "^2.0.0", + "jest-each": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-runner": "^26.6.3", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2", + "stack-utils": "^2.0.2", + "throat": "^5.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "jest-config": { "version": "26.6.3", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz", @@ -8206,9 +8518,9 @@ "dev": true }, "parse-json": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", - "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -8924,9 +9236,9 @@ "dev": true }, "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "dev": true, "requires": { "minimist": "^1.2.5" @@ -9014,9 +9326,9 @@ } }, "loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", "dev": true }, "loader-utils": { @@ -9051,9 +9363,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "lodash._arraycopy": { @@ -9133,6 +9445,12 @@ "lodash._isiterateecall": "^3.0.0" } }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, "lodash.defaultsdeep": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", @@ -9228,6 +9546,12 @@ "semver": "^5.6.0" } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "makeerror": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", @@ -9237,6 +9561,14 @@ "tmpl": "1.0.x" } }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "requires": { + "p-defer": "^1.0.0" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -9269,14 +9601,55 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, + "mem": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-8.0.0.tgz", + "integrity": "sha512-qrcJOe6uD+EW8Wrci1Vdiua/15Xw3n/QnaNXE7varnB6InxSk7nu3/i5jfy3S6kWxr8WYJ6R1o0afMUtvorTsA==", + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.1.0" + } + }, "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", "dev": true, "requires": { "errno": "^0.1.3", "readable-stream": "^2.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "merge-descriptors": { @@ -9341,25 +9714,24 @@ "dev": true }, "mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", "dev": true }, "mime-types": { - "version": "2.1.28", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", - "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", "dev": true, "requires": { - "mime-db": "1.45.0" + "mime-db": "1.46.0" } }, "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==" }, "minimalistic-assert": { "version": "1.0.1", @@ -9395,33 +9767,6 @@ "yallist": "^4.0.0" } }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, "minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", @@ -9432,24 +9777,6 @@ "yallist": "^4.0.0" } }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -9627,6 +9954,15 @@ "object-keys": "^1.0.11" } }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", @@ -9727,40 +10063,6 @@ } } }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -9853,12 +10155,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -9877,9 +10173,9 @@ } }, "nise": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", - "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0", @@ -9906,6 +10202,11 @@ } } }, + "node-abort-controller": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-1.1.0.tgz", + "integrity": "sha512-dEYmUqjtbivotqjraOe8UvhT/poFfog1BQRNsZm/MSEDDESk2cQ1tvD8kGyuN07TM/zoW+n42odL8zTeJupYdQ==" + }, "node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", @@ -9937,56 +10238,6 @@ "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", "dev": true }, - "node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - }, - "dependencies": { - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, "node-modules-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", @@ -10021,9 +10272,9 @@ } }, "node-releases": { - "version": "1.1.69", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.69.tgz", - "integrity": "sha512-DGIjo79VDEyAnRlfSqYTsy+yoHd2IOjJiKUozD2MV2D85Vso6Bug56mb9tT/fY5Urt0iqk01H7x+llAruDR2zA==", + "version": "1.1.70", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz", + "integrity": "sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw==", "dev": true }, "node-status-codes": { @@ -10180,14 +10431,14 @@ } }, "object.getownpropertydescriptors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz", - "integrity": "sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", + "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" + "es-abstract": "^1.18.0-next.2" } }, "object.pick": { @@ -10200,14 +10451,14 @@ } }, "object.values": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", - "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", + "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has": "^1.0.3" } }, @@ -10235,8 +10486,22 @@ "dev": true, "requires": { "mimic-fn": "^2.1.0" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + } } }, + "opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -10267,12 +10532,6 @@ "wcwidth": "^1.0.1" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -10394,11 +10653,10 @@ } } }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" }, "p-each-series": { "version": "2.2.0", @@ -10409,16 +10667,14 @@ "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { @@ -10428,6 +10684,17 @@ "dev": true, "requires": { "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } } }, "p-map": { @@ -10439,6 +10706,43 @@ "aggregate-error": "^3.0.0" } }, + "p-memoize": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/p-memoize/-/p-memoize-4.0.1.tgz", + "integrity": "sha512-km0sP12uE0dOZ5qP+s7kGVf07QngxyG0gS8sYFvFWhqlgzOsSy+m71aUejf/0akxj5W7gE//2G74qTv6b4iMog==", + "requires": { + "mem": "^6.0.1", + "mimic-fn": "^3.0.0" + }, + "dependencies": { + "mem": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-6.1.1.tgz", + "integrity": "sha512-Ci6bIfq/UgcxPTYa8dQQ5FY3BzKkT894bwXWXxC/zqs0XgMO2cT20CGkOqda7gZNkmK5VP4x89IGZ6K7hfbn3Q==", + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.0.0" + } + } + } + }, + "p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "requires": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + } + }, + "p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "requires": { + "p-finally": "^1.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -10506,23 +10810,6 @@ "thunkify": "^2.1.2" } }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", - "dev": true, - "requires": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -10554,12 +10841,6 @@ "error-ex": "^1.2.0" } }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, "parse5": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", @@ -10578,12 +10859,6 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", @@ -10733,12 +11008,6 @@ "react-is": "^17.0.1" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -10783,12 +11052,6 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, "promise-memoize": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/promise-memoize/-/promise-memoize-1.2.1.tgz", @@ -10919,29 +11182,6 @@ "once": "^1.3.1" } }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -10949,11 +11189,11 @@ "dev": true }, "pvtsutils": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.1.1.tgz", - "integrity": "sha512-Evbhe6L4Sxwu4SPLQ4LQZhgfWDQO3qa1lju9jM5cxsQp8vE10VipcSmo7hiJW48TmiHgVLgDtC2TL6/+ND+IVg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.1.2.tgz", + "integrity": "sha512-Yfm9Dsk1zfEpOWCaJaHfqtNXAFWNNHMFSCLN6jTnhuCCBCC2nqge4sAgo7UrkRBoAAYIL8TN/6LlLoNfZD/b5A==", "requires": { - "tslib": "^2.0.3" + "tslib": "^2.1.0" } }, "pvutils": { @@ -10966,24 +11206,17 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, "queue-microtask": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz", "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==", "dev": true }, + "quick-lru": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.0.0.tgz", + "integrity": "sha512-kQ3ACYYIALMi7x8xvMU+qSF6N6baMZms8/q3dn2XFiORhFrLbpR6vTRNGR80HwlakWSoY4RnGoCJWUgnyH6zZQ==" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -11003,14 +11236,6 @@ "safe-buffer": "^5.1.0" } }, - "randomstring": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/randomstring/-/randomstring-1.1.5.tgz", - "integrity": "sha1-bfBij3XL1ZMpMNn+OrTpVqGFGMM=", - "requires": { - "array-uniq": "1.0.2" - } - }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -11043,6 +11268,38 @@ "requires": { "pinkie-promise": "^2.0.0", "readable-stream": "^2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "read-pkg": { @@ -11135,18 +11392,13 @@ } }, "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, "readdirp": { @@ -11159,14 +11411,50 @@ "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "optional": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, - "receptacle": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/receptacle/-/receptacle-1.3.2.tgz", - "integrity": "sha512-HrsFvqZZheusncQRiEE7GatOAETrARKV/lnfYicIm8lbvp/JQOdADOfhjBd2DajvoszEyxSM6RlAAIZgEoeu/A==", + "rechoir": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", + "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", + "dev": true, "requires": { - "ms": "^2.1.1" + "resolve": "^1.9.0" } }, "regenerate": { @@ -11235,9 +11523,9 @@ "dev": true }, "regjsparser": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.6.tgz", - "integrity": "sha512-jjyuCp+IEMIm3N1H1LLTJW1EISEJV9+5oHdEyrt43Pg9cDSb6rrLZei2cVWpl0xTjmmlpec/lEQGYgM7xfpGCQ==", + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.7.tgz", + "integrity": "sha512-ib77G0uxsA2ovgiYbCVGx4Pv3PSttAx2vIwidqQzbL2U5S4Q+j00HdSAneSBuyVcMvEnTXMjiGgB+DlXozVhpQ==", "dev": true, "requires": { "jsesc": "~0.5.0" @@ -11396,12 +11684,12 @@ "dev": true }, "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { - "is-core-module": "^2.1.0", + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, @@ -11422,29 +11710,6 @@ } } }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "dependencies": { - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - } - } - }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -11513,20 +11778,10 @@ "queue-microtask": "^1.2.2" } }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safe-regex": { "version": "1.1.0", @@ -11697,12 +11952,6 @@ } } }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, "setprototypeof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", @@ -11720,22 +11969,11 @@ } }, "sha3": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/sha3/-/sha3-2.1.3.tgz", - "integrity": "sha512-Io53D4o9qOmf3Ow9p/DoGLQiQHhtuR0ulbyambvRSG+OX5yXExk2yYfvjHtb7AtOyk6K6+sPeK/qaowWc/E/GA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/sha3/-/sha3-2.1.4.tgz", + "integrity": "sha512-S8cNxbyb0UGUM2VhRD4Poe5N58gJnJsLJ5vC7FYWGUmGhcsj4++WaIOBFVDxlG0W3To6xBuiRh+i0Qp2oNCOtg==", "requires": { - "buffer": "5.6.0" - }, - "dependencies": { - "buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - } + "buffer": "6.0.3" } }, "shallow-clone": { @@ -11775,20 +12013,15 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, - "simple-lru-cache": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/simple-lru-cache/-/simple-lru-cache-0.0.2.tgz", - "integrity": "sha1-1ZzDoZPBpdAyD4Tucy9uRxPlEd0=" - }, "sinon": { - "version": "9.2.3", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.3.tgz", - "integrity": "sha512-m+DyAWvqVHZtjnjX/nuShasykFeiZ+nPuEfD4G3gpvKGkXRhkF/6NSt2qN2FjZhfrcHXFzUzI+NLnk+42fnLEw==", + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", + "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", "dev": true, "requires": { "@sinonjs/commons": "^1.8.1", "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.0", + "@sinonjs/samsam": "^5.3.1", "diff": "^4.0.2", "nise": "^4.0.4", "supports-color": "^7.1.0" @@ -11817,6 +12050,25 @@ } } }, + "sirv": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.11.tgz", + "integrity": "sha512-SR36i3/LSWja7AJNRBz4fF/Xjpn7lQFI30tZ434dIy+bitLYSP+ZEenHg36i23V2SGEz+kqjksg0uOGZ5LPiqg==", + "dev": true, + "requires": { + "@polka/url": "^1.0.0-next.9", + "mime": "^2.3.1", + "totalist": "^1.0.0" + }, + "dependencies": { + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true + } + } + }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -12069,9 +12321,9 @@ } }, "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", "dev": true }, "spdx-correct": { @@ -12138,15 +12390,6 @@ "tweetnacl": "~0.14.0" } }, - "ssri": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", - "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - }, "stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", @@ -12197,68 +12440,33 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, + "streamr-client-protocol": { + "version": "8.0.0-beta.2", + "resolved": "https://registry.npmjs.org/streamr-client-protocol/-/streamr-client-protocol-8.0.0-beta.2.tgz", + "integrity": "sha512-TwNkaBIQCyarkkTxpQuMBCu7Uqs0sH5CUK+/g6751J3ZL7VenZgv/dPRuQaatFDP5LboyRTo/qJxD+75TBfZBw==", "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "streamr-client-protocol": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/streamr-client-protocol/-/streamr-client-protocol-5.3.3.tgz", - "integrity": "sha512-9pdyuzAvE5QZLAP/bwt5m7LRtIsdHVmN+TRhx+NSsw9K9FdaXqJrnVlci07uPfidVlITu23/ahXDm629ZvWwfQ==", - "requires": { - "@babel/runtime-corejs3": "^7.11.2", - "core-js": "^3.6.5", - "debug": "^4.2.0", - "ethers": "^5.0.14", + "@babel/runtime-corejs3": "^7.12.13", + "debug": "^4.3.1", + "ethers": "^5.0.24", "eventemitter3": "^4.0.7", - "hashring": "^3.2.0", "heap": "^0.2.6", "promise-memoize": "^1.2.1", "secp256k1": "^4.0.2", - "sha3": "^2.1.3" + "sha3": "^2.1.3", + "strict-event-emitter-types": "^2.0.0" } }, "streamr-test-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/streamr-test-utils/-/streamr-test-utils-1.2.1.tgz", - "integrity": "sha512-rQYAxqZ+LNuPlbZSUV7yuu0innb5BeERvEHsyRuxaYIGRyj0qq6u896IyNeH3Lgdk1A1fGUf6OCgW4/EFnJA2g==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/streamr-test-utils/-/streamr-test-utils-1.3.1.tgz", + "integrity": "sha512-3ol+bRQOSUz6Qjso0/VDBNzTxD9msizCOtsHgx7YqGYkxtIUSlGbsVtZh3JhBnnm53BNyaNHS74+N7Mjoa+w5Q==", "dev": true }, + "strict-event-emitter-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz", + "integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==" + }, "string-length": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.1.tgz", @@ -12269,12 +12477,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -12297,12 +12499,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -12335,12 +12531,11 @@ } }, "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" } }, "strip-ansi": { @@ -12350,6 +12545,14 @@ "dev": true, "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, "strip-bom": { @@ -12431,9 +12634,9 @@ }, "dependencies": { "ajv": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz", - "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.1.1.tgz", + "integrity": "sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -12478,6 +12681,17 @@ "requires": { "debug": "4.3.1", "is2": "^2.0.6" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } } }, "terminal-link": { @@ -12491,9 +12705,9 @@ } }, "terser": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", - "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.6.0.tgz", + "integrity": "sha512-vyqLMoqadC1uR0vywqOZzriDYzgEkNJFK4q9GeyOBHIbiECHiWLKcWfbQWAUaPfxkjDhapSlZB9f7fkMrvkVjA==", "dev": true, "requires": { "commander": "^2.20.0", @@ -12516,31 +12730,19 @@ } }, "terser-webpack-plugin": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", - "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz", + "integrity": "sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q==", "dev": true, "requires": { - "cacache": "^15.0.5", - "find-cache-dir": "^3.3.1", - "jest-worker": "^26.5.0", - "p-limit": "^3.0.2", + "jest-worker": "^26.6.2", + "p-limit": "^3.1.0", "schema-utils": "^3.0.0", "serialize-javascript": "^5.0.1", "source-map": "^0.6.1", - "terser": "^5.3.4", - "webpack-sources": "^1.4.3" + "terser": "^5.5.1" }, "dependencies": { - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, "schema-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", @@ -12583,16 +12785,6 @@ "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", "dev": true }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, "thunkify": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", @@ -12605,27 +12797,12 @@ "integrity": "sha1-84sK6B03R9YoAB9B2vxlKs5nHAo=", "dev": true }, - "timers-browserify": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, "tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", "dev": true }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -12680,6 +12857,12 @@ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", "dev": true }, + "totalist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", + "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", + "dev": true + }, "tough-cookie": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", @@ -12708,6 +12891,174 @@ "punycode": "^2.1.1" } }, + "ts-jest": { + "version": "26.5.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.1.tgz", + "integrity": "sha512-G7Rmo3OJMvlqE79amJX8VJKDiRcd7/r61wh9fnvvG8cAjhA9edklGw/dCxRSQmfZ/z8NDums5srSVgwZos1qfg==", + "dev": true, + "requires": { + "@types/jest": "26.x", + "bs-logger": "0.x", + "buffer-from": "1.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^26.1.0", + "json5": "2.x", + "lodash": "4.x", + "make-error": "1.x", + "mkdirp": "1.x", + "semver": "7.x", + "yargs-parser": "20.x" + }, + "dependencies": { + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yargs-parser": { + "version": "20.2.6", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.6.tgz", + "integrity": "sha512-AP1+fQIWSM/sMiET8fyayjx/J+JmTPt2Mr0FkrgqB4todtfa53sOsrSAcIrJRD5XS20bKUwaDIuMkWKCEiQLKA==", + "dev": true + } + } + }, + "ts-loader": { + "version": "8.0.17", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.0.17.tgz", + "integrity": "sha512-OeVfSshx6ot/TCxRwpBHQ/4lRzfgyTkvi7ghDVrLXOHzTbSK413ROgu/xNqM72i3AFeAIJgQy78FwSMKmOW68w==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^2.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "ts-toolbelt": { + "version": "9.3.12", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.3.12.tgz", + "integrity": "sha512-xxvVS/vhnuiBnOplvkKQe4Npp+KvClBCf62v3LqEOMzcOL/6V8eEIqhNHm+dJQq5Obvx6e87eHe56yapW73xSQ==" + }, "tsconfig-paths": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", @@ -12736,11 +13087,22 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true + "tsutils": { + "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" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } }, "tunnel-agent": { "version": "0.6.0", @@ -12788,12 +13150,6 @@ "mime-types": "~2.1.24" } }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -12803,6 +13159,12 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "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": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -12843,24 +13205,6 @@ "set-value": "^2.0.1" } }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -12941,24 +13285,6 @@ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, "url-parse-lax": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", @@ -12974,28 +13300,33 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, + "utf-8-validate": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.4.tgz", + "integrity": "sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==", + "optional": true, "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } + "node-gyp-build": "^4.2.0" } }, - "util-deprecate": { + "util": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz", + "integrity": "sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { "version": "1.0.1", @@ -13060,12 +13391,6 @@ "extsprintf": "^1.2.0" } }, - "vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", - "dev": true - }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -13094,59 +13419,13 @@ } }, "watchpack": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", - "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", - "dev": true, - "requires": { - "chokidar": "^3.4.1", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0", - "watchpack-chokidar2": "^2.0.1" - } - }, - "watchpack-chokidar2": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", - "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz", + "integrity": "sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw==", "dev": true, - "optional": true, "requires": { - "chokidar": "^2.1.8" - }, - "dependencies": { - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - } + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" } }, "wcwidth": { @@ -13159,15 +13438,15 @@ } }, "webcrypto-core": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.1.8.tgz", - "integrity": "sha512-hKnFXsqh0VloojNeTfrwFoRM4MnaWzH6vtXcaFcGjPEu+8HmBdQZnps3/2ikOFqS8bJN1RYr6mI2P/FJzyZnXg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.2.0.tgz", + "integrity": "sha512-p76Z/YLuE4CHCRdc49FB/ETaM4bzM3roqWNJeGs+QNY1fOTzKTOVnhmudW1fuO+5EZg6/4LG9NJ6gaAyxTk9XQ==", "requires": { - "@peculiar/asn1-schema": "^2.0.12", + "@peculiar/asn1-schema": "^2.0.27", "@peculiar/json-schema": "^1.1.12", "asn1js": "^2.0.26", - "pvtsutils": "^1.0.11", - "tslib": "^2.0.1" + "pvtsutils": "^1.1.2", + "tslib": "^2.1.0" } }, "webidl-conversions": { @@ -13177,470 +13456,227 @@ "dev": true }, "webpack": { - "version": "4.46.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", - "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/wasm-edit": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.4.1", - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1", + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.24.0.tgz", + "integrity": "sha512-ZkDxabL/InAQy9jluQTA8VIB7Gkhsv5uMJdAIz4QP2u4zaOX6+Tig7Jv+WSwhHp9qTnAx0rmn0dVTUPqZGRLbg==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.46", + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/wasm-edit": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "acorn": "^8.0.4", + "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.5.0", - "eslint-scope": "^4.0.3", + "enhanced-resolve": "^5.7.0", + "es-module-lexer": "^0.4.0", + "eslint-scope": "^5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.4.0", - "loader-utils": "^1.2.3", - "memory-fs": "^0.4.1", - "micromatch": "^3.1.10", - "mkdirp": "^0.5.3", - "neo-async": "^2.6.1", - "node-libs-browser": "^2.2.1", - "schema-utils": "^1.0.0", - "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.7.4", - "webpack-sources": "^1.4.1" + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.1", + "watchpack": "^2.0.0", + "webpack-sources": "^2.1.1" }, "dependencies": { "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - }, - "cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.5.tgz", + "integrity": "sha512-v+DieK/HJkJOpFBETDJioequtc3PfxsWMaxIdIwujtF7FEV/MAyDQLlm6/zPvr7Mix07mLh6ccVwIsloceodlg==", "dev": true }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "enhanced-resolve": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz", + "integrity": "sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==", "dev": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" } }, - "find-up": { + "schema-utils": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" } }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "tapable": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", + "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", + "dev": true + } + } + }, + "webpack-bundle-analyzer": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.4.0.tgz", + "integrity": "sha512-9DhNa+aXpqdHk8LkLPTBU/dMfl84Y+WE2+KnfI6rSpNRNVKa0VGLjPd2pjFubDeqnWmulFggxmWBxhfJXZnR0g==", + "dev": true, + "requires": { + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "chalk": "^4.1.0", + "commander": "^6.2.0", + "gzip-size": "^6.0.0", + "lodash": "^4.17.20", + "opener": "^1.5.2", + "sirv": "^1.0.7", + "ws": "^7.3.1" + }, + "dependencies": { + "acorn": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.5.tgz", + "integrity": "sha512-v+DieK/HJkJOpFBETDJioequtc3PfxsWMaxIdIwujtF7FEV/MAyDQLlm6/zPvr7Mix07mLh6ccVwIsloceodlg==", "dev": true }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } + "acorn-walk": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.0.2.tgz", + "integrity": "sha512-+bpA9MJsHdZ4bgfDcpk0ozQyhhVct7rzOmO0s1IIr0AGGgKBljss8n2zp11rRP2wid5VGeh04CgeKzgat5/25A==", + "dev": true }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "yallist": "^3.0.2" + "color-convert": "^2.0.1" } }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "requires": { - "minimist": "^1.2.5" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "color-name": "~1.1.4" } }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true }, - "serialize-javascript": { + "has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - } - }, - "terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" + "has-flag": "^4.0.0" } - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true } } }, "webpack-cli": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", - "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "cross-spawn": "^6.0.5", - "enhanced-resolve": "^4.1.1", - "findup-sync": "^3.0.0", - "global-modules": "^2.0.0", - "import-local": "^2.0.0", - "interpret": "^1.4.0", - "loader-utils": "^1.4.0", - "supports-color": "^6.1.0", - "v8-compile-cache": "^2.1.1", - "yargs": "^13.3.2" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.5.0.tgz", + "integrity": "sha512-wXg/ef6Ibstl2f50mnkcHblRPN/P9J4Nlod5Hg9HGFgSeF8rsqDGHJeVe4aR26q9l62TUJi6vmvC2Qz96YJw1Q==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.0.1", + "@webpack-cli/info": "^1.2.2", + "@webpack-cli/serve": "^1.3.0", + "colorette": "^1.2.1", + "commander": "^7.0.0", + "enquirer": "^2.3.6", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "v8-compile-cache": "^2.2.0", + "webpack-merge": "^5.7.3" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "commander": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz", + "integrity": "sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg==", "dev": true }, - "cliui": { + "execa": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "dev": true, - "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" } }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", "dev": true }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "resolve-cwd": { + "is-stream": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "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.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "path-key": "^3.0.0" } } } @@ -13661,13 +13697,13 @@ "integrity": "sha512-aHdl/y2N7PW2Sx7K+r3AxpJO+aDMcYzMQd60Qxefq3+EwhewSbTBqNumOsCE1JsCUNoyfGj5465N0sSf6hc/5w==" }, "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.2.0.tgz", + "integrity": "sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==", "dev": true, "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" }, "dependencies": { "source-map": { @@ -13719,6 +13755,21 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "which-typed-array": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz", + "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.0", + "es-abstract": "^1.18.0-next.1", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + } + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -13773,15 +13824,6 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -13793,12 +13835,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -13852,9 +13888,9 @@ } }, "ws": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.2.tgz", - "integrity": "sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA==" + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz", + "integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==" }, "xml-name-validator": { "version": "3.0.0", @@ -13874,12 +13910,6 @@ "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", "dev": true }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, "y18n": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", @@ -13980,6 +14010,15 @@ "path-exists": "^3.0.0" } }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", @@ -14069,8 +14108,7 @@ "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" } } } diff --git a/package.json b/package.json index 31128c020..9834a2dd7 100644 --- a/package.json +++ b/package.json @@ -1,31 +1,57 @@ { "name": "streamr-client", - "version": "4.1.6", + "version": "5.0.0-beta.10", "description": "JavaScript client library for Streamr", "repository": { "type": "git", "url": "git://github.com/streamr-dev/streamr-client.git" }, - "main": "dist/streamr-client.nodejs.js", - "browser": "dist/streamr-client.web.min.js", - "directories": { - "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 dist/*; NODE_ENV=production webpack --mode=production --progress", - "benchmarks": "node test/benchmarks/publish.js", + "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", + "benchmark-build": "npm run build-benchmark", "benchmark": "npm run benchmarks", "prepack": "npm run build", - "dev": "webpack --progress --colors --watch --mode=development", - "eslint": "eslint .", + "prebuild": "npm run eslint -- --cache", + "watch": "webpack --progress --watch --mode=development", + "eslint": "eslint --cache-location=node_modules/.cache/.eslintcache/ '*/**/*.{js,ts}'", "test": "jest --detectOpenHandles", "test-unit": "jest test/unit --detectOpenHandles", + "test-types": "(cd test/exports && npm run link) && tsc --noEmit --incremental --project ./tsconfig.test.json", "coverage": "jest --coverage", - "test-integration": "jest --testPathIgnorePatterns='DataUnion' test/integration", - "test-integration-flakey": "jest test/integration/DataUnionEndpoints.test.js", + "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", + "test-flakey": "jest --forceExit test/flakey/*", "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" + "build-example": "cd examples/webpack && npm run build-with-parent", + "clear-cache": "rm -rf node_modules/.cache; rm -rf .cache; rm -rf dist; rm -rf vendor; jest --clearCache;" }, "engines": { "node": ">= 12" @@ -33,54 +59,104 @@ "author": "Streamr", "license": "Apache-2.0", "devDependencies": { - "@babel/cli": "^7.11.6", - "@babel/core": "^7.11.6", - "@babel/plugin-proposal-class-properties": "^7.10.1", - "@babel/plugin-transform-classes": "^7.10.3", - "@babel/plugin-transform-modules-commonjs": "^7.10.1", - "@babel/plugin-transform-runtime": "^7.11.5", - "@babel/preset-env": "^7.11.5", - "babel-loader": "^8.1.0", - "babel-plugin-add-module-exports": "^1.0.2", + "@babel/cli": "^7.12.17", + "@babel/core": "^7.12.17", + "@babel/helper-call-delegate": "^7.12.13", + "@babel/plugin-proposal-class-properties": "^7.12.13", + "@babel/plugin-transform-classes": "^7.12.13", + "@babel/plugin-transform-modules-commonjs": "^7.12.13", + "@babel/plugin-transform-runtime": "^7.12.17", + "@babel/preset-env": "^7.12.17", + "@babel/preset-typescript": "^7.12.17", + "@tsconfig/node14": "^1.0.0", + "@types/debug": "^4.1.5", + "@types/express": "^4.17.11", + "@types/jest": "^26.0.20", + "@types/lodash.uniqueid": "^4.0.6", + "@types/node": "^14.14.31", + "@types/node-fetch": "^2.5.8", + "@types/qs": "^6.9.5", + "@types/sinon": "^9.0.10", + "@types/uuid": "^8.3.0", + "@types/ws": "^7.4.0", + "@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", "benchmark": "^2.1.4", "buffer": "^6.0.3", "chromedriver": "^88.0.0", - "core-js": "^3.6.5", - "eslint": "^7.8.1", - "eslint-config-airbnb": "^18.2.0", + "core-js": "^3.9.0", + "crypto-browserify": "^3.12.0", + "eslint": "^7.20.0", + "eslint-config-airbnb": "^18.2.1", "eslint-config-streamr-nodejs": "^1.3.0", "eslint-loader": "^4.0.2", - "eslint-plugin-import": "^2.22.0", - "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-promise": "^4.3.1", + "ethers": "^5.0.31", "express": "^4.17.1", - "geckodriver": "^1.20.0", - "jest": "^26.4.2", - "nightwatch": "^1.4.1", - "sinon": "^9.0.3", - "streamr-test-utils": "^1.0.4", - "terser-webpack-plugin": "^4.1.0", - "webpack": "^4.44.1", - "webpack-cli": "^3.3.12", - "webpack-merge": "^5.1.3" + "geckodriver": "^1.22.1", + "git-revision-webpack-plugin": "^3.0.6", + "jest": "^26.6.3", + "jest-circus": "^26.6.3", + "nightwatch": "^1.5.1", + "process": "^0.11.10", + "sinon": "^9.2.4", + "streamr-test-utils": "^1.3.1", + "terser-webpack-plugin": "^5.1.1", + "ts-jest": "^26.5.1", + "ts-loader": "^8.0.17", + "typescript": "^4.2.3", + "util": "^0.12.3", + "webpack": "^5.23.0", + "webpack-bundle-analyzer": "^4.4.0", + "webpack-cli": "^4.5.0", + "webpack-merge": "^5.7.3" }, "#IMPORTANT": "babel-runtime must be in dependencies, not devDependencies", "dependencies": { - "@babel/runtime": "^7.11.2", - "debug": "^4.1.1", - "ethers": "^5.0.12", + "@babel/runtime": "^7.12.18", + "@babel/runtime-corejs3": "^7.12.18", + "@ethersproject/abi": "^5.0.12", + "@ethersproject/address": "^5.0.10", + "@ethersproject/bignumber": "^5.0.14", + "@ethersproject/bytes": "^5.0.10", + "@ethersproject/contracts": "^5.0.11", + "@ethersproject/keccak256": "^5.0.8", + "@ethersproject/providers": "^5.0.23", + "@ethersproject/sha2": "^5.0.8", + "@ethersproject/transactions": "^5.0.10", + "@ethersproject/wallet": "^5.0.11", + "@ethersproject/web": "^5.0.13", + "debug": "^4.3.2", "eventemitter3": "^4.0.7", "lodash.uniqueid": "^4.0.1", + "mem": "^8.0.0", + "node-abort-controller": "^1.1.0", "node-fetch": "^2.6.1", - "node-webcrypto-ossl": "^2.1.1", + "node-webcrypto-ossl": "^2.1.2", "once": "^1.4.0", + "p-limit": "^3.1.0", + "p-memoize": "^4.0.1", + "p-queue": "^6.6.2", "promise-memoize": "^1.2.1", - "qs": "^6.9.4", - "randomstring": "^1.1.5", - "receptacle": "^1.3.2", - "streamr-client-protocol": "^5.3.3", - "uuid": "^8.3.0", + "qs": "^6.9.6", + "quick-lru": "^6.0.0", + "readable-stream": "^3.6.0", + "streamr-client-protocol": "^8.0.0-beta.2", + "ts-toolbelt": "^9.3.12", + "uuid": "^8.3.2", "webpack-node-externals": "^2.5.2", - "ws": "^7.3.1" - } + "ws": "^7.4.3" + }, + "optionalDependencies": { + "bufferutil": "^4.0.3", + "utf-8-validate": "^5.0.4" + }, + "bugs": { + "url": "https://github.com/streamr-dev/streamr-client/issues" + }, + "homepage": "https://github.com/streamr-dev/streamr-client#readme" } diff --git a/src/AbstractSubscription.js b/src/AbstractSubscription.js deleted file mode 100644 index 8f49b4b29..000000000 --- a/src/AbstractSubscription.js +++ /dev/null @@ -1,287 +0,0 @@ -import { Errors, Utils } from 'streamr-client-protocol' - -import Subscription from './Subscription' -import UnableToDecryptError from './errors/UnableToDecryptError' - -const { OrderingUtil } = Utils - -const MAX_NB_GROUP_KEY_REQUESTS = 10 - -function decryptErrorToDisplay(error) { - const ciphertext = error.streamMessage.getSerializedContent() - return ciphertext.length > 100 ? `${ciphertext.slice(0, 100)}...` : ciphertext -} - -export default class AbstractSubscription extends Subscription { - constructor(streamId, streamPartition, callback, groupKeys, propagationTimeout, resendTimeout, orderMessages = true, onUnableToDecrypt, debug) { - super(streamId, streamPartition, callback, groupKeys, propagationTimeout, resendTimeout, debug) - this.callback = callback - this.pendingResendRequestIds = {} - this._lastMessageHandlerPromise = {} - if (onUnableToDecrypt) { - this.onUnableToDecrypt = onUnableToDecrypt - } - this.onUnableToDecrypt = this.onUnableToDecrypt.bind(this) - this.orderingUtil = (orderMessages) ? new OrderingUtil(streamId, streamPartition, (orderedMessage) => { - this._inOrderHandler(orderedMessage) - }, (from, to, publisherId, msgChainId) => { - this.emit('gap', from, to, publisherId, msgChainId) - }, this.propagationTimeout, this.resendTimeout) : undefined - - /** * Message handlers ** */ - - this.on('unsubscribed', () => { - this._clearGaps() - this.setResending(false) - }) - - this.on('disconnected', () => { - this.setState(Subscription.State.unsubscribed) - this._clearGaps() - this.setResending(false) - }) - - this.on('error', (error) => { - this._clearGaps() - this.onError(error) - }) - - this.encryptedMsgsQueues = {} - this.waitingForGroupKey = {} - this.nbGroupKeyRequests = {} - } - - /** - * Override to control output - */ - - onError(error) { // eslint-disable-line class-methods-use-this - console.error(error) - } - - // eslint-disable-next-line class-methods-use-this - onUnableToDecrypt(error) { - this.debug(`WARN: Unable to decrypt: ${decryptErrorToDisplay(error)}`) - } - - _addMsgToQueue(encryptedMsg) { - const publisherId = encryptedMsg.getPublisherId().toLowerCase() - if (!this.encryptedMsgsQueues[publisherId]) { - this.encryptedMsgsQueues[publisherId] = [] - } - this.encryptedMsgsQueues[publisherId].push(encryptedMsg) - } - - _emptyMsgQueues() { - const queues = Object.values(this.encryptedMsgsQueues) - for (let i = 0; i < queues.length; i++) { - if (queues[i].length > 0) { - return false - } - } - return true - } - - _inOrderHandler(orderedMessage) { - return this._catchAndEmitErrors(() => { - if (!this.waitingForGroupKey[orderedMessage.getPublisherId().toLowerCase()]) { - this._decryptAndHandle(orderedMessage) - } else { - this._addMsgToQueue(orderedMessage) - } - }) - } - - _decryptAndHandle(orderedMessage) { - let success - try { - success = this._decryptOrRequestGroupKey(orderedMessage, orderedMessage.getPublisherId().toLowerCase()) - } catch (err) { - if (err instanceof UnableToDecryptError) { - this.onUnableToDecrypt(err) - } else { - throw err - } - } - if (success) { - this.callback(orderedMessage.getParsedContent(), orderedMessage) - if (orderedMessage.isByeMessage()) { - this.emit('done') - } - } else { - this.debug('Failed to decrypt. Requested the correct decryption key(s) and going to try again.') - } - } - - _requestGroupKeyAndQueueMessage(msg, start, end) { - this.emit('groupKeyMissing', msg.getPublisherId(), start, end) - const publisherId = msg.getPublisherId().toLowerCase() - this.nbGroupKeyRequests[publisherId] = 1 // reset retry counter - clearInterval(this.waitingForGroupKey[publisherId]) - this.waitingForGroupKey[publisherId] = setInterval(() => { - if (this.nbGroupKeyRequests[publisherId] < MAX_NB_GROUP_KEY_REQUESTS) { - this.nbGroupKeyRequests[publisherId] += 1 - this.emit('groupKeyMissing', msg.getPublisherId(), start, end) - } else { - this.debug(`WARN: Failed to receive group key response from ${publisherId} after ${MAX_NB_GROUP_KEY_REQUESTS} requests.`) - this._cancelGroupKeyRequest(publisherId) - } - }, this.propagationTimeout) - this._addMsgToQueue(msg) - } - - _handleEncryptedQueuedMsgs(publisherId) { - this._cancelGroupKeyRequest(publisherId.toLowerCase()) - const queue = this.encryptedMsgsQueues[publisherId.toLowerCase()] - while (queue.length > 0) { - this._decryptAndHandle(queue.shift()) - } - } - - _cancelGroupKeyRequest(publisherId) { - clearInterval(this.waitingForGroupKey[publisherId]) - this.waitingForGroupKey[publisherId] = undefined - delete this.waitingForGroupKey[publisherId] - } - - addPendingResendRequestId(requestId) { - this.pendingResendRequestIds[requestId] = true - } - - async handleResentMessage(msg, requestId, verifyFn) { - this._lastMessageHandlerPromise[requestId] = this._catchAndEmitErrors(async () => { - if (!this.isResending()) { - throw new Error(`There is no resend in progress, but received resent message ${msg.serialize()}`) - } else { - await this._handleMessage(msg, verifyFn) - } - }) - return this._lastMessageHandlerPromise[requestId] - } - - async handleResending(response) { - return this._catchAndEmitErrors(() => { - if (!this.pendingResendRequestIds[response.requestId]) { - throw new Error(`Received unexpected ResendResponseResending message ${response.serialize()}`) - } - this.emit('resending', response) - }) - } - - async handleResent(response) { - return this._catchAndEmitErrors(async () => { - if (!this.pendingResendRequestIds[response.requestId]) { - throw new Error(`Received unexpected ResendResponseResent message ${response.serialize()}`) - } - - if (!this._lastMessageHandlerPromise[response.requestId]) { - throw new Error('Attempting to handle ResendResponseResent, but no messages have been received!') - } - - // Delay event emission until the last message in the resend has been handled - await this._lastMessageHandlerPromise[response.requestId] - try { - this.emit('resent', response) - } finally { - this.cleanupResponse(response) - } - }) - } - - async handleNoResend(response) { - return this._catchAndEmitErrors(async () => { - if (!this.pendingResendRequestIds[response.requestId]) { - throw new Error(`Received unexpected ResendResponseNoResend message ${response.serialize()}`) - } - try { - this.emit('no_resend', response) - } finally { - this.cleanupResponse(response) - } - }) - } - - cleanupResponse(response) { - delete this.pendingResendRequestIds[response.requestId] - delete this._lastMessageHandlerPromise[response.requestId] - if (Object.keys(this.pendingResendRequestIds).length === 0) { - this.finishResend() - } - } - - _clearGaps() { - if (this.orderingUtil) { - this.orderingUtil.clearGaps() - } - Object.keys(this.waitingForGroupKey).forEach((publisherId) => this._cancelGroupKeyRequest(publisherId)) - } - - stop() { - this._clearGaps() - } - - getState() { - return this.state - } - - setState(state) { - this.debug(`Subscription: Stream ${this.streamId} state changed ${this.state} => ${state}`) - this.state = state - this.emit(state) - } - - handleError(err) { - /** - * If parsing the (expected) message failed, we should still mark it as received. Otherwise the - * gap detection will think a message was lost, and re-request the failing message. - */ - if (err instanceof Errors.InvalidJsonError && err.streamMessage && this.orderingUtil) { - this.orderingUtil.markMessageExplicitly(err.streamMessage) - } - this.emit('error', err) - } - - async _catchAndEmitErrors(fn) { - try { - return await fn() - } catch (err) { - this.emit('error', err) - // Swallow rejection - return Promise.resolve() - } - } - - /** - * Ensures validations resolve in order that they were triggered - */ - - async _queuedValidate(msg, verifyFn) { - // wait for previous validation (if any) - const queue = Promise.all([ - this.validationQueue, - // kick off job in parallel - verifyFn(msg), - ]).then((value) => { - this.validationQueue = null // clean up (allow gc) - return value - }, (err) => { - this.validationQueue = null // clean up (allow gc) - throw err - }) - this.validationQueue = queue - return queue - } - - async _handleMessage(msg, verifyFn) { - await this._queuedValidate(msg, verifyFn) - this.emit('message received') - if (this.orderingUtil) { - this.orderingUtil.add(msg) - } else { - this._inOrderHandler(msg) - } - } -} - -AbstractSubscription.defaultUnableToDecrypt = AbstractSubscription.prototype.defaultUnableToDecrypt -AbstractSubscription.MAX_NB_GROUP_KEY_REQUESTS = MAX_NB_GROUP_KEY_REQUESTS diff --git a/src/CombinedSubscription.js b/src/CombinedSubscription.js deleted file mode 100644 index ad143b6d6..000000000 --- a/src/CombinedSubscription.js +++ /dev/null @@ -1,137 +0,0 @@ -import HistoricalSubscription from './HistoricalSubscription' -import RealTimeSubscription from './RealTimeSubscription' -import Subscription from './Subscription' -import AbstractSubscription from './AbstractSubscription' - -export default class CombinedSubscription extends Subscription { - constructor(streamId, streamPartition, callback, options, groupKeys, propagationTimeout, resendTimeout, orderMessages = true, - onUnableToDecrypt = AbstractSubscription.defaultUnableToDecrypt, debug) { - super(streamId, streamPartition, callback, groupKeys, propagationTimeout, resendTimeout) - - this.sub = new HistoricalSubscription(streamId, streamPartition, callback, options, - groupKeys, this.propagationTimeout, this.resendTimeout, orderMessages, onUnableToDecrypt, debug) - this.realTimeMsgsQueue = [] - this.sub.on('message received', (msg) => { - if (msg) { - this.realTimeMsgsQueue.push(msg) - } - }) - this.sub.on('initial_resend_done', async () => { - this._unbindListeners(this.sub) - const realTime = new RealTimeSubscription(streamId, streamPartition, callback, - groupKeys, this.propagationTimeout, this.resendTimeout, orderMessages, onUnableToDecrypt, debug) - this._bindListeners(realTime) - if (this.sub.orderingUtil) { - realTime.orderingUtil.orderedChains = this.sub.orderingUtil.orderedChains - Object.keys(this.sub.orderingUtil.orderedChains).forEach((key) => { - realTime.orderingUtil.orderedChains[key].inOrderHandler = realTime.orderingUtil.inOrderHandler - realTime.orderingUtil.orderedChains[key].gapHandler = realTime.orderingUtil.gapHandler - }) - } - await Promise.all(this.realTimeMsgsQueue.map((msg) => realTime.handleBroadcastMessage(msg, () => true))) - this.realTimeMsgsQueue = [] - this.sub = realTime - }) - this._bindListeners(this.sub) - } - - _bindListeners(sub) { - sub.on('done', () => this.emit('done')) - sub.on('gap', (from, to, publisherId, msgChainId) => this.emit('gap', from, to, publisherId, msgChainId)) - sub.on('error', (err) => this.emit('error', err)) - sub.on('resending', (response) => this.emit('resending', response)) - sub.on('resent', (response) => this.emit('resent', response)) - sub.on('no_resend', (response) => this.emit('no_resend', response)) - sub.on('initial_resend_done', (response) => this.emit('initial_resend_done', response)) - sub.on('message received', () => this.emit('message received')) - sub.on('groupKeyMissing', (publisherId, start, end) => this.emit('groupKeyMissing', publisherId, start, end)) - - // hack to ensure inner subscription state is reflected in the outer subscription state - // restore in _unbindListeners - // still not foolproof though - /* eslint-disable no-param-reassign */ - sub.setState = this.setState.bind(this) - sub.getState = this.getState.bind(this) - /* eslint-enable no-param-reassign */ - } - - _unbindListeners(sub) { - this.sub.removeAllListeners() - - // delete to (probably) restore original (prototype) methods - /* eslint-disable no-param-reassign */ - if (Object.hasOwnProperty.call(sub, 'setState')) { - delete sub.setState - } - - if (Object.hasOwnProperty.call(sub, 'getState')) { - delete sub.getState - } - /* eslint-enable no-param-reassign */ - } - - stop() { - return this.sub.stop() - } - - addPendingResendRequestId(requestId) { - this.sub.addPendingResendRequestId(requestId) - } - - async handleResentMessage(msg, requestId, verifyFn) { - return this.sub.handleResentMessage(msg, requestId, verifyFn) - } - - async handleResending(response) { - return this.sub.handleResending(response) - } - - async handleResent(response) { - return this.sub.handleResent(response) - } - - async handleNoResend(response) { - return this.sub.handleNoResend(response) - } - - async handleBroadcastMessage(msg, verifyFn) { - return this.sub.handleBroadcastMessage(msg, verifyFn) - } - - finishResend() { - return this.sub.finishResend() - } - - hasResendOptions() { - return this.sub.hasResendOptions() - } - - getResendOptions() { - return this.sub.getResendOptions() - } - - setResending(resending) { - return this.sub.setResending(resending) - } - - setState(state) { - this.sub.state = state - super.setState(state) - } - - setGroupKeys(publisherId, groupKeys) { - this.sub.setGroupKeys(publisherId, groupKeys) - } - - handleError(err) { - return this.sub.handleError(err) - } - - onDisconnected() { - this.sub.onDisconnected() - } - - isResending() { - return this.sub.isResending() - } -} diff --git a/src/Config.ts b/src/Config.ts new file mode 100644 index 000000000..156c6bd94 --- /dev/null +++ b/src/Config.ts @@ -0,0 +1,165 @@ +import qs from 'qs' +import { ControlLayer, MessageLayer } from 'streamr-client-protocol' +import { ExternalProvider, JsonRpcFetchFunc } from '@ethersproject/providers' +import { BigNumber } from '@ethersproject/bignumber' +import { getVersionString } from './utils' +import { ConnectionInfo } from '@ethersproject/web' +import { EthereumAddress, Todo } from './types' +import { BytesLike } from '@ethersproject/bytes' + +export type EthereumConfig = ExternalProvider|JsonRpcFetchFunc + +export type StrictStreamrClientOptions = { + auth: { + privateKey?: BytesLike + ethereum?: EthereumConfig + apiKey?: string + username?: string + password?: string + } + url: string + restUrl: string + streamrNodeAddress: EthereumAddress + autoConnect: boolean + autoDisconnect: boolean + orderMessages: boolean + retryResendAfter: number + gapFillTimeout: number + maxGapRequests: number + maxPublishQueueSize: number + publishWithSignature: Todo + verifySignatures: Todo + publisherStoreKeyHistory: boolean + groupKeys: Todo + keyExchange: Todo + mainnet?: ConnectionInfo|string + sidechain: ConnectionInfo & { chainId?: number } + 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 + +/** @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 + + // Streamr Core options + url: 'wss://streamr.network/api/v1/ws', // The server to connect to + restUrl: 'https://streamr.network/api/v1', // Core API calls go here + streamrNodeAddress: '0xf3E5A65851C3779f468c9EcB32E6f25D9D68601a', // joinPartAgent when using EE for join part handling + + // P2P Streamr Network options + autoConnect: true, // Automatically connect on first subscribe + autoDisconnect: true, // Automatically disconnect on last unsubscribe + orderMessages: true, + retryResendAfter: 5000, + gapFillTimeout: 5000, + maxGapRequests: 5, + maxPublishQueueSize: 10000, + + // Encryption options + publishWithSignature: 'auto', + verifySignatures: 'auto', + publisherStoreKeyHistory: true, + groupKeys: {}, // {streamId: groupKey} + keyExchange: {}, + + // 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: { + url: 'https://rpc.xdaichain.com/', + chainId: 100 + }, + tokenAddress: '0x0Cf0Ee63788A0849fE5297F3407f701E122cC023', + dataUnion: { + minimumWithdrawTokenWei: '1000000', // Threshold value set in AMB configs, smallest token amount to pass over the bridge + // 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 + freeWithdraw: false, + factoryMainnetAddress: '0x7d55f9981d4E10A193314E001b96f72FCc901e40', + factorySidechainAddress: '0x1b55587Beea0b5Bc96Bb2ADa56bD692870522e9f', + templateMainnetAddress: '0x5FE790E3751dd775Cb92e9086Acd34a2adeB8C7b', + templateSidechainAddress: '0xf1E9d6E254BeA3f0129018AcA1A50AEcb7D528be', + }, + cache: { + maxSize: 10000, + maxAge: 30 * 60 * 1000, // 30 minutes + } + } + + const options: StrictStreamrClientOptions = { + ...defaults, + ...opts, // sidechain is not merged with the defaults + dataUnion: { + ...defaults.dataUnion, + ...opts.dataUnion + }, + cache: { + ...opts.cache, + ...defaults.cache, + } + } + + const parts = options.url!.split('?') + if (parts.length === 1) { // there is no query string + const controlLayer = `controlLayerVersion=${ControlMessage.LATEST_VERSION}` + const messageLayer = `messageLayerVersion=${StreamMessage.LATEST_VERSION}` + options.url = `${options.url}?${controlLayer}&${messageLayer}` + } else { + const queryObj = qs.parse(parts[1]) + if (!queryObj.controlLayerVersion) { + options.url = `${options.url}&controlLayerVersion=1` + } + + if (!queryObj.messageLayerVersion) { + options.url = `${options.url}&messageLayerVersion=31` + } + } + + // always add streamrClient version + options.url = `${options.url}&streamrClient=${getVersionString()}` + + // Backwards compatibility for option 'authKey' => 'apiKey' + // @ts-expect-error + if (options.authKey && !options.apiKey) { + // @ts-expect-error + options.apiKey = options.authKey + } + + // @ts-expect-error + if (options.apiKey) { + // @ts-expect-error + options.auth.apiKey = options.apiKey + } + + options.auth = options.auth || {} + + if ('privateKey' in options.auth) { + const { privateKey } = options.auth + if (typeof privateKey === 'string' && !privateKey.startsWith('0x')) { + options.auth.privateKey = `0x${options.auth!.privateKey}` + } + } + + return options +} diff --git a/src/Connection.js b/src/Connection.js deleted file mode 100644 index 41b0f98cb..000000000 --- a/src/Connection.js +++ /dev/null @@ -1,169 +0,0 @@ -import EventEmitter from 'eventemitter3' -import debugFactory from 'debug' -import uniqueId from 'lodash.uniqueid' -import WebSocket from 'ws' -import { ControlLayer } from 'streamr-client-protocol' - -class Connection extends EventEmitter { - constructor(options, socket) { - super() - if (!options.url) { - throw new Error('URL is not defined!') - } - const id = uniqueId('Connection') - if (options.debug) { - this.debug = options.debug.extend(id) - } else { - this.debug = debugFactory(`StreamrClient::${id}`) - } - this.options = options - this.state = Connection.State.DISCONNECTED - this.socket = socket - this._reconnectTimeout = null - } - - updateState(state) { - this.state = state - this.emit(state) - } - - async connect() { - if (this.state === Connection.State.CONNECTING) { - throw new Error('Already connecting!') - } - - if (this.state === Connection.State.CONNECTED) { - throw new Error('Already connected!') - } - - if (this.state === Connection.State.DISCONNECTING) { - return new Promise((resolve) => { - this.once('disconnected', () => resolve(this.connect())) - }) - } - - if (!this.socket || this.socket.readyState === WebSocket.CLOSED) { - this.debug('Trying to open new websocket to %s', this.options.url) - this.socket = new WebSocket(this.options.url) - } - - this.socket.binaryType = 'arraybuffer' - this.socket.events = new EventEmitter() - - this.socket.onopen = () => this.socket.events.emit('open') - this.socket.onclose = () => this.socket.events.emit('close') - this.socket.onerror = () => this.socket.events.emit('error') - - this.updateState(Connection.State.CONNECTING) - - this.socket.events.on('open', () => { - this.debug('Connected to ', this.options.url) - this.updateState(Connection.State.CONNECTED) - }) - - this.socket.events.on('error', (err) => { - this.debug('Error in websocket.') - if (err) { - console.error(err) - } - this.socket.close() - }) - - this.socket.events.on('close', () => { - if (this.state !== Connection.State.DISCONNECTING) { - this.debug('Connection lost. Attempting to reconnect') - clearTimeout(this._reconnectTimeout) - this._reconnectTimeout = setTimeout(() => { - this.connect().catch((err) => { - console.error(err) - }) - }, 2000) - } - - this.updateState(Connection.State.DISCONNECTED) - }) - - this.socket.onmessage = (messageEvent) => { - let controlMessage - try { - this.debug('<< %s', messageEvent.data) - controlMessage = ControlLayer.ControlMessage.deserialize(messageEvent.data) - } catch (err) { - this.emit('error', err) - return - } - this.emit(controlMessage.type, controlMessage) - } - - return new Promise((resolve) => { - this.socket.events.once('open', () => { - resolve() - }) - }) - } - - clearReconnectTimeout() { - clearTimeout(this._reconnectTimeout) - } - - async disconnect() { - this.clearReconnectTimeout() - - if (this.state === Connection.State.DISCONNECTING) { - throw new Error('Already disconnecting!') - } - - if (this.state === Connection.State.DISCONNECTED) { - throw new Error('Already disconnected!') - } - - if (this.socket === undefined) { - throw new Error('Something is wrong: socket is undefined!') - } - - if (this.state === Connection.State.CONNECTING) { - return new Promise((resolve) => { - this.once('connected', () => resolve(this.disconnect().catch((err) => console.error(err)))) - }) - } - - return new Promise((resolve) => { - this.updateState(Connection.State.DISCONNECTING) - this.socket.events.once('close', resolve) - this.socket.close() - }) - } - - async send(controlLayerRequest) { - return new Promise((resolve, reject) => { - try { - const serialized = controlLayerRequest.serialize() - this.debug('>> %s', serialized) - this.socket.send(serialized, (err) => { - if (err) { - reject(err) - } else { - resolve(controlLayerRequest) - } - }) - - if (process.browser) { - resolve(controlLayerRequest) - } - } catch (err) { - this.emit('error', err) - reject(err) - } - }) - } -} - -Connection.State = { - DISCONNECTED: 'disconnected', - CONNECTING: 'connecting', - CONNECTED: 'connected', - DISCONNECTING: 'disconnecting', -} - -export default Connection - diff --git a/src/Connection.ts b/src/Connection.ts new file mode 100644 index 000000000..92c3fdb52 --- /dev/null +++ b/src/Connection.ts @@ -0,0 +1,807 @@ +import { inspect } from 'util' + +import EventEmitter from 'eventemitter3' +import Debug from 'debug' +import WebSocket from 'ws' + +import { Scaffold, counterId, pLimitFn, pOne } from './utils' +import { Todo } from './types' + +const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) + +// add global support for pretty millisecond formatting with %n +// @ts-expect-error +Debug.formatters.n = (v) => Debug.humanize(v) + +export interface ConnectionOptions { + url?: string, + autoConnect?: boolean + autoDisconnect?: boolean + disconnectDelay?: number + maxRetries?: number + retryBackoffFactor?: number + maxRetryWait?: number +} + +export class ConnectionError extends Error { + reason?: Todo + + constructor(err: Todo, ...args: Todo[]) { + if (err instanceof ConnectionError) { + return err + } + + if (err && err.stack) { + const { message, stack } = err + // @ts-expect-error + super(message, ...args) + Object.assign(this, err) + this.stack = stack + this.reason = err + } else { + // @ts-expect-error + super(err, ...args) + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor) + } + } + } +} + +const openSockets = new Set() +const FORCE_CLOSED = Symbol('FORCE_CLOSED') + +async function OpenWebSocket(url: string, opts: Todo, ...args: Todo[]) { + return new Promise((resolve, reject) => { + try { + if (!url) { + const err = new ConnectionError('URL is not defined!') + reject(err) + throw err + } + + // @ts-expect-error + const socket = process.browser ? new WebSocket(url) : new WebSocket(url, opts, ...args) + let error: Todo + Object.assign(socket, { + id: counterId('ws'), + binaryType: 'arraybuffer', + onopen() { + openSockets.add(socket) + resolve(socket) + }, + onclose() { + openSockets.delete(socket) + reject(new ConnectionError(error || 'socket closed')) + }, + onerror(event: Todo) { + error = new ConnectionError(event.error || event) + }, + }) + + // attach debug + // @ts-expect-error + socket.debug = opts.debug.extend(socket.id) + // @ts-expect-error + socket.debug.color = opts.debug.color // use existing colour + } catch (err) { + reject(err) + } + }) +} + +async function CloseWebSocket(socket: Todo) { + return new Promise((resolve, reject) => { + if (!socket || socket.readyState === WebSocket.CLOSED) { + resolve(undefined) + return + } + + const waitThenClose = () => ( + resolve(CloseWebSocket(socket)) + ) + + // @ts-expect-error + if (socket.readyState === WebSocket.OPENING) { + socket.addEventListener('error', waitThenClose) + socket.addEventListener('open', waitThenClose) + } + + if (socket.readyState === WebSocket.OPEN) { + socket.addEventListener('close', resolve) + try { + socket.close() + } catch (err) { + reject(err) + return + } + } + + if (socket.readyState === WebSocket.CLOSING) { + socket.addEventListener('close', resolve) + } + }) +} + +const STATE = { + AUTO: 'AUTO', + CONNECTED: 'CONNECTED', + DISCONNECTED: 'DISCONNECTED', +} + +/* eslint-disable no-underscore-dangle, no-param-reassign */ +function SocketConnector(connection: Connection) { + let next: Todo + let socket: Todo + let startedConnecting = false + let didCloseUnexpectedly = false + + const onClose = () => { + didCloseUnexpectedly = true + if (!next.pendingCount && !next.activeCount) { + // if no pending actions run next & emit any errors + next().catch((err: Todo) => { + connection.emit('error', err) + }) + } + } + + const isValid = () => connection.hasRetries() && connection.isConnectionValid() + + // Connection should go up if connection valid and didn't close unexpectedly + const shouldConnectCheck = async () => { + const valid = isValid() + if ( + // socket goes into disconnecting state before close event fires + // we can detect that here + !didCloseUnexpectedly + && connection.isDisconnecting() + && valid + && startedConnecting + ) { + didCloseUnexpectedly = true + startedConnecting = false + } + + return !didCloseUnexpectedly && valid + } + + next = Scaffold([ + // handle retry + async () => { + if (connection.retryCount > 0) { + // backoff delay if retrying + await connection.backoffWait() + } + return () => { + // increase retries on connection end + connection.retryCount += 1 + if (connection.hasRetries()) { + // throw away error if going to retry (otherwise will throw) + next.clearError() + } + didCloseUnexpectedly = false + } + }, + // connecting events + () => { + connection.emitTransition('connecting') + return async () => { + connection.emitTransition('disconnected') + } + }, + // reconnecting events + () => { + if (connection.retryCount > 0) { + connection.emitTransition('reconnecting', connection.retryCount) + } + }, + // connect + async () => { + startedConnecting = true + socket = await OpenWebSocket(connection.options.url!, { + perMessageDeflate: false, + debug: connection._debug, + }) + socket.addEventListener('close', onClose) + socket.addEventListener('close', () => { + // if forced closed by Connection.closeOpen, disable reconnect + if (socket[FORCE_CLOSED]) { + connection._setShouldDisconnect() + } + }) + return async () => { // disconnect + startedConnecting = false + // remove close listener before closing + socket.removeEventListener('close', onClose) + await CloseWebSocket(socket) + } + }, + // set socket + () => { + connection.socket = socket + + return () => { + connection.socket = undefined + } + }, + // attach message handler + () => { + const onMessage = (messageEvent: Todo, ...args: Todo|[]) => { + connection.emit('message', messageEvent, ...args) + } + socket.addEventListener('message', onMessage) + return async () => { + socket.removeEventListener('message', onMessage) + } + }, + () => { + return async () => { + // don't wait if socket already closed + if (connection.isDisconnected()) { return } + const { disconnectDelay = 250 } = connection.options + await wait(disconnectDelay || 0) // wait a moment before closing + } + } + ], shouldConnectCheck, { + onChange: async (isConnecting) => { + // emit disconnecting as soon as we start going down + if (!isConnecting) { + connection.emit('disconnecting') + } + }, + onDone: async (isConnected, err) => { + // maybe try again + if (didCloseUnexpectedly && isValid()) { + didCloseUnexpectedly = false + await next.next() + return + } + + didCloseUnexpectedly = false + + if (isConnected) { + connection.retryCount = 0 // eslint-disable-line no-param-reassign + } + + next.clearError() + + try { + // emit connected or done depending on whether we're up or down + connection.emitTransition(isConnected ? 'connected' : 'done', err) + } finally { + // firing event above might have changed status + if (isValid() && isConnected && !connection.isConnected()) { + didCloseUnexpectedly = true + } + + next.clearError() + await next.next() + } + }, + }) + + return next +} +/* eslint-enable no-underscore-dangle, no-param-reassign */ + +const DEFAULT_MAX_RETRIES = 10 + +/** + * Wraps WebSocket open/close with promise methods + * adds events + * handles simultaneous calls to open/close + * waits for pending close/open before continuing + */ + +export default class Connection extends EventEmitter { + + _debug: Todo + options: ConnectionOptions + retryCount: Todo + wantsState: Todo + connectionHandles: Todo + step: Todo + socket?: Todo + didDisableAutoConnect?: Todo + isWaiting?: Todo + _isReconnecting: Todo + _backoffTimeout: Todo + sendID: Todo + + static getOpen() { + return openSockets.size + } + + static async closeOpen() { + return Promise.all([...openSockets].map(async (socket: Todo) => { + socket[FORCE_CLOSED] = true // eslint-disable-line no-param-reassign + return CloseWebSocket(socket).catch((err) => { + socket.debug(err) // ignore error + }) + })) + } + + constructor(options: ConnectionOptions = {}, debug?: Debug.Debugger) { + super() + this._debug = debug !== undefined + ? debug.extend(counterId(this.constructor.name)) + : Debug(`StreamrClient::${counterId(this.constructor.name)}`) + + this.options = options + this.options.autoConnect = !!this.options.autoConnect + this.options.autoDisconnect = !!this.options.autoDisconnect + this.isConnectionValid = this.isConnectionValid.bind(this) + + this.retryCount = 0 + this.wantsState = STATE.AUTO // target state or auto + this.connectionHandles = new Set() // autoConnect when this is not empty, autoDisconnect when empty + this.backoffWait = pLimitFn(this.backoffWait.bind(this)) + this.step = SocketConnector(this) + this.debug = this.debug.bind(this) + // @ts-expect-error + this.maybeConnect = pOne(this.maybeConnect.bind(this)) + this.nextConnection = pOne(this.nextConnection.bind(this)) + this.nextDisconnection = pOne(this.nextDisconnection.bind(this)) + } + + debug(...args: Todo[]) { + if (this.socket) { + return this.socket.debug(...args) + } + return this._debug(...args) + } + + emit(event: Todo, ...args: Todo[]) { + if (event === 'error') { + let [err] = args + const [, ...rest] = args + err = new ConnectionError(err) + this.debug('emit', event, ...args) + return super.emit(event, err, ...rest) + } + + if (event !== 'message' && typeof event !== 'number' && !(event.startsWith && event.startsWith('_'))) { + // don't log for messages or events starting with _ + this.debug('emit', event, ...args) + } + + // note if event handler is async and it rejects we're kinda hosed + // until node lands unhandledrejection support + // in eventemitter + let result + try { + result = super.emit(event, ...args) + } catch (err) { + super.emit('error', err) + return true + } + return result + } + + emitTransition(event: Todo, ...args: Todo[]) { + const prevWantsState = this.wantsState + if (prevWantsState === STATE.AUTO) { + return this.emit(event, ...args) + } + + const result = this.emit(event, ...args) + if (this.wantsState === STATE.AUTO) { + return result + } + + // if event emitter changed wantsState state, throw + if (prevWantsState !== this.wantsState) { + this.debug('transitioned in event handler %s: wantsState %s -> %s', event, prevWantsState, this.wantsState) + if (this.wantsState === STATE.CONNECTED) { + throw new ConnectionError(`connect called in ${event} handler`) + } + + if (this.wantsState === STATE.DISCONNECTED) { + throw new ConnectionError(`disconnect called in ${event} handler`) + } + } + + return result + } + + /** + * Connection + */ + + async connect() { + this.debug('connect()') + this.wantsState = STATE.CONNECTED + this.enableAutoConnect(false) + this.enableAutoDisconnect(false) + this.retryCount = 0 + await this.step() + if (!this.isConnectionValid()) { + const err = new ConnectionError('disconnected before connected') + if (this.isWaiting) { + this.emit('_error', err) + } + throw err + } + } + + enableAutoDisconnect(autoDisconnect = true) { + let delay + if (typeof autoDisconnect === 'number') { + delay = autoDisconnect + autoDisconnect = true // eslint-disable-line no-param-reassign + } + autoDisconnect = !!autoDisconnect // eslint-disable-line no-param-reassign + this.options.autoDisconnect = autoDisconnect + + if (autoDisconnect) { + this.wantsState = STATE.AUTO + } + + if (delay != null) { + this.options.disconnectDelay = delay + } + } + + enableAutoConnect(autoConnect = true) { + autoConnect = !!autoConnect // eslint-disable-line no-param-reassign + if (this.options.autoConnect && !autoConnect) { + this.didDisableAutoConnect = true + } + + this.options.autoConnect = autoConnect + if (autoConnect) { + this.wantsState = STATE.AUTO + this.didDisableAutoConnect = false + } + } + + async nextConnection() { + if (this.isConnected()) { + return Promise.resolve() + } + + this.isWaiting = true + return new Promise((resolve, reject) => { + let onError: Todo + let onDone: Todo + const onConnected = () => { + this.off('done', onDone) + this.off('error', onError) + this.off('_error', onError) + resolve(undefined) + } + onDone = (err: Todo) => { + this.off('error', onError) + this.off('_error', onError) + this.off('connected', onConnected) + if (err) { + reject(err) + } else { + resolve(undefined) + } + } + onError = (err: Todo) => { + this.off('done', onDone) + this.off('connected', onConnected) + reject(err) + } + this.once('connected', onConnected) + this.once('done', onDone) + this.once('error', onError) + this.once('_error', onError) + }).finally(() => { + this.isWaiting = false + }) + } + + couldConnect() { + switch (this.wantsState) { + case STATE.DISCONNECTED: { + return false + } + case STATE.CONNECTED: { + return true + } + case STATE.AUTO: { + return !!this.options.autoConnect + } + default: { + throw new Error(`unknown state wanted: ${this.wantsState}`) + } + } + } + + isConnectionValid() { + switch (this.wantsState) { + case STATE.DISCONNECTED: { + return false + } + case STATE.CONNECTED: { + return true + } + case STATE.AUTO: { + if (this.options.autoConnect) { + return !!(this.connectionHandles.size) && !this._couldAutoDisconnect() + } + return false + } + default: { + throw new Error(`unknown state wanted: ${this.wantsState}`) + } + } + } + + hasRetries() { + const { maxRetries = DEFAULT_MAX_RETRIES } = this.options + return this.retryCount < maxRetries + } + + async maybeConnect() { + await this.step() + } + + async needsConnection(msg?: Todo) { + await this.maybeConnect() + if (!this.isConnected()) { + const { autoConnect, autoDisconnect } = this.options + let autoConnectMsg = `autoConnect: ${!!autoConnect} & autoDisconnect: ${!!autoDisconnect} with ${this.connectionHandles.size} handles.` + if (!autoConnect && this.didDisableAutoConnect) { + autoConnectMsg += '\nautoConnect disabled automatically after explicit call to connect/disconnect().' + } + // note we can't just let socket.send fail, + // have to do this check ourselves because the error appears + // to be uncatchable in the browser + throw new ConnectionError([ + `Needs connection but – connection: ${this.getState()} & wants: ${this.wantsState}`, + autoConnectMsg, + typeof msg === 'function' ? msg() : msg + ].join('\n')) + } + } + + /** + * Disconnection + */ + + _setShouldDisconnect() { + this.didDisableAutoConnect = !!this.options.autoConnect + this.options.autoConnect = false // reset auto-connect on manual disconnect + this.options.autoDisconnect = false // reset auto-disconnect on manual disconnect + this.wantsState = STATE.DISCONNECTED + } + + async disconnect() { + this.debug('disconnect()') + this._setShouldDisconnect() + + await this.step() + if (this.isConnectionValid()) { + throw new ConnectionError('connected before disconnected') + } + } + + async nextDisconnection() { + if (this.isDisconnected()) { + return Promise.resolve() + } + + return new Promise((resolve, reject) => { + let onError: Todo + const onDisconnected = () => { + this.off('error', onError) + resolve(undefined) + } + onError = (err: Todo) => { + this.off('disconnected', onDisconnected) + reject(err) + } + this.once('disconnected', onDisconnected) + this.once('error', onError) + }) + } + + async backoffWait() { + const { retryBackoffFactor = 1.2, maxRetryWait = 10000 } = this.options + return new Promise((resolve) => { + clearTimeout(this._backoffTimeout) + const timeout = Math.min( + maxRetryWait, // max wait time + Math.round((this.retryCount * 10) ** retryBackoffFactor) + ) || 0 + const { debug } = this + debug('waiting %n', timeout) + this._backoffTimeout = setTimeout(() => { + debug('waited %n', timeout) + resolve(undefined) + }, timeout) + }) + } + + /** + * Auto Connect/Disconnect counters. + */ + + async addHandle(id: Todo) { + if ( + this.connectionHandles.has(id) + && this.isConnected() + && this.isConnectionValid() + ) { + return // shortcut if already connected with this handle + } + + this.connectionHandles.add(id) + await this.maybeConnect() + } + + /** + * When no more handles and autoDisconnect is true, disconnect. + */ + + async removeHandle(id: Todo) { + const hadConnection = this.connectionHandles.has(id) + this.connectionHandles.delete(id) + if (hadConnection && this._couldAutoDisconnect()) { + await this.step() + } + } + + _couldAutoDisconnect(minSize = 0) { + return !!( + this.options.autoDisconnect + && this.wantsState !== STATE.CONNECTED + && this.connectionHandles.size === minSize + && (this.socket ? this.socket.bufferedAmount === 0 : true) + ) + } + + async send(msg: Todo) { + this.sendID = this.sendID + 1 || 1 + const handle = `send${this.sendID}` + this.debug('(%s) send()', this.getState()) + await this.addHandle(handle) + try { + if (!this.isConnected() || !this.isConnectionValid()) { + // shortcut await if connected + await this.needsConnection(() => { + const data = typeof msg.serialize === 'function' ? msg.serialize() : msg + return `sending ${inspect(data)}...` + }) + } + return await this._send(msg) + } finally { + await this.removeHandle(handle) + } + } + + async _send(msg: Todo) { + return new Promise((resolve, reject) => { + this.debug('(%s) >> %o', this.getState(), msg) + // promisify send + const data = typeof msg.serialize === 'function' ? msg.serialize() : msg + // send callback doesn't exist with browser websockets, just resolve + /* istanbul ignore next */ + this.emit('_send', msg) // for informational purposes + // @ts-expect-error + if (process.browser) { + this.socket.send(data) + resolve(data) + } else { + this.socket.send(data, (err: Todo) => { + /* istanbul ignore next */ + if (err) { + reject(new ConnectionError(err)) + return + } + resolve(data) + }) + } + }) + } + + /** + * Status flags + */ + + getState() { + if (this.isConnected()) { + return 'connected' + } + + if (this.isConnecting()) { + // this check must go before isDisconnected + return 'connecting' + } + + if (this.isDisconnected()) { + return 'disconnected' + } + + if (this.isDisconnecting()) { + return 'disconnecting' + } + + return 'unknown' + } + + isReconnecting() { + return this._isReconnecting + } + + isConnected() { + if (!this.socket) { + return false + } + + return this.socket.readyState === WebSocket.OPEN + } + + isDisconnected() { + if (!this.socket) { + return true + } + + return this.socket.readyState === WebSocket.CLOSED + } + + isDisconnecting() { + if (!this.socket) { + return false + } + return this.socket.readyState === WebSocket.CLOSING + } + + isConnecting() { + if (!this.socket) { + return false + } + return this.socket.readyState === WebSocket.CONNECTING + } + + onTransition({ + onConnected = () => {}, + onConnecting = () => {}, + onDisconnecting = () => {}, + onDisconnected = () => {}, + onDone = () => {}, + // @ts-expect-error + onError, + }) { + let onDoneHandler: Todo + const cleanUp = async () => { + this + .off('connecting', onConnecting) + .off('connected', onConnected) + .off('disconnecting', onDisconnecting) + .off('disconnected', onDisconnected) + .off('done', onDoneHandler) + if (onError) { + this.off('error', onError) + } + } + + onDoneHandler = async (...args: Todo[]) => { + // @ts-expect-error + cleanUp(...args) + // @ts-expect-error + return onDone(...args) + } + + this + .on('connecting', onConnecting) + .on('connected', onConnected) + .on('disconnecting', onDisconnecting) + .on('disconnected', onDisconnected) + .on('done', onDoneHandler) + + if (onError) { + this.on('error', onError) + } + + return cleanUp + } +} + +// @ts-expect-error +Connection.ConnectionError = ConnectionError diff --git a/src/DecryptionKeySequence.js b/src/DecryptionKeySequence.js deleted file mode 100644 index 943545fb7..000000000 --- a/src/DecryptionKeySequence.js +++ /dev/null @@ -1,36 +0,0 @@ -import EncryptionUtil from './EncryptionUtil' -import UnableToDecryptError from './errors/UnableToDecryptError' - -export default class DecryptionKeySequence { - constructor(keys) { - this.keys = keys - this.currentIndex = 0 - } - - tryToDecryptResent(msg) { - try { - EncryptionUtil.decryptStreamMessage(msg, this.keys[this.currentIndex]) - } catch (err) { - // the current might not be valid anymore - if (err instanceof UnableToDecryptError) { - const nextKey = this._getNextKey() - if (!nextKey) { - throw err - } - // try to decrypt with the next key - EncryptionUtil.decryptStreamMessage(msg, nextKey) - // if successful (no error thrown) update the current key - this.currentIndex += 1 - } else { - throw err - } - } - } - - _getNextKey() { - if (this.currentIndex === this.keys.length - 1) { - return undefined - } - return this.keys[this.currentIndex + 1] - } -} diff --git a/src/EncryptionUtil.js b/src/EncryptionUtil.js deleted file mode 100644 index 95165adee..000000000 --- a/src/EncryptionUtil.js +++ /dev/null @@ -1,241 +0,0 @@ -import crypto from 'crypto' -import util from 'util' - -// this is shimmed out for actual browser build allows us to run tests in node against browser API -import { Crypto } from 'node-webcrypto-ossl' -import { ethers } from 'ethers' -import { MessageLayer } from 'streamr-client-protocol' - -import UnableToDecryptError from './errors/UnableToDecryptError' -import InvalidGroupKeyError from './errors/InvalidGroupKeyError' - -const { StreamMessage } = MessageLayer - -function ab2str(buf) { - return String.fromCharCode.apply(null, new Uint8Array(buf)) -} - -// shim browser btoa for node -function btoa(str) { - if (global.btoa) { return global.btoa(str) } - let buffer - - if (str instanceof Buffer) { - buffer = str - } else { - buffer = Buffer.from(str.toString(), 'binary') - } - - return buffer.toString('base64') -} - -async function exportCryptoKey(key, { isPrivate = false } = {}) { - const WebCrypto = new Crypto() - const keyType = isPrivate ? 'pkcs8' : 'spki' - const exported = await WebCrypto.subtle.exportKey(keyType, key) - const exportedAsString = ab2str(exported) - const exportedAsBase64 = btoa(exportedAsString) - const TYPE = isPrivate ? 'PRIVATE' : 'PUBLIC' - return `-----BEGIN ${TYPE} KEY-----\n${exportedAsBase64}\n-----END ${TYPE} KEY-----\n` -} - -export default class EncryptionUtil { - constructor(options = {}) { - if (options.privateKey && options.publicKey) { - EncryptionUtil.validatePrivateKey(options.privateKey) - EncryptionUtil.validatePublicKey(options.publicKey) - this.privateKey = options.privateKey - this.publicKey = options.publicKey - } else { - this._generateKeyPair() - } - } - - async onReady() { - if (this.isReady()) { return undefined } - return this._generateKeyPair() - } - - isReady() { - return !!this.privateKey - } - - // Returns a Buffer - decryptWithPrivateKey(ciphertext, isHexString = false) { - if (!this.isReady()) { throw new Error('EncryptionUtil not ready.') } - let ciphertextBuffer = ciphertext - if (isHexString) { - ciphertextBuffer = ethers.utils.arrayify(`0x${ciphertext}`) - } - return crypto.privateDecrypt(this.privateKey, ciphertextBuffer) - } - - // Returns a String (base64 encoding) - getPublicKey() { - if (!this.isReady()) { throw new Error('EncryptionUtil not ready.') } - return this.publicKey - } - - // Returns a Buffer or a hex String - static encryptWithPublicKey(plaintextBuffer, publicKey, hexlify = false) { - EncryptionUtil.validatePublicKey(publicKey) - const ciphertextBuffer = crypto.publicEncrypt(publicKey, plaintextBuffer) - if (hexlify) { - return ethers.utils.hexlify(ciphertextBuffer).slice(2) - } - return ciphertextBuffer - } - - /* - Both 'data' and 'groupKey' must be Buffers. Returns a hex string without the '0x' prefix. - */ - static encrypt(data, groupKey) { - const iv = crypto.randomBytes(16) // always need a fresh IV when using CTR mode - const cipher = crypto.createCipheriv('aes-256-ctr', groupKey, iv) - return ethers.utils.hexlify(iv).slice(2) + cipher.update(data, null, 'hex') + cipher.final('hex') - } - - /* - 'ciphertext' must be a hex string (without '0x' prefix), 'groupKey' must be a Buffer. Returns a Buffer. - */ - static decrypt(ciphertext, groupKey) { - const iv = ethers.utils.arrayify(`0x${ciphertext.slice(0, 32)}`) - const decipher = crypto.createDecipheriv('aes-256-ctr', groupKey, iv) - return Buffer.concat([decipher.update(ciphertext.slice(32), 'hex', null), decipher.final(null)]) - } - - /* - Sets the content of 'streamMessage' with the encryption result of the old content with 'groupKey'. - */ - static encryptStreamMessage(streamMessage, groupKey) { - /* eslint-disable no-param-reassign */ - streamMessage.encryptionType = StreamMessage.ENCRYPTION_TYPES.AES - streamMessage.serializedContent = this.encrypt(Buffer.from(streamMessage.getSerializedContent(), 'utf8'), groupKey) - streamMessage.parsedContent = undefined - /* eslint-enable no-param-reassign */ - } - - /* - Sets the content of 'streamMessage' with the encryption result of a plaintext with 'groupKey'. The - plaintext is the concatenation of 'newGroupKey' and the old serialized content of 'streamMessage'. - */ - static encryptStreamMessageAndNewKey(newGroupKey, streamMessage, groupKey) { - /* eslint-disable no-param-reassign */ - streamMessage.encryptionType = StreamMessage.ENCRYPTION_TYPES.NEW_KEY_AND_AES - const plaintext = Buffer.concat([newGroupKey, Buffer.from(streamMessage.getSerializedContent(), 'utf8')]) - streamMessage.serializedContent = EncryptionUtil.encrypt(plaintext, groupKey) - streamMessage.parsedContent = undefined - /* eslint-enable no-param-reassign */ - } - - /* - Decrypts the serialized content of 'streamMessage' with 'groupKey'. If the resulting plaintext is the concatenation - of a new group key and a message content, sets the content of 'streamMessage' with that message content and returns - the key. If the resulting plaintext is only a message content, sets the content of 'streamMessage' with that - message content and returns null. - */ - static decryptStreamMessage(streamMessage, groupKey) { - if ((streamMessage.encryptionType === StreamMessage.ENCRYPTION_TYPES.AES - || streamMessage.encryptionType === StreamMessage.ENCRYPTION_TYPES.NEW_KEY_AND_AES) && !groupKey) { - throw new UnableToDecryptError(streamMessage) - } - /* eslint-disable no-param-reassign */ - - if (streamMessage.encryptionType === StreamMessage.ENCRYPTION_TYPES.AES) { - streamMessage.encryptionType = StreamMessage.ENCRYPTION_TYPES.NONE - const serializedContent = this.decrypt(streamMessage.getSerializedContent(), groupKey).toString() - try { - streamMessage.parsedContent = JSON.parse(serializedContent) - streamMessage.serializedContent = serializedContent - } catch (err) { - streamMessage.encryptionType = StreamMessage.ENCRYPTION_TYPES.AES - throw new UnableToDecryptError(streamMessage) - } - } else if (streamMessage.encryptionType === StreamMessage.ENCRYPTION_TYPES.NEW_KEY_AND_AES) { - streamMessage.encryptionType = StreamMessage.ENCRYPTION_TYPES.NONE - const plaintext = this.decrypt(streamMessage.getSerializedContent(), groupKey) - const serializedContent = plaintext.slice(32).toString() - try { - streamMessage.parsedContent = JSON.parse(serializedContent) - streamMessage.serializedContent = serializedContent - } catch (err) { - streamMessage.encryptionType = StreamMessage.ENCRYPTION_TYPES.NEW_KEY_AND_AES - throw new UnableToDecryptError(streamMessage) - } - return plaintext.slice(0, 32) - } - return null - /* eslint-enable no-param-reassign */ - } - - async _generateKeyPair() { - if (!this._generateKeyPairPromise) { - this._generateKeyPairPromise = this.__generateKeyPair() - } - return this._generateKeyPairPromise - } - - async __generateKeyPair() { - if (process.browser) { return this._keyPairBrowser() } - return this._keyPairServer() - } - - async _keyPairServer() { - const generateKeyPair = util.promisify(crypto.generateKeyPair) - const { publicKey, privateKey } = await generateKeyPair('rsa', { - modulusLength: 4096, - publicKeyEncoding: { - type: 'spki', - format: 'pem', - }, - privateKeyEncoding: { - type: 'pkcs8', - format: 'pem', - }, - }) - - this.privateKey = privateKey - this.publicKey = publicKey - } - - async _keyPairBrowser() { - const WebCrypto = new Crypto() - const { publicKey, privateKey } = await WebCrypto.subtle.generateKey({ - name: 'RSA-OAEP', - modulusLength: 4096, - publicExponent: new Uint8Array([1, 0, 1]), // 65537 - hash: 'SHA-256' - }, true, ['encrypt', 'decrypt']) - - this.privateKey = await exportCryptoKey(privateKey, { - isPrivate: true, - }) - this.publicKey = await exportCryptoKey(publicKey, { - isPrivate: false, - }) - } - - static validatePublicKey(publicKey) { - if (typeof publicKey !== 'string' || !publicKey.startsWith('-----BEGIN PUBLIC KEY-----') - || !publicKey.endsWith('-----END PUBLIC KEY-----\n')) { - throw new Error('"publicKey" must be a PKCS#8 RSA public key as a string in the PEM format') - } - } - - static validatePrivateKey(privateKey) { - if (typeof privateKey !== 'string' || !privateKey.startsWith('-----BEGIN PRIVATE KEY-----') - || !privateKey.endsWith('-----END PRIVATE KEY-----\n')) { - throw new Error('"privateKey" must be a PKCS#8 RSA public key as a string in the PEM format') - } - } - - static validateGroupKey(groupKey) { - if (!(groupKey instanceof Buffer)) { - throw new InvalidGroupKeyError(`Group key must be a Buffer: ${groupKey}`) - } - - if (groupKey.length !== 32) { - throw new InvalidGroupKeyError(`Group key must have a size of 256 bits, not ${groupKey.length * 8}`) - } - } -} diff --git a/src/Ethereum.js b/src/Ethereum.js new file mode 100644 index 000000000..f159ec236 --- /dev/null +++ b/src/Ethereum.js @@ -0,0 +1,108 @@ +import { Wallet } from '@ethersproject/wallet' +import { getDefaultProvider, JsonRpcProvider, Web3Provider } from '@ethersproject/providers' +import { computeAddress } from '@ethersproject/transactions' +import { getAddress } from '@ethersproject/address' + +export default class StreamrEthereum { + static generateEthereumAccount() { + const wallet = Wallet.createRandom() + return { + address: wallet.address, + privateKey: wallet.privateKey, + } + } + + constructor(client) { + this.client = client + const { options } = client + const { auth } = options + if (auth.privateKey) { + const key = auth.privateKey + const address = getAddress(computeAddress(key)) + this._getAddress = async () => address + this.getSigner = () => new Wallet(key, this.getMainnetProvider()) + this.getSidechainSigner = async () => new Wallet(key, this.getSidechainProvider()) + } else if (auth.ethereum) { + this._getAddress = async () => { + try { + const accounts = await auth.ethereum.request({ method: 'eth_requestAccounts' }) + const account = getAddress(accounts[0]) // convert to checksum case + return account + } catch { + throw new Error('no addresses connected+selected in Metamask') + } + } + this._getSigner = () => { + const metamaskProvider = new Web3Provider(auth.ethereum) + const metamaskSigner = metamaskProvider.getSigner() + return metamaskSigner + } + this._getSidechainSigner = async () => { + if (!options.sidechain || !options.sidechain.chainId) { + throw new Error('Streamr sidechain not configured (with chainId) in the StreamrClient options!') + } + + const metamaskProvider = new Web3Provider(auth.ethereum) + const { chainId } = await metamaskProvider.getNetwork() + if (chainId !== options.sidechain.chainId) { + throw new Error( + `Please connect Metamask to Ethereum blockchain with chainId ${options.sidechain.chainId}: current chainId is ${chainId}` + ) + } + const metamaskSigner = metamaskProvider.getSigner() + return metamaskSigner + } + // TODO: handle events + // ethereum.on('accountsChanged', (accounts) => { }) + // https://docs.metamask.io/guide/ethereum-provider.html#events says: + // "We recommend reloading the page unless you have a very good reason not to" + // Of course we can't and won't do that, but if we need something chain-dependent... + // ethereum.on('chainChanged', (chainId) => { window.location.reload() }); + } + } + + async getAddress() { + if (!this._getAddress) { + // _getAddress is assigned in constructor + throw new Error('StreamrClient is not authenticated with private key') + } + + return this._getAddress() + } + + getSigner() { + if (!this._getSigner) { + // _getSigner is assigned in constructor + throw new Error("StreamrClient not authenticated! Can't send transactions or sign messages.") + } + + return this._getSigner() + } + + async getSidechainSigner() { + if (!this._getSidechainSigner) { + // _getSidechainSigner is assigned in constructor + throw new Error("StreamrClient not authenticated! Can't send transactions or sign messages.") + } + + return this._getSidechainSigner() + } + + /** @returns Ethers.js Provider, a connection to the Ethereum network (mainnet) */ + getMainnetProvider() { + if (!this.client.options.mainnet) { + return getDefaultProvider() + } + + return new JsonRpcProvider(this.client.options.mainnet) + } + + /** @returns Ethers.js Provider, a connection to the Streamr EVM sidechain */ + getSidechainProvider() { + if (!this.client.options.sidechain) { + throw new Error('StreamrClient has no sidechain configuration.') + } + + return new JsonRpcProvider(this.client.options.sidechain) + } +} diff --git a/src/GroupKeyHistory.js b/src/GroupKeyHistory.js deleted file mode 100644 index 89ef46979..000000000 --- a/src/GroupKeyHistory.js +++ /dev/null @@ -1,53 +0,0 @@ -/* -This class contains the history of group keys used by the client as a publisher to encrypt messages for a particular stream. -The history is used to answer group key requests from subscribers who may ask for the latest key (getLatestKey() method) -in case of real-time messages or a sequence of historical keys (getKeysBetween() method) in case of resends. - */ -export default class GroupKeyHistory { - // initialGroupKey is an object with fields "groupKey" and "start" - constructor(initialGroupKey) { - this.keys = [] - if (initialGroupKey) { - this.keys.push(initialGroupKey) - } - } - - getLatestKey() { - return this.keys[this.keys.length - 1] - } - - getKeysBetween(start, end) { - if (typeof start !== 'number' || typeof end !== 'number' || start > end) { - throw new Error('Both "start" and "end" must be defined numbers and "start" must be less than or equal to "end".') - } - let i = 0 - // discard keys that ended before 'start' - while (i < this.keys.length - 1 && this._getKeyEnd(i) < start) { - i += 1 - } - const selectedKeys = [] - // add keys as long as they started before 'end' - while (i < this.keys.length && this.keys[i].start <= end) { - selectedKeys.push(this.keys[i]) - i += 1 - } - return selectedKeys - } - - addKey(groupKey, start) { - if (this.keys.length > 0 && this.keys[this.keys.length - 1].start > start) { - throw new Error(`Cannot add an older key to a group key history (${this.keys[this.keys.length - 1].start} > ${start})`) - } - this.keys.push({ - groupKey, - start: start || Date.now() - }) - } - - _getKeyEnd(keyIndex) { - if (keyIndex < 0 || keyIndex >= this.keys.length - 1) { - return undefined - } - return this.keys[keyIndex + 1].start - 1 - } -} diff --git a/src/HistoricalSubscription.js b/src/HistoricalSubscription.js deleted file mode 100644 index a319db3c6..000000000 --- a/src/HistoricalSubscription.js +++ /dev/null @@ -1,94 +0,0 @@ -import { MessageLayer } from 'streamr-client-protocol' - -import AbstractSubscription from './AbstractSubscription' -import DecryptionKeySequence from './DecryptionKeySequence' - -const { StreamMessage } = MessageLayer - -export default class HistoricalSubscription extends AbstractSubscription { - constructor(streamId, streamPartition, callback, options, groupKeys, propagationTimeout, resendTimeout, orderMessages = true, - onUnableToDecrypt = AbstractSubscription.defaultUnableToDecrypt) { - super(streamId, streamPartition, callback, groupKeys, propagationTimeout, resendTimeout, orderMessages, onUnableToDecrypt) - this.resendOptions = options - if (!this.resendOptions || (!this.resendOptions.from && !this.resendOptions.last)) { - throw new Error('Resend options (either "from", "from" and "to", or "last") must be defined in a historical subscription.') - } - - if (this.resendOptions.from != null && this.resendOptions.last != null) { - throw new Error(`Multiple resend options active! Please use only one: ${JSON.stringify(this.resendOptions)}`) - } - - if (this.resendOptions.msgChainId != null && typeof this.resendOptions.publisherId === 'undefined') { - throw new Error('publisherId must be defined as well if msgChainId is defined.') - } - - if (this.resendOptions.from == null && this.resendOptions.to != null) { - throw new Error('"from" must be defined as well if "to" is defined.') - } - this.keySequences = {} - Object.keys(this.groupKeys).forEach((publisherId) => { - this.keySequences[publisherId] = new DecryptionKeySequence([this.groupKeys[publisherId]]) - }) - } - - // passing publisherId separately to ensure it is lowercase (See call of this function in AbstractSubscription.js) - _decryptOrRequestGroupKey(msg, publisherId) { - if (msg.encryptionType !== StreamMessage.ENCRYPTION_TYPES.AES && msg.encryptionType !== StreamMessage.ENCRYPTION_TYPES.NEW_KEY_AND_AES) { - return true - } - - if (!this.keySequences[publisherId]) { - const start = msg.getTimestamp() - const end = this.resendOptions.to ? this.resendOptions.to : Date.now() - this._requestGroupKeyAndQueueMessage(msg, start, end) - return false - } - this.keySequences[publisherId].tryToDecryptResent(msg) - return true - } - - async handleBroadcastMessage(msg, verifyFn) { - await this._queuedValidate(msg, verifyFn) - this.emit('message received', msg) - } - - /* eslint-disable class-methods-use-this */ - hasResendOptions() { - return true - } - - isResending() { - return true - } - - setResending() {} - /* eslint-enable class-methods-use-this */ - - getResendOptions() { - return this.resendOptions - } - - setGroupKeys(publisherId, groupKeys) { - if (this.keySequences[publisherId.toLowerCase()]) { - throw new Error(`Received historical group keys for publisher ${publisherId} for a second time.`) - } - this.keySequences[publisherId.toLowerCase()] = new DecryptionKeySequence(groupKeys) - this._handleEncryptedQueuedMsgs(publisherId) - if (this.resendDone && this._emptyMsgQueues()) { // the messages in the queue were the last ones to handle - this.emit('resend done') - } - } - - finishResend() { - this._lastMessageHandlerPromise = null - if (!this._emptyMsgQueues()) { // received all historical messages but not yet the keys to decrypt them - this.resendDone = true - } else if (Object.keys(this.pendingResendRequestIds).length === 0) { - this.emit('initial_resend_done') - } - } - - /* eslint-disable class-methods-use-this */ - onDisconnected() {} - /* eslint-enable class-methods-use-this */ -} diff --git a/src/KeyExchangeUtil.js b/src/KeyExchangeUtil.js deleted file mode 100644 index 6ce8ff948..000000000 --- a/src/KeyExchangeUtil.js +++ /dev/null @@ -1,118 +0,0 @@ -import uniqueId from 'lodash.uniqueid' - -import EncryptionUtil from './EncryptionUtil' -import InvalidGroupKeyRequestError from './errors/InvalidGroupKeyRequestError' -import InvalidGroupKeyResponseError from './errors/InvalidGroupKeyResponseError' -import InvalidGroupKeyError from './errors/InvalidGroupKeyError' - -const SUBSCRIBERS_EXPIRATION_TIME = 5 * 60 * 1000 // 5 minutes - -export default class KeyExchangeUtil { - static getKeyExchangeStreamId(publisherId) { - if (!publisherId || typeof publisherId !== 'string') { throw new Error(`non-empty publisherId string required: ${publisherId}`) } - return `SYSTEM/keyexchange/${publisherId.toLowerCase()}` - } - - constructor(client) { - this._client = client - this.debug = client.debug.extend(uniqueId('KeyExchangeUtil')) - this.isSubscriberPromises = {} - } - - async handleGroupKeyRequest(streamMessage) { - // No need to check if parsedContent contains the necessary fields because it was already checked during deserialization - const { streamId, range, requestId, publicKey } = streamMessage.getParsedContent() - let keys = [] - if (range) { - keys = this._client.keyStorageUtil.getKeysBetween(streamId, range.start, range.end) - } else { - const groupKeyObj = this._client.keyStorageUtil.getLatestKey(streamId, true) - if (groupKeyObj) { - keys.push(groupKeyObj) - } - } - - if (keys.length === 0) { - throw new InvalidGroupKeyRequestError(`Received group key request for stream '${streamId}' but no group key is set`) - } - const subscriberId = streamMessage.getPublisherId() - - const encryptedGroupKeys = [] - keys.forEach((keyObj) => { - const encryptedGroupKey = EncryptionUtil.encryptWithPublicKey(keyObj.groupKey, publicKey, true) - encryptedGroupKeys.push({ - groupKey: encryptedGroupKey, - start: keyObj.start, - }) - }) - const response = await this._client.msgCreationUtil.createGroupKeyResponse({ - subscriberAddress: subscriberId, - streamId, - encryptedGroupKeys, - requestId, - }) - return this._client.publishStreamMessage(response) - } - - handleGroupKeyResponse(streamMessage) { - // No need to check if parsedContent contains the necessary fields because it was already checked during deserialization - const parsedContent = streamMessage.getParsedContent() - // TODO: fix this hack in other PR - if (!this._client.subscribedStreamPartitions[parsedContent.streamId + '0']) { - throw new InvalidGroupKeyResponseError('Received group key response for a stream to which the client is not subscribed.') - } - - if (!this._client.encryptionUtil) { - throw new InvalidGroupKeyResponseError('Cannot decrypt group key response without the private key.') - } - - const decryptedGroupKeys = [] - parsedContent.keys.forEach((encryptedGroupKeyObj) => { - const groupKey = this._client.encryptionUtil.decryptWithPrivateKey(encryptedGroupKeyObj.groupKey, true) - try { - EncryptionUtil.validateGroupKey(groupKey) - } catch (err) { - if (err instanceof InvalidGroupKeyError) { - throw new InvalidGroupKeyResponseError(err.message) - } else { - throw err - } - } - decryptedGroupKeys.push({ - groupKey, - start: encryptedGroupKeyObj.start - }) - }) - /* eslint-disable no-underscore-dangle */ - this._client._setGroupKeys(parsedContent.streamId, streamMessage.getPublisherId(), decryptedGroupKeys) - /* eslint-enable no-underscore-dangle */ - this.debug('INFO: Updated group key for stream "%s" and publisher "%s"', parsedContent.streamId, streamMessage.getPublisherId()) - } - - async getSubscribers(streamId) { - if (!this.subscribersPromise || (Date.now() - this.lastAccess) > SUBSCRIBERS_EXPIRATION_TIME) { - this.subscribersPromise = this._client.getStreamSubscribers(streamId).then((subscribers) => { - const map = {} - subscribers.forEach((s) => { - map[s] = true - }) - return map - }) - this.lastAccess = Date.now() - } - return this.subscribersPromise - } - - async isSubscriber(streamId, subscriberId) { - if (!this.isSubscriberPromises[streamId]) { - this.isSubscriberPromises[streamId] = {} - } - - if (!this.isSubscriberPromises[streamId][subscriberId]) { - this.isSubscriberPromises[streamId][subscriberId] = this._client.isStreamSubscriber(streamId, subscriberId) - } - return this.isSubscriberPromises[streamId][subscriberId] - } -} - -KeyExchangeUtil.SUBSCRIBERS_EXPIRATION_TIME = SUBSCRIBERS_EXPIRATION_TIME diff --git a/src/KeyHistoryStorageUtil.js b/src/KeyHistoryStorageUtil.js deleted file mode 100644 index 8d4af8a39..000000000 --- a/src/KeyHistoryStorageUtil.js +++ /dev/null @@ -1,35 +0,0 @@ -import GroupKeyHistory from './GroupKeyHistory' - -export default class KeyHistoryStorageUtil { - constructor(publisherGroupKeys = {}) { - this.groupKeyHistories = {} - Object.keys(publisherGroupKeys).forEach((streamId) => { - this.groupKeyHistories[streamId] = new GroupKeyHistory(publisherGroupKeys[streamId]) - }) - } - - hasKey(streamId) { - return this.groupKeyHistories[streamId] !== undefined - } - - getLatestKey(streamId) { - if (this.groupKeyHistories[streamId]) { - return this.groupKeyHistories[streamId].getLatestKey() - } - return undefined - } - - getKeysBetween(streamId, start, end) { - if (this.groupKeyHistories[streamId]) { - return this.groupKeyHistories[streamId].getKeysBetween(start, end) - } - return [] - } - - addKey(streamId, groupKey, start) { - if (!this.groupKeyHistories[streamId]) { - this.groupKeyHistories[streamId] = new GroupKeyHistory() - } - this.groupKeyHistories[streamId].addKey(groupKey, start) - } -} diff --git a/src/KeyStorageUtil.js b/src/KeyStorageUtil.js deleted file mode 100644 index c289770aa..000000000 --- a/src/KeyStorageUtil.js +++ /dev/null @@ -1,42 +0,0 @@ -import KeyHistoryStorageUtil from './KeyHistoryStorageUtil' -import LatestKeyStorageUtil from './LatestKeyStorageUtil' -import EncryptionUtil from './EncryptionUtil' - -export default class KeyStorageUtil { - static getKeyStorageUtil(publisherGroupKeys = {}, storeHistoricalKeys = true) { - if (storeHistoricalKeys) { - return new KeyHistoryStorageUtil(publisherGroupKeys) - } - return new LatestKeyStorageUtil(publisherGroupKeys) - } - - static validateAndAddStart(publisherGroupKeys, subscriberGroupKeys) { - const validatedPublisherGroupKeys = {} - Object.keys(publisherGroupKeys).forEach((streamId) => { - validatedPublisherGroupKeys[streamId] = this._getValidatedKeyObject(publisherGroupKeys[streamId]) - }) - - const validatedSubscriberGroupKeys = {} - Object.keys(subscriberGroupKeys).forEach((streamId) => { - const streamGroupKeys = subscriberGroupKeys[streamId] - validatedSubscriberGroupKeys[streamId] = {} - Object.keys(streamGroupKeys).forEach((publisherId) => { - validatedSubscriberGroupKeys[streamId][publisherId] = this._getValidatedKeyObject(streamGroupKeys[publisherId]) - }) - }) - - return [validatedPublisherGroupKeys, validatedSubscriberGroupKeys] - } - - static _getValidatedKeyObject(groupKeyObjOrString) { - if (groupKeyObjOrString.groupKey && groupKeyObjOrString.start) { - EncryptionUtil.validateGroupKey(groupKeyObjOrString.groupKey) - return groupKeyObjOrString - } - EncryptionUtil.validateGroupKey(groupKeyObjOrString) - return { - groupKey: groupKeyObjOrString, - start: Date.now() - } - } -} diff --git a/src/LatestKeyStorageUtil.js b/src/LatestKeyStorageUtil.js deleted file mode 100644 index 21197d48e..000000000 --- a/src/LatestKeyStorageUtil.js +++ /dev/null @@ -1,30 +0,0 @@ -export default class LatestKeyStorageUtil { - constructor(publisherGroupKeys = {}) { - this.latestKeys = publisherGroupKeys - } - - hasKey(streamId) { - return this.latestKeys[streamId] !== undefined - } - - getLatestKey(streamId) { - return this.latestKeys[streamId] - } - - /* eslint-disable class-methods-use-this */ - getKeysBetween(streamId, start, end) { - throw new Error(`Cannot retrieve historical keys for stream ${streamId} between ${start} and ${end} because only the latest key is stored. - Set options.publisherStoreKeyHistory to true to store all historical keys.`) - } - /* eslint-enable class-methods-use-this */ - - addKey(streamId, groupKey, start) { - if (this.latestKeys[streamId] && this.latestKeys[streamId].start > start) { - throw new Error(`Cannot add an older key as latest key (${this.latestKeys[streamId].start} > ${start})`) - } - this.latestKeys[streamId] = { - groupKey, - start - } - } -} diff --git a/src/MessageCreationUtil.js b/src/MessageCreationUtil.js deleted file mode 100644 index 96f918de6..000000000 --- a/src/MessageCreationUtil.js +++ /dev/null @@ -1,287 +0,0 @@ -import crypto from 'crypto' - -import Receptacle from 'receptacle' -import randomstring from 'randomstring' -import { MessageLayer } from 'streamr-client-protocol' -import { ethers } from 'ethers' - -import Stream from './rest/domain/Stream' -import EncryptionUtil from './EncryptionUtil' -import KeyStorageUtil from './KeyStorageUtil' -import KeyExchangeUtil from './KeyExchangeUtil' -import InvalidGroupKeyRequestError from './errors/InvalidGroupKeyRequestError' -import InvalidGroupKeyResponseError from './errors/InvalidGroupKeyResponseError' -import InvalidMessageTypeError from './errors/InvalidMessageTypeError' -import { uuid } from './utils' - -const { StreamMessage, MessageID, MessageRef } = MessageLayer -const { getKeyExchangeStreamId } = KeyExchangeUtil - -export default class MessageCreationUtil { - constructor(auth, signer, getUserInfo, getStreamFunction, keyStorageUtil) { - this.auth = auth - this._signer = signer - this.getUserInfo = getUserInfo - this.getStreamFunction = getStreamFunction - this.cachedStreams = new Receptacle({ - max: 10000, - }) - this.publishedStreams = {} - this.keyStorageUtil = keyStorageUtil || KeyStorageUtil.getKeyStorageUtil() - this.msgChainId = randomstring.generate(20) - this.cachedHashes = {} - } - - stop() { - this.cachedStreams.clear() - } - - async getUsername() { - if (!this.usernamePromise) { - // In the edge case where StreamrClient.auth.apiKey is an anonymous key, userInfo.id is that anonymous key - this.usernamePromise = this.getUserInfo().then((userInfo) => userInfo.username || userInfo.id) - } - return this.usernamePromise - } - - async getStream(streamId) { - if (!this.cachedStreams.get(streamId)) { - const streamPromise = this.getStreamFunction(streamId).then((stream) => ({ - id: stream.id, - partitions: stream.partitions, - })) - const success = this.cachedStreams.set(streamId, streamPromise, { - ttl: 30 * 60 * 1000, // 30 minutes - refresh: true, // reset ttl on access - }) - if (!success) { - console.warn(`Could not store stream with id ${streamId} in local cache.`) - return streamPromise - } - } - return this.cachedStreams.get(streamId) - } - - async getPublisherId() { - if (!this.publisherId) { - if (this.auth.privateKey !== undefined) { - this.publisherId = ethers.utils.computeAddress(this.auth.privateKey).toLowerCase() - } else if (this.auth.provider !== undefined) { - const provider = new ethers.providers.Web3Provider(this.auth.provider) - this.publisherId = (await provider.getSigner().getAddress()).toLowerCase() - } else if (this.auth.apiKey !== undefined) { - const hexString = ethers.utils.hexlify(Buffer.from(await this.getUsername(), 'utf8')) - this.publisherId = ethers.utils.sha256(hexString) - } else if (this.auth.username !== undefined) { - const hexString = ethers.utils.hexlify(Buffer.from(this.auth.username, 'utf8')) - this.publisherId = ethers.utils.sha256(hexString) - } else if (this.auth.sessionToken !== undefined) { - const hexString = ethers.utils.hexlify(Buffer.from(await this.getUsername(), 'utf8')) - this.publisherId = ethers.utils.sha256(hexString) - } else { - throw new Error('Need either "privateKey", "provider", "apiKey", "username"+"password" or "sessionToken" to derive the publisher Id.') - } - } - return this.publisherId - } - - getNextSequenceNumber(key, timestamp) { - if (timestamp !== this.getPrevTimestamp(key)) { - return 0 - } - return this.getPrevSequenceNumber(key) + 1 - } - - getPrevMsgRef(key) { - const prevTimestamp = this.getPrevTimestamp(key) - if (!prevTimestamp) { - return null - } - const prevSequenceNumber = this.getPrevSequenceNumber(key) - return new MessageRef(prevTimestamp, prevSequenceNumber) - } - - getPrevTimestamp(key) { - return this.publishedStreams[key].prevTimestamp - } - - getPrevSequenceNumber(key) { - return this.publishedStreams[key].prevSequenceNumber - } - - async createStreamMessage(streamObjectOrId, data, timestamp = Date.now(), partitionKey = null, groupKey) { - // Validate data - if (typeof data !== 'object') { - throw new Error(`Message data must be an object! Was: ${data}`) - } - - if (groupKey) { - EncryptionUtil.validateGroupKey(groupKey) - } - - const stream = (streamObjectOrId instanceof Stream) ? streamObjectOrId : await this.getStream(streamObjectOrId) - const streamPartition = this.computeStreamPartition(stream.partitions, partitionKey) - const publisherId = await this.getPublisherId() - const [messageId, prevMsgRef] = this.createMsgIdAndPrevRef(stream.id, streamPartition, timestamp, publisherId) - - const streamMessage = new StreamMessage({ - messageId, - prevMsgRef, - content: data, - messageType: StreamMessage.MESSAGE_TYPES.MESSAGE, - }) - - if (groupKey && this.keyStorageUtil.hasKey(stream.id) && groupKey !== this.keyStorageUtil.getLatestKey(stream.id).groupKey) { - EncryptionUtil.encryptStreamMessageAndNewKey(groupKey, streamMessage, this.keyStorageUtil.getLatestKey(stream.id).groupKey) - this.keyStorageUtil.addKey(stream.id, groupKey) - } else if (groupKey || this.keyStorageUtil.hasKey(stream.id)) { - if (groupKey) { - this.keyStorageUtil.addKey(stream.id, groupKey) - } - EncryptionUtil.encryptStreamMessage(streamMessage, this.keyStorageUtil.getLatestKey(stream.id).groupKey) - } - - if (this._signer) { - await this._signer.signStreamMessage(streamMessage) - } - return streamMessage - } - - async createGroupKeyRequest({ - messagePublisherAddress, - streamId, - publicKey, - start, - end, - }) { - if (!this._signer) { - throw new Error('Cannot create unsigned group key request. Must authenticate with "privateKey" or "provider"') - } - const publisherId = await this.getPublisherId() - const requestId = uuid('GroupKeyRequest') - const data = { - streamId, - requestId, - publicKey, - } - if (start && end) { - data.range = { - start, - end, - } - } - const [messageId, prevMsgRef] = this.createDefaultMsgIdAndPrevRef(getKeyExchangeStreamId(messagePublisherAddress), publisherId) - const streamMessage = new StreamMessage({ - messageId, - prevMsgRef, - messageType: StreamMessage.MESSAGE_TYPES.GROUP_KEY_REQUEST, - content: data, - }) - await this._signer.signStreamMessage(streamMessage) - return streamMessage - } - - async createGroupKeyResponse({ subscriberAddress, streamId, requestId, encryptedGroupKeys }) { - if (!this._signer) { - throw new Error('Cannot create unsigned group key response. Must authenticate with "privateKey" or "provider"') - } - const publisherId = await this.getPublisherId() - const data = { - requestId, - streamId, - keys: encryptedGroupKeys, - } - const [messageId, prevMsgRef] = this.createDefaultMsgIdAndPrevRef(getKeyExchangeStreamId(subscriberAddress), publisherId) - const streamMessage = new StreamMessage({ - messageId, - prevMsgRef, - messageType: StreamMessage.MESSAGE_TYPES.GROUP_KEY_RESPONSE, - encryptionType: StreamMessage.ENCRYPTION_TYPES.RSA, - content: data, - }) - await this._signer.signStreamMessage(streamMessage) - return streamMessage - } - - async createErrorMessage({ keyExchangeStreamId, streamId, error, requestId }) { - if (!this._signer) { - throw new Error('Cannot create unsigned error message. Must authenticate with "privateKey" or "provider"') - } - const publisherId = await this.getPublisherId() - const data = { - code: MessageCreationUtil.getErrorCodeFromError(error), - message: error.message, - streamId, - requestId, - } - const [messageId, prevMsgRef] = this.createDefaultMsgIdAndPrevRef(keyExchangeStreamId, publisherId) - const streamMessage = new StreamMessage({ - messageId, - prevMsgRef, - messageType: StreamMessage.MESSAGE_TYPES.GROUP_KEY_ERROR_RESPONSE, - content: data, - }) - - await this._signer.signStreamMessage(streamMessage) - return streamMessage - } - - createMsgIdAndPrevRef(streamId, streamPartition, timestamp, publisherId) { - const key = streamId + streamPartition - if (!this.publishedStreams[key]) { - this.publishedStreams[key] = { - prevTimestamp: null, - prevSequenceNumber: 0, - } - } - - const sequenceNumber = this.getNextSequenceNumber(key, timestamp) - const messageId = new MessageID(streamId, streamPartition, timestamp, sequenceNumber, publisherId, this.msgChainId) - const prevMsgRef = this.getPrevMsgRef(key) - this.publishedStreams[key].prevTimestamp = timestamp - this.publishedStreams[key].prevSequenceNumber = sequenceNumber - return [messageId, prevMsgRef] - } - - createDefaultMsgIdAndPrevRef(streamId, publisherId) { - return this.createMsgIdAndPrevRef(streamId, 0, Date.now(), publisherId) - } - - static getErrorCodeFromError(error) { - if (error instanceof InvalidGroupKeyRequestError) { - return 'INVALID_GROUP_KEY_REQUEST' - } - - if (error instanceof InvalidGroupKeyResponseError) { - return 'INVALID_GROUP_KEY_RESPONSE' - } - - if (error instanceof InvalidMessageTypeError) { - return 'INVALID_MESSAGE_TYPE' - } - return 'UNEXPECTED_ERROR' - } - - hash(stringToHash) { - if (this.cachedHashes[stringToHash] === undefined) { - this.cachedHashes[stringToHash] = crypto.createHash('md5').update(stringToHash).digest() - } - return this.cachedHashes[stringToHash] - } - - computeStreamPartition(partitionCount, partitionKey) { - if (!partitionCount) { - throw new Error('partitionCount is falsey!') - } else if (partitionCount === 1) { - // Fast common case - return 0 - } else if (partitionKey) { - const buffer = this.hash(partitionKey) - const intHash = buffer.readInt32LE() - return Math.abs(intHash) % partitionCount - } else { - // Fallback to random partition if no key - return Math.floor(Math.random() * partitionCount) - } - } -} diff --git a/src/RealTimeSubscription.js b/src/RealTimeSubscription.js deleted file mode 100644 index e460943a9..000000000 --- a/src/RealTimeSubscription.js +++ /dev/null @@ -1,89 +0,0 @@ -import debugFactory from 'debug' -import uniqueId from 'lodash.uniqueid' - -import Subscription from './Subscription' -import AbstractSubscription from './AbstractSubscription' -import EncryptionUtil from './EncryptionUtil' -import UnableToDecryptError from './errors/UnableToDecryptError' - -export default class RealTimeSubscription extends AbstractSubscription { - constructor(streamId, streamPartition, callback, groupKeys, propagationTimeout, resendTimeout, orderMessages = true, - onUnableToDecrypt = AbstractSubscription.defaultUnableToDecrypt, debug) { - super(streamId, streamPartition, callback, groupKeys, propagationTimeout, resendTimeout, orderMessages, onUnableToDecrypt) - - const id = uniqueId('Subscription') - if (debug) { - this.debug = debug.extend(id) - } else { - this.debug = debugFactory(`StreamrClient::${id}`) - } - - this.alreadyFailedToDecrypt = {} - this.resending = false - } - - // All the handle* methods should: - // - return a promise for consistency - // - swallow exceptions and emit them as 'error' events - - async handleBroadcastMessage(msg, verifyFn) { - return this._catchAndEmitErrors(() => this._handleMessage(msg, verifyFn)) - } - - finishResend() { - this.setResending(false) - } - - // passing publisherId separately to ensure it is lowercase (See call of this function in AbstractSubscription.js) - _decryptOrRequestGroupKey(msg, publisherId) { - let newGroupKey - try { - newGroupKey = EncryptionUtil.decryptStreamMessage(msg, this.groupKeys[publisherId]) - } catch (e) { - if (e instanceof UnableToDecryptError && !this.alreadyFailedToDecrypt[publisherId]) { - this._requestGroupKeyAndQueueMessage(msg) - this.alreadyFailedToDecrypt[publisherId] = true - return false - } - throw e - } - delete this.alreadyFailedToDecrypt[publisherId] - if (newGroupKey) { - this.groupKeys[publisherId] = newGroupKey - } - return true - } - - /* eslint-disable class-methods-use-this */ - hasResendOptions() { - return false - } - - getResendOptions() { - return {} - } - /* eslint-enable class-methods-use-this */ - - isResending() { - return this.resending - } - - setResending(resending) { - this.debug(`Subscription: Stream ${this.streamId} resending: ${resending}`) - this.resending = resending - } - - setGroupKeys(publisherId, groupKeys) { - if (groupKeys.length !== 1) { - throw new Error('Received multiple group keys for a real time subscription (expected one).') - } - /* eslint-disable prefer-destructuring */ - this.groupKeys[publisherId.toLowerCase()] = groupKeys[0] - /* eslint-enable prefer-destructuring */ - this._handleEncryptedQueuedMsgs(publisherId) - } - - onDisconnected() { - this.setState(Subscription.State.unsubscribed) - } -} diff --git a/src/ResendUtil.js b/src/ResendUtil.js deleted file mode 100644 index 91702c3f7..000000000 --- a/src/ResendUtil.js +++ /dev/null @@ -1,45 +0,0 @@ -import EventEmitter from 'eventemitter3' -import { ControlLayer } from 'streamr-client-protocol' - -import { uuid } from './utils' - -const { ControlMessage } = ControlLayer - -export default class ResendUtil extends EventEmitter { - constructor() { - super() - this.subForRequestId = {} - } - - /* eslint-disable-next-line class-methods-use-this */ - generateRequestId() { - return uuid('r') - } - - _subForRequestIdExists(requestId) { - return requestId in this.subForRequestId - } - - getSubFromResendResponse(response) { - if (!this._subForRequestIdExists(response.requestId)) { - const error = new Error(`Received unexpected ${response.constructor.name} message ${response.serialize()}`) - this.emit('error', error) - } - - return this.subForRequestId[response.requestId] - } - - deleteDoneSubsByResponse(response) { - // TODO: replace with response.requestId - if (response.type === ControlMessage.TYPES.ResendResponseResent || response.type === ControlMessage.TYPES.ResendResponseNoResend) { - delete this.subForRequestId[response.requestId] - } - } - - registerResendRequestForSub(sub) { - const requestId = this.generateRequestId() - this.subForRequestId[requestId] = sub - sub.addPendingResendRequestId(requestId) - return requestId - } -} diff --git a/src/Session.js b/src/Session.js deleted file mode 100644 index d862108d5..000000000 --- a/src/Session.js +++ /dev/null @@ -1,98 +0,0 @@ -import EventEmitter from 'eventemitter3' -import { ethers } from 'ethers' - -export default class Session extends EventEmitter { - constructor(client, options) { - super() - this._client = client - this.options = options || {} - this.state = Session.State.LOGGED_OUT - - if (typeof this.options.privateKey !== 'undefined') { - const wallet = new ethers.Wallet(this.options.privateKey) - this.loginFunction = async () => this._client.loginWithChallengeResponse((d) => wallet.signMessage(d), wallet.address) - } else if (typeof this.options.provider !== 'undefined') { - const provider = new ethers.providers.Web3Provider(this.options.provider) - const signer = provider.getSigner() - this.loginFunction = async () => this._client.loginWithChallengeResponse((d) => signer.signMessage(d), await signer.getAddress()) - } else if (typeof this.options.apiKey !== 'undefined') { - this.loginFunction = async () => this._client.loginWithApiKey(this.options.apiKey) - } else if (typeof this.options.username !== 'undefined' && typeof this.options.password !== 'undefined') { - this.loginFunction = async () => this._client.loginWithUsernamePassword(this.options.username, this.options.password) - } else { - if (!this.options.sessionToken) { - this.options.unauthenticated = true - } - this.loginFunction = async () => { - throw new Error('Need either "privateKey", "provider", "apiKey", "username"+"password" or "sessionToken" to login.') - } - } - } - - isUnauthenticated() { - return this.options.unauthenticated - } - - updateState(newState) { - this.state = newState - this.emit(newState) - } - - async getSessionToken(requireNewToken = false) { - if (this.options.sessionToken && !requireNewToken) { - return this.options.sessionToken - } - - if (this.options.unauthenticated) { - return undefined - } - - if (this.state !== Session.State.LOGGING_IN) { - if (this.state === Session.State.LOGGING_OUT) { - this.sessionTokenPromise = new Promise((resolve) => { - this.once(Session.State.LOGGED_OUT, () => resolve(this.getSessionToken(requireNewToken))) - }) - } else { - this.updateState(Session.State.LOGGING_IN) - this.sessionTokenPromise = this.loginFunction().then((tokenObj) => { - this.options.sessionToken = tokenObj.token - this.updateState(Session.State.LOGGED_IN) - return tokenObj.token - }, (err) => { - this.updateState(Session.State.LOGGED_OUT) - throw err - }) - } - } - return this.sessionTokenPromise - } - - async logout() { - if (this.state === Session.State.LOGGED_OUT) { - throw new Error('Already logged out!') - } - - if (this.state === Session.State.LOGGING_OUT) { - throw new Error('Already logging out!') - } - - if (this.state === Session.State.LOGGING_IN) { - await new Promise((resolve) => { - this.once(Session.State.LOGGED_IN, () => resolve(this.logout())) - }) - return - } - - this.updateState(Session.State.LOGGING_OUT) - await this._client.logoutEndpoint() - this.options.sessionToken = undefined - this.updateState(Session.State.LOGGED_OUT) - } -} - -Session.State = { - LOGGING_OUT: 'logging out', - LOGGED_OUT: 'logged out', - LOGGING_IN: 'logging in', - LOGGED_IN: 'logged in', -} diff --git a/src/Session.ts b/src/Session.ts new file mode 100644 index 000000000..4e47f9e76 --- /dev/null +++ b/src/Session.ts @@ -0,0 +1,135 @@ +import EventEmitter from 'eventemitter3' +import { Wallet } from '@ethersproject/wallet' +import { ExternalProvider, JsonRpcFetchFunc, Web3Provider } from '@ethersproject/providers' +import { StreamrClient } from './StreamrClient' +import { BytesLike } from '@ethersproject/bytes' + +enum State { + LOGGING_OUT = 'logging out', + LOGGED_OUT = 'logged out', + LOGGING_IN ='logging in', + LOGGED_IN = 'logged in', +} + +export interface SessionOptions { + privateKey?: BytesLike + ethereum?: ExternalProvider|JsonRpcFetchFunc + apiKey?: string + username?: string + password?: string + sessionToken?: string + unauthenticated?: boolean +} + +interface TokenObject { + token: string +} + +/** @internal */ +export default class Session extends EventEmitter { + + _client: StreamrClient + options: SessionOptions + state: State + loginFunction: () => Promise + sessionTokenPromise?: Promise + + constructor(client: StreamrClient, options: SessionOptions = {}) { + super() + this._client = client + this.options = { + ...options + } + + this.state = State.LOGGED_OUT + + // TODO: move loginFunction to StreamrClient constructor where "auth type" is checked + if (typeof this.options.privateKey !== 'undefined') { + const wallet = new Wallet(this.options.privateKey) + this.loginFunction = async () => ( + this._client.loginWithChallengeResponse((d: string) => wallet.signMessage(d), wallet.address) + ) + } else if (typeof this.options.ethereum !== 'undefined') { + const provider = new Web3Provider(this.options.ethereum) + const signer = provider.getSigner() + this.loginFunction = async () => ( + this._client.loginWithChallengeResponse((d: string) => signer.signMessage(d), await signer.getAddress()) + ) + } else if (typeof this.options.apiKey !== 'undefined') { + this.loginFunction = async () => ( + this._client.loginWithApiKey(this.options.apiKey!) + ) + } else if (typeof this.options.username !== 'undefined' && typeof this.options.password !== 'undefined') { + this.loginFunction = async () => ( + this._client.loginWithUsernamePassword(this.options.username!, this.options.password!) + ) + } else { + if (!this.options.sessionToken) { + this.options.unauthenticated = true + } + this.loginFunction = async () => { + throw new Error('Need either "privateKey", "ethereum", "apiKey", "username"+"password" or "sessionToken" to login.') + } + } + } + + isUnauthenticated() { + return this.options.unauthenticated + } + + updateState(newState: State) { + this.state = newState + this.emit(newState) + } + + async getSessionToken(requireNewToken = false) { + if (this.options.sessionToken && !requireNewToken) { + return this.options.sessionToken + } + + if (this.options.unauthenticated) { + return undefined + } + + if (this.state !== State.LOGGING_IN) { + if (this.state === State.LOGGING_OUT) { + this.sessionTokenPromise = new Promise((resolve) => { + this.once(State.LOGGED_OUT, () => resolve(this.getSessionToken(requireNewToken))) + }) + } else { + this.updateState(State.LOGGING_IN) + this.sessionTokenPromise = this.loginFunction().then((tokenObj: TokenObject) => { + this.options.sessionToken = tokenObj.token + this.updateState(State.LOGGED_IN) + return tokenObj.token + }, (err: Error) => { + this.updateState(State.LOGGED_OUT) + throw err + }) + } + } + return this.sessionTokenPromise + } + + async logout() { + if (this.state === State.LOGGED_OUT) { + throw new Error('Already logged out!') + } + + if (this.state === State.LOGGING_OUT) { + throw new Error('Already logging out!') + } + + if (this.state === State.LOGGING_IN) { + await new Promise((resolve) => { + this.once(State.LOGGED_IN, () => resolve(this.logout())) + }) + return + } + + this.updateState(State.LOGGING_OUT) + await this._client.logoutEndpoint() + this.options.sessionToken = undefined + this.updateState(State.LOGGED_OUT) + } +} diff --git a/src/Signer.js b/src/Signer.js deleted file mode 100644 index bfcda3c3e..000000000 --- a/src/Signer.js +++ /dev/null @@ -1,70 +0,0 @@ -import { MessageLayer, Utils } from 'streamr-client-protocol' -import { ethers } from 'ethers' - -const { StreamMessage } = MessageLayer -const { SigningUtil } = Utils -const { SIGNATURE_TYPES } = StreamMessage - -export default class Signer { - constructor(options = {}) { - // copy options to prevent possible later mutation - this.options = { - ...options, - } - const { privateKey, provider } = this.options - if (privateKey) { - const address = ethers.utils.computeAddress(privateKey) - const key = (typeof privateKey === 'string' && privateKey.startsWith('0x')) - ? privateKey.slice(2) // strip leading 0x - : privateKey - this.sign = async (d) => { - return SigningUtil.sign(d, key) - } - this.getAddress = async () => address - } else if (provider) { - const web3Provider = new ethers.providers.Web3Provider(provider) - const signer = web3Provider.getSigner() - this.getAddress = async () => signer.getAddress() - this.sign = async (d) => signer.signMessage(d) - } else { - throw new Error('Need either "privateKey" or "provider".') - } - } - - async signData(data, signatureType = SIGNATURE_TYPES.ETH) { - if (signatureType === SIGNATURE_TYPES.ETH_LEGACY || signatureType === SIGNATURE_TYPES.ETH) { - return this.sign(data) - } - throw new Error(`Unrecognized signature type: ${signatureType}`) - } - - async signStreamMessage(streamMessage, signatureType = SIGNATURE_TYPES.ETH) { - if (!streamMessage.getTimestamp()) { - throw new Error('Timestamp is required as part of the data to sign.') - } - /* eslint-disable no-param-reassign */ - // set signature & publisher so getting of payload works correctly - streamMessage.signatureType = signatureType - // eslint-disable-next-line require-atomic-updates - streamMessage.messageId.publisherId = await this.getAddress() // changing the id seems bad - const payload = streamMessage.getPayloadToSign() - // eslint-disable-next-line require-atomic-updates - streamMessage.signature = await this.signData(payload, signatureType) - /* eslint-enable no-param-reassign */ - } - - static createSigner(options, publishWithSignature) { - if (publishWithSignature === 'never') { - return undefined - } - - if (publishWithSignature === 'auto' && !options.privateKey && !options.provider) { - return undefined - } - - if (publishWithSignature === 'auto' || publishWithSignature === 'always') { - return new Signer(options) - } - throw new Error(`Unknown parameter value: ${publishWithSignature}`) - } -} diff --git a/src/StreamrClient.js b/src/StreamrClient.js deleted file mode 100644 index 710a8a68c..000000000 --- a/src/StreamrClient.js +++ /dev/null @@ -1,916 +0,0 @@ -import EventEmitter from 'eventemitter3' -import debugFactory from 'debug' -import qs from 'qs' -import once from 'once' -import { Wallet } from 'ethers' -import { ControlLayer, MessageLayer, Errors } from 'streamr-client-protocol' -import uniqueId from 'lodash.uniqueid' - -import HistoricalSubscription from './HistoricalSubscription' -import Connection from './Connection' -import Session from './Session' -import Signer from './Signer' -import SubscribedStreamPartition from './SubscribedStreamPartition' -import Stream from './rest/domain/Stream' -import FailedToPublishError from './errors/FailedToPublishError' -import MessageCreationUtil from './MessageCreationUtil' -import { waitFor, getVersionString } from './utils' -import RealTimeSubscription from './RealTimeSubscription' -import CombinedSubscription from './CombinedSubscription' -import Subscription from './Subscription' -import EncryptionUtil from './EncryptionUtil' -import KeyExchangeUtil from './KeyExchangeUtil' -import KeyStorageUtil from './KeyStorageUtil' -import ResendUtil from './ResendUtil' -import InvalidMessageTypeError from './errors/InvalidMessageTypeError' - -const { - SubscribeRequest, - UnsubscribeRequest, - ResendLastRequest, - ResendFromRequest, - ResendRangeRequest, - ControlMessage, -} = ControlLayer - -const { StreamMessage, MessageRef } = MessageLayer - -export default class StreamrClient extends EventEmitter { - constructor(options, connection) { - super() - this.id = uniqueId('StreamrClient') - this.debug = debugFactory(this.id) - // Default options - this.options = { - debug: this.debug, - // The server to connect to - url: 'wss://streamr.network/api/v1/ws', - restUrl: 'https://streamr.network/api/v1', - // Automatically connect on first subscribe - autoConnect: true, - // Automatically disconnect on last unsubscribe - autoDisconnect: true, - orderMessages: true, - auth: {}, - publishWithSignature: 'auto', - verifySignatures: 'auto', - retryResendAfter: 5000, - gapFillTimeout: 5000, - maxPublishQueueSize: 10000, - // encryption options - publisherStoreKeyHistory: true, - publisherGroupKeys: {}, // {streamId: groupKey} - subscriberGroupKeys: {}, // {streamId: {publisherId: groupKey}} - keyExchange: {}, - streamrNodeAddress: '0xf3E5A65851C3779f468c9EcB32E6f25D9D68601a', - streamrOperatorAddress: '0xc0aa4dC0763550161a6B59fa430361b5a26df28C', - tokenAddress: '0x0Cf0Ee63788A0849fE5297F3407f701E122cC023', - } - - this.subscribedStreamPartitions = {} - - Object.assign(this.options, options || {}) - - const parts = this.options.url.split('?') - if (parts.length === 1) { // there is no query string - const controlLayer = `controlLayerVersion=${ControlMessage.LATEST_VERSION}` - const messageLayer = `messageLayerVersion=${StreamMessage.LATEST_VERSION}` - this.options.url = `${this.options.url}?${controlLayer}&${messageLayer}` - } else { - const queryObj = qs.parse(parts[1]) - if (!queryObj.controlLayerVersion) { - this.options.url = `${this.options.url}&controlLayerVersion=1` - } - - if (!queryObj.messageLayerVersion) { - this.options.url = `${this.options.url}&messageLayerVersion=31` - } - } - - // always add streamrClient version - this.options.url = `${this.options.url}&streamrClient=${getVersionString()}` - - // Backwards compatibility for option 'authKey' => 'apiKey' - if (this.options.authKey && !this.options.apiKey) { - this.options.apiKey = this.options.authKey - } - - if (this.options.apiKey) { - this.options.auth.apiKey = this.options.apiKey - } - - if (this.options.auth.privateKey && !this.options.auth.privateKey.startsWith('0x')) { - this.options.auth.privateKey = `0x${this.options.auth.privateKey}` - } - - if (this.options.keyExchange) { - this.encryptionUtil = new EncryptionUtil(this.options.keyExchange) - this.keyExchangeUtil = new KeyExchangeUtil(this) - } - - // add the start time to every group key if missing - const validated = KeyStorageUtil.validateAndAddStart(this.options.publisherGroupKeys, this.options.subscriberGroupKeys) - /* eslint-disable prefer-destructuring */ - this.options.publisherGroupKeys = validated[0] - this.options.subscriberGroupKeys = validated[1] - /* eslint-enable prefer-destructuring */ - - this.keyStorageUtil = KeyStorageUtil.getKeyStorageUtil( - this.options.publisherGroupKeys, this.options.publisherStoreKeyHistory - ) - - this.publishQueue = [] - this.session = new Session(this, this.options.auth) - this.signer = Signer.createSigner({ - ...this.options.auth, - debug: this.debug, - }, this.options.publishWithSignature) - // Event handling on connection object - this.connection = connection || new Connection(this.options) - - this.getUserInfo = this.getUserInfo.bind(this) - - if (this.session.isUnauthenticated()) { - this.msgCreationUtil = null - } else { - this.msgCreationUtil = new MessageCreationUtil( - this.options.auth, this.signer, once(() => this.getUserInfo()), - (streamId) => this.getStream(streamId) - .catch((err) => this.emit('error', err)), this.keyStorageUtil, - ) - } - - this.resendUtil = new ResendUtil() - this.resendUtil.on('error', (err) => this.emit('error', err)) - - this.on('error', (...args) => { - this.onError(...args) - this.ensureDisconnected() - }) - - // Broadcast messages to all subs listening on stream-partition - this.connection.on(ControlMessage.TYPES.BroadcastMessage, (msg) => { - const stream = this._getSubscribedStreamPartition(msg.streamMessage.getStreamId(), msg.streamMessage.getStreamPartition()) - if (stream) { - const verifyFn = once(() => stream.verifyStreamMessage(msg.streamMessage)) // ensure verification occurs only once - // sub.handleBroadcastMessage never rejects: on any error it emits an 'error' event on the Subscription - stream.getSubscriptions().forEach((sub) => sub.handleBroadcastMessage(msg.streamMessage, verifyFn)) - } else { - this.debug('WARN: message received for stream with no subscriptions: %s', msg.streamMessage.getStreamId()) - } - }) - - // Unicast messages to a specific subscription only - this.connection.on(ControlMessage.TYPES.UnicastMessage, async (msg) => { - const stream = this._getSubscribedStreamPartition(msg.streamMessage.getStreamId(), msg.streamMessage.getStreamPartition()) - if (stream) { - const sub = this.resendUtil.getSubFromResendResponse(msg) - - if (sub && stream.getSubscription(sub.id)) { - // sub.handleResentMessage never rejects: on any error it emits an 'error' event on the Subscription - sub.handleResentMessage( - msg.streamMessage, msg.requestId, - once(() => stream.verifyStreamMessage(msg.streamMessage)), // ensure verification occurs only once - ) - } else { - this.debug('WARN: request id not found for stream: %s, sub: %s', msg.streamMessage.getStreamId(), msg.requestId) - } - } else { - this.debug('WARN: message received for stream with no subscriptions: %s', msg.streamMessage.getStreamId()) - } - }) - - this.connection.on(ControlMessage.TYPES.SubscribeResponse, (response) => { - const stream = this._getSubscribedStreamPartition(response.streamId, response.streamPartition) - if (stream) { - stream.setSubscribing(false) - stream.getSubscriptions().filter((sub) => !sub.resending) - .forEach((sub) => sub.setState(Subscription.State.subscribed)) - } - this.debug('Client subscribed: streamId: %s, streamPartition: %s', response.streamId, response.streamPartition) - }) - - this.connection.on(ControlMessage.TYPES.UnsubscribeResponse, (response) => { - this.debug('Client unsubscribed: streamId: %s, streamPartition: %s', response.streamId, response.streamPartition) - const stream = this._getSubscribedStreamPartition(response.streamId, response.streamPartition) - if (stream) { - stream.getSubscriptions().forEach((sub) => { - this._removeSubscription(sub) - sub.setState(Subscription.State.unsubscribed) - }) - } - - this._checkAutoDisconnect() - }) - - // Route resending state messages to corresponding Subscriptions - this.connection.on(ControlMessage.TYPES.ResendResponseResending, (response) => { - const stream = this._getSubscribedStreamPartition(response.streamId, response.streamPartition) - const sub = this.resendUtil.getSubFromResendResponse(response) - - if (stream && sub && stream.getSubscription(sub.id)) { - stream.getSubscription(sub.id).handleResending(response) - } else { - this.debug('resent: Subscription %s is gone already', response.requestId) - } - }) - - this.connection.on(ControlMessage.TYPES.ResendResponseNoResend, (response) => { - const stream = this._getSubscribedStreamPartition(response.streamId, response.streamPartition) - const sub = this.resendUtil.getSubFromResendResponse(response) - this.resendUtil.deleteDoneSubsByResponse(response) - - if (stream && sub && stream.getSubscription(sub.id)) { - stream.getSubscription(sub.id).handleNoResend(response) - } else { - this.debug('resent: Subscription %s is gone already', response.requestId) - } - }) - - this.connection.on(ControlMessage.TYPES.ResendResponseResent, (response) => { - const stream = this._getSubscribedStreamPartition(response.streamId, response.streamPartition) - const sub = this.resendUtil.getSubFromResendResponse(response) - this.resendUtil.deleteDoneSubsByResponse(response) - - if (stream && sub && stream.getSubscription(sub.id)) { - stream.getSubscription(sub.id).handleResent(response) - } else { - this.debug('resent: Subscription %s is gone already', response.requestId) - } - }) - - // On connect/reconnect, send pending subscription requests - this.connection.on('connected', async () => { - await new Promise((resolve) => setTimeout(resolve, 0)) // wait a tick to let event handlers finish - if (!this.isConnected()) { return } - this.debug('Connected!') - this.emit('connected') - try { - await this._subscribeToKeyExchangeStream() - if (!this.isConnected()) { return } - // Check pending subscriptions - Object.keys(this.subscribedStreamPartitions).forEach((key) => { - this.subscribedStreamPartitions[key].getSubscriptions().forEach((sub) => { - if (sub.getState() !== Subscription.State.subscribed) { - this._resendAndSubscribe(sub).catch((err) => { - this.emit('error', err) - }) - } - }) - }) - - // Check pending publish requests - const publishQueueCopy = this.publishQueue.slice(0) - this.publishQueue = [] - publishQueueCopy.forEach((publishFn) => publishFn()) - } catch (err) { - this.emit('error', err) - } - }) - - this.connection.on('disconnected', () => { - this.debug('Disconnected.') - this.emit('disconnected') - - Object.keys(this.subscribedStreamPartitions) - .forEach((key) => { - const stream = this.subscribedStreamPartitions[key] - stream.setSubscribing(false) - stream.getSubscriptions().forEach((sub) => { - sub.onDisconnected() - }) - }) - }) - - this.connection.on(ControlMessage.TYPES.ErrorResponse, (err) => { - const errorObject = new Error(err.errorMessage) - this.emit('error', errorObject) - }) - - this.connection.on('error', async (err) => { - // If there is an error parsing a json message in a stream, fire error events on the relevant subs - if (err instanceof Errors.InvalidJsonError) { - const stream = this._getSubscribedStreamPartition(err.streamMessage.getStreamId(), err.streamMessage.getStreamPartition()) - if (stream) { - stream.getSubscriptions().forEach((sub) => sub.handleError(err)) - } else { - this.debug('WARN: InvalidJsonError received for stream with no subscriptions: %s', err.streamId) - } - } else { - // if it looks like an error emit as-is, otherwise wrap in new Error - const errorObject = (err && err.stack && err.message) ? err : new Error(err) - this.emit('error', errorObject) - } - }) - } - - /** - * Override to control output - */ - - onError(error) { // eslint-disable-line class-methods-use-this - console.error(error) - } - - async _subscribeToKeyExchangeStream() { - if (!this.options.auth.privateKey && !this.options.auth.provider) { - return - } - await this.session.getSessionToken() // trigger auth errors if any - // subscribing to own keyexchange stream - const publisherId = await this.getPublisherId() - const streamId = KeyExchangeUtil.getKeyExchangeStreamId(publisherId) - this.subscribe(streamId, async (parsedContent, streamMessage) => { - if (streamMessage.messageType === StreamMessage.MESSAGE_TYPES.GROUP_KEY_REQUEST) { - if (this.keyExchangeUtil) { - try { - await this.keyExchangeUtil.handleGroupKeyRequest(streamMessage) - } catch (error) { - this.debug('WARN: %s', error.message) - const msg = streamMessage.getParsedContent() - const errorMessage = await this.msgCreationUtil.createErrorMessage({ - keyExchangeStreamId: streamId, - requestId: msg.requestId, - streamId: msg.streamId, - error, - }) - this.publishStreamMessage(errorMessage) - } - } - } else if (streamMessage.messageType === StreamMessage.MESSAGE_TYPES.GROUP_KEY_RESPONSE) { - if (this.keyExchangeUtil) { - this.keyExchangeUtil.handleGroupKeyResponse(streamMessage) - } - } else if (streamMessage.messageType === StreamMessage.MESSAGE_TYPES.GROUP_KEY_ERROR_RESPONSE) { - this.debug('WARN: Received error of type %s from %s: %s', - streamMessage.getParsedContent().code, streamMessage.getPublisherId(), streamMessage.getParsedContent().message) - } else { - throw new InvalidMessageTypeError(`Cannot handle message with type: ${streamMessage.messageType}`) - } - }) - } - - _getSubscribedStreamPartition(streamId, streamPartition) { - const key = streamId + streamPartition - return this.subscribedStreamPartitions[key] - } - - _getSubscribedStreamPartitionsForStream(streamId) { - // TODO: pretty crude method, could improve - return Object.values(this.subscribedStreamPartitions) - .filter((stream) => stream.streamId === streamId) - } - - _addSubscribedStreamPartition(subscribedStreamPartition) { - const key = subscribedStreamPartition.streamId + subscribedStreamPartition.streamPartition - this.subscribedStreamPartitions[key] = subscribedStreamPartition - } - - _deleteSubscribedStreamPartition(subscribedStreamPartition) { - const key = subscribedStreamPartition.streamId + subscribedStreamPartition.streamPartition - delete this.subscribedStreamPartitions[key] - } - - _addSubscription(sub) { - let sp = this._getSubscribedStreamPartition(sub.streamId, sub.streamPartition) - if (!sp) { - sp = new SubscribedStreamPartition(this, sub.streamId, sub.streamPartition) - this._addSubscribedStreamPartition(sp) - } - sp.addSubscription(sub) - } - - _removeSubscription(sub) { - const sp = this._getSubscribedStreamPartition(sub.streamId, sub.streamPartition) - if (sp) { - sp.removeSubscription(sub) - if (sp.getSubscriptions().length === 0) { - this._deleteSubscribedStreamPartition(sp) - } - } - } - - getSubscriptions(streamId, streamPartition) { - let subs = [] - - if (streamPartition) { - const sp = this._getSubscribedStreamPartition(streamId, streamPartition) - if (sp) { - subs = sp.getSubscriptions() - } - } else { - const sps = this._getSubscribedStreamPartitionsForStream(streamId) - sps.forEach((sp) => sp.getSubscriptions().forEach((sub) => subs.push(sub))) - } - - return subs - } - - async publish(streamObjectOrId, data, timestamp = new Date(), partitionKey = null, groupKey) { - if (this.session.isUnauthenticated()) { - throw new Error('Need to be authenticated to publish.') - } - // Validate streamObjectOrId - let streamId - if (streamObjectOrId instanceof Stream) { - streamId = streamObjectOrId.id - } else if (typeof streamObjectOrId === 'string') { - streamId = streamObjectOrId - } else { - throw new Error(`First argument must be a Stream object or the stream id! Was: ${streamObjectOrId}`) - } - - const timestampAsNumber = timestamp instanceof Date ? timestamp.getTime() : new Date(timestamp).getTime() - const [sessionToken, streamMessage] = await Promise.all([ - this.session.getSessionToken(), - this.msgCreationUtil.createStreamMessage(streamObjectOrId, data, timestampAsNumber, partitionKey, groupKey), - ]) - - if (this.isConnected()) { - // If connected, emit a publish request - return this._requestPublish(streamMessage, sessionToken) - } - - if (this.options.autoConnect) { - if (this.publishQueue.length >= this.options.maxPublishQueueSize) { - throw new FailedToPublishError( - streamId, - data, - `publishQueue exceeded maxPublishQueueSize=${this.options.maxPublishQueueSize}`, - ) - } - - const published = new Promise((resolve, reject) => { - this.publishQueue.push(async () => { - let publishRequest - try { - publishRequest = await this._requestPublish(streamMessage, sessionToken) - } catch (err) { - reject(err) - this.emit('error', err) - return - } - resolve(publishRequest) - }) - }) - // be sure to trigger connection *after* queueing publish - await this.ensureConnected() // await to ensure connection error fails publish - return published - } - - throw new FailedToPublishError( - streamId, - data, - 'Wait for the "connected" event before calling publish, or set autoConnect to true!', - ) - } - - async resend(optionsOrStreamId, callback) { - const options = this._validateParameters(optionsOrStreamId, callback) - - if (!options.stream) { - throw new Error('resend: Invalid arguments: options.stream is not given') - } - - if (!options.resend) { - throw new Error('resend: Invalid arguments: options.resend is not given') - } - - await this.ensureConnected() - - const sub = new HistoricalSubscription(options.stream, options.partition || 0, callback, options.resend, - this.options.subscriberGroupKeys[options.stream], this.options.gapFillTimeout, this.options.retryResendAfter, - this.options.orderMessages, options.onUnableToDecrypt, this.debug) - - // TODO remove _addSubscription after uncoupling Subscription and Resend - sub.setState(Subscription.State.subscribed) - this._addSubscription(sub) - sub.once('initial_resend_done', () => this._removeSubscription(sub)) - await this._requestResend(sub) - return sub - } - - // eslint-disable-next-line class-methods-use-this - _validateParameters(optionsOrStreamId, callback) { - if (!optionsOrStreamId) { - throw new Error('subscribe/resend: Invalid arguments: options is required!') - } else if (!callback) { - throw new Error('subscribe/resend: Invalid arguments: callback is required!') - } - - // Backwards compatibility for giving a streamId as first argument - let options - if (typeof optionsOrStreamId === 'string') { - options = { - stream: optionsOrStreamId, - } - } else if (typeof optionsOrStreamId === 'object') { - options = optionsOrStreamId - } else { - throw new Error(`subscribe/resend: options must be an object! Given: ${optionsOrStreamId}`) - } - - return options - } - - subscribe(optionsOrStreamId, callback, legacyOptions) { - const options = this._validateParameters(optionsOrStreamId, callback) - - // Backwards compatibility for giving an options object as third argument - Object.assign(options, legacyOptions) - - if (!options.stream) { - throw new Error('subscribe: Invalid arguments: options.stream is not given') - } - - if (options.groupKeys) { - const now = Date.now() - Object.keys(options.groupKeys).forEach((publisherId) => { - EncryptionUtil.validateGroupKey(options.groupKeys[publisherId]) - if (!this.options.subscriberGroupKeys[options.stream]) { - this.options.subscriberGroupKeys[options.stream] = {} - } - this.options.subscriberGroupKeys[options.stream][publisherId] = { - groupKey: options.groupKeys[publisherId], - start: now - } - }) - } - - const groupKeys = {} - if (this.options.subscriberGroupKeys[options.stream]) { - Object.keys(this.options.subscriberGroupKeys[options.stream]).forEach((publisherId) => { - groupKeys[publisherId] = this.options.subscriberGroupKeys[options.stream][publisherId].groupKey - }) - } - - // Create the Subscription object and bind handlers - let sub - if (options.resend) { - sub = new CombinedSubscription( - options.stream, options.partition || 0, callback, options.resend, - groupKeys, this.options.gapFillTimeout, this.options.retryResendAfter, - this.options.orderMessages, options.onUnableToDecrypt, this.debug, - ) - } else { - sub = new RealTimeSubscription(options.stream, options.partition || 0, callback, - groupKeys, this.options.gapFillTimeout, this.options.retryResendAfter, - this.options.orderMessages, options.onUnableToDecrypt, this.debug) - } - sub.on('gap', (from, to, publisherId, msgChainId) => { - if (!sub.resending) { - this._requestResend(sub, { - from, to, publisherId, msgChainId, - }) - } - }) - sub.on('done', () => { - this.debug('done event for sub %d', sub.id) - this.unsubscribe(sub) - }) - sub.on('groupKeyMissing', async (messagePublisherAddress, start, end) => { - if (this.encryptionUtil) { - await this.encryptionUtil.onReady() - const streamMessage = await this.msgCreationUtil.createGroupKeyRequest({ - messagePublisherAddress, - streamId: sub.streamId, - publicKey: this.encryptionUtil.getPublicKey(), - start, - end, - }) - await this.publishStreamMessage(streamMessage) - } - }) - - // Add to lookups - this._addSubscription(sub) - - // If connected, emit a subscribe request - if (this.isConnected()) { - this._resendAndSubscribe(sub) - } else if (this.options.autoConnect) { - this.ensureConnected() - } - - return sub - } - - unsubscribe(sub) { - if (!sub || !sub.streamId) { - throw new Error('unsubscribe: please give a Subscription object as an argument!') - } - - const sp = this._getSubscribedStreamPartition(sub.streamId, sub.streamPartition) - - // If this is the last subscription for this stream-partition, unsubscribe the client too - if (sp && sp.getSubscriptions().length === 1 - && this.isConnected() - && sub.getState() === Subscription.State.subscribed) { - sub.setState(Subscription.State.unsubscribing) - this._requestUnsubscribe(sub) - } else if (sub.getState() !== Subscription.State.unsubscribing && sub.getState() !== Subscription.State.unsubscribed) { - // Else the sub can be cleaned off immediately - this._removeSubscription(sub) - sub.setState(Subscription.State.unsubscribed) - this._checkAutoDisconnect() - } - } - - unsubscribeAll(streamId, streamPartition) { - if (!streamId) { - throw new Error('unsubscribeAll: a stream id is required!') - } else if (typeof streamId !== 'string') { - throw new Error('unsubscribe: stream id must be a string!') - } - - let streamPartitions = [] - - // Unsubscribe all subs for the given stream-partition - if (streamPartition) { - const sp = this._getSubscribedStreamPartition(streamId, streamPartition) - if (sp) { - streamPartitions = [sp] - } - } else { - streamPartitions = this._getSubscribedStreamPartitionsForStream(streamId) - } - - streamPartitions.forEach((sp) => { - sp.getSubscriptions().forEach((sub) => { - this.unsubscribe(sub) - }) - }) - } - - isConnected() { - return this.connection.state === Connection.State.CONNECTED - } - - isConnecting() { - return this.connection.state === Connection.State.CONNECTING - } - - isDisconnecting() { - return this.connection.state === Connection.State.DISCONNECTING - } - - isDisconnected() { - return this.connection.state === Connection.State.DISCONNECTED - } - - reconnect() { - return this.connect() - } - - async connect() { - try { - if (this.isConnected()) { - throw new Error('Already connected!') - } - - if (this.connection.state === Connection.State.CONNECTING) { - throw new Error('Already connecting!') - } - - this.debug('Connecting to %s', this.options.url) - await this.connection.connect() - } catch (err) { - this.emit('error', err) - throw err - } - } - - pause() { - return this.connection.disconnect() - } - - disconnect() { - if (this.msgCreationUtil) { - this.msgCreationUtil.stop() - } - - this.subscribedStreamPartitions = {} - return this.connection.disconnect() - } - - logout() { - return this.session.logout() - } - - getPublisherId() { - return this.msgCreationUtil.getPublisherId() - } - - /** - * Starts new connection if disconnected. - * Waits for connection if connecting. - * No-op if already connected. - */ - - async ensureConnected() { - if (this.isConnected()) { return Promise.resolve() } - - if (!this.isConnecting()) { - await this.connect() - } - return waitFor(this, 'connected') - } - - /** - * Starts disconnection if connected. - * Waits for disconnection if disconnecting. - * No-op if already disconnected. - */ - - async ensureDisconnected() { - this.connection.clearReconnectTimeout() - if (this.msgCreationUtil) { - this.msgCreationUtil.stop() - } - - if (this.isDisconnected()) { return } - - if (this.isDisconnecting()) { - await waitFor(this, 'disconnected') - return - } - - await this.disconnect() - } - - _checkAutoDisconnect() { - // Disconnect if no longer subscribed to any streams - if (this.options.autoDisconnect && Object.keys(this.subscribedStreamPartitions).length === 0) { - this.debug('Disconnecting due to no longer being subscribed to any streams') - this.disconnect() - } - } - - async _resendAndSubscribe(sub) { - if (sub.getState() === Subscription.State.subscribing || sub.resending) { return } - sub.setState(Subscription.State.subscribing) - // Once subscribed, ask for a resend - sub.once('subscribed', () => { - if (!sub.hasResendOptions()) { return } - - this._requestResend(sub) - // once a message is received, gap filling in Subscription.js will check if this satisfies the resend and request - // another resend if it doesn't. So we can anyway clear this resend request. - const handler = () => { - sub.removeListener('initial_resend_done', handler) - sub.removeListener('message received', handler) - sub.removeListener('unsubscribed', handler) - sub.removeListener('error', handler) - } - sub.once('initial_resend_done', handler) - sub.once('message received', handler) - sub.once('unsubscribed', handler) - sub.once('error', handler) - }) - await this._requestSubscribe(sub) - } - - async _requestSubscribe(sub) { - const sp = this._getSubscribedStreamPartition(sub.streamId, sub.streamPartition) - let subscribedSubs = [] - // never reuse subscriptions when incoming subscription needs resends - // i.e. only reuse realtime subscriptions - if (!sub.hasResendOptions()) { - subscribedSubs = sp.getSubscriptions().filter((it) => ( - it.getState() === Subscription.State.subscribed - // don't resuse subscriptions currently resending - && !it.isResending() - )) - } - - const sessionToken = await this.session.getSessionToken() - - // If this is the first subscription for this stream-partition, send a subscription request to the server - if (!sp.isSubscribing() && subscribedSubs.length === 0) { - const request = new SubscribeRequest({ - streamId: sub.streamId, - streamPartition: sub.streamPartition, - sessionToken, - requestId: this.resendUtil.generateRequestId(), - }) - this.debug('_requestSubscribe: subscribing client: %o', request) - sp.setSubscribing(true) - await this.connection.send(request).catch((err) => { - sub.setState(Subscription.State.unsubscribed) - this.emit('error', `Failed to send subscribe request: ${err}`) - }) - } else if (subscribedSubs.length > 0) { - // If there already is a subscribed subscription for this stream, this new one will just join it immediately - this.debug('_requestSubscribe: another subscription for same stream: %s, insta-subscribing', sub.streamId) - - setTimeout(() => { - sub.setState(Subscription.State.subscribed) - }) - } - } - - async _requestUnsubscribe(sub) { - this.debug('Client unsubscribing stream %o partition %o', sub.streamId, sub.streamPartition) - const unsubscribeRequest = new UnsubscribeRequest({ - streamId: sub.streamId, - streamPartition: sub.streamPartition, - requestId: this.resendUtil.generateRequestId(), - }) - await this.connection.send(unsubscribeRequest).catch((err) => { - sub.setState(Subscription.State.subscribed) - this.handleError(`Failed to send unsubscribe request: ${err}`) - }) - } - - async _requestResend(sub, resendOptions) { - sub.setResending(true) - const requestId = this.resendUtil.registerResendRequestForSub(sub) - const options = resendOptions || sub.getResendOptions() - const sessionToken = await this.session.getSessionToken() - // don't bother requesting resend if not connected - if (!this.isConnected()) { return } - let request - if (options.last > 0) { - request = new ResendLastRequest({ - streamId: sub.streamId, - streamPartition: sub.streamPartition, - requestId, - numberLast: options.last, - sessionToken, - }) - } else if (options.from && !options.to) { - request = new ResendFromRequest({ - streamId: sub.streamId, - streamPartition: sub.streamPartition, - requestId, - fromMsgRef: new MessageRef(options.from.timestamp, options.from.sequenceNumber), - publisherId: options.publisherId, - msgChainId: options.msgChainId, - sessionToken, - }) - } else if (options.from && options.to) { - request = new ResendRangeRequest({ - streamId: sub.streamId, - streamPartition: sub.streamPartition, - requestId, - fromMsgRef: new MessageRef(options.from.timestamp, options.from.sequenceNumber), - toMsgRef: new MessageRef(options.to.timestamp, options.to.sequenceNumber), - publisherId: options.publisherId, - msgChainId: options.msgChainId, - sessionToken, - }) - } - - if (request) { - this.debug('_requestResend: %o', request) - await this.connection.send(request).catch((err) => { - this.handleError(`Failed to send resend request: ${err}`) - }) - } else { - this.handleError("Can't _requestResend without resendOptions") - } - } - - async publishStreamMessage(streamMessage) { - const sessionToken = await this.session.getSessionToken() - return this._requestPublish(streamMessage, sessionToken) - } - - _requestPublish(streamMessage, sessionToken) { - const requestId = this.resendUtil.generateRequestId() - const request = new ControlLayer.PublishRequest({ - streamMessage, - requestId, - sessionToken, - }) - this.debug('_requestPublish: %o', request) - return this.connection.send(request) - } - - // each element of the array "groupKeys" is an object with 2 fields: "groupKey" and "start" - _setGroupKeys(streamId, publisherId, groupKeys) { - if (!this.options.subscriberGroupKeys[streamId]) { - this.options.subscriberGroupKeys[streamId] = {} - } - const last = groupKeys[groupKeys.length - 1] - const current = this.options.subscriberGroupKeys[streamId][publisherId] - if (!current || last.start > current.start) { - this.options.subscriberGroupKeys[streamId][publisherId] = last - } - // TODO: fix this hack in other PR - this.subscribedStreamPartitions[streamId + '0'].setSubscriptionsGroupKeys(publisherId, groupKeys.map((obj) => obj.groupKey)) - } - - handleError(msg) { - this.debug(msg) - this.emit('error', msg) - } - - static generateEthereumAccount() { - const wallet = Wallet.createRandom() - return { - address: wallet.address, - privateKey: wallet.privateKey, - } - } -} diff --git a/src/StreamrClient.ts b/src/StreamrClient.ts new file mode 100644 index 000000000..b688e0bb5 --- /dev/null +++ b/src/StreamrClient.ts @@ -0,0 +1,446 @@ +import EventEmitter from 'eventemitter3' +import { ControlLayer } from 'streamr-client-protocol' +import Debug from 'debug' + +import { counterId, uuid, CacheAsyncFn } from './utils' +import { validateOptions } from './stream/utils' +import Config, { StreamrClientOptions, StrictStreamrClientOptions } from './Config' +import StreamrEthereum from './Ethereum' +import Session from './Session' +import Connection, { ConnectionError, ConnectionOptions } from './Connection' +import Publisher from './publish' +import { Subscriber, Subscription } from './subscribe' +import { getUserId } from './user' +import { Todo, MaybeAsync, EthereumAddress } from './types' +import { StreamEndpoints } from './rest/StreamEndpoints' +import { LoginEndpoints } from './rest/LoginEndpoints' +import { DataUnion, DataUnionDeployOptions } from './dataunion/DataUnion' +import { BigNumber } from '@ethersproject/bignumber' +import { getAddress } from '@ethersproject/address' +import { Contract } from '@ethersproject/contracts' +import { StreamPartDefinition } from './stream' + +// TODO get metadata type from streamr-protocol-js project (it doesn't export the type definitions yet) +export type OnMessageCallback = MaybeAsync<(message: any, metadata: any) => void> + +export type ResendOptions = { + from?: { timestamp: number, sequenceNumber?: number } + to?: { timestamp: number, sequenceNumber?: number } + last?: number +} + +export type SubscribeOptions = { + resend?: ResendOptions +} & ResendOptions + +interface MessageEvent { + data: any +} + +/** + * Wrap connection message events with message parsing. + */ +class StreamrConnection extends Connection { + // TODO define args type when we convert Connection class to TypeScript + constructor(options: ConnectionOptions, debug?: Debug.Debugger) { + super(options, debug) + this.on('message', this.onConnectionMessage) + } + + // eslint-disable-next-line class-methods-use-this + parse(messageEvent: MessageEvent) { + return ControlLayer.ControlMessage.deserialize(messageEvent.data) + } + + onConnectionMessage(messageEvent: MessageEvent) { + let controlMessage + try { + controlMessage = this.parse(messageEvent) + } catch (err) { + this.debug('(%o) << %o', this.getState(), messageEvent && messageEvent.data) + this.debug('deserialize error', err) + this.emit('error', err) + return + } + + if (!controlMessage) { + return + } + + this.debug('(%o) << %o', this.getState(), controlMessage) + this.emit(controlMessage.type, controlMessage) + } +} + +class StreamrCached { + + client: StreamrClient + // TODO change all "any" types in this class to valid types when CacheAsyncFn is converted to TypeScript + getStream: any + getUserInfo: any + isStreamPublisher: any + isStreamSubscriber: any + getUserId: any + + constructor(client: StreamrClient) { + this.client = client + const cacheOptions: Todo = client.options.cache + this.getStream = CacheAsyncFn(client.getStream.bind(client), { + ...cacheOptions, + cacheKey([maybeStreamId]: any) { + const { streamId } = validateOptions(maybeStreamId) + return streamId + } + }) + this.getUserInfo = CacheAsyncFn(client.getUserInfo.bind(client), cacheOptions) + this.isStreamPublisher = CacheAsyncFn(client.isStreamPublisher.bind(client), { + ...cacheOptions, + cacheKey([maybeStreamId, ethAddress]: any) { + const { streamId } = validateOptions(maybeStreamId) + return `${streamId}|${ethAddress}` + } + }) + + this.isStreamSubscriber = CacheAsyncFn(client.isStreamSubscriber.bind(client), { + ...cacheOptions, + cacheKey([maybeStreamId, ethAddress]: any) { + const { streamId } = validateOptions(maybeStreamId) + return `${streamId}|${ethAddress}` + } + }) + + this.getUserId = CacheAsyncFn(client.getUserId.bind(client), cacheOptions) + } + + clearStream(streamId: string) { + this.getStream.clear() + this.isStreamPublisher.clearMatching((s: string) => s.startsWith(streamId)) + this.isStreamSubscriber.clearMatching((s: string) => s.startsWith(streamId)) + } + + clearUser() { + this.getUserInfo.clear() + this.getUserId.clear() + } + + clear() { + this.clearUser() + // @ts-expect-error + this.clearStream() + } +} + +// use process id in node uid +const uid = process.pid != null ? process.pid : `${uuid().slice(-4)}${uuid().slice(0, 4)}` + +/** + * Take prototype functions from srcInstance and attach them to targetInstance while keeping them bound to srcInstance. + */ +function Plugin(targetInstance: any, srcInstance: any) { + Object.getOwnPropertyNames(srcInstance.constructor.prototype).forEach((name) => { + const value = srcInstance.constructor.prototype[name] + if (typeof value !== 'function') { return } + // eslint-disable-next-line no-param-reassign + targetInstance[name] = srcInstance[name].bind(srcInstance) + }) + return srcInstance +} + +// these are mixed in via Plugin function above +export interface StreamrClient extends StreamEndpoints, LoginEndpoints {} + +// eslint-disable-next-line no-redeclare +export class StreamrClient extends EventEmitter { + /** @internal */ + id: string + /** @internal */ + debug: Debug.Debugger + /** @internal */ + options: StrictStreamrClientOptions + /** @internal */ + session: Session + /** @internal */ + connection: StreamrConnection + /** @internal */ + publisher: Todo + /** @internal */ + subscriber: Subscriber + /** @internal */ + cached: StreamrCached + /** @internal */ + ethereum: StreamrEthereum + + // TODO annotate connection parameter as internal parameter if possible? + constructor(options: StreamrClientOptions = {}, connection?: StreamrConnection) { + super() + this.id = counterId(`${this.constructor.name}:${uid}`) + this.debug = Debug(this.id) + + this.options = Config(options) + + this.debug('new StreamrClient %s: %o', this.id, { + version: process.env.version, + GIT_VERSION: process.env.GIT_VERSION, + GIT_COMMITHASH: process.env.GIT_COMMITHASH, + GIT_BRANCH: process.env.GIT_BRANCH, + }) + + // bind event handlers + this.onConnectionConnected = this.onConnectionConnected.bind(this) + this.onConnectionDisconnected = this.onConnectionDisconnected.bind(this) + this._onError = this._onError.bind(this) + this.onConnectionError = this.onConnectionError.bind(this) + this.getErrorEmitter = this.getErrorEmitter.bind(this) + + this.on('error', this._onError) // attach before creating sub-components incase they fire error events + + this.session = new Session(this, this.options.auth) + this.connection = connection || new StreamrConnection(this.options, this.debug) + + this.connection + .on('connected', this.onConnectionConnected) + .on('disconnected', this.onConnectionDisconnected) + .on('error', this.onConnectionError) + + this.publisher = Publisher(this) + this.subscriber = new Subscriber(this) + this.ethereum = new StreamrEthereum(this) + + Plugin(this, new StreamEndpoints(this)) + Plugin(this, new LoginEndpoints(this)) + this.cached = new StreamrCached(this) + } + + /** @internal */ + async onConnectionConnected() { + this.debug('Connected!') + this.emit('connected') + } + + /** @internal */ + async onConnectionDisconnected() { + this.debug('Disconnected.') + this.emit('disconnected') + } + + /** @internal */ + onConnectionError(err: Todo) { + this.emit('error', new ConnectionError(err)) + } + + /** @internal */ + getErrorEmitter(source: Todo) { + return (err: Todo) => { + if (!(err instanceof ConnectionError || err.reason instanceof ConnectionError)) { + // emit non-connection errors + this.emit('error', err) + } else { + source.debug(err) + } + } + } + + /** @internal */ + _onError(err: Todo, ...args: Todo) { + // @ts-expect-error + this.onError(err, ...args) + } + + /** @internal */ + async send(request: Todo) { + return this.connection.send(request) + } + + /** + * Override to control output + * @internal */ + onError(error: Todo) { // eslint-disable-line class-methods-use-this + console.error(error) + } + + isConnected() { + return this.connection.isConnected() + } + + isConnecting() { + return this.connection.isConnecting() + } + + isDisconnecting() { + return this.connection.isDisconnecting() + } + + isDisconnected() { + return this.connection.isDisconnected() + } + + async connect() { + return this.connection.connect() + } + + /** @internal */ + async nextConnection() { + return this.connection.nextConnection() + } + + disconnect() { + this.publisher.stop() + return Promise.all([ + this.subscriber.subscriptions.removeAll(), + this.connection.disconnect() + ]) + } + + getSubscriptions(): Subscription[] { + return this.subscriber.getAll() + } + + getSubscription(definition: StreamPartDefinition) { + // @ts-expect-error + return this.subscriber.get(definition) + } + + async ensureConnected() { + return this.connect() + } + + async ensureDisconnected() { + return this.disconnect() + } + + logout() { + return this.session.logout() + } + + async publish(streamObjectOrId: StreamPartDefinition, content: object, timestamp?: number|string|Date, partitionKey?: string) { + return this.publisher.publish(streamObjectOrId, content, timestamp, partitionKey) + } + + async getUserId() { + return getUserId(this) + } + + /** @internal */ + setNextGroupKey(...args: Todo) { + return this.publisher.setNextGroupKey(...args) + } + + /** @internal */ + rotateGroupKey(...args: Todo) { + return this.publisher.rotateGroupKey(...args) + } + + async subscribe(opts: SubscribeOptions & StreamPartDefinition, onMessage?: OnMessageCallback) { + let subTask: Todo + let sub: Todo + const hasResend = !!(opts.resend || opts.from || opts.to || opts.last) + const onEnd = () => { + if (sub && typeof onMessage === 'function') { + sub.off('message', onMessage) + } + } + + if (hasResend) { + subTask = this.subscriber.resendSubscribe(opts, onEnd) + } else { + subTask = this.subscriber.subscribe(opts, onEnd) + } + + if (typeof onMessage === 'function') { + Promise.resolve(subTask).then(async (s) => { + sub = s + sub.on('message', onMessage) + for await (const msg of sub) { + sub.emit('message', msg.getParsedContent(), msg) + } + return sub + }).catch((err) => { + this.emit('error', err) + }) + } + return subTask + } + + async unsubscribe(subscription: Subscription) { + await this.subscriber.unsubscribe(subscription) + } + + /** @internal */ + async resend(opts: Todo, onMessage?: OnMessageCallback): Promise { + const task = this.subscriber.resend(opts) + if (typeof onMessage !== 'function') { + return task + } + + Promise.resolve(task).then(async (sub) => { + for await (const msg of sub) { + await onMessage(msg.getParsedContent(), msg) + } + + return sub + }).catch((err) => { + this.emit('error', err) + }) + + return task + } + + enableAutoConnect(autoConnect?: boolean) { + return this.connection.enableAutoConnect(autoConnect) + } + + enableAutoDisconnect(autoDisconnect?: boolean) { + return this.connection.enableAutoDisconnect(autoDisconnect) + } + + async getAddress(): Promise { + return this.ethereum.getAddress() + } + + async getPublisherId(): Promise { + return this.getAddress() + } + + /** + * Get token balance in "wei" (10^-18 parts) for given address + */ + async getTokenBalance(address: EthereumAddress): Promise { + const { tokenAddress } = this.options + if (!tokenAddress) { + throw new Error('StreamrClient has no tokenAddress configuration.') + } + const addr = getAddress(address) + const provider = this.ethereum.getMainnetProvider() + + const token = new Contract(tokenAddress, [{ + name: 'balanceOf', + inputs: [{ type: 'address' }], + outputs: [{ type: 'uint256' }], + constant: true, + payable: false, + stateMutability: 'view', + type: 'function' + }], provider) + return token.balanceOf(addr) + } + + getDataUnion(contractAddress: EthereumAddress) { + return DataUnion._fromContractAddress(contractAddress, this) // eslint-disable-line no-underscore-dangle + } + + async deployDataUnion(options?: DataUnionDeployOptions) { + return DataUnion._deploy(options, this) // eslint-disable-line no-underscore-dangle + } + + /** @internal */ + _getDataUnionFromName({ dataUnionName, deployerAddress }: { dataUnionName: string, deployerAddress: EthereumAddress}) { + return DataUnion._fromName({ // eslint-disable-line no-underscore-dangle + dataUnionName, + deployerAddress + }, this) + } + + static generateEthereumAccount() { + return StreamrEthereum.generateEthereumAccount() + } +} diff --git a/src/SubscribedStreamPartition.js b/src/SubscribedStreamPartition.js deleted file mode 100644 index 3262b8259..000000000 --- a/src/SubscribedStreamPartition.js +++ /dev/null @@ -1,119 +0,0 @@ -import { Utils, MessageLayer } from 'streamr-client-protocol' -import memoize from 'promise-memoize' - -import SignatureRequiredError from './errors/SignatureRequiredError' - -const { StreamMessageValidator } = Utils -const { StreamMessage } = MessageLayer - -const memoizeOpts = { - maxAge: 15 * 60 * 1000, - maxErrorAge: 60 * 1000, -} - -export default class SubscribedStreamPartition { - constructor(client, streamId, streamPartition) { - this._client = client - this.streamId = streamId - this.streamPartition = streamPartition - this.subscriptions = {} - this.getStream = memoize(this.getStream.bind(this), memoizeOpts) - this.validator = new StreamMessageValidator({ - getStream: this.getStream, - isPublisher: memoize(async (publisherId, _streamId) => ( - this._client.isStreamPublisher(_streamId, publisherId) - ), memoizeOpts), - isSubscriber: memoize(async (ethAddress, _streamId) => ( - this._client.isStreamSubscriber(_streamId, ethAddress) - ), memoizeOpts), - }) - this.getPublishers = memoize(this.getPublishers.bind(this), memoizeOpts) - this.getSubscribers = memoize(this.getSubscribers.bind(this), memoizeOpts) - this.isValidPublisher = memoize(this.isValidPublisher.bind(this), memoizeOpts) - this.isValidSubscriber = memoize(this.isValidSubscriber.bind(this), memoizeOpts) - } - - async getPublishers() { - const publishers = await this._client.getStreamPublishers(this.streamId) - return publishers.reduce((obj, key) => ( - Object.assign(obj, { - [key]: true - }) - ), {}) - } - - async getSubscribers() { - const subscribers = await this._client.getStreamSubscribers(this.streamId) - return subscribers.reduce((obj, key) => ( - Object.assign(obj, { - [key]: true - }) - ), {}) - } - - async isValidPublisher(publisherId) { - return this._client.isStreamPublisher(this.streamId, publisherId) - } - - async isValidSubscriber(ethAddress) { - return this._client.isStreamSubscriber(this.streamId, ethAddress) - } - - async verifyStreamMessage(msg) { - // Check special cases controlled by the verifySignatures policy - const { options } = this._client - if (options.verifySignatures === 'never' && msg.messageType === StreamMessage.MESSAGE_TYPES.MESSAGE) { - return // no validation required - } - - if (options.verifySignatures === 'always' && !msg.signature) { - throw new SignatureRequiredError(msg) - } - - // In all other cases validate using the validator - await this.validator.validate(msg) // will throw with appropriate validation failure - } - - async getStream() { - return this._client.getStream(this.streamId) - } - - getSubscription(subscriptionId) { - return this.subscriptions[subscriptionId] - } - - getSubscriptions() { - return Object.values(this.subscriptions) || [] - } - - isSubscribing() { - return this.subscribing - } - - setSubscribing(value) { - this.subscribing = value - } - - emptySubscriptionsSet() { - return Object.keys(this.subscriptions).length === 0 - } - - addSubscription(sub) { - this.subscriptions[sub.id] = sub - } - - removeSubscription(sub) { - if (this.subscriptions[sub.id]) { - this.subscriptions[sub.id].stop() - delete this.subscriptions[sub.id] - } - } - - setSubscriptionsGroupKeys(publisherId, groupKeys) { - Object.values(this.subscriptions).forEach((sub) => { - sub.setGroupKeys(publisherId, groupKeys) - }) - } -} - -SubscribedStreamPartition.memoizeOpts = memoizeOpts diff --git a/src/Subscription.js b/src/Subscription.js deleted file mode 100644 index bb959f735..000000000 --- a/src/Subscription.js +++ /dev/null @@ -1,66 +0,0 @@ -import EventEmitter from 'eventemitter3' -import debugFactory from 'debug' -import uniqueId from 'lodash.uniqueid' - -const DEFAULT_PROPAGATION_TIMEOUT = 5000 -const DEFAULT_RESEND_TIMEOUT = 5000 - -/* -'interface' containing the default parameters and functionalities common to every subscription (Combined, RealTime and Historical) - */ -export default class Subscription extends EventEmitter { - constructor(streamId, streamPartition, callback, groupKeys, - propagationTimeout = DEFAULT_PROPAGATION_TIMEOUT, resendTimeout = DEFAULT_RESEND_TIMEOUT, debug) { - super() - - if (!callback) { - throw new Error('No callback given!') - } - this.streamId = streamId - this.streamPartition = streamPartition - this.callback = callback - const id = uniqueId('sub') - this.id = id - if (debug) { - this.debug = debug.extend(this.constructor.name).extend(id) - } else { - this.debug = debugFactory(`StreamrClient::${this.constructor.name}`).extend(id) - } - - if (!streamId) { - throw new Error('No stream id given!') - } - this.groupKeys = {} - if (groupKeys) { - Object.keys(groupKeys).forEach((publisherId) => { - this.groupKeys[publisherId.toLowerCase()] = groupKeys[publisherId] - }) - } - this.propagationTimeout = propagationTimeout - this.resendTimeout = resendTimeout - this.state = Subscription.State.unsubscribed - } - - getState() { - return this.state - } - - setState(state) { - this.debug(`Subscription: Stream ${this.streamId} state changed ${this.state} => ${state}`) - this.state = state - this.emit(state) - } - - /* eslint-disable class-methods-use-this */ - onDisconnected() { - throw new Error('Must be defined in child class') - } - /* eslint-enable class-methods-use-this */ -} - -Subscription.State = { - unsubscribed: 'unsubscribed', - subscribing: 'subscribing', - subscribed: 'subscribed', - unsubscribing: 'unsubscribing', -} diff --git a/src/dataunion/Contracts.ts b/src/dataunion/Contracts.ts new file mode 100644 index 000000000..fa87273bf --- /dev/null +++ b/src/dataunion/Contracts.ts @@ -0,0 +1,331 @@ +import { getCreate2Address, isAddress } from '@ethersproject/address' +import { arrayify, hexZeroPad } from '@ethersproject/bytes' +import { Contract, ContractReceipt } from '@ethersproject/contracts' +import { keccak256 } from '@ethersproject/keccak256' +import { defaultAbiCoder } from '@ethersproject/abi' +import { verifyMessage } from '@ethersproject/wallet' +import debug from 'debug' +import { EthereumAddress, Todo } from '../types' +import { dataUnionMainnetABI, dataUnionSidechainABI, factoryMainnetABI, mainnetAmbABI, sidechainAmbABI } from './abi' +import { until } from '../utils' +import { BigNumber } from '@ethersproject/bignumber' +import StreamrEthereum from '../Ethereum' +import { StreamrClient } from '../StreamrClient' + +const log = debug('StreamrClient::DataUnion') + +function validateAddress(name: string, address: EthereumAddress) { + if (!isAddress(address)) { + throw new Error(`${name} is ${address ? 'not a valid Ethereum address' : 'missing'}`) + } +} + +export class Contracts { + + ethereum: StreamrEthereum + factoryMainnetAddress: EthereumAddress + factorySidechainAddress: EthereumAddress + templateMainnetAddress: EthereumAddress + templateSidechainAddress: EthereumAddress + cachedSidechainAmb?: Todo + + constructor(client: StreamrClient) { + this.ethereum = client.ethereum + 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( + dataUnionName: string, + deployerAddress: EthereumAddress + ): Promise { + const provider = this.ethereum.getMainnetProvider() + const factoryMainnet = new Contract(this.factoryMainnetAddress, factoryMainnetABI, provider) + return factoryMainnet.mainnetAddress(deployerAddress, dataUnionName) + } + + getDataUnionMainnetAddress(dataUnionName: string, deployerAddress: EthereumAddress) { + validateAddress('StreamrClient factoryMainnetAddress', this.factoryMainnetAddress) + validateAddress('StreamrClient templateMainnetAddress', this.templateMainnetAddress) + // 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) + } + + async fetchDataUnionSidechainAddress(duMainnetAddress: EthereumAddress): Promise { + const provider = this.ethereum.getMainnetProvider() + const factoryMainnet = new Contract(this.factoryMainnetAddress, factoryMainnetABI, provider) + return factoryMainnet.sidechainAddress(duMainnetAddress) + } + + getDataUnionSidechainAddress(mainnetAddress: EthereumAddress) { + validateAddress('StreamrClient factorySidechainAddress', this.factorySidechainAddress) + validateAddress('StreamrClient templateSidechainAddress', this.templateSidechainAddress) + // This magic hex comes from https://github.com/streamr-dev/data-union-solidity/blob/master/contracts/CloneLib.sol#L19 + const code = `0x3d602d80600a3d3981f3363d3d373d3d3d363d73${this.templateSidechainAddress.slice(2)}5af43d82803e903d91602b57fd5bf3` + const codeHash = keccak256(code) + return getCreate2Address(this.factorySidechainAddress, hexZeroPad(mainnetAddress, 32), codeHash) + } + + getMainnetContractReadOnly(contractAddress: EthereumAddress) { + validateAddress('contractAddress', contractAddress) + const provider = this.ethereum.getMainnetProvider() + return new Contract(contractAddress, dataUnionMainnetABI, provider) + } + + getMainnetContract(contractAddress: EthereumAddress) { + const du = this.getMainnetContractReadOnly(contractAddress) + const signer = this.ethereum.getSigner() + return du.connect(signer) + } + + async getSidechainContract(contractAddress: EthereumAddress) { + const signer = await this.ethereum.getSidechainSigner() + const duMainnet = this.getMainnetContractReadOnly(contractAddress) + const duSidechainAddress = this.getDataUnionSidechainAddress(duMainnet.address) + const duSidechain = new Contract(duSidechainAddress, dataUnionSidechainABI, signer) + return duSidechain + } + + async getSidechainContractReadOnly(contractAddress: EthereumAddress) { + const provider = this.ethereum.getSidechainProvider() + const duMainnet = this.getMainnetContractReadOnly(contractAddress) + const duSidechainAddress = this.getDataUnionSidechainAddress(duMainnet.address) + const duSidechain = new Contract(duSidechainAddress, dataUnionSidechainABI, provider) + return duSidechain + } + + // Find the Asyncronous Message-passing Bridge sidechain ("home") contract + async getSidechainAmb() { + if (!this.cachedSidechainAmb) { + const getAmbPromise = async () => { + const sidechainProvider = this.ethereum.getSidechainProvider() + const factorySidechain = new Contract(this.factorySidechainAddress, [{ + name: 'amb', + inputs: [], + outputs: [{ type: 'address' }], + stateMutability: 'view', + type: 'function' + }], sidechainProvider) + const sidechainAmbAddress = await factorySidechain.amb() + return new Contract(sidechainAmbAddress, sidechainAmbABI, sidechainProvider) + } + this.cachedSidechainAmb = getAmbPromise() + this.cachedSidechainAmb = await this.cachedSidechainAmb // eslint-disable-line require-atomic-updates + } + return this.cachedSidechainAmb + } + + async getMainnetAmb() { + const mainnetProvider = this.ethereum.getMainnetProvider() + const factoryMainnet = new Contract(this.factoryMainnetAddress, factoryMainnetABI, mainnetProvider) + const mainnetAmbAddress = await factoryMainnet.amb() + return new Contract(mainnetAmbAddress, mainnetAmbABI, mainnetProvider) + } + + async requiredSignaturesHaveBeenCollected(messageHash: Todo) { + const sidechainAmb = await this.getSidechainAmb() + const requiredSignatureCount = await sidechainAmb.requiredSignatures() + + // Bit 255 is set to mark completion, double check though + const sigCountStruct = await sidechainAmb.numMessagesSigned(messageHash) + const collectedSignatureCount = sigCountStruct.mask(255) + const markedComplete = sigCountStruct.shr(255).gt(0) + + log(`${collectedSignatureCount.toString()} out of ${requiredSignatureCount.toString()} collected`) + if (markedComplete) { log('All signatures collected') } + return markedComplete + } + + // move signatures from sidechain to mainnet + async transportSignaturesForMessage(messageHash: string) { + const sidechainAmb = await this.getSidechainAmb() + const message = await sidechainAmb.message(messageHash) + const messageId = '0x' + message.substr(2, 64) + const sigCountStruct = await sidechainAmb.numMessagesSigned(messageHash) + const collectedSignatureCount = sigCountStruct.mask(255).toNumber() + + log(`${collectedSignatureCount} signatures reported, getting them from the sidechain AMB...`) + const signatures = await Promise.all(Array(collectedSignatureCount).fill(0).map(async (_, i) => sidechainAmb.signature(messageHash, i))) + + const [vArray, rArray, sArray]: Todo = [[], [], []] + signatures.forEach((signature: string, i) => { + log(` Signature ${i}: ${signature} (len=${signature.length}=${signature.length / 2 - 1} bytes)`) + rArray.push(signature.substr(2, 64)) + sArray.push(signature.substr(66, 64)) + vArray.push(signature.substr(130, 2)) + }) + const packedSignatures = BigNumber.from(signatures.length).toHexString() + vArray.join('') + rArray.join('') + sArray.join('') + log(`All signatures packed into one: ${packedSignatures}`) + + // Gas estimation also checks that the transaction would succeed, and provides a helpful error message in case it would fail + const mainnetAmb = await this.getMainnetAmb() + log(`Estimating gas using mainnet AMB @ ${mainnetAmb.address}, message=${message}`) + let gasLimit + try { + // magic number suggested by https://github.com/poanetwork/tokenbridge/blob/master/oracle/src/utils/constants.js + gasLimit = BigNumber.from(await mainnetAmb.estimateGas.executeSignatures(message, packedSignatures)).add(200000) + log(`Calculated gas limit: ${gasLimit.toString()}`) + } catch (e) { + // Failure modes from https://github.com/poanetwork/tokenbridge/blob/master/oracle/src/events/processAMBCollectedSignatures/estimateGas.js + log('Gas estimation failed: Check if the message was already processed') + 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 freeWithdraw=false (attempt self-service), but bridge actually paid before your client') + return null + } + + log('Gas estimation failed: Check if number of signatures is enough') + const mainnetProvider = this.ethereum.getMainnetProvider() + const validatorContractAddress = await mainnetAmb.validatorContract() + const validatorContract = new Contract(validatorContractAddress, [{ + name: 'isValidator', + inputs: [{ type: 'address' }], + outputs: [{ type: 'bool' }], + stateMutability: 'view', + type: 'function' + }, { + name: 'requiredSignatures', + inputs: [], + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }], mainnetProvider) + const requiredSignatures = await validatorContract.requiredSignatures() + if (requiredSignatures.gt(signatures.length)) { + throw new Error('The number of required signatures does not match between sidechain(' + + signatures.length + ' and mainnet( ' + requiredSignatures.toString()) + } + + log('Gas estimation failed: Check if all the signatures were made by validators') + log(` Recover signer addresses from signatures [${signatures.join(', ')}]`) + const signers = signatures.map((signature) => verifyMessage(arrayify(message), signature)) + log(` Check that signers are validators [[${signers.join(', ')}]]`) + const isValidatorArray = await Promise.all(signers.map((address) => [address, validatorContract.isValidator(address)])) + const nonValidatorSigners = isValidatorArray.filter(([, isValidator]) => !isValidator) + if (nonValidatorSigners.length > 0) { + throw new Error(`Following signers are not listed as validators in mainnet validator contract at ${validatorContractAddress}:\n - ` + + nonValidatorSigners.map(([address]) => address).join('\n - ')) + } + + throw new Error(`Gas estimation failed: Unknown error while processing message ${message} with ${e.stack}`) + } + + const signer = this.ethereum.getSigner() + log(`Sending message from signer=${await signer.getAddress()}`) + const txAMB = await mainnetAmb.connect(signer).executeSignatures(message, packedSignatures) + const trAMB = await txAMB.wait() + return trAMB + } + + async transportSignaturesForTransaction(tr: ContractReceipt, options: { pollingIntervalMs?: number, retryTimeoutMs?: number } = {}) { + const { + pollingIntervalMs = 1000, + retryTimeoutMs = 60000, + } = options + log(`Got receipt, filtering UserRequestForSignature from ${tr.events!.length} events...`) + // event UserRequestForSignature(bytes32 indexed messageId, bytes encodedData); + const sigEventArgsArray = tr.events!.filter((e: Todo) => e.event === 'UserRequestForSignature').map((e: Todo) => e.args) + 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) { + const messageId = eventArgs[0] + const messageHash = keccak256(eventArgs[1]) + + log(`Waiting until sidechain AMB has collected required signatures for hash=${messageHash}...`) + await until(async () => this.requiredSignaturesHaveBeenCollected(messageHash), pollingIntervalMs, retryTimeoutMs) + + log(`Checking mainnet AMB hasn't already processed messageId=${messageId}`) + const mainnetAmb = await this.getMainnetAmb() + const alreadySent = await mainnetAmb.messageCallStatus(messageId) + const failAddress = await mainnetAmb.failedMessageSender(messageId) + + // 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 freeWithdraw=false (attempt self-service), but bridge actually paid before your client') + continue + } + + log(`Transporting signatures for hash=${messageHash}`) + await this.transportSignaturesForMessage(messageHash) + } + /* eslint-enable no-await-in-loop */ + } + + async deployDataUnion({ + ownerAddress, + agentAddressList, + duName, + deployerAddress, + adminFeeBN, + sidechainRetryTimeoutMs, + sidechainPollingIntervalMs, + confirmations, + gasPrice + }: { + ownerAddress: EthereumAddress, + agentAddressList: EthereumAddress[] + duName: string + deployerAddress: EthereumAddress + adminFeeBN: BigNumber + sidechainRetryTimeoutMs: number + sidechainPollingIntervalMs: number + confirmations: number + gasPrice?: BigNumber, + }) { + const mainnetProvider = this.ethereum.getMainnetProvider() + const mainnetWallet = this.ethereum.getSigner() + const sidechainProvider = this.ethereum.getSidechainProvider() + + const duMainnetAddress = await this.fetchDataUnionMainnetAddress(duName, deployerAddress) + const duSidechainAddress = await this.fetchDataUnionSidechainAddress(duMainnetAddress) + + if (await mainnetProvider.getCode(duMainnetAddress) !== '0x') { + throw new Error(`Mainnet data union "${duName}" contract ${duMainnetAddress} already exists!`) + } + + validateAddress('StreamrClient factoryMainnetAddress', this.factoryMainnetAddress) + + if (await mainnetProvider.getCode(this.factoryMainnetAddress) === '0x') { + 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) + const ethersOptions: any = {} + if (gasPrice) { + ethersOptions.gasPrice = gasPrice + } + const tx = await factoryMainnet.deployNewDataUnion( + ownerAddress, + adminFeeBN, + agentAddressList, + duName, + ethersOptions + ) + await tx.wait(confirmations) + + log(`Data Union "${duName}" (mainnet: ${duMainnetAddress}, sidechain: ${duSidechainAddress}) deployed to mainnet, waiting for side-chain...`) + await until( + async () => await sidechainProvider.getCode(duSidechainAddress) !== '0x', + sidechainRetryTimeoutMs, + sidechainPollingIntervalMs + ) + + const dataUnion = new Contract(duMainnetAddress, dataUnionMainnetABI, mainnetWallet) + // @ts-expect-error + dataUnion.sidechain = new Contract(duSidechainAddress, dataUnionSidechainABI, sidechainProvider) + return dataUnion + + } +} diff --git a/src/dataunion/DataUnion.ts b/src/dataunion/DataUnion.ts new file mode 100644 index 000000000..bbf32e2d1 --- /dev/null +++ b/src/dataunion/DataUnion.ts @@ -0,0 +1,567 @@ +import { getAddress } from '@ethersproject/address' +import { BigNumber } from '@ethersproject/bignumber' +import { arrayify, hexZeroPad } from '@ethersproject/bytes' +import { Contract } from '@ethersproject/contracts' +import { TransactionReceipt, TransactionResponse } from '@ethersproject/providers' +import debug from 'debug' +import { Contracts } from './Contracts' +import { StreamrClient } from '../StreamrClient' +import { EthereumAddress } from '../types' +import { until, getEndpointUrl } from '../utils' +import authFetch from '../rest/authFetch' + +export interface DataUnionDeployOptions { + owner?: EthereumAddress, + joinPartAgents?: EthereumAddress[], + dataUnionName?: string, + adminFee?: number, + sidechainPollingIntervalMs?: number, + sidechainRetryTimeoutMs?: number + confirmations?: number + gasPrice?: BigNumber +} + +export enum JoinRequestState { + PENDING = 'PENDING', + ACCEPTED = 'ACCEPTED', + REJECTED = 'REJECTED' +} + +export interface JoinResponse { + id: string + state: JoinRequestState +} + +export interface DataUnionWithdrawOptions { + pollingIntervalMs?: number + retryTimeoutMs?: number + freeWithdraw?: boolean +} + +export interface DataUnionMemberListModificationOptions { + confirmations?: number +} + +export interface DataUnionStats { + activeMemberCount: BigNumber, + inactiveMemberCount: BigNumber, + joinPartAgentCount: BigNumber, + totalEarnings: BigNumber, + totalWithdrawable: BigNumber, + lifetimeMemberEarnings: BigNumber +} + +export enum MemberStatus { + ACTIVE = 'ACTIVE', + INACTIVE = 'INACTIVE', + NONE = 'NONE', +} + +export interface MemberStats { + status: MemberStatus + earningsBeforeLastJoin: BigNumber + totalEarnings: BigNumber + withdrawableEarnings: BigNumber +} + +const log = debug('StreamrClient::DataUnion') + +export class DataUnion { + + private contractAddress: EthereumAddress + private sidechainAddress: EthereumAddress + private client: StreamrClient + + /** @internal */ + constructor(contractAddress: EthereumAddress, sidechainAddress: EthereumAddress, client: StreamrClient) { + // validate and convert to checksum case + this.contractAddress = getAddress(contractAddress) + this.sidechainAddress = getAddress(sidechainAddress) + this.client = client + } + + getAddress() { + return this.contractAddress + } + + getSidechainAddress() { + return this.sidechainAddress + } + + // Member functions + + /** + * Send a joinRequest, or get into data union instantly with a data union secret + */ + async join(secret?: string): Promise { + const memberAddress = await this.client.getAddress() + const body: any = { + memberAddress + } + if (secret) { body.secret = secret } + + const url = getEndpointUrl(this.client.options.restUrl, 'dataunions', this.contractAddress, 'joinRequests') + const response = await authFetch( + url, + this.client.session, + { + method: 'POST', + body: JSON.stringify(body), + headers: { + 'Content-Type': 'application/json', + }, + }, + ) + if (secret) { + await until(async () => this.isMember(memberAddress)) + } + return response + } + + async isMember(memberAddress: EthereumAddress): Promise { + const address = getAddress(memberAddress) + const duSidechain = await this.getContracts().getSidechainContractReadOnly(this.contractAddress) + const ACTIVE = 1 // memberData[0] is enum ActiveStatus {None, Active, Inactive} + const memberData = await duSidechain.memberData(address) + const state = memberData[0] + return (state === ACTIVE) + } + + /** + * Withdraw all your earnings + * @returns receipt once withdraw is complete (tokens are seen in mainnet) + */ + async withdrawAll(options?: DataUnionWithdrawOptions): Promise { + const recipientAddress = await this.client.getAddress() + return this._executeWithdraw( + () => this.getWithdrawAllTx(), + recipientAddress, + options + ) + } + + /** + * Get the tx promise for withdrawing all your earnings + * @returns await on call .wait to actually send the tx + */ + private async getWithdrawAllTx(): Promise { + const signer = await this.client.ethereum.getSidechainSigner() + const address = await signer.getAddress() + const duSidechain = await this.getContracts().getSidechainContract(this.contractAddress) + + const withdrawable = await duSidechain.getWithdrawableEarnings(address) + if (withdrawable.eq(0)) { + throw new Error(`${address} has nothing to withdraw in (sidechain) data union ${duSidechain.address}`) + } + + 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.dataUnion.minimumWithdrawTokenWei})`) + } + return duSidechain.withdrawAll(address, true) // sendToMainnet=true + } + + /** + * Withdraw earnings and "donate" them to the given address + * @returns get receipt once withdraw is complete (tokens are seen in mainnet) + */ + async withdrawAllTo( + recipientAddress: EthereumAddress, + options?: DataUnionWithdrawOptions + ): Promise { + const to = getAddress(recipientAddress) // throws if bad address + return this._executeWithdraw( + () => this.getWithdrawAllToTx(to), + to, + options + ) + } + + /** + * Withdraw earnings and "donate" them to the given address + * @param recipientAddress - the address to receive the tokens + * @returns await on call .wait to actually send the tx + */ + private async getWithdrawAllToTx(recipientAddress: EthereumAddress): Promise { + const signer = await this.client.ethereum.getSidechainSigner() + const address = await signer.getAddress() + const duSidechain = await this.getContracts().getSidechainContract(this.contractAddress) + const withdrawable = await duSidechain.getWithdrawableEarnings(address) + if (withdrawable.eq(0)) { + throw new Error(`${address} has nothing to withdraw in (sidechain) data union ${duSidechain.address}`) + } + return duSidechain.withdrawAllTo(recipientAddress, true) // sendToMainnet=true + } + + /** + * Member can sign off to "donate" all earnings to another address such that someone else + * can submit the transaction (and pay for the gas) + * This signature is only valid until next withdrawal takes place (using this signature or otherwise). + * Note that while it's a "blank cheque" for withdrawing all earnings at the moment it's used, it's + * invalidated by the first withdraw after signing it. In other words, any signature can be invalidated + * by making a "normal" withdraw e.g. `await streamrClient.withdrawAll()` + * Admin can execute the withdraw using this signature: ``` + * await adminStreamrClient.withdrawAllToSigned(memberAddress, recipientAddress, signature) + * ``` + * @param recipientAddress - the address authorized to receive the tokens + * @returns signature authorizing withdrawing all earnings to given recipientAddress + */ + async signWithdrawAllTo(recipientAddress: EthereumAddress): Promise { + return this.signWithdrawAmountTo(recipientAddress, BigNumber.from(0)) + } + + /** + * Member can sign off to "donate" specific amount of earnings to another address such that someone else + * can submit the transaction (and pay for the gas) + * This signature is only valid until next withdrawal takes place (using this signature or otherwise). + * @param recipientAddress - the address authorized to receive the tokens + * @param amountTokenWei - that the signature is for (can't be used for less or for more) + * @returns signature authorizing withdrawing all earnings to given recipientAddress + */ + async signWithdrawAmountTo( + recipientAddress: EthereumAddress, + amountTokenWei: BigNumber|number|string + ): Promise { + const to = getAddress(recipientAddress) // throws if bad address + const signer = this.client.ethereum.getSigner() // it shouldn't matter if it's mainnet or sidechain signer since key should be the same + const address = await signer.getAddress() + const duSidechain = await this.getContracts().getSidechainContractReadOnly(this.contractAddress) + const memberData = await duSidechain.memberData(address) + if (memberData[0] === '0') { throw new Error(`${address} is not a member in Data Union (sidechain address ${duSidechain.address})`) } + const withdrawn = memberData[3] + // @ts-expect-error + const message = to + hexZeroPad(amountTokenWei, 32).slice(2) + duSidechain.address.slice(2) + hexZeroPad(withdrawn, 32).slice(2) + const signature = await signer.signMessage(arrayify(message)) + return signature + } + + // Query functions + + async getStats(): Promise { + const duSidechain = await this.getContracts().getSidechainContractReadOnly(this.contractAddress) + const [ + totalEarnings, + totalEarningsWithdrawn, + activeMemberCount, + inactiveMemberCount, + lifetimeMemberEarnings, + joinPartAgentCount, + ] = await duSidechain.getStats() + const totalWithdrawable = totalEarnings.sub(totalEarningsWithdrawn) + return { + activeMemberCount, + inactiveMemberCount, + joinPartAgentCount, + totalEarnings, + totalWithdrawable, + lifetimeMemberEarnings, + } + } + + /** + * Get stats of a single data union member + */ + async getMemberStats(memberAddress: EthereumAddress): Promise { + const address = getAddress(memberAddress) + // TODO: use duSidechain.getMemberStats(address) once it's implemented, to ensure atomic read + // (so that memberData is from same block as getEarnings, otherwise withdrawable will be foobar) + const duSidechain = await this.getContracts().getSidechainContractReadOnly(this.contractAddress) + const mdata = await duSidechain.memberData(address) + const total = await duSidechain.getEarnings(address).catch(() => BigNumber.from(0)) + const withdrawnEarnings = mdata[3] + const withdrawable = total ? total.sub(withdrawnEarnings) : BigNumber.from(0) + const STATUSES = [MemberStatus.NONE, MemberStatus.ACTIVE, MemberStatus.INACTIVE] + return { + status: STATUSES[mdata[0]], + earningsBeforeLastJoin: mdata[1], + totalEarnings: total, + withdrawableEarnings: withdrawable, + } + } + + /** + * Get the amount of tokens the member would get from a successful withdraw + */ + async getWithdrawableEarnings(memberAddress: EthereumAddress): Promise { + const address = getAddress(memberAddress) + const duSidechain = await this.getContracts().getSidechainContractReadOnly(this.contractAddress) + return duSidechain.getWithdrawableEarnings(address) + } + + /** + * Get data union admin fee fraction (between 0.0 and 1.0) that admin gets from each revenue event + */ + async getAdminFee(): Promise { + const duMainnet = this.getContracts().getMainnetContractReadOnly(this.contractAddress) + const adminFeeBN = await duMainnet.adminFeeFraction() + return +adminFeeBN.toString() / 1e18 + } + + async getAdminAddress(): Promise { + const duMainnet = this.getContracts().getMainnetContractReadOnly(this.contractAddress) + return duMainnet.owner() + } + + /** + * Figure out if given mainnet address is old DataUnion (v 1.0) or current 2.0 + * NOTE: Current version of streamr-client-javascript can only handle current version! + */ + async getVersion(): Promise { + const provider = this.client.ethereum.getMainnetProvider() + const du = new Contract(this.contractAddress, [{ + name: 'version', + inputs: [], + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + type: 'function' + }], provider) + try { + const version = await du.version() + return +version + } catch (e) { + // "not a data union" + return 0 + } + } + + // Admin functions + + /** + * Add a new data union secret + */ + async createSecret(name: string = 'Untitled Data Union Secret'): Promise { + const url = getEndpointUrl(this.client.options.restUrl, 'dataunions', this.contractAddress, 'secrets') + const res = await authFetch<{secret: string}>( + url, + this.client.session, + { + method: 'POST', + body: JSON.stringify({ + name + }), + headers: { + 'Content-Type': 'application/json', + }, + }, + ) + return res.secret + } + + /** + * Add given Ethereum addresses as data union members + */ + async addMembers( + memberAddressList: EthereumAddress[], + options: DataUnionMemberListModificationOptions = {} + ): Promise { + const members = memberAddressList.map(getAddress) // throws if there are bad addresses + const duSidechain = await this.getContracts().getSidechainContract(this.contractAddress) + const tx = await duSidechain.addMembers(members) + // TODO: wrap promise for better error reporting in case tx fails (parse reason, throw proper error) + const { confirmations = 1 } = options + return tx.wait(confirmations) + } + + /** + * Remove given members from data union + */ + async removeMembers( + memberAddressList: EthereumAddress[], + options: DataUnionMemberListModificationOptions = {}, + ): Promise { + const members = memberAddressList.map(getAddress) // throws if there are bad addresses + const duSidechain = await this.getContracts().getSidechainContract(this.contractAddress) + const tx = await duSidechain.partMembers(members) + // TODO: wrap promise for better error reporting in case tx fails (parse reason, throw proper error) + const { confirmations = 1 } = options + return tx.wait(confirmations) + } + + /** + * Admin: withdraw earnings (pay gas) on behalf of a member + * TODO: add test + * @param memberAddress - the other member who gets their tokens out of the Data Union + * @returns Receipt once withdraw transaction is confirmed + */ + async withdrawAllToMember( + memberAddress: EthereumAddress, + options?: DataUnionWithdrawOptions + ): Promise { + const address = getAddress(memberAddress) // throws if bad address + return this._executeWithdraw( + () => this.getWithdrawAllToMemberTx(address), + address, + options + ) + } + + /** + * Admin: get the tx promise for withdrawing all earnings on behalf of a member + * @param memberAddress - the other member who gets their tokens out of the Data Union + * @returns await on call .wait to actually send the tx + */ + private async getWithdrawAllToMemberTx(memberAddress: EthereumAddress): Promise { + const a = getAddress(memberAddress) // throws if bad address + const duSidechain = await this.getContracts().getSidechainContract(this.contractAddress) + return duSidechain.withdrawAll(a, true) // sendToMainnet=true + } + + /** + * Admin: Withdraw a member's earnings to another address, signed by the member + * @param memberAddress - the member whose earnings are sent out + * @param recipientAddress - the address to receive the tokens in mainnet + * @param signature - from member, produced using signWithdrawAllTo + * @returns receipt once withdraw transaction is confirmed + */ + async withdrawAllToSigned( + memberAddress: EthereumAddress, + recipientAddress: EthereumAddress, + signature: string, + options?: DataUnionWithdrawOptions + ): Promise { + const from = getAddress(memberAddress) // throws if bad address + const to = getAddress(recipientAddress) + return this._executeWithdraw( + () => this.getWithdrawAllToSignedTx(from, to, signature), + to, + options + ) + } + + /** + * Admin: Withdraw a member's earnings to another address, signed by the member + * @param memberAddress - the member whose earnings are sent out + * @param recipientAddress - the address to receive the tokens in mainnet + * @param signature - from member, produced using signWithdrawAllTo + * @returns await on call .wait to actually send the tx + */ + private async getWithdrawAllToSignedTx( + memberAddress: EthereumAddress, + recipientAddress: EthereumAddress, + signature: string, + ): Promise { + const duSidechain = await this.getContracts().getSidechainContract(this.contractAddress) + return duSidechain.withdrawAllToSigned(memberAddress, recipientAddress, true, signature) // sendToMainnet=true + } + + /** + * Admin: set admin fee (between 0.0 and 1.0) for the data union + */ + async setAdminFee(newFeeFraction: number): Promise { + if (newFeeFraction < 0 || newFeeFraction > 1) { + throw new Error('newFeeFraction argument must be a number between 0...1, got: ' + newFeeFraction) + } + const adminFeeBN = BigNumber.from((newFeeFraction * 1e18).toFixed()) // last 2...3 decimals are going to be gibberish + const duMainnet = this.getContracts().getMainnetContract(this.contractAddress) + const tx = await duMainnet.setAdminFee(adminFeeBN) + return tx.wait() + } + + /** + * Create a new DataUnionMainnet contract to mainnet with DataUnionFactoryMainnet + * This triggers DataUnionSidechain contract creation in sidechain, over the bridge (AMB) + * @return that resolves when the new DU is deployed over the bridge to side-chain + * @internal + */ + static async _deploy(options: DataUnionDeployOptions = {}, client: StreamrClient): Promise { + const deployerAddress = await client.getAddress() + const { + owner, + joinPartAgents, + dataUnionName, + adminFee = 0, + sidechainPollingIntervalMs = 1000, + sidechainRetryTimeoutMs = 600000, + confirmations = 1, + gasPrice + } = options + + let duName = dataUnionName + if (!duName) { + duName = `DataUnion-${Date.now()}` // TODO: use uuid + log(`dataUnionName generated: ${duName}`) + } + + if (adminFee < 0 || adminFee > 1) { throw new Error('options.adminFeeFraction must be a number between 0...1, got: ' + adminFee) } + const adminFeeBN = BigNumber.from((adminFee * 1e18).toFixed()) // last 2...3 decimals are going to be gibberish + + const ownerAddress = (owner) ? getAddress(owner) : deployerAddress + + let agentAddressList + if (Array.isArray(joinPartAgents)) { + // getAddress throws if there's an invalid address in the array + agentAddressList = joinPartAgents.map(getAddress) + } else { + // streamrNode needs to be joinPartAgent so that EE join with secret works (and join approvals from Marketplace UI) + agentAddressList = [ownerAddress] + if (client.options.streamrNodeAddress) { + agentAddressList.push(getAddress(client.options.streamrNodeAddress)) + } + } + + const contract = await new Contracts(client).deployDataUnion({ + ownerAddress, + agentAddressList, + duName, + deployerAddress, + adminFeeBN, + sidechainRetryTimeoutMs, + sidechainPollingIntervalMs, + confirmations, + gasPrice + }) + return new DataUnion(contract.address, contract.sidechain.address, client) + } + + // Internal functions + + /** @internal */ + static _fromContractAddress(contractAddress: string, client: StreamrClient) { + const contracts = new Contracts(client) + const sidechainAddress = contracts.getDataUnionSidechainAddress(getAddress(contractAddress)) // throws if bad address + return new DataUnion(contractAddress, sidechainAddress, client) + } + + /** @internal */ + static _fromName({ dataUnionName, deployerAddress }: { dataUnionName: string, deployerAddress: string}, client: StreamrClient) { + const contracts = new Contracts(client) + const contractAddress = contracts.getDataUnionMainnetAddress(dataUnionName, getAddress(deployerAddress)) // throws if bad address + return DataUnion._fromContractAddress(contractAddress, client) // eslint-disable-line no-underscore-dangle + } + + /** @internal */ + async _getContract() { + const ret = this.getContracts().getMainnetContract(this.contractAddress) + // @ts-expect-error + ret.sidechain = await this.getContracts().getSidechainContract(this.contractAddress) + return ret + } + + private getContracts() { + return new Contracts(this.client) + } + + // template for withdraw functions + // client could be replaced with AMB (mainnet and sidechain) + private async _executeWithdraw( + getWithdrawTxFunc: () => Promise, + recipientAddress: EthereumAddress, + options: DataUnionWithdrawOptions = {} + ): Promise { + const { + pollingIntervalMs = 1000, + retryTimeoutMs = 60000, + 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 (!freeWithdraw) { + await this.getContracts().transportSignaturesForTransaction(tr, options) + } + log(`Waiting for balance ${balanceBefore.toString()} to change`) + await until(async () => !(await getBalanceFunc()).eq(balanceBefore), retryTimeoutMs, pollingIntervalMs) + return tr + } +} diff --git a/src/dataunion/abi.ts b/src/dataunion/abi.ts new file mode 100644 index 000000000..df28546ac --- /dev/null +++ b/src/dataunion/abi.ts @@ -0,0 +1,223 @@ +export const dataUnionMainnetABI = [{ + name: 'sendTokensToBridge', + inputs: [], + outputs: [{ type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function' +}, { + name: 'token', + inputs: [], + outputs: [{ type: 'address' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'owner', + inputs: [], + outputs: [{ type: 'address' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'setAdminFee', + inputs: [{ type: 'uint256' }], + outputs: [], + stateMutability: 'nonpayable', + type: 'function' +}, { + name: 'adminFeeFraction', + inputs: [], + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + type: 'function' +}] + +export const dataUnionSidechainABI = [{ + name: 'addMembers', + inputs: [{ type: 'address[]', internalType: 'address payable[]', }], + outputs: [], + stateMutability: 'nonpayable', + type: 'function' +}, { + name: 'partMembers', + inputs: [{ type: 'address[]' }], + outputs: [], + stateMutability: 'nonpayable', + type: 'function' +}, { + name: 'withdrawAll', + inputs: [{ type: 'address' }, { type: 'bool' }], + outputs: [{ type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function' +}, { + name: 'withdrawAllTo', + inputs: [{ type: 'address' }, { type: 'bool' }], + outputs: [{ type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function' +}, { + name: 'withdrawAllToSigned', + inputs: [{ type: 'address' }, { type: 'address' }, { type: 'bool' }, { type: 'bytes' }], + outputs: [{ type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function' +}, { + // enum ActiveStatus {None, Active, Inactive, Blocked} + // struct MemberInfo { + // ActiveStatus status; + // uint256 earnings_before_last_join; + // uint256 lme_at_join; + // uint256 withdrawnEarnings; + // } + name: 'memberData', + inputs: [{ type: 'address' }], + outputs: [{ type: 'uint8' }, { type: 'uint256' }, { type: 'uint256' }, { type: 'uint256' }], + stateMutability: 'view', + type: 'function' +}, { + inputs: [], + name: 'getStats', + outputs: [{ type: 'uint256[6]' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'getEarnings', + inputs: [{ type: 'address' }], + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'getWithdrawableEarnings', + inputs: [{ type: 'address' }], + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'lifetimeMemberEarnings', + inputs: [], + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'totalWithdrawable', + inputs: [], + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'totalEarnings', + inputs: [], + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'activeMemberCount', + inputs: [], + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + type: 'function' +}, { + // this event is emitted by withdrawing process, + // see https://github.com/poanetwork/tokenbridge-contracts/blob/master/contracts/upgradeable_contracts/arbitrary_message/HomeAMB.sol + name: 'UserRequestForSignature', + inputs: [ + { indexed: true, name: 'messageId', type: 'bytes32' }, + { indexed: false, name: 'encodedData', type: 'bytes' } + ], + anonymous: false, + type: 'event' +}] + +// Only the part of ABI that is needed by deployment (and address resolution) +export const factoryMainnetABI = [{ + type: 'constructor', + inputs: [{ type: 'address' }, { type: 'address' }, { type: 'address' }, { type: 'address' }, { type: 'uint256' }], + stateMutability: 'nonpayable' +}, { + name: 'sidechainAddress', + inputs: [{ type: 'address' }], + outputs: [{ type: 'address' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'mainnetAddress', + inputs: [{ type: 'address' }, { type: 'string' }], + outputs: [{ type: 'address' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'deployNewDataUnion', + inputs: [{ type: 'address' }, { type: 'uint256' }, { type: 'address[]' }, { type: 'string' }], + outputs: [{ type: 'address' }], + stateMutability: 'nonpayable', + type: 'function' +}, { + name: 'amb', + inputs: [], + outputs: [{ type: 'address' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'data_union_sidechain_factory', + inputs: [], + outputs: [{ type: 'address' }], + stateMutability: 'view', + type: 'function' +}] + +export const mainnetAmbABI = [{ + name: 'executeSignatures', + inputs: [{ type: 'bytes' }, { type: 'bytes' }], // data, signatures + outputs: [], + stateMutability: 'nonpayable', + type: 'function' +}, { + name: 'messageCallStatus', + inputs: [{ type: 'bytes32' }], // messageId + outputs: [{ type: 'bool' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'failedMessageSender', + inputs: [{ type: 'bytes32' }], // messageId + outputs: [{ type: 'address' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'relayedMessages', + inputs: [{ type: 'bytes32' }], // messageId, was called "_txhash" though?! + outputs: [{ name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'validatorContract', + inputs: [], + outputs: [{ type: 'address' }], + stateMutability: 'view', + type: 'function' +}] + +export const sidechainAmbABI = [{ + name: 'signature', + inputs: [{ type: 'bytes32' }, { type: 'uint256' }], // messageHash, index + outputs: [{ type: 'bytes' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'message', + inputs: [{ type: 'bytes32' }], // messageHash + outputs: [{ type: 'bytes' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'requiredSignatures', + inputs: [], + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + type: 'function' +}, { + name: 'numMessagesSigned', + inputs: [{ type: 'bytes32' }], // messageHash (TODO: double check) + outputs: [{ type: 'uint256' }], + stateMutability: 'view', + type: 'function' +}] diff --git a/src/errors/AuthFetchError.js b/src/errors/AuthFetchError.js deleted file mode 100644 index 63fba0969..000000000 --- a/src/errors/AuthFetchError.js +++ /dev/null @@ -1,13 +0,0 @@ -export default class AuthFetchError extends Error { - constructor(message, response, body) { - // add leading space if there is a body set - const bodyMessage = body ? ` ${(typeof body === 'string' ? body : JSON.stringify(body))}` : '' - super(message + bodyMessage) - this.response = response - this.body = body - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor) - } - } -} diff --git a/src/errors/FailedToPublishError.js b/src/errors/FailedToPublishError.js deleted file mode 100644 index 8dd0e0d58..000000000 --- a/src/errors/FailedToPublishError.js +++ /dev/null @@ -1,11 +0,0 @@ -export default class FailedToPublishError extends Error { - constructor(streamId, msg, reason) { - super(`Failed to publish to stream ${streamId} due to: ${reason}. Message was: ${msg}`) - this.streamId = streamId - this.msg = msg - this.reason = reason - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor) - } - } -} diff --git a/src/errors/InvalidGroupKeyError.js b/src/errors/InvalidGroupKeyError.js deleted file mode 100644 index b27ae946f..000000000 --- a/src/errors/InvalidGroupKeyError.js +++ /dev/null @@ -1,8 +0,0 @@ -export default class InvalidGroupKeyError extends Error { - constructor(message) { - super(message) - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor) - } - } -} diff --git a/src/errors/InvalidGroupKeyRequestError.js b/src/errors/InvalidGroupKeyRequestError.js deleted file mode 100644 index 76fc00a30..000000000 --- a/src/errors/InvalidGroupKeyRequestError.js +++ /dev/null @@ -1,8 +0,0 @@ -export default class InvalidGroupKeyRequestError extends Error { - constructor(message) { - super(message) - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor) - } - } -} diff --git a/src/errors/InvalidGroupKeyResponseError.js b/src/errors/InvalidGroupKeyResponseError.js deleted file mode 100644 index 42754b85a..000000000 --- a/src/errors/InvalidGroupKeyResponseError.js +++ /dev/null @@ -1,8 +0,0 @@ -export default class InvalidGroupKeyResponseError extends Error { - constructor(message) { - super(message) - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor) - } - } -} diff --git a/src/errors/InvalidMessageTypeError.js b/src/errors/InvalidMessageTypeError.js deleted file mode 100644 index 8e3e1313f..000000000 --- a/src/errors/InvalidMessageTypeError.js +++ /dev/null @@ -1,8 +0,0 @@ -export default class InvalidMessageTypeError extends Error { - constructor(message) { - super(message) - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor) - } - } -} diff --git a/src/errors/SignatureRequiredError.js b/src/errors/SignatureRequiredError.js deleted file mode 100644 index 294650701..000000000 --- a/src/errors/SignatureRequiredError.js +++ /dev/null @@ -1,15 +0,0 @@ -import { Errors } from 'streamr-client-protocol' - -const EMPTY_MESSAGE = { - serialize() {} -} - -export default class SignatureRequiredError extends Errors.ValidationError { - constructor(streamMessage = EMPTY_MESSAGE) { - super(`Client requires data to be signed. Message: ${streamMessage.serialize()}`) - this.streamMessage = streamMessage - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor) - } - } -} diff --git a/src/errors/UnableToDecryptError.js b/src/errors/UnableToDecryptError.js deleted file mode 100644 index 0e097e09f..000000000 --- a/src/errors/UnableToDecryptError.js +++ /dev/null @@ -1,6 +0,0 @@ -export default class UnableToDecryptError extends Error { - constructor(streamMessage) { - super(`Unable to decrypt ${streamMessage.getSerializedContent()}`) - this.streamMessage = streamMessage - } -} diff --git a/src/errors/VerificationFailedError.js b/src/errors/VerificationFailedError.js deleted file mode 100644 index d6ba7731a..000000000 --- a/src/errors/VerificationFailedError.js +++ /dev/null @@ -1,10 +0,0 @@ -export default class VerificationFailedError extends Error { - constructor(streamMessage, cause) { - super(`Verification failed for message: ${streamMessage.serialize()}, cause: ${cause.stack || cause}`) - this.streamMessage = streamMessage - this.cause = cause - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor) - } - } -} 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.js b/src/index.js deleted file mode 100644 index a70115695..000000000 --- a/src/index.js +++ /dev/null @@ -1,13 +0,0 @@ -import StreamrClient from './StreamrClient' -import * as StreamEndpoints from './rest/StreamEndpoints' -import * as LoginEndpoints from './rest/LoginEndpoints' -import * as DataUnionEndpoints from './rest/DataUnionEndpoints' - -// Mixin the rest endpoints to the StreamrClient -Object.assign(StreamrClient.prototype, { - ...StreamEndpoints, - ...LoginEndpoints, - ...DataUnionEndpoints, -}) - -export default StreamrClient diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 000000000..c113fec71 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,28 @@ +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 { BytesLike, Bytes } from '@ethersproject/bytes' +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 new file mode 100644 index 000000000..b35e265b4 --- /dev/null +++ b/src/publish/Encrypt.ts @@ -0,0 +1,45 @@ +import { MessageLayer } from 'streamr-client-protocol' + +import EncryptionUtil from '../stream/Encryption' +import { Stream } from '../stream' +import { StreamrClient } from '../StreamrClient' +import { PublisherKeyExhange } from '../stream/KeyExchange' + +const { StreamMessage } = MessageLayer + +type PublisherKeyExhangeAPI = ReturnType + +export default function Encrypt(client: StreamrClient) { + const publisherKeyExchange = PublisherKeyExhange(client, { + groupKeys: { + ...client.options.groupKeys, + } + }) + async function encrypt(streamMessage: MessageLayer.StreamMessage, stream: Stream) { + if ( + !publisherKeyExchange.hasAnyGroupKey(stream.id) + && !stream.requireEncryptedData + ) { + // not needed + return + } + + if (streamMessage.messageType !== StreamMessage.MESSAGE_TYPES.MESSAGE) { + return + } + const groupKey = await publisherKeyExchange.useGroupKey(stream.id) + await EncryptionUtil.encryptStreamMessage(streamMessage, groupKey) + } + + return Object.assign(encrypt, { + setNextGroupKey(...args: Parameters) { + return publisherKeyExchange.setNextGroupKey(...args) + }, + rotateGroupKey(...args: Parameters) { + return publisherKeyExchange.rotateGroupKey(...args) + }, + stop() { + return publisherKeyExchange.stop() + } + }) +} diff --git a/src/publish/Signer.ts b/src/publish/Signer.ts new file mode 100644 index 000000000..44e5bb875 --- /dev/null +++ b/src/publish/Signer.ts @@ -0,0 +1,94 @@ +import { MessageLayer, Utils } from 'streamr-client-protocol' +import { Web3Provider } from '@ethersproject/providers' + +import { pLimitFn, sleep } from '../utils' +import type { EthereumConfig } from '../Config' + +const { StreamMessage } = MessageLayer +const { SigningUtil } = Utils +const { SIGNATURE_TYPES } = StreamMessage + +type AuthOption = { + ethereum: undefined + privateKey: string | Uint8Array +} | { + privateKey: undefined + ethereum: EthereumConfig +} | { + ethereum: undefined + privateKey: undefined +} + +function getSigningFunction({ + privateKey, + ethereum, +}: AuthOption) { + if (privateKey) { + const key = (typeof privateKey === 'string' && privateKey.startsWith('0x')) + ? privateKey.slice(2) // strip leading 0x + : privateKey + return async (d: string) => SigningUtil.sign(d, key.toString()) + } + + if (ethereum) { + const web3Provider = new Web3Provider(ethereum) + const signer = web3Provider.getSigner() + // sign one at a time & wait a moment before asking for next signature + // otherwise metamask extension may not show the prompt window + return pLimitFn(async (d) => { + const sig = await signer.signMessage(d) + await sleep(50) + return sig + }, 1) + } + + throw new Error('Need either "privateKey" or "ethereum".') +} + +export default function Signer(options: AuthOption, publishWithSignature = 'auto') { + const { privateKey, ethereum } = options + const noSignStreamMessage = (streamMessage: MessageLayer.StreamMessage) => streamMessage + + if (publishWithSignature === 'never') { + return noSignStreamMessage + } + + if (publishWithSignature === 'auto' && !privateKey && !ethereum) { + return noSignStreamMessage + } + + if (publishWithSignature !== 'auto' && publishWithSignature !== 'always') { + throw new Error(`Unknown parameter value: ${publishWithSignature}`) + } + + const sign = getSigningFunction(options) + + async function signStreamMessage( + streamMessage: MessageLayer.StreamMessage, + signatureType: MessageLayer.StreamMessage['signatureType'] = SIGNATURE_TYPES.ETH + ) { + if (!streamMessage) { + throw new Error('streamMessage required as part of the data to sign.') + } + + if (typeof streamMessage.getTimestamp !== 'function' || !streamMessage.getTimestamp()) { + throw new Error('Timestamp is required as part of the data to sign.') + } + + if (signatureType !== SIGNATURE_TYPES.ETH_LEGACY && signatureType !== SIGNATURE_TYPES.ETH) { + throw new Error(`Unrecognized signature type: ${signatureType}`) + } + + // set signature so getting of payload works correctly + // (publisherId should already be set) + streamMessage.signatureType = signatureType // eslint-disable-line no-param-reassign + const signature = await sign(streamMessage.getPayloadToSign()) + return Object.assign(streamMessage, { + signature, + }) + } + + return Object.assign(signStreamMessage, { + signData: sign, // this mainly for tests + }) +} diff --git a/src/publish/index.js b/src/publish/index.js new file mode 100644 index 000000000..292065a08 --- /dev/null +++ b/src/publish/index.js @@ -0,0 +1,314 @@ +import { inspect } from 'util' +import crypto from 'crypto' + +import { ControlLayer, MessageLayer } from 'streamr-client-protocol' +import mem from 'mem' + +import { uuid, CacheFn, LimitAsyncFnByKey, randomString } from '../utils' +import { waitForRequestResponse } from '../stream/utils' + +import Signer from './Signer' +import Encrypt from './Encrypt' + +export class FailedToPublishError extends Error { + constructor(streamId, msg, reason) { + super(`Failed to publish to stream ${streamId} due to: ${reason && reason.stack ? reason.stack : reason}. Message was: ${inspect(msg)}`) + this.streamId = streamId + this.msg = msg + this.reason = reason + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor) + } + } +} + +const { StreamMessage, MessageID, MessageRef } = MessageLayer + +function getStreamId(streamObjectOrId) { + if (streamObjectOrId.streamId != null) { + return streamObjectOrId.streamId + } + + if (streamObjectOrId.id != null) { + return streamObjectOrId.id + } + + if (streamObjectOrId && typeof streamObjectOrId === 'string') { + return streamObjectOrId + } + + throw new Error(`First argument must be a Stream object or the stream id! Was: ${inspect(streamObjectOrId)}`) +} + +function hash(stringToHash) { + return crypto.createHash('md5').update(stringToHash).digest() +} + +function MessageChainer({ streamId, streamPartition, publisherId, msgChainId = randomString(20) } = {}) { + let prevMsgRef = null + + /** + * Generate the next message MessageID + previous MessageRef for this message chain. + * Messages with same timestamp get incremented sequence numbers. + */ + + return function add(timestamp) { + // NOTE: publishing back-dated (i.e. non-sequentially timestamped) messages will 'break' sequencing. + // i.e. we lose track of biggest sequence number whenever timestamp changes for stream id+partition combo + // so backdated messages will start at sequence 0 again, regardless of the sequencing of existing messages. + // storage considers timestamp+sequence number unique, so the newer messages will clobber the older messages + // Not feasible to keep greatest sequence number for every millisecond timestamp so not sure a good way around this. + // Possible we should keep a global sequence number + const isSameTimestamp = prevMsgRef && prevMsgRef.timestamp === timestamp + const isBackdated = prevMsgRef && prevMsgRef.timestamp > timestamp + // increment if timestamp the same, otherwise 0 + const nextSequenceNumber = isSameTimestamp ? prevMsgRef.sequenceNumber + 1 : 0 + const messageId = new MessageID(streamId, streamPartition, timestamp, nextSequenceNumber, publisherId, msgChainId) + // update latest timestamp + sequence for this streamId+partition + // (see note above about clobbering sequencing) + // don't update latest if timestamp < previous timestamp + // this "fixes" the sequence breaking issue above, but this message will silently disappear + const currentPrevMsgRef = prevMsgRef + if (!isBackdated) { + prevMsgRef = new MessageRef(timestamp, nextSequenceNumber) + } + return [messageId, currentPrevMsgRef] + } +} + +function StreamPartitioner(cacheOptions) { + const cachedHash = CacheFn(hash, cacheOptions) + function computeStreamPartition(partitionCount, partitionKey) { + if (!(Number.isSafeInteger(partitionCount) && partitionCount > 0)) { + throw new Error(`partitionCount is not a safe positive integer! ${partitionCount}`) + } + + if (partitionCount === 1) { + // Fast common case + return 0 + } + + if (typeof partitionKey === 'number') { + return Math.abs(partitionKey) % partitionCount + } + + if (!partitionKey) { + // Fallback to random partition if no key + return Math.floor(Math.random() * partitionCount) + } + + const buffer = cachedHash(partitionKey) + const intHash = buffer.readInt32LE() + return Math.abs(intHash) % partitionCount + } + + computeStreamPartition.clear = cachedHash.clear + return computeStreamPartition +} + +/* + * Get function for creating stream messages. + */ + +function getCreateStreamMessage(client) { + const cacheOptions = client.options.cache + const computeStreamPartition = StreamPartitioner(cacheOptions) + const encrypt = Encrypt(client) + + // one chainer per streamId + streamPartition + publisherId + msgChainId + const getMsgChainer = Object.assign(mem(MessageChainer, { + cacheKey: ([{ streamId, streamPartition, publisherId, msgChainId }]) => ( + // undefined msgChainId is fine + [streamId, streamPartition, publisherId, msgChainId].join('|') + ), + ...cacheOptions, + }), { + clear() { + mem.clear(getMsgChainer) + } + }) + + // message signer + const signStreamMessage = Signer({ + ...client.options.auth, + debug: client.debug, + }, client.options.publishWithSignature) + + // per-stream queue so messages processed in-order + const queue = LimitAsyncFnByKey(1) + + function createStreamMessage(streamObjectOrId, { + content, + timestamp, + partitionKey, + msgChainId, + ...opts + }) { + const streamId = getStreamId(streamObjectOrId) + // streamId as queue key + return queue(streamId, async () => { + // load cached stream + publisher details + const [stream, publisherId] = await Promise.all([ + client.cached.getStream(streamId), + client.cached.getUserId(client), + ]) + + // figure out partition + const streamPartition = computeStreamPartition(stream.partitions, partitionKey) + + // chain messages + const chainMessage = getMsgChainer({ + streamId, streamPartition, publisherId, msgChainId + }) + + const timestampAsNumber = timestamp instanceof Date ? timestamp.getTime() : new Date(timestamp).getTime() + const [messageId, prevMsgRef] = chainMessage(timestampAsNumber) + + const streamMessage = (content && typeof content.toStreamMessage === 'function') + ? content.toStreamMessage(messageId, prevMsgRef) + : new StreamMessage({ + messageId, + prevMsgRef, + content, + ...opts + }) + + await encrypt(streamMessage, stream) + // sign, noop if not needed + await signStreamMessage(streamMessage) + + return streamMessage + }) + } + + return Object.assign(createStreamMessage, { + setNextGroupKey(maybeStreamId, newKey) { + return encrypt.setNextGroupKey(maybeStreamId, newKey) + }, + rotateGroupKey(maybeStreamId) { + return encrypt.rotateGroupKey(maybeStreamId) + }, + clear() { + computeStreamPartition.clear() + getMsgChainer.clear() + queue.clear() + } + }) +} + +/** + * Add handle to keep connection open while publishing. + * Refreshes handle timeout on each call. + * Only remove publish handle after inactivity of options.publishAutoDisconnectDelay ms. + */ + +const PUBLISH_HANDLE = Symbol('publish') + +async function setupPublishHandle(client) { + const onConnectionDone = () => clearTimeout(setupPublishHandle.timeout) + try { + clearTimeout(setupPublishHandle.timeout) + client.connection.addListener('done', onConnectionDone) + await client.connection.addHandle(PUBLISH_HANDLE) + } finally { + const { publishAutoDisconnectDelay = 5000 } = client.options + clearTimeout(setupPublishHandle.timeout) + setupPublishHandle.timeout = setTimeout(async () => { // eslint-disable-line require-atomic-updates + try { + await client.connection.removeHandle(PUBLISH_HANDLE) + } catch (err) { + client.emit('error', err) + } + }, publishAutoDisconnectDelay || 0) + } +} + +export default function Publisher(client) { + const debug = client.debug.extend('Publisher') + const sendQueue = LimitAsyncFnByKey(1) + const createStreamMessage = getCreateStreamMessage(client) + const onErrorEmit = client.getErrorEmitter({ + debug + }) + + async function listenForErrors(request) { + // listen for errors for this request for 3s + return waitForRequestResponse(client, request, { + timeout: 3000, + rejectOnTimeout: false, + }) + } + + async function publishMessage(streamObjectOrId, { content, timestamp = new Date(), partitionKey = null } = {}) { + if (client.session.isUnauthenticated()) { + throw new Error('Need to be authenticated to publish.') + } + + const streamId = getStreamId(streamObjectOrId) + + // get session, connection + generate stream message in parallel + // NOTE: createStreamMessage *must* be executed in publish() call order or sequencing will be broken. + // i.e. don't do anything async before calling createStreamMessage + + const asyncDepsTask = Promise.all([ // intentional no await + // no async before running createStreamMessage + createStreamMessage(streamObjectOrId, { + content, + timestamp, + partitionKey + }), + client.session.getSessionToken(), // fetch in parallel + setupPublishHandle(client), + ]) + + // no async before running sendQueue + return sendQueue(streamId, async () => { + const [streamMessage, sessionToken] = await asyncDepsTask + const requestId = uuid('pub') + const request = new ControlLayer.PublishRequest({ + streamMessage, + requestId, + sessionToken, + }) + + listenForErrors(request).catch(onErrorEmit) // unchained async + + // send calls should probably also fire in-order otherwise new realtime streams + // can miss messages that are sent late + await client.send(request) + return request + }) + } + + return { + async publish(streamObjectOrId, content, timestamp, partitionKey) { + // wrap publish in error emitter + try { + return await publishMessage(streamObjectOrId, { + content, + timestamp, + partitionKey, + }) + } catch (err) { + const streamId = getStreamId(streamObjectOrId) + const error = new FailedToPublishError( + streamId, + content, + err + ) + onErrorEmit(error) + throw error + } + }, + async stop() { + sendQueue.clear() + createStreamMessage.clear() + }, + rotateGroupKey(streamId) { + return createStreamMessage.rotateGroupKey(streamId) + }, + setNextGroupKey(streamId, newKey) { + return createStreamMessage.setNextGroupKey(streamId, newKey) + } + } +} diff --git a/src/rest/DataUnionEndpoints.js b/src/rest/DataUnionEndpoints.js deleted file mode 100644 index 73e14c1ae..000000000 --- a/src/rest/DataUnionEndpoints.js +++ /dev/null @@ -1,518 +0,0 @@ -/** - * Streamr Data Union related functions - * - * Table of Contents: - * member: JOIN & QUERY DATA UNION Publicly available info about dataunions and their members (with earnings and proofs) - * member: WITHDRAW EARNINGS Withdrawing functions, there's many: normal, agent, donate - * admin: DEPLOY AND SETUP DATA UNION Functions for deploying the contract and adding secrets for smooth joining - * admin: MANAGE DATA UNION Kick and add members - */ - -import fetch from 'node-fetch' -import { - Contract, - ContractFactory, - Wallet, - getDefaultProvider, - providers, - BigNumber, - utils as ethersUtils, -} from 'ethers' -import debugFactory from 'debug' - -import * as DataUnion from '../../contracts/DataUnion.json' -import { getEndpointUrl } from '../utils' - -import authFetch, { DEFAULT_HEADERS } from './authFetch' - -const { computeAddress, getAddress } = ethersUtils - -const debug = debugFactory('StreamrClient::DataUnionEndpoints') - -/** @typedef {String} EthereumAddress */ - -function throwIfBadAddress(address, variableDescription) { - try { - return getAddress(address) - } catch (e) { - throw new Error(`${variableDescription || 'Error'}: Bad Ethereum address ${address}. Original error: ${e.stack}.`) - } -} - -async function throwIfNotContract(eth, address, variableDescription) { - const addr = throwIfBadAddress(address, variableDescription) - if (await eth.getCode(address) === '0x') { - throw new Error(`${variableDescription || 'Error'}: No contract at ${address}`) - } - return addr -} - -function sleep(ms) { - return new Promise((resolve) => { - setTimeout(resolve, ms) - }) -} - -async function get(client, dataUnionContractAddress, endpoint, opts = {}) { - const url = getEndpointUrl(client.options.restUrl, 'communities', dataUnionContractAddress) + endpoint - const response = await fetch(url, { - ...opts, - headers: { - ...DEFAULT_HEADERS, - ...opts.headers, - }, - }) - const json = await response.json() - // server may return things like { code: "ConnectionPoolTimeoutException", message: "Timeout waiting for connection from pool" } - // they must still be handled as errors - if (!response.ok && !json.error) { - json.error = `Server returned ${response.status} ${response.statusText}` - } - - if (json.code && !json.error) { - json.error = json.code - } - return json -} - -async function getOrThrow(...args) { - const res = await get(...args) - if (res.error) { - throw new Error(JSON.stringify(res)) - } - return res -} - -/** - * @typedef {Object} EthereumOptions all optional, hence "options" - * @property {Wallet | String} wallet or private key, default is currently logged in StreamrClient (if auth: privateKey) - * @property {String} key private key, alias for String wallet - * @property {String} privateKey, alias for String wallet - * @property {providers.Provider} provider to use in case wallet was a String, or omitted - * @property {Number} confirmations, default is 1 - * @property {BigNumber} gasPrice in wei (part of ethers overrides), default is whatever the network recommends (ethers.js default) - * @see https://docs.ethers.io/ethers.js/html/api-contract.html#overrides - */ - -// TODO: gasPrice to overrides (not needed for browser, but would be useful in node.js) - -/** - * Get a wallet from options, e.g. by parsing something that looks like a private key - * @param {StreamrClient} client this - * @param {EthereumOptions} options includes wallet which is Wallet or private key, or provider so StreamrClient auth: privateKey will be used - * @returns {Wallet} "wallet with provider" that can be used to sign and send transactions - */ -function parseWalletFromOptions(client, options) { - if (options.wallet instanceof Wallet) { return options.wallet } - - const key = typeof options.wallet === 'string' ? options.wallet : options.key || options.privateKey || client.options.auth.privateKey - if (key) { - const provider = options.provider instanceof providers.Provider ? options.provider : getDefaultProvider() - return new Wallet(key, provider) - } - - // TODO: check metamask before erroring! - throw new Error("Please provide options.wallet, or options.privateKey string, if you're not authenticated using a privateKey") -} - -// ////////////////////////////////////////////////////////////////// -// admin: DEPLOY AND SETUP DATA UNION -// ////////////////////////////////////////////////////////////////// - -/** - * Deploy a new DataUnion contract and create the required joinPartStream - * Note that the Promise resolves with an ethers.js TransactionResponse, so it's only sent to the chain at that point, but not yet deployed - * @param {EthereumOptions} options such as blockFreezePeriodSeconds (default: 0), adminFee (default: 0) - * @return {Promise} has methods that can be awaited: contract is deployed (`.deployed()`), operator is started (`.isReady()`) - */ -export async function deployDataUnion(options) { - const wallet = parseWalletFromOptions(this, options) - const { - blockFreezePeriodSeconds = 0, - adminFee = 0, - tokenAddress = this.options.tokenAddress, - streamrNodeAddress = this.options.streamrNodeAddress, - streamrOperatorAddress = this.options.streamrOperatorAddress - } = options - - await throwIfNotContract(wallet.provider, tokenAddress, 'options.tokenAddress') - await throwIfBadAddress(streamrNodeAddress, 'options.streamrNodeAddress') - await throwIfBadAddress(streamrOperatorAddress, 'options.streamrOperatorAddress') - - if (adminFee < 0 || adminFee > 1) { throw new Error('options.adminFeeFraction must be a number between 0...1, got: ' + adminFee) } - const adminFeeBN = BigNumber.from((adminFee * 1e18).toFixed()) // last 2...3 decimals are going to be gibberish - - const stream = await this.createStream({ - name: `Join-Part-${wallet.address.slice(0, 10)}-${Date.now()}` - }) - debug(`Stream created: ${JSON.stringify(stream.toObject())}`) - - let res - res = await stream.grantPermission('stream_get', null) - debug(`Grant stream_get permission response from server: ${JSON.stringify(res)}`) - res = await stream.grantPermission('stream_subscribe', null) - debug(`Grant stream_subscribe permission response from server: ${JSON.stringify(res)}`) - res = await stream.grantPermission('stream_get', streamrNodeAddress) - debug(`Grant stream_get permission response to ${streamrNodeAddress} from server: ${JSON.stringify(res)}`) - res = await stream.grantPermission('stream_publish', streamrNodeAddress) - debug(`Grant stream_publish permission response to ${streamrNodeAddress} from server: ${JSON.stringify(res)}`) - - const deployer = new ContractFactory(DataUnion.abi, DataUnion.bytecode, wallet) - const result = await deployer.deploy(streamrOperatorAddress, stream.id, tokenAddress, blockFreezePeriodSeconds, adminFeeBN) - const { address } = result // this can be known in advance - debug(`Data Union contract @ ${address} deployment started`) - - // add the waiting method so that caller can await data union being operated by server (so that EE calls work) - const client = this - result.isReady = async (pollingIntervalMs, timeoutMs) => client.dataUnionIsReady(address, pollingIntervalMs, timeoutMs) - return result -} - -/** - * Await this function when you want to make sure a data union is deployed and ready to use - * @param {EthereumAddress} dataUnionContractAddress - * @param {Number} pollingIntervalMs (optional, default: 1000) ask server if data union is ready - * @param {Number} retryTimeoutMs (optional, default: 60000) give up sending more retries - * @return {Promise} resolves when data union server is ready to operate the data union (or fails with HTTP error) - */ -export async function dataUnionIsReady(dataUnionContractAddress, pollingIntervalMs = 1000, retryTimeoutMs = 60000) { - let stats = await get(this, dataUnionContractAddress, '/stats') - const startTime = Date.now() - while (stats.error && Date.now() < startTime + retryTimeoutMs && (!stats.dataUnion || stats.dataUnion.state !== 'failed')) { - debug(`Waiting for data union ${dataUnionContractAddress} to start. Status: ${JSON.stringify(stats)}`) - await sleep(pollingIntervalMs) // eslint-disable-line no-await-in-loop - stats = await get(this, dataUnionContractAddress, '/stats') // eslint-disable-line no-await-in-loop - } - if (stats.error) { - throw new Error(`Data Union failed to start, retried for ${retryTimeoutMs} ms. Status: ${JSON.stringify(stats)}`) - } -} - -/** - * Add a new data union secret - * @param {EthereumAddress} dataUnionContractAddress - * @param {String} name describes the secret - * @returns {String} the server-generated secret - */ -export async function createSecret(dataUnionContractAddress, name = 'Untitled Data Union Secret') { - const duAddress = getAddress(dataUnionContractAddress) // throws if bad address - const url = getEndpointUrl(this.options.restUrl, 'dataunions', duAddress, 'secrets') - const res = await authFetch( - url, - this.session, - { - method: 'POST', - body: JSON.stringify({ - name - }), - headers: { - 'Content-Type': 'application/json', - }, - }, - ) - return res.secret -} - -// ////////////////////////////////////////////////////////////////// -// member: JOIN & QUERY DATA UNION -// ////////////////////////////////////////////////////////////////// - -/** - * Send a joinRequest, or get into data union instantly with a data union secret - * @param {EthereumAddress} dataUnionContractAddress to join - * @param {String} secret (optional) if given, and correct, join the data union immediately - */ -export async function joinDataUnion(dataUnionContractAddress, secret) { - const authKey = this.options.auth && this.options.auth.privateKey - if (!authKey) { - throw new Error('joinDataUnion: StreamrClient must have auth: privateKey') - } - - const body = { - memberAddress: computeAddress(authKey) - } - if (secret) { body.secret = secret } - - const url = getEndpointUrl(this.options.restUrl, 'communities', dataUnionContractAddress, 'joinRequests') - return authFetch( - url, - this.session, - { - method: 'POST', - body: JSON.stringify(body), - headers: { - 'Content-Type': 'application/json', - }, - }, - ) -} - -/** - * Await this function when you want to make sure a member is accepted in the data union - * @param {EthereumAddress} dataUnionContractAddress - * @param {EthereumAddress} memberAddress (optional, default is StreamrClient's auth: privateKey) - * @param {Number} pollingIntervalMs (optional, default: 1000) ask server if member is in - * @param {Number} retryTimeoutMs (optional, default: 60000) give up - * @return {Promise} resolves when member is in the data union (or fails with HTTP error) - */ -export async function hasJoined(dataUnionContractAddress, memberAddress, pollingIntervalMs = 1000, retryTimeoutMs = 60000) { - let address = memberAddress - if (!address) { - const authKey = this.options.auth && this.options.auth.privateKey - if (!authKey) { - throw new Error("StreamrClient wasn't authenticated with privateKey, and memberAddress argument not supplied") - } - address = computeAddress(authKey) - } - - let stats = await get(this, dataUnionContractAddress, `/members/${address}`) - const startTime = Date.now() - while (stats.error && Date.now() < startTime + retryTimeoutMs && (!stats.dataUnion || stats.dataUnion.state !== 'failed')) { - debug(`Waiting for member ${address} to be accepted into data union ${dataUnionContractAddress}. Status: ${JSON.stringify(stats)}`) - await sleep(pollingIntervalMs) // eslint-disable-line no-await-in-loop - stats = await get(this, dataUnionContractAddress, `/members/${address}`) // eslint-disable-line no-await-in-loop - } - if (stats.error) { - throw new Error(`Member failed to join, retried for ${retryTimeoutMs} ms. Status: ${JSON.stringify(stats)}`) - } -} - -/** - * Get stats of a single data union member, including proof - * @param {EthereumAddress} dataUnionContractAddress to query - * @param {EthereumAddress} memberAddress (optional) if not supplied, get the stats of currently logged in StreamrClient (if auth: privateKey) - */ -export async function getMemberStats(dataUnionContractAddress, memberAddress) { - let address = memberAddress - if (!address) { - const authKey = this.options.auth && this.options.auth.privateKey - if (!authKey) { - throw new Error("StreamrClient wasn't authenticated with privateKey, and memberAddress argument not supplied") - } - address = computeAddress(authKey) - } - - return getOrThrow(this, dataUnionContractAddress, `/members/${address}`) -} - -/** - * @typedef {Object} BalanceResponse - * @property {BigNumber} total tokens earned less withdrawn previously, what you'd get once Operator commits the earnings to DataUnion contract - * @property {BigNumber} withdrawable number of tokens that you'd get if you withdraw now - */ - -/** - * Calculate the amount of tokens the member would get from a successful withdraw - * @param dataUnionContractAddress - * @param memberAddress - * @return {Promise} earnings minus withdrawn tokens - */ -export async function getBalance(dataUnionContractAddress, memberAddress, provider) { - let address = memberAddress - if (!address) { - const authKey = this.options.auth && this.options.auth.privateKey - if (!authKey) { - throw new Error("StreamrClient wasn't authenticated with privateKey, and memberAddress argument not supplied") - } - address = computeAddress(authKey) - } - - const stats = await get(this, dataUnionContractAddress, `/members/${address}`) - if (stats.error || stats.earnings === '0') { - return { - total: BigNumber.ZERO, withdrawable: BigNumber.ZERO - } - } - const earningsBN = BigNumber.from(stats.earnings) - - if (stats.withdrawableEarnings === '0') { - return { - total: earningsBN, withdrawable: BigNumber.ZERO - } - } - const withdrawableEarningsBN = BigNumber.from(stats.withdrawableEarnings) - - const dataUnionContract = new Contract(dataUnionContractAddress, DataUnion.abi, provider || getDefaultProvider()) - const withdrawnBN = await dataUnionContract.withdrawn(address) - const total = earningsBN.sub(withdrawnBN) - const withdrawable = withdrawableEarningsBN.sub(withdrawnBN) - return { - total, withdrawable - } -} - -// TODO: filter? That JSON blob could be big -export async function getMembers(dataUnionContractAddress) { - return getOrThrow(this, dataUnionContractAddress, '/members') -} - -export async function getDataUnionStats(dataUnionContractAddress) { - return getOrThrow(this, dataUnionContractAddress, '/stats') -} - -// ////////////////////////////////////////////////////////////////// -// member: WITHDRAW EARNINGS -// ////////////////////////////////////////////////////////////////// - -/* eslint-disable no-await-in-loop, no-else-return */ -/** - * Validate the proof given by the server with the smart contract (ground truth) - * Wait for options.retryBlocks Ethereum blocks (default: 5) - * @param {EthereumAddress} dataUnionContractAddress to query - * @param {EthereumAddress} memberAddress to query - * @param {providers.Provider} provider (optional) e.g. `wallet.provider`, default is `ethers.getDefaultProvider()` (mainnet) - * @return {Object} containing the validated proof, withdrawableEarnings and withdrawableBlock - */ -export async function validateProof(dataUnionContractAddress, options) { - const wallet = parseWalletFromOptions(this, options) - const contract = new Contract(dataUnionContractAddress, DataUnion.abi, wallet) - - const { retryBlocks = 5 } = options - for (let retryCount = 0; retryCount < retryBlocks; retryCount++) { - const stats = await this.getMemberStats(dataUnionContractAddress, wallet.address) // throws on connection errors - if (!stats.withdrawableBlockNumber) { - throw new Error('No earnings to withdraw.') - } - const wasCorrect = await contract.proofIsCorrect( - stats.withdrawableBlockNumber, - wallet.address, - stats.withdrawableEarnings, - stats.proof, - ).catch((e) => e) - if (wasCorrect === true) { - return stats - } else if (wasCorrect === false) { - console.error(`Server gave bad proof: ${JSON.stringify(stats)}`) - } else if (wasCorrect instanceof Error && wasCorrect.message.endsWith('error_blockNotFound')) { - // commit hasn't been yet accepted into blockchain, just wait until next block and try again - } else { - console.error(`Unexpected: ${wasCorrect}`) - } - await new Promise((resolve) => { - wallet.provider.once('block', resolve) - }) - } - throw new Error(`Failed to validate proof after ${retryBlocks} Ethereum blocks`) -} -/* eslint-enable no-await-in-loop, no-else-return */ - -/** - * Withdraw all your earnings - * @param {EthereumAddress} dataUnionContractAddress - * @param {EthereumOptions} options - * @returns {Promise} get receipt once withdraw transaction is confirmed - */ -export async function withdraw(dataUnionContractAddress, options) { - const tx = await this.getWithdrawTx(dataUnionContractAddress, options) - return tx.wait(options.confirmations || 1) -} - -/** - * Get the tx promise for withdrawing all your earnings - * @param {EthereumAddress} dataUnionContractAddress - * @param {EthereumOptions} options - * @returns {Promise} await on call .wait to actually send the tx - */ -export async function getWithdrawTx(dataUnionContractAddress, options) { - const wallet = parseWalletFromOptions(this, options) - const stats = await this.getMemberStats(dataUnionContractAddress, wallet.address) // throws on connection errors - if (!stats.withdrawableBlockNumber) { - throw new Error(`No earnings to withdraw. Server response: ${JSON.stringify(stats)}`) - } - const contract = new Contract(dataUnionContractAddress, DataUnion.abi, wallet) - return contract.withdrawAll(stats.withdrawableBlockNumber, stats.withdrawableEarnings, stats.proof) -} - -/** - * Withdraw earnings (pay gas) on behalf of another member - * @param {EthereumAddress} memberAddress the other member who gets their tokens out of the Data Union - * @param {EthereumAddress} dataUnionContractAddress - * @param {EthereumOptions} options - * @returns {Promise} get receipt once withdraw transaction is confirmed - */ -export async function withdrawFor(memberAddress, dataUnionContractAddress, options) { - const tx = await this.getWithdrawTxFor(memberAddress, dataUnionContractAddress, options) - return tx.wait(options.confirmations || 1) -} - -/** - * Get the tx promise for withdrawing all earnings on behalf of another member - * @param {EthereumAddress} dataUnionContractAddress - * @param {EthereumOptions} options - * @returns {Promise} await on call .wait to actually send the tx - */ -export async function getWithdrawTxFor(memberAddress, dataUnionContractAddress, options) { - const stats = await this.getMemberStats(dataUnionContractAddress, memberAddress) // throws on connection errors - if (!stats.withdrawableBlockNumber) { - throw new Error(`No earnings to withdraw. Server response: ${JSON.stringify(stats)}`) - } - const wallet = parseWalletFromOptions(this, options) - const contract = new Contract(dataUnionContractAddress, DataUnion.abi, wallet) - return contract.withdrawAllFor(memberAddress, stats.withdrawableBlockNumber, stats.withdrawableEarnings, stats.proof) -} - -/** - * Withdraw earnings and "donate" them to the given address - * @param {EthereumAddress} dataUnionContractAddress - * @param {EthereumAddress} recipientAddress the address to receive the tokens - * @param {EthereumOptions} options - * @returns {Promise} get receipt once withdraw transaction is confirmed - */ -export async function withdrawTo(recipientAddress, dataUnionContractAddress, options) { - const tx = await this.getWithdrawTxTo(recipientAddress, dataUnionContractAddress, options) - return tx.wait(options.confirmations || 1) -} - -/** - * Withdraw earnings and "donate" them to the given address - * @param {EthereumAddress} dataUnionContractAddress - * @param {EthereumAddress} recipientAddress the address to receive the tokens - * @param {EthereumOptions} options - * @returns {Promise} await on call .wait to actually send the tx - */ -export async function getWithdrawTxTo(recipientAddress, dataUnionContractAddress, options) { - const wallet = parseWalletFromOptions(this, options) - const stats = await this.getMemberStats(dataUnionContractAddress, wallet.address) // throws on connection errors - if (!stats.withdrawableBlockNumber) { - throw new Error(`No earnings to withdraw. Server response: ${JSON.stringify(stats)}`) - } - const contract = new Contract(dataUnionContractAddress, DataUnion.abi, wallet) - return contract.withdrawAllTo(recipientAddress, stats.withdrawableBlockNumber, stats.withdrawableEarnings, stats.proof, options) -} - -// ////////////////////////////////////////////////////////////////// -// admin: MANAGE DATA UNION -// ////////////////////////////////////////////////////////////////// - -/** - * Directly poke into joinPartStream, circumventing EE joinRequest tools etc. - * Obviously requires write access to the stream, so only available to admins - * TODO: find a way to check that the join/part has gone through and been registered by the server - */ -async function sendToJoinPartStream(client, type, dataUnionContractAddress, addresses, provider) { - const contract = new Contract(dataUnionContractAddress, DataUnion.abi, provider || getDefaultProvider()) - const joinPartStreamId = await contract.joinPartStream() - return client.publish(joinPartStreamId, { - type, addresses, - }) -} - -/** - * Kick given members from data union - * @param {EthereumAddress} dataUnionContractAddress to manage - * @param {List} memberAddressList to kick - * @param {providers.Provider} provider (optional) default is mainnet - */ -export async function kick(dataUnionContractAddress, memberAddressList, provider) { - return sendToJoinPartStream(this, 'part', dataUnionContractAddress, memberAddressList, provider) -} - -/** - * Add given Ethereum addresses as data union members - * @param {EthereumAddress} dataUnionContractAddress to manage - * @param {List} memberAddressList to kick - * @param {providers.Provider} provider (optional) default is mainnet - */ -export async function addMembers(dataUnionContractAddress, memberAddressList, provider) { - return sendToJoinPartStream(this, 'join', dataUnionContractAddress, memberAddressList, provider) -} diff --git a/src/rest/LoginEndpoints.js b/src/rest/LoginEndpoints.js deleted file mode 100644 index 4d869e750..000000000 --- a/src/rest/LoginEndpoints.js +++ /dev/null @@ -1,98 +0,0 @@ -import { getEndpointUrl } from '../utils' -import AuthFetchError from '../errors/AuthFetchError' - -import authFetch from './authFetch' - -async function getSessionToken(url, props) { - return authFetch( - url, - undefined, - { - method: 'POST', - body: JSON.stringify(props), - headers: { - 'Content-Type': 'application/json', - }, - }, - ) -} - -export async function getChallenge(address) { - this.debug('getChallenge', { - address, - }) - const url = getEndpointUrl(this.options.restUrl, 'login', 'challenge', address) - return authFetch( - url, - undefined, - { - method: 'POST', - }, - ) -} - -export async function sendChallengeResponse(challenge, signature, address) { - this.debug('sendChallengeResponse', { - challenge, - signature, - address, - }) - const url = getEndpointUrl(this.options.restUrl, 'login', 'response') - const props = { - challenge, - signature, - address, - } - return getSessionToken(url, props) -} - -export async function loginWithChallengeResponse(signingFunction, address) { - this.debug('loginWithChallengeResponse', { - address, - }) - const challenge = await this.getChallenge(address) - const signature = await signingFunction(challenge.challenge) - return this.sendChallengeResponse(challenge, signature, address) -} - -export async function loginWithApiKey(apiKey) { - this.debug('loginWithApiKey', { - apiKey, - }) - const url = getEndpointUrl(this.options.restUrl, 'login', 'apikey') - const props = { - apiKey, - } - return getSessionToken(url, props) -} - -export async function loginWithUsernamePassword(username, password) { - const url = getEndpointUrl(this.options.restUrl, 'login', 'password') - const props = { - username, - password, - } - try { - return await getSessionToken(url, props) - } catch (err) { - if (err && err.response && err.response.status === 404) { - // this 404s if running against new backend with username/password support removed - // wrap with appropriate error message - const message = 'username/password auth is no longer supported. Please create an ethereum identity.' - throw new AuthFetchError(message, err.response, err.body) - } - throw err - } -} - -export async function getUserInfo() { - this.debug('getUserInfo') - return authFetch(`${this.options.restUrl}/users/me`, this.session) -} - -export async function logoutEndpoint() { - this.debug('logoutEndpoint') - return authFetch(`${this.options.restUrl}/logout`, this.session, { - method: 'POST', - }) -} diff --git a/src/rest/LoginEndpoints.ts b/src/rest/LoginEndpoints.ts new file mode 100644 index 000000000..f67ec19e3 --- /dev/null +++ b/src/rest/LoginEndpoints.ts @@ -0,0 +1,126 @@ +import { StreamrClient } from '../StreamrClient' +import { getEndpointUrl } from '../utils' + +import authFetch, { AuthFetchError } from './authFetch' + +export interface UserDetails { + name: string + username: string + imageUrlSmall?: string + imageUrlLarge?: string + lastLogin?: string +} + +async function getSessionToken(url: string, props: any) { + return authFetch<{ token: string }>( + url, + undefined, + { + method: 'POST', + body: JSON.stringify(props), + headers: { + 'Content-Type': 'application/json', + }, + }, + ) +} + +/** TODO the class should be annotated with at-internal, but adding the annotation hides the methods */ +export class LoginEndpoints { + + /** @internal */ + client: StreamrClient + + constructor(client: StreamrClient) { + this.client = client + } + + /** @internal */ + async getChallenge(address: string) { + this.client.debug('getChallenge %o', { + address, + }) + const url = getEndpointUrl(this.client.options.restUrl, 'login', 'challenge', address) + return authFetch<{ challenge: string }>( + url, + undefined, + { + method: 'POST', + }, + ) + } + + /** @internal */ + async sendChallengeResponse(challenge: { challenge: string }, signature: string, address: string) { + this.client.debug('sendChallengeResponse %o', { + challenge, + signature, + address, + }) + const url = getEndpointUrl(this.client.options.restUrl, 'login', 'response') + const props = { + challenge, + signature, + address, + } + return getSessionToken(url, props) + } + + /** @internal */ + async loginWithChallengeResponse(signingFunction: (challenge: string) => Promise, address: string) { + this.client.debug('loginWithChallengeResponse %o', { + address, + }) + const challenge = await this.getChallenge(address) + const signature = await signingFunction(challenge.challenge) + return this.sendChallengeResponse(challenge, signature, address) + } + + /** @internal */ + async loginWithApiKey(apiKey: string) { + this.client.debug('loginWithApiKey %o', { + apiKey, + }) + const url = getEndpointUrl(this.client.options.restUrl, 'login', 'apikey') + const props = { + apiKey, + } + return getSessionToken(url, props) + } + + /** @internal */ + async loginWithUsernamePassword(username: string, password: string) { + this.client.debug('loginWithUsernamePassword %o', { + username, + }) + const url = getEndpointUrl(this.client.options.restUrl, 'login', 'password') + const props = { + username, + password, + } + try { + return await getSessionToken(url, props) + } catch (err) { + if (err && err.response && err.response.status === 404) { + // this 404s if running against new backend with username/password support removed + // wrap with appropriate error message + const message = 'username/password auth is no longer supported. Please create an ethereum identity.' + throw new AuthFetchError(message, err.response, err.body) + } + throw err + } + } + + async getUserInfo() { + this.client.debug('getUserInfo') + return authFetch(`${this.client.options.restUrl}/users/me`, this.client.session) + } + + /** @internal */ + async logoutEndpoint(): Promise { + this.client.debug('logoutEndpoint') + await authFetch(`${this.client.options.restUrl}/logout`, this.client.session, { + method: 'POST', + }) + } +} diff --git a/src/rest/StreamEndpoints.js b/src/rest/StreamEndpoints.js deleted file mode 100644 index 700a94138..000000000 --- a/src/rest/StreamEndpoints.js +++ /dev/null @@ -1,199 +0,0 @@ -import { Agent as HttpAgent } from 'http' -import { Agent as HttpsAgent } from 'https' - -import qs from 'qs' -import debugFactory from 'debug' - -import { getEndpointUrl } from '../utils' - -import Stream from './domain/Stream' -import authFetch from './authFetch' - -const debug = debugFactory('StreamrClient') - -const agentSettings = { - keepAlive: true, - keepAliveMsecs: 5000, -} - -const agentByProtocol = { - http: new HttpAgent(agentSettings), - https: new HttpsAgent(agentSettings), -} - -function getKeepAliveAgentForUrl(url) { - if (url.startsWith('https')) { - return agentByProtocol.https - } - - if (url.startsWith('http')) { - return agentByProtocol.http - } - - throw new Error(`Unknown protocol in URL: ${url}`) -} - -// These function are mixed in to StreamrClient.prototype. -// In the below functions, 'this' is intended to be the StreamrClient -export async function getStream(streamId) { - this.debug('getStream', { - streamId, - }) - const url = getEndpointUrl(this.options.restUrl, 'streams', streamId) - try { - const json = await authFetch(url, this.session) - return new Stream(this, json) - } catch (e) { - if (e.response && e.response.status === 404) { - return undefined - } - throw e - } -} - -export async function listStreams(query = {}) { - this.debug('listStreams', { - query, - }) - const url = getEndpointUrl(this.options.restUrl, 'streams') + '?' + qs.stringify(query) - const json = await authFetch(url, this.session) - return json ? json.map((stream) => new Stream(this, stream)) : [] -} - -export async function getStreamByName(name) { - this.debug('getStreamByName', { - name, - }) - const json = await this.listStreams({ - name, - public: false, - }) - return json[0] ? new Stream(this, json[0]) : undefined -} - -export async function createStream(props) { - this.debug('createStream', { - props, - }) - const json = await authFetch( - getEndpointUrl(this.options.restUrl, 'streams'), - this.session, - { - method: 'POST', - body: JSON.stringify(props), - }, - ) - return json ? new Stream(this, json) : undefined -} - -export async function getOrCreateStream(props) { - this.debug('getOrCreateStream', { - props, - }) - let json - - // Try looking up the stream by id or name, whichever is defined - if (props.id) { - json = await this.getStream(props.id) - } else if (props.name) { - json = await this.getStreamByName(props.name) - } - - // If not found, try creating the stream - if (!json) { - json = await this.createStream(props) - debug('Created stream: %s (%s)', props.name, json.id) - } - - // If still nothing, throw - if (!json) { - throw new Error(`Unable to find or create stream: ${props.name || props.id}`) - } else { - return new Stream(this, json) - } -} - -export async function getStreamPublishers(streamId) { - this.debug('getStreamPublishers', { - streamId, - }) - const url = getEndpointUrl(this.options.restUrl, 'streams', streamId, 'publishers') - const json = await authFetch(url, this.session) - return json.addresses.map((a) => a.toLowerCase()) -} - -export async function isStreamPublisher(streamId, ethAddress) { - this.debug('isStreamPublisher', { - streamId, - ethAddress, - }) - const url = getEndpointUrl(this.options.restUrl, 'streams', streamId, 'publisher', ethAddress) - try { - await authFetch(url, this.session) - return true - } catch (e) { - if (e.response && e.response.status === 404) { - return false - } - throw e - } -} - -export async function getStreamSubscribers(streamId) { - this.debug('getStreamSubscribers', { - streamId, - }) - const url = getEndpointUrl(this.options.restUrl, 'streams', streamId, 'subscribers') - const json = await authFetch(url, this.session) - return json.addresses.map((a) => a.toLowerCase()) -} - -export async function isStreamSubscriber(streamId, ethAddress) { - this.debug('isStreamSubscriber', { - streamId, - ethAddress, - }) - const url = getEndpointUrl(this.options.restUrl, 'streams', streamId, 'subscriber', ethAddress) - try { - await authFetch(url, this.session) - return true - } catch (e) { - if (e.response && e.response.status === 404) { - return false - } - throw e - } -} - -export async function getStreamValidationInfo(streamId) { - this.debug('getStreamValidationInfo', { - streamId, - }) - const url = getEndpointUrl(this.options.restUrl, 'streams', streamId, 'validation') - const json = await authFetch(url, this.session) - return json -} - -export async function publishHttp(streamObjectOrId, data, requestOptions = {}, keepAlive = true) { - let streamId - if (streamObjectOrId instanceof Stream) { - streamId = streamObjectOrId.id - } else { - streamId = streamObjectOrId - } - this.debug('publishHttp', { - streamId, data, - }) - - // Send data to the stream - return authFetch( - getEndpointUrl(this.options.restUrl, 'streams', streamId, 'data'), - this.session, - { - ...requestOptions, - method: 'POST', - body: JSON.stringify(data), - agent: keepAlive ? getKeepAliveAgentForUrl(this.options.restUrl) : undefined, - }, - ) -} diff --git a/src/rest/StreamEndpoints.ts b/src/rest/StreamEndpoints.ts new file mode 100644 index 000000000..cd5a0ca08 --- /dev/null +++ b/src/rest/StreamEndpoints.ts @@ -0,0 +1,280 @@ +import { Agent as HttpAgent } from 'http' +import { Agent as HttpsAgent } from 'https' + +import qs from 'qs' +import debugFactory from 'debug' + +import { getEndpointUrl } from '../utils' +import { validateOptions } from '../stream/utils' +import { Stream, StreamOperation, StreamProperties } from '../stream' +import StreamPart from '../stream/StreamPart' +import { isKeyExchangeStream } from '../stream/KeyExchange' + +import authFetch, { ErrorCode, NotFoundError } from './authFetch' +import { EthereumAddress } 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' + +const debug = debugFactory('StreamrClient') + +export interface StreamListQuery { + name?: string + uiChannel?: boolean + noConfig?: boolean + search?: string + sortBy?: string + order?: 'asc'|'desc' + max?: number + offset?: number + grantedAccess?: boolean + publicAccess?: boolean + operation?: StreamOperation +} + +export interface StreamValidationInfo { + partitions: number, + requireSignedData: boolean + requireEncryptedData: boolean +} + +export interface StreamMessageAsObject { // TODO this could be in streamr-protocol + streamId: string + streamPartition: number + timestamp: number + sequenceNumber: number + publisherId: string + msgChainId: string + messageType: StreamMessageType + contentType: ContentType + encryptionType: EncryptionType + groupKeyId: string|null + content: any + signatureType: SignatureType + signature: string|null +} + +const agentSettings = { + keepAlive: true, + keepAliveMsecs: 5000, +} + +const agentByProtocol = { + http: new HttpAgent(agentSettings), + https: new HttpsAgent(agentSettings), +} + +function getKeepAliveAgentForUrl(url: string) { + if (url.startsWith('https')) { + return agentByProtocol.https + } + + if (url.startsWith('http')) { + return agentByProtocol.http + } + + 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 { + + /** @internal */ + client: StreamrClient + + constructor(client: StreamrClient) { + this.client = client + } + + async getStream(streamId: string) { + this.client.debug('getStream %o', { + streamId, + }) + + if (isKeyExchangeStream(streamId)) { + return new Stream(this.client, { + id: streamId, + partitions: 1, + }) + } + + const url = getEndpointUrl(this.client.options.restUrl, 'streams', streamId) + const json = await authFetch(url, this.client.session) + return new Stream(this.client, json) + } + + async listStreams(query: StreamListQuery = {}): Promise { + this.client.debug('listStreams %o', { + query, + }) + const url = getEndpointUrl(this.client.options.restUrl, 'streams') + '?' + qs.stringify(query) + const json = await authFetch(url, this.client.session) + return json ? json.map((stream: StreamProperties) => new Stream(this.client, stream)) : [] + } + + async getStreamByName(name: string) { + this.client.debug('getStreamByName %o', { + name, + }) + const json = await this.listStreams({ + name, + // @ts-expect-error + public: false, + }) + return json[0] ? new Stream(this.client, json[0]) : Promise.reject(new NotFoundError('Stream: name=' + name)) + } + + async createStream(props?: Partial) { + this.client.debug('createStream %o', { + props, + }) + + const json = await authFetch( + getEndpointUrl(this.client.options.restUrl, 'streams'), + this.client.session, + { + method: 'POST', + body: JSON.stringify(props), + }, + ) + return new Stream(this.client, json) + } + + async getOrCreateStream(props: { id: string, name?: never } | { id?: never, name: string }) { + this.client.debug('getOrCreateStream %o', { + props, + }) + // Try looking up the stream by id or name, whichever is defined + try { + if (props.id) { + const stream = await this.getStream(props.id) + return stream + } + const stream = await this.getStreamByName(props.name!) + return stream + } catch (err: any) { + if (err.errorCode !== ErrorCode.NOT_FOUND) { + throw err + } + } + + const stream = await this.createStream(props) + debug('Created stream: %s (%s)', props.name, stream.id) + return stream + } + + async getStreamPublishers(streamId: string) { + this.client.debug('getStreamPublishers %o', { + streamId, + }) + const url = getEndpointUrl(this.client.options.restUrl, 'streams', streamId, 'publishers') + const json = await authFetch<{ addresses: string[]}>(url, this.client.session) + return json.addresses.map((a: string) => a.toLowerCase()) + } + + async isStreamPublisher(streamId: string, ethAddress: EthereumAddress) { + this.client.debug('isStreamPublisher %o', { + streamId, + ethAddress, + }) + const url = getEndpointUrl(this.client.options.restUrl, 'streams', streamId, 'publisher', ethAddress) + try { + await authFetch(url, this.client.session) + return true + } catch (e) { + this.client.debug(e) + if (e.response && e.response.status === 404) { + return false + } + throw e + } + } + + async getStreamSubscribers(streamId: string) { + this.client.debug('getStreamSubscribers %o', { + streamId, + }) + const url = getEndpointUrl(this.client.options.restUrl, 'streams', streamId, 'subscribers') + const json = await authFetch<{ addresses: string[] }>(url, this.client.session) + return json.addresses.map((a: string) => a.toLowerCase()) + } + + async isStreamSubscriber(streamId: string, ethAddress: EthereumAddress) { + this.client.debug('isStreamSubscriber %o', { + streamId, + ethAddress, + }) + const url = getEndpointUrl(this.client.options.restUrl, 'streams', streamId, 'subscriber', ethAddress) + try { + await authFetch(url, this.client.session) + return true + } catch (e) { + if (e.response && e.response.status === 404) { + return false + } + throw e + } + } + + async getStreamValidationInfo(streamId: string) { + this.client.debug('getStreamValidationInfo %o', { + streamId, + }) + const url = getEndpointUrl(this.client.options.restUrl, 'streams', streamId, 'validation') + const json = await authFetch(url, this.client.session) + return json + } + + async getStreamLast(streamObjectOrId: Stream|string): Promise { + // @ts-expect-error + const { streamId, streamPartition = 0, count = 1 } = validateOptions(streamObjectOrId) + this.client.debug('getStreamLast %o', { + streamId, + streamPartition, + count, + }) + + const url = ( + // @ts-expect-error + getEndpointUrl(this.client.options.restUrl, 'streams', streamId, 'data', 'partitions', streamPartition, 'last') + + `?${qs.stringify({ count })}` + ) + + const json = await authFetch(url, this.client.session) + return json + } + + 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[] = [] + json.forEach((stream: ItemType) => { + result = result.concat(StreamPart.fromStream(stream)) + }) + return result + } + + async publishHttp(streamObjectOrId: Stream|string, data: any, requestOptions: any = {}, keepAlive: boolean = true) { + let streamId + if (streamObjectOrId instanceof Stream) { + streamId = streamObjectOrId.id + } else { + streamId = streamObjectOrId + } + this.client.debug('publishHttp %o', { + streamId, data, + }) + + // Send data to the stream + await authFetch( + getEndpointUrl(this.client.options.restUrl, 'streams', streamId, 'data'), + this.client.session, + { + ...requestOptions, + method: 'POST', + body: JSON.stringify(data), + agent: keepAlive ? getKeepAliveAgentForUrl(this.client.options.restUrl!) : undefined, + }, + ) + } +} diff --git a/src/rest/authFetch.js b/src/rest/authFetch.js deleted file mode 100644 index 54fa359b8..000000000 --- a/src/rest/authFetch.js +++ /dev/null @@ -1,53 +0,0 @@ -import fetch from 'node-fetch' -import debugFactory from 'debug' - -import AuthFetchError from '../errors/AuthFetchError' -import { getVersionString } from '../utils' - -export const DEFAULT_HEADERS = { - 'Streamr-Client': `streamr-client-javascript/${getVersionString()}`, -} - -const debug = debugFactory('StreamrClient:utils') - -const authFetch = async (url, session, opts = {}, requireNewToken = false) => { - const options = { - ...opts, - headers: { - ...DEFAULT_HEADERS, - ...opts.headers, - } - } - // add default 'Content-Type: application/json' header for all POST and PUT requests - if (!options.headers['Content-Type'] && (options.method === 'POST' || options.method === 'PUT')) { - options.headers['Content-Type'] = 'application/json' - } - - debug('authFetch: ', url, opts) - - const response = await fetch(url, { - ...opts, - headers: { - ...(session && !session.options.unauthenticated ? { - Authorization: `Bearer ${await session.getSessionToken(requireNewToken)}`, - } : {}), - ...options.headers, - }, - }) - - const body = await response.text() - - if (response.ok) { - try { - return JSON.parse(body || '{}') - } catch (e) { - throw new AuthFetchError(e.message, response, body) - } - } else if ([400, 401].includes(response.status) && !requireNewToken) { - return authFetch(url, session, options, true) - } else { - throw new AuthFetchError(`Request to ${url} returned with error code ${response.status}.`, response, body) - } -} - -export default authFetch diff --git a/src/rest/authFetch.ts b/src/rest/authFetch.ts new file mode 100644 index 000000000..f38acb6a2 --- /dev/null +++ b/src/rest/authFetch.ts @@ -0,0 +1,120 @@ +import fetch, { Response } from 'node-fetch' +import Debug from 'debug' + +import { getVersionString } from '../utils' +import Session from '../Session' + +export enum ErrorCode { + NOT_FOUND = 'NOT_FOUND', + VALIDATION_ERROR = 'VALIDATION_ERROR', + UNKNOWN = 'UNKNOWN' +} + +export const DEFAULT_HEADERS = { + 'Streamr-Client': `streamr-client-javascript/${getVersionString()}`, +} + +export class AuthFetchError extends Error { + response?: Response + body?: any + errorCode: ErrorCode + + constructor(message: string, response?: Response, body?: any, errorCode?: ErrorCode) { + const typePrefix = errorCode ? errorCode + ': ' : '' + // add leading space if there is a body set + const bodyMessage = body ? ` ${(typeof body === 'string' ? body : JSON.stringify(body).slice(0, 1024))}...` : '' + super(typePrefix + message + bodyMessage) + this.response = response + this.body = body + this.errorCode = errorCode || ErrorCode.UNKNOWN + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor) + } + } +} + +export class ValidationError extends AuthFetchError { + constructor(message: string, response?: Response, body?: any) { + super(message, response, body, ErrorCode.VALIDATION_ERROR) + } +} + +export class NotFoundError extends AuthFetchError { + constructor(message: string, response?: Response, body?: any) { + super(message, response, body, ErrorCode.NOT_FOUND) + } +} + +const ERROR_TYPES = new Map() +ERROR_TYPES.set(ErrorCode.VALIDATION_ERROR, ValidationError) +ERROR_TYPES.set(ErrorCode.NOT_FOUND, NotFoundError) +ERROR_TYPES.set(ErrorCode.UNKNOWN, AuthFetchError) + +const parseErrorCode = (body: string) => { + let json + try { + json = JSON.parse(body) + } catch (err) { + return ErrorCode.UNKNOWN + } + const { code } = json + return code in ErrorCode ? code : ErrorCode.UNKNOWN +} + +const debug = Debug('StreamrClient:utils:authfetch') // TODO: could use the debug instance from the client? (e.g. client.debug.extend('authFetch')) + +let ID = 0 + +/** @internal */ +export default async function authFetch(url: string, session?: Session, opts?: any, requireNewToken = false): Promise { + ID += 1 + const timeStart = Date.now() + const id = ID + + const options = { + ...opts, + headers: { + ...DEFAULT_HEADERS, + ...(opts && opts.headers), + }, + } + // add default 'Content-Type: application/json' header for all POST and PUT requests + if (!options.headers['Content-Type'] && (options.method === 'POST' || options.method === 'PUT')) { + options.headers['Content-Type'] = 'application/json' + } + + debug('%d %s >> %o', id, url, opts) + + const response: Response = await fetch(url, { + ...opts, + headers: { + ...(session && !session.options.unauthenticated ? { + Authorization: `Bearer ${await session.getSessionToken(requireNewToken)}`, + } : {}), + ...options.headers, + }, + }) + const timeEnd = Date.now() + // @ts-expect-error + debug('%d %s << %d %s %s %s', id, url, response.status, response.statusText, Debug.humanize(timeEnd - timeStart)) + + const body = await response.text() + + if (response.ok) { + try { + return JSON.parse(body || '{}') + } catch (e) { + debug('%d %s – failed to parse body: %s', id, url, e.stack) + throw new AuthFetchError(e.message, response, body) + } + } else if ([400, 401].includes(response.status) && !requireNewToken) { + debug('%d %s – revalidating session') + return authFetch(url, session, options, true) + } else { + debug('%d %s – failed', id, url) + const errorCode = parseErrorCode(body) + const ErrorClass = ERROR_TYPES.get(errorCode)! + throw new ErrorClass(`Request ${id} to ${url} returned with error code ${response.status}.`, response, body, errorCode) + } +} diff --git a/src/rest/domain/Stream.js b/src/rest/domain/Stream.js deleted file mode 100644 index 132027f04..000000000 --- a/src/rest/domain/Stream.js +++ /dev/null @@ -1,115 +0,0 @@ -import { getEndpointUrl } from '../../utils' -import authFetch from '../authFetch' - -export default class Stream { - constructor(client, props) { - this._client = client - Object.assign(this, props) - } - - async update() { - const json = await authFetch( - getEndpointUrl(this._client.options.restUrl, 'streams', this.id), - this._client.session, - { - method: 'PUT', - body: JSON.stringify(this.toObject()), - }, - ) - return json ? new Stream(this._client, json) : undefined - } - - toObject() { - const result = {} - Object.keys(this).forEach((key) => { - if (!key.startsWith('_')) { - result[key] = this[key] - } - }) - return result - } - - async delete() { - return authFetch( - getEndpointUrl(this._client.options.restUrl, 'streams', this.id), - this._client.session, - { - method: 'DELETE', - }, - ) - } - - async getPermissions() { - return authFetch( - getEndpointUrl(this._client.options.restUrl, 'streams', this.id, 'permissions'), - this._client.session, - ) - } - - async getMyPermissions() { - return authFetch( - getEndpointUrl(this._client.options.restUrl, 'streams', this.id, 'permissions', 'me'), - this._client.session, - ) - } - - async hasPermission(operation, userId) { - // eth addresses may be in checksumcase, but userId from server has no case - - const userIdCaseInsensitive = typeof userId === 'string' ? userId.toLowerCase() : undefined // if not string then undefined - const permissions = await this.getPermissions() - - return permissions.find((p) => { - if (p.operation !== operation) { return false } - - if (userIdCaseInsensitive === undefined) { - return !!p.anonymous // match nullish userId against p.anonymous - } - return p.user && p.user.toLowerCase() === userIdCaseInsensitive // match against userId - }) - } - - async grantPermission(operation, userId) { - const permissionObject = { - operation, - } - - const userIdCaseInsensitive = typeof userId === 'string' ? userId.toLowerCase() : undefined - - if (userIdCaseInsensitive !== undefined) { - permissionObject.user = userIdCaseInsensitive - } else { - permissionObject.anonymous = true - } - - return authFetch( - getEndpointUrl(this._client.options.restUrl, 'streams', this.id, 'permissions'), - this._client.session, - { - method: 'POST', - body: JSON.stringify(permissionObject), - }, - ) - } - - async revokePermission(permissionId) { - return authFetch( - getEndpointUrl(this._client.options.restUrl, 'streams', this.id, 'permissions', permissionId), - this._client.session, - { - method: 'DELETE', - }, - ) - } - - async detectFields() { - return authFetch( - getEndpointUrl(this._client.options.restUrl, 'streams', this.id, 'detectFields'), - this._client.session, - ) - } - - async publish(...theArgs) { - return this._client.publish(this.id, ...theArgs) - } -} diff --git a/src/shim/ws.js b/src/shim/ws.js index c088e1fdc..ba3be47a6 100644 --- a/src/shim/ws.js +++ b/src/shim/ws.js @@ -1,4 +1,6 @@ // NB: THIS FILE MUST BE IN ES5 // In browsers, the ws package is replaced with this to use native websockets -export default typeof WebSocket !== 'undefined' ? WebSocket : window.WebSocket +export default typeof WebSocket !== 'undefined' ? WebSocket : function WebsocketWrap(url) { + return new window.WebSocket(url) +} diff --git a/src/stream/Encryption.js b/src/stream/Encryption.js new file mode 100644 index 000000000..d3b2771f1 --- /dev/null +++ b/src/stream/Encryption.js @@ -0,0 +1,347 @@ +import crypto from 'crypto' +import util from 'util' + +// this is shimmed out for actual browser build allows us to run tests in node against browser API +import { Crypto } from 'node-webcrypto-ossl' +import { arrayify, hexlify } from '@ethersproject/bytes' +import { MessageLayer } from 'streamr-client-protocol' + +import { uuid } from '../utils' + +export class UnableToDecryptError extends Error { + constructor(message = '', streamMessage) { + super(`Unable to decrypt. ${message} ${util.inspect(streamMessage)}`) + this.streamMessage = streamMessage + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor) + } + } +} + +class InvalidGroupKeyError extends Error { + constructor(message, groupKey) { + super(message) + this.groupKey = groupKey + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor) + } + } +} + +export class GroupKey { + static InvalidGroupKeyError = InvalidGroupKeyError + + static validate(maybeGroupKey) { + if (!maybeGroupKey) { + throw new InvalidGroupKeyError(`value must be a ${this.name}: ${util.inspect(maybeGroupKey)}`) + } + + if (!(maybeGroupKey instanceof this)) { + throw new InvalidGroupKeyError(`value must be a ${this.name}: ${util.inspect(maybeGroupKey)}`) + } + + if (!maybeGroupKey.id || typeof maybeGroupKey.id !== 'string') { + throw new InvalidGroupKeyError(`${this.name} id must be a string: ${util.inspect(maybeGroupKey)}`) + } + + if (!maybeGroupKey.data || !Buffer.isBuffer(maybeGroupKey.data)) { + throw new InvalidGroupKeyError(`${this.name} data must be a buffer: ${util.inspect(maybeGroupKey)}`) + } + + if (!maybeGroupKey.hex || typeof maybeGroupKey.hex !== 'string') { + throw new InvalidGroupKeyError(`${this.name} hex must be a string: ${util.inspect(maybeGroupKey)}`) + } + + if (maybeGroupKey.data.length !== 32) { + throw new InvalidGroupKeyError(`Group key must have a size of 256 bits, not ${maybeGroupKey.data.length * 8}`) + } + } + + constructor(groupKeyId, groupKeyBufferOrHexString) { + this.id = groupKeyId + if (!groupKeyId) { + throw new InvalidGroupKeyError(`groupKeyId must not be falsey ${util.inspect(groupKeyId)}`) + } + + if (!groupKeyBufferOrHexString) { + throw new InvalidGroupKeyError(`groupKeyBufferOrHexString must not be falsey ${util.inspect(groupKeyBufferOrHexString)}`) + } + + if (typeof groupKeyBufferOrHexString === 'string') { + this.hex = groupKeyBufferOrHexString + this.data = Buffer.from(this.hex, 'hex') + } else { + this.data = groupKeyBufferOrHexString + this.hex = Buffer.from(this.data).toString('hex') + } + + this.constructor.validate(this) + } + + equals(other) { + if (!(other instanceof GroupKey)) { + return false + } + + return this === other || (this.hex === other.hex && this.id === other.id) + } + + toString() { + return this.id + } + + static generate(id = uuid('GroupKey')) { + const keyBytes = crypto.randomBytes(32) + return new GroupKey(id, keyBytes) + } + + static from(maybeGroupKey) { + if (!maybeGroupKey || typeof maybeGroupKey !== 'object') { + throw new InvalidGroupKeyError(`Group key must be object ${util.inspect(maybeGroupKey)}`) + } + + if (maybeGroupKey instanceof GroupKey) { + return maybeGroupKey + } + + try { + return new GroupKey(maybeGroupKey.id || maybeGroupKey.groupKeyId, maybeGroupKey.hex || maybeGroupKey.data || maybeGroupKey.groupKeyHex) + } catch (err) { + if (err instanceof InvalidGroupKeyError) { + // wrap err with logging of original object + throw new InvalidGroupKeyError(`${err.message}. From: ${util.inspect(maybeGroupKey)}`) + } + throw err + } + } +} + +const { StreamMessage } = MessageLayer + +function ab2str(buf) { + return String.fromCharCode.apply(null, new Uint8Array(buf)) +} + +// shim browser btoa for node +function btoa(str) { + if (global.btoa) { return global.btoa(str) } + let buffer + + if (str instanceof Buffer) { + buffer = str + } else { + buffer = Buffer.from(str.toString(), 'binary') + } + + return buffer.toString('base64') +} + +async function exportCryptoKey(key, { isPrivate = false } = {}) { + const WebCrypto = new Crypto() + const keyType = isPrivate ? 'pkcs8' : 'spki' + const exported = await WebCrypto.subtle.exportKey(keyType, key) + const exportedAsString = ab2str(exported) + const exportedAsBase64 = btoa(exportedAsString) + const TYPE = isPrivate ? 'PRIVATE' : 'PUBLIC' + return `-----BEGIN ${TYPE} KEY-----\n${exportedAsBase64}\n-----END ${TYPE} KEY-----\n` +} + +// put all static functions into EncryptionUtilBase, with exception of create, +// so it's clearer what the static & instance APIs look like +class EncryptionUtilBase { + static validatePublicKey(publicKey) { + if (typeof publicKey !== 'string' || !publicKey.startsWith('-----BEGIN PUBLIC KEY-----') + || !publicKey.endsWith('-----END PUBLIC KEY-----\n')) { + throw new Error('"publicKey" must be a PKCS#8 RSA public key as a string in the PEM format') + } + } + + static validatePrivateKey(privateKey) { + if (typeof privateKey !== 'string' || !privateKey.startsWith('-----BEGIN PRIVATE KEY-----') + || !privateKey.endsWith('-----END PRIVATE KEY-----\n')) { + throw new Error('"privateKey" must be a PKCS#8 RSA public key as a string in the PEM format') + } + } + + static validateGroupKey(groupKey) { + return GroupKey.validate(groupKey) + } + + /* + * Returns a Buffer or a hex String + */ + static encryptWithPublicKey(plaintextBuffer, publicKey, outputInHex = false) { + this.validatePublicKey(publicKey) + const ciphertextBuffer = crypto.publicEncrypt(publicKey, plaintextBuffer) + if (outputInHex) { + return hexlify(ciphertextBuffer).slice(2) + } + return ciphertextBuffer + } + + /* + * Both 'data' and 'groupKey' must be Buffers. Returns a hex string without the '0x' prefix. + */ + static encrypt(data, groupKey) { + GroupKey.validate(groupKey) + const iv = crypto.randomBytes(16) // always need a fresh IV when using CTR mode + const cipher = crypto.createCipheriv('aes-256-ctr', groupKey.data, iv) + return hexlify(iv).slice(2) + cipher.update(data, null, 'hex') + cipher.final('hex') + } + + /* + * 'ciphertext' must be a hex string (without '0x' prefix), 'groupKey' must be a Buffer. Returns a Buffer. + */ + static decrypt(ciphertext, groupKey) { + GroupKey.validate(groupKey) + const iv = arrayify(`0x${ciphertext.slice(0, 32)}`) + const decipher = crypto.createDecipheriv('aes-256-ctr', groupKey.data, iv) + return Buffer.concat([decipher.update(ciphertext.slice(32), 'hex', null), decipher.final(null)]) + } + + /* + * Sets the content of 'streamMessage' with the encryption result of the old content with 'groupKey'. + */ + + static encryptStreamMessage(streamMessage, groupKey) { + GroupKey.validate(groupKey) + /* eslint-disable no-param-reassign */ + streamMessage.encryptionType = StreamMessage.ENCRYPTION_TYPES.AES + streamMessage.groupKeyId = groupKey.id + streamMessage.serializedContent = this.encrypt(Buffer.from(streamMessage.getSerializedContent(), 'utf8'), groupKey) + streamMessage.parsedContent = undefined + /* eslint-enable no-param-reassign */ + } + + /* + * Decrypts the serialized content of 'streamMessage' with 'groupKey'. If the resulting plaintext is the concatenation + * of a new group key and a message content, sets the content of 'streamMessage' with that message content and returns + * the key. If the resulting plaintext is only a message content, sets the content of 'streamMessage' with that + * message content and returns null. + */ + + static decryptStreamMessage(streamMessage, groupKey) { + if ((streamMessage.encryptionType !== StreamMessage.ENCRYPTION_TYPES.AES)) { + return null + } + + try { + GroupKey.validate(groupKey) + } catch (err) { + throw new UnableToDecryptError(`${err.message}`, streamMessage) + } + + /* eslint-disable no-param-reassign */ + try { + streamMessage.encryptionType = StreamMessage.ENCRYPTION_TYPES.NONE + const serializedContent = this.decrypt(streamMessage.getSerializedContent(), groupKey).toString() + streamMessage.parsedContent = JSON.parse(serializedContent) + streamMessage.serializedContent = serializedContent + } catch (err) { + streamMessage.encryptionType = StreamMessage.ENCRYPTION_TYPES.AES + throw new UnableToDecryptError(err.message, streamMessage) + } + return null + /* eslint-enable no-param-reassign */ + } +} + +/** @internal */ +export default class EncryptionUtil extends EncryptionUtilBase { + /** + * Creates a new instance + waits for ready. + * Convenience. + */ + + static async create(...args) { + const encryptionUtil = new EncryptionUtil(...args) + await encryptionUtil.onReady() + return encryptionUtil + } + + constructor(options = {}) { + super(options) + if (options.privateKey && options.publicKey) { + EncryptionUtil.validatePrivateKey(options.privateKey) + EncryptionUtil.validatePublicKey(options.publicKey) + this.privateKey = options.privateKey + this.publicKey = options.publicKey + } + } + + async onReady() { + if (this.isReady()) { return undefined } + return this._generateKeyPair() + } + + isReady() { + return !!this.privateKey + } + + // Returns a Buffer + decryptWithPrivateKey(ciphertext, isHexString = false) { + if (!this.isReady()) { throw new Error('EncryptionUtil not ready.') } + let ciphertextBuffer = ciphertext + if (isHexString) { + ciphertextBuffer = arrayify(`0x${ciphertext}`) + } + return crypto.privateDecrypt(this.privateKey, ciphertextBuffer) + } + + // Returns a String (base64 encoding) + getPublicKey() { + if (!this.isReady()) { throw new Error('EncryptionUtil not ready.') } + return this.publicKey + } + + async _generateKeyPair() { + if (!this._generateKeyPairPromise) { + this._generateKeyPairPromise = this.__generateKeyPair() + } + return this._generateKeyPairPromise + } + + async __generateKeyPair() { + if (process.browser) { return this._keyPairBrowser() } + return this._keyPairServer() + } + + async _keyPairServer() { + const generateKeyPair = util.promisify(crypto.generateKeyPair) + const { publicKey, privateKey } = await generateKeyPair('rsa', { + modulusLength: 4096, + publicKeyEncoding: { + type: 'spki', + format: 'pem', + }, + privateKeyEncoding: { + type: 'pkcs8', + format: 'pem', + }, + }) + + this.privateKey = privateKey + this.publicKey = publicKey + } + + async _keyPairBrowser() { + const WebCrypto = new Crypto() + const { publicKey, privateKey } = await WebCrypto.subtle.generateKey({ + name: 'RSA-OAEP', + modulusLength: 4096, + publicExponent: new Uint8Array([1, 0, 1]), // 65537 + hash: 'SHA-256' + }, true, ['encrypt', 'decrypt']) + + const [exportedPrivate, exportedPublic] = await Promise.all([ + exportCryptoKey(privateKey, { + isPrivate: true, + }), + exportCryptoKey(publicKey, { + isPrivate: false, + }) + ]) + this.privateKey = exportedPrivate + this.publicKey = exportedPublic + } +} diff --git a/src/stream/KeyExchange.js b/src/stream/KeyExchange.js new file mode 100644 index 000000000..159c5ea6e --- /dev/null +++ b/src/stream/KeyExchange.js @@ -0,0 +1,548 @@ +import { MessageLayer, Errors } from 'streamr-client-protocol' +import mem from 'mem' + +import { uuid, Defer } from '../utils' +import Scaffold from '../utils/Scaffold' + +import { validateOptions } from './utils' +import EncryptionUtil, { GroupKey } from './Encryption' + +const { + StreamMessage, GroupKeyRequest, GroupKeyResponse, GroupKeyErrorResponse, EncryptedGroupKey +} = MessageLayer + +const KEY_EXCHANGE_STREAM_PREFIX = 'SYSTEM/keyexchange' + +const { ValidationError } = Errors + +export function isKeyExchangeStream(id = '') { + return id.startsWith(KEY_EXCHANGE_STREAM_PREFIX) +} + +class InvalidGroupKeyRequestError extends ValidationError { + constructor(...args) { + super(...args) + this.code = 'INVALID_GROUP_KEY_REQUEST' + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor) + } + } +} + +/* +class InvalidGroupKeyResponseError extends Error { + constructor(...args) { + super(...args) + this.code = 'INVALID_GROUP_KEY_RESPONSE' + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor) + } + } +} + +class InvalidContentTypeError extends Error { + constructor(...args) { + super(...args) + this.code = 'INVALID_MESSAGE_TYPE' + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor) + } + } +} +*/ + +function getKeyExchangeStreamId(address) { + if (isKeyExchangeStream(address)) { + return address // prevent ever double-handling + } + return `${KEY_EXCHANGE_STREAM_PREFIX}/${address.toLowerCase()}` +} + +function GroupKeyStore({ groupKeys }) { + const store = new Map(groupKeys) + + let currentGroupKeyId // current key id if any + let nextGroupKey // key to use next, disappears if not actually used. + + store.forEach((groupKey) => { + GroupKey.validate(groupKey) + // use last init key as current + currentGroupKeyId = groupKey.id + }) + + function storeKey(groupKey) { + GroupKey.validate(groupKey) + if (store.has(groupKey.id)) { + const existingKey = store.get(groupKey.id) + if (!existingKey.equals(groupKey)) { + throw new GroupKey.InvalidGroupKeyError( + `Trying to add groupKey ${groupKey.id} but key exists & is not equivalent to new GroupKey: ${groupKey}.` + ) + } + + store.delete(groupKey.id) // sort key at end by deleting existing entry before re-adding + store.set(groupKey.id, existingKey) // reuse existing instance + return existingKey + } + + store.set(groupKey.id, groupKey) + return groupKey + } + + return { + has(id) { + if (currentGroupKeyId === id) { return true } + + if (nextGroupKey && nextGroupKey.id === id) { return true } + + return store.has(id) + }, + isEmpty() { + return !nextGroupKey && store.size === 0 + }, + useGroupKey() { + if (nextGroupKey) { + // next key becomes current key + storeKey(nextGroupKey) + + currentGroupKeyId = nextGroupKey.id + nextGroupKey = undefined + } + + if (!currentGroupKeyId) { + // generate & use key if none already set + this.rotateGroupKey() + return this.useGroupKey() + } + + return store.get(currentGroupKeyId) + }, + get(id) { + return store.get(id) + }, + clear() { + currentGroupKeyId = undefined + nextGroupKey = undefined + return store.clear() + }, + rotateGroupKey() { + return this.setNextGroupKey(GroupKey.generate()) + }, + add(groupKey) { + return storeKey(groupKey) + }, + setNextGroupKey(newKey) { + GroupKey.validate(newKey) + nextGroupKey = newKey + } + } +} + +function parseGroupKeys(groupKeys = {}) { + return new Map(Object.entries(groupKeys || {}).map(([key, value]) => { + if (!value || !key) { return null } + return [key, GroupKey.from(value)] + }).filter(Boolean)) +} + +function waitForSubMessage(sub, matchFn) { + const task = Defer() + const onMessage = (content, streamMessage) => { + try { + if (matchFn(content, streamMessage)) { + task.resolve(streamMessage) + } + } catch (err) { + task.reject(err) + } + } + sub.on('message', onMessage) + sub.once('error', task.reject) + // eslint-disable-next-line promise/catch-or-return + task.finally(() => { + sub.off('message', onMessage) + sub.off('error', task.reject) + }) + return task +} + +async function subscribeToKeyExchangeStream(client, onKeyExchangeMessage) { + const { options } = client + if ((!options.auth.privateKey && !options.auth.ethereum) || !options.keyExchange) { + return Promise.resolve() + } + + await client.session.getSessionToken() // trigger auth errors if any + // subscribing to own keyexchange stream + const publisherId = await client.getUserId() + const streamId = getKeyExchangeStreamId(publisherId) + return client.subscribe(streamId, onKeyExchangeMessage) +} + +async function catchKeyExchangeError(client, streamMessage, fn) { + try { + return await fn() + } catch (error) { + const subscriberId = streamMessage.getPublisherId() + const msg = streamMessage.getParsedContent() + const { streamId, requestId, groupKeyIds } = GroupKeyRequest.fromArray(msg) + return client.publish(getKeyExchangeStreamId(subscriberId), new GroupKeyErrorResponse({ + requestId, + streamId, + errorCode: error.code || 'UNEXPECTED_ERROR', + errorMessage: error.message, + groupKeyIds + })) + } +} + +async function PublisherKeyExhangeSubscription(client, getGroupKeyStore) { + async function onKeyExchangeMessage(parsedContent, streamMessage) { + return catchKeyExchangeError(client, streamMessage, async () => { + if (streamMessage.messageType !== StreamMessage.MESSAGE_TYPES.GROUP_KEY_REQUEST) { + return Promise.resolve() + } + + // No need to check if parsedContent contains the necessary fields because it was already checked during deserialization + const { requestId, streamId, rsaPublicKey, groupKeyIds } = GroupKeyRequest.fromArray(streamMessage.getParsedContent()) + + const subscriberId = streamMessage.getPublisherId() + + const groupKeyStore = getGroupKeyStore(streamId) + const encryptedGroupKeys = groupKeyIds.map((id) => { + const groupKey = groupKeyStore.get(id) + if (!groupKey) { + return null // will be filtered out + } + + return new EncryptedGroupKey(id, EncryptionUtil.encryptWithPublicKey(groupKey.data, rsaPublicKey, true)) + }).filter(Boolean) + + client.debug('Publisher: Subscriber requested groupKeys: %d. Got: %d. %o', groupKeyIds.length, encryptedGroupKeys.length, { + subscriberId, + groupKeyIds, + responseKeys: encryptedGroupKeys.map(({ groupKeyId }) => groupKeyId), + }) + + const response = new GroupKeyResponse({ + streamId, + requestId, + encryptedGroupKeys, + encryptionType: StreamMessage.ENCRYPTION_TYPES.RSA, + }) + + // hack overriding toStreamMessage method to set correct encryption type + const toStreamMessage = response.toStreamMessage.bind(response) + response.toStreamMessage = (...args) => { + const msg = toStreamMessage(...args) + msg.encryptionType = StreamMessage.ENCRYPTION_TYPES.RSA + return msg + } + + return client.publish(getKeyExchangeStreamId(subscriberId), response) + }) + } + + const sub = await subscribeToKeyExchangeStream(client, onKeyExchangeMessage) + sub.on('error', (err) => { + if (!err.streamMessage) { + return // do nothing + } + + // wrap error and translate into ErrorResponse. + catchKeyExchangeError(client, err.streamMessage, () => { // eslint-disable-line promise/no-promise-in-callback + // rethrow so catchKeyExchangeError handles it + throw new InvalidGroupKeyRequestError(err.message, err.streamMessage) + }).catch((unexpectedError) => { + sub.emit('error', unexpectedError) + }) + }) + + return sub +} + +export function PublisherKeyExhange(client, { groupKeys = {} } = {}) { + let enabled = true + const getGroupKeyStore = mem((streamId) => GroupKeyStore({ + groupKeys: parseGroupKeys(groupKeys[streamId]) + }), { + cacheKey([maybeStreamId]) { + const { streamId } = validateOptions(maybeStreamId) + return streamId + } + }) + let sub + const next = Scaffold([ + async () => { + sub = await PublisherKeyExhangeSubscription(client, getGroupKeyStore) + return async () => { + if (!sub) { return } + const cancelTask = sub.cancel() + sub = undefined + await cancelTask() + } + } + ], () => enabled) + + function rotateGroupKey(streamId) { + if (!enabled) { return } + const groupKeyStore = getGroupKeyStore(streamId) + groupKeyStore.rotateGroupKey() + } + + function setNextGroupKey(streamId, groupKey) { + if (!enabled) { return } + const groupKeyStore = getGroupKeyStore(streamId) + + groupKeyStore.setNextGroupKey(groupKey) + } + + async function useGroupKey(streamId) { + await next() + if (!enabled) { return undefined } + const groupKeyStore = getGroupKeyStore(streamId) + + return groupKeyStore.useGroupKey() + } + + function hasAnyGroupKey(streamId) { + const groupKeyStore = getGroupKeyStore(streamId) + return !groupKeyStore.isEmpty() + } + + return { + setNextGroupKey, + useGroupKey, + rotateGroupKey, + hasAnyGroupKey, + async start() { + enabled = true + return next() + }, + async stop() { + enabled = false + return next() + } + } +} + +async function getGroupKeysFromStreamMessage(streamMessage, encryptionUtil) { + const { encryptedGroupKeys } = GroupKeyResponse.fromArray(streamMessage.getParsedContent()) + return Promise.all(encryptedGroupKeys.map(async (encryptedGroupKey) => ( + new GroupKey(encryptedGroupKey.groupKeyId, await encryptionUtil.decryptWithPrivateKey(encryptedGroupKey.encryptedGroupKeyHex, true)) + ))) +} + +async function SubscriberKeyExhangeSubscription(client, getGroupKeyStore, encryptionUtil) { + let sub + async function onKeyExchangeMessage(parsedContent, streamMessage) { + try { + const { messageType } = streamMessage + const { MESSAGE_TYPES } = StreamMessage + if (messageType !== MESSAGE_TYPES.GROUP_KEY_ANNOUNCE) { + return + } + + const groupKeys = await getGroupKeysFromStreamMessage(streamMessage, encryptionUtil) + const groupKeyStore = getGroupKeyStore(streamMessage.getStreamId()) + groupKeys.forEach((groupKey) => { + groupKeyStore.add(groupKey) + }) + } catch (err) { + sub.emit('error', err) + } + } + + sub = await subscribeToKeyExchangeStream(client, onKeyExchangeMessage) + return sub +} + +export function SubscriberKeyExchange(client, { groupKeys = {} } = {}) { + let enabled = true + const encryptionUtil = new EncryptionUtil(client.options.keyExchange) + + const getGroupKeyStore = mem((streamId) => GroupKeyStore({ + groupKeys: parseGroupKeys(groupKeys[streamId]) + }), { + cacheKey([maybeStreamId]) { + const { streamId } = validateOptions(maybeStreamId) + return streamId + } + }) + + let sub + + async function requestKeys({ streamId, publisherId, groupKeyIds }) { + let done = false + const requestId = uuid('GroupKeyRequest') + const rsaPublicKey = encryptionUtil.getPublicKey() + const keyExchangeStreamId = getKeyExchangeStreamId(publisherId) + let responseTask + let cancelTask + let receivedGroupKeys = [] + let response + const step = Scaffold([ + async () => { + cancelTask = Defer() + responseTask = waitForSubMessage(sub, (content, streamMessage) => { + const { messageType } = streamMessage + const matchesMessageType = ( + messageType === StreamMessage.MESSAGE_TYPES.GROUP_KEY_RESPONSE + || messageType === StreamMessage.MESSAGE_TYPES.GROUP_KEY_ERROR_RESPONSE + ) + + if (!matchesMessageType) { + return false + } + + const groupKeyResponse = GroupKeyResponse.fromArray(content) + return groupKeyResponse.requestId === requestId + }) + + cancelTask.then(responseTask.resolve).catch(responseTask.reject) + return () => { + cancelTask.resolve({}) + } + }, async () => { + const msg = new GroupKeyRequest({ + streamId, + requestId, + rsaPublicKey, + groupKeyIds, + }) + await client.publish(keyExchangeStreamId, msg) + }, async () => { + response = await responseTask + return () => { + response = undefined + } + }, async () => { + receivedGroupKeys = await getGroupKeysFromStreamMessage(response, encryptionUtil) + + return () => { + receivedGroupKeys = [] + } + }, + ], () => enabled && !done, { + onChange(isGoingUp) { + if (!isGoingUp && cancelTask) { + cancelTask.resolve({}) + } + } + }) + + requestKeys.step = step + await step() + const keys = receivedGroupKeys.slice() + done = true + await step() + return keys + } + + const pending = new Map() + const getBuffer = mem(() => []) + const timeouts = {} + + async function getKey(streamMessage) { + const streamId = streamMessage.getStreamId() + const publisherId = streamMessage.getPublisherId() + const { groupKeyId } = streamMessage + if (!groupKeyId) { + return Promise.resolve() + } + const groupKeyStore = getGroupKeyStore(streamId) + if (groupKeyStore.has(groupKeyId)) { + return groupKeyStore.get(groupKeyId) + } + + if (pending.has(groupKeyId)) { + return pending.get(groupKeyId) + } + + const key = `${streamId}.${publisherId}` + const buffer = getBuffer(key) + buffer.push(groupKeyId) + pending.set(groupKeyId, Defer()) + + async function processBuffer() { + const currentBuffer = getBuffer(key) + const groupKeyIds = currentBuffer.slice() + currentBuffer.length = 0 + try { + const receivedGroupKeys = await requestKeys({ + streamId, + publisherId, + groupKeyIds, + }) + receivedGroupKeys.forEach((groupKey) => { + groupKeyStore.add(groupKey) + }) + groupKeyIds.forEach((id) => { + if (!pending.has(id)) { return } + const groupKey = groupKeyStore.get(id) + const task = pending.get(id) + pending.delete(id) + task.resolve(groupKey) + }) + } catch (err) { + groupKeyIds.forEach((id) => { + if (!pending.has(id)) { return } + const task = pending.get(id) + pending.delete(id) + task.reject(err) + }) + } + } + + if (!timeouts[key]) { + timeouts[key] = setTimeout(() => { + delete timeouts[key] + processBuffer() + }, 1000) + } + + return pending.get(groupKeyId) + } + + const next = Scaffold([ + async () => { + [sub] = await Promise.all([ + SubscriberKeyExhangeSubscription(client, getGroupKeyStore, encryptionUtil), + encryptionUtil.onReady(), + ]) + return async () => { + mem.clear(getGroupKeyStore) + if (!sub) { return } + const cancelTask = sub.cancel() + sub = undefined + await cancelTask() + } + } + ], () => enabled, { + async onDone() { + // clean up requestKey + if (requestKeys.step) { + await requestKeys.step() + } + } + }) + + async function getGroupKey(streamMessage) { + if (!streamMessage.groupKeyId) { return undefined } + await next() + if (!enabled) { return undefined } + + return getKey(streamMessage) + } + + return Object.assign(getGroupKey, { + async start() { + enabled = true + return next() + }, + async stop() { + enabled = false + return next() + } + }) +} diff --git a/src/stream/StorageNode.ts b/src/stream/StorageNode.ts new file mode 100644 index 000000000..ccb89b630 --- /dev/null +++ b/src/stream/StorageNode.ts @@ -0,0 +1,14 @@ +import { EthereumAddress } from '../types' + +export default class StorageNode { + + private _address: EthereumAddress + + constructor(address: EthereumAddress) { + this._address = address + } + + getAddress() { + return this._address + } +} diff --git a/src/stream/StreamPart.ts b/src/stream/StreamPart.ts new file mode 100644 index 000000000..9371b7ae6 --- /dev/null +++ b/src/stream/StreamPart.ts @@ -0,0 +1,26 @@ +export default class StreamPart { + + _streamId: string + _streamPartition: number + + constructor(streamId: string, streamPartition: number) { + this._streamId = streamId + this._streamPartition = streamPartition + } + + static fromStream({ id, partitions }: { id: string, partitions: number }) { + const result: StreamPart[] = [] + for (let i = 0; i < partitions; i++) { + result.push(new StreamPart(id, i)) + } + return result + } + + getStreamId() { + return this._streamId + } + + getStreamPartition() { + return this._streamPartition + } +} diff --git a/src/stream/index.ts b/src/stream/index.ts new file mode 100644 index 000000000..4476be363 --- /dev/null +++ b/src/stream/index.ts @@ -0,0 +1,257 @@ +import { getEndpointUrl } from '../utils' +import authFetch from '../rest/authFetch' + +import StorageNode from './StorageNode' +import { StreamrClient } from '../StreamrClient' + +// TODO explicit types: e.g. we never provide both streamId and id, or both streamPartition and partition +export type StreamPartDefinition = string | { streamId?: string, streamPartition?: number, id?: string, partition?: number, stream?: Stream } + +export type ValidatedStreamPartDefinition = { streamId: string, streamPartition: number, key: string} + +interface StreamPermisionBase { + id: number + operation: StreamOperation +} + +export interface UserStreamPermission extends StreamPermisionBase { + user: string +} + +export interface AnonymousStreamPermisson extends StreamPermisionBase { + anonymous: true +} + +export type StreamPermision = UserStreamPermission | AnonymousStreamPermisson + +export enum StreamOperation { + STREAM_GET = 'stream_get', + STREAM_EDIT = 'stream_edit', + STREAM_DELETE = 'stream_delete', + STREAM_PUBLISH = 'stream_publish', + STREAM_SUBSCRIBE = 'stream_subscribe', + STREAM_SHARE = 'stream_share' +} + +export interface StreamProperties { + id?: string + name?: string + description?: string + config?: { + fields: Field[]; + } + partitions?: number + requireSignedData?: boolean + requireEncryptedData?: boolean + storageDays?: number + inactivityThresholdHours?: number +} + +const VALID_FIELD_TYPES = ['number', 'string', 'boolean', 'list', 'map'] as const + +export type Field = { + name: string; + type: typeof VALID_FIELD_TYPES[number]; +} + +function getFieldType(value: any): (Field['type'] | undefined) { + const type = typeof value + switch (true) { + case Array.isArray(value): { + return 'list' + } + case type === 'object': { + return 'map' + } + case (VALID_FIELD_TYPES as ReadonlyArray).includes(type): { + // see https://github.com/microsoft/TypeScript/issues/36275 + return type as Field['type'] + } + default: { + return undefined + } + } +} + +export class Stream { + // @ts-expect-error + id: string + // @ts-expect-error + name: string + description?: string + config: { + fields: Field[]; + } = { fields: [] } + partitions?: number + /** @internal */ + _client: StreamrClient + requireEncryptedData?: boolean + requireSignedData?: boolean + storageDays?: number + inactivityThresholdHours?: number + + constructor(client: StreamrClient, props: StreamProperties) { + this._client = client + Object.assign(this, props) + } + + async update() { + const json = await authFetch( + getEndpointUrl(this._client.options.restUrl, 'streams', this.id), + this._client.session, + { + method: 'PUT', + body: JSON.stringify(this.toObject()), + }, + ) + return json ? new Stream(this._client, json) : undefined + } + + /** @internal */ + toObject() { + const result = {} + Object.keys(this).forEach((key) => { + if (!key.startsWith('_')) { + // @ts-expect-error + result[key] = this[key] + } + }) + return result + } + + async delete() { + await authFetch( + getEndpointUrl(this._client.options.restUrl, 'streams', this.id), + this._client.session, + { + method: 'DELETE', + }, + ) + } + + async getPermissions() { + return authFetch( + getEndpointUrl(this._client.options.restUrl, 'streams', this.id, 'permissions'), + this._client.session, + ) + } + + async getMyPermissions() { + return authFetch( + getEndpointUrl(this._client.options.restUrl, 'streams', this.id, 'permissions', 'me'), + this._client.session, + ) + } + + async hasPermission(operation: StreamOperation, userId: string|undefined) { + // eth addresses may be in checksumcase, but userId from server has no case + + const userIdCaseInsensitive = typeof userId === 'string' ? userId.toLowerCase() : undefined // if not string then undefined + const permissions = await this.getPermissions() + + return permissions.find((p: any) => { + if (p.operation !== operation) { return false } + + if (userIdCaseInsensitive === undefined) { + return !!p.anonymous // match nullish userId against p.anonymous + } + return p.user && p.user.toLowerCase() === userIdCaseInsensitive // match against userId + }) + } + + async grantPermission(operation: StreamOperation, userId: string|undefined) { + const permissionObject: any = { + operation, + } + + const userIdCaseInsensitive = typeof userId === 'string' ? userId.toLowerCase() : undefined + + if (userIdCaseInsensitive !== undefined) { + permissionObject.user = userIdCaseInsensitive + } else { + permissionObject.anonymous = true + } + + return authFetch( + getEndpointUrl(this._client.options.restUrl, 'streams', this.id, 'permissions'), + this._client.session, + { + method: 'POST', + body: JSON.stringify(permissionObject), + }, + ) + } + + async revokePermission(permissionId: number) { + await authFetch( + getEndpointUrl(this._client.options.restUrl, 'streams', this.id, 'permissions', String(permissionId)), + this._client.session, + { + method: 'DELETE', + }, + ) + } + + async detectFields() { + // Get last message of the stream to be used for field detecting + const sub = await this._client.resend({ + stream: this.id, + resend: { + last: 1, + }, + }) + + const receivedMsgs = await sub.collect() + + if (!receivedMsgs.length) { return } + + const [lastMessage] = receivedMsgs + + const fields = Object.entries(lastMessage).map(([name, value]) => { + const type = getFieldType(value) + return !!type && { + name, + type, + } + }).filter(Boolean) as Field[] // see https://github.com/microsoft/TypeScript/issues/30621 + + // Save field config back to the stream + this.config.fields = fields + await this.update() + } + + async addToStorageNode(address: string) { + await authFetch( + getEndpointUrl(this._client.options.restUrl, 'streams', this.id, 'storageNodes'), + this._client.session, + { + method: 'POST', + body: JSON.stringify({ + address + }) + }, + ) + } + + async removeFromStorageNode(address: string) { + await authFetch( + getEndpointUrl(this._client.options.restUrl, 'streams', this.id, 'storageNodes', address), + this._client.session, + { + method: 'DELETE' + }, + ) + } + + async getStorageNodes() { + const json = await authFetch<{ storageNodeAddress: string}[] >( + getEndpointUrl(this._client.options.restUrl, 'streams', this.id, 'storageNodes'), + this._client.session, + ) + return json.map((item: any) => new StorageNode(item.storageNodeAddress)) + } + + async publish(content: object, timestamp?: number|string|Date, partitionKey?: string) { + return this._client.publish(this.id, content, timestamp, partitionKey) + } +} diff --git a/src/stream/utils.ts b/src/stream/utils.ts new file mode 100644 index 000000000..91c716b7d --- /dev/null +++ b/src/stream/utils.ts @@ -0,0 +1,201 @@ +/** + * Utilities shared between publish & subscribe + */ + +import { inspect } from 'util' + +import { ControlLayer } from 'streamr-client-protocol' + +import { pTimeout } from '../utils' +import { Todo } from '../types' +import { StreamrClient } from '../StreamrClient' +import { StreamPartDefinition, ValidatedStreamPartDefinition } from '.' + +export function StreamKey({ streamId, streamPartition = 0 }: Todo) { + if (streamId == null) { throw new Error(`StreamKey: invalid streamId (${typeof streamId}): ${streamId}`) } + + if (!Number.isInteger(streamPartition) || streamPartition < 0) { + throw new Error(`StreamKey: invalid streamPartition (${typeof streamPartition}): ${streamPartition}`) + } + return `${streamId}::${streamPartition}` +} + +export function validateOptions(optionsOrStreamId: StreamPartDefinition): ValidatedStreamPartDefinition { + if (!optionsOrStreamId) { + throw new Error('streamId is required!') + } + + // Backwards compatibility for giving a streamId as first argument + let options: Todo = {} + if (typeof optionsOrStreamId === 'string') { + options = { + streamId: optionsOrStreamId, + streamPartition: 0, + } + } else if (typeof optionsOrStreamId === 'object') { + if (optionsOrStreamId.stream) { + const { stream, ...other } = optionsOrStreamId + return validateOptions({ + ...other, + ...validateOptions(stream), + }) + } + + if (optionsOrStreamId.id != null && optionsOrStreamId.streamId == null) { + options.streamId = optionsOrStreamId.id + } + + if (optionsOrStreamId.partition != null && optionsOrStreamId.streamPartition == null) { + options.streamPartition = optionsOrStreamId.partition + } + + // shallow copy + options = { + streamPartition: 0, + ...options, + ...optionsOrStreamId + } + } else { + throw new Error(`options must be an object! Given: ${inspect(optionsOrStreamId)}`) + } + + if (options.streamId == null) { + throw new Error(`streamId must be set! Given: ${inspect(optionsOrStreamId)}`) + } + + options.streamPartition = options.streamPartition || 0 + + options.key = StreamKey(options) + + return options +} + +const { ControlMessage } = ControlLayer + +const ResendResponses = [ControlMessage.TYPES.ResendResponseResending, ControlMessage.TYPES.ResendResponseNoResend] + +export const STREAM_MESSAGE_TYPES = [ControlMessage.TYPES.UnicastMessage, ControlMessage.TYPES.BroadcastMessage] + +const PAIRS = new Map([ + [ControlMessage.TYPES.SubscribeRequest, [ControlMessage.TYPES.SubscribeResponse]], + [ControlMessage.TYPES.UnsubscribeRequest, [ControlMessage.TYPES.UnsubscribeResponse]], + [ControlMessage.TYPES.ResendLastRequest, ResendResponses], + [ControlMessage.TYPES.ResendFromRequest, ResendResponses], + [ControlMessage.TYPES.ResendRangeRequest, ResendResponses], +]) + +export async function waitForMatchingMessage({ + connection, + matchFn, + timeout, + types = [], + rejectOnTimeout = true, + timeoutMessage, + cancelTask, +}: Todo) { + if (typeof matchFn !== 'function') { + throw new Error(`matchFn required, got: (${typeof matchFn}) ${matchFn}`) + } + + await connection.nextConnection() + let cleanup = () => {} + + const matchTask = new Promise((resolve, reject) => { + const tryMatch = (...args: Todo[]) => { + try { + return matchFn(...args) + } catch (err) { + cleanup() + reject(err) + return false + } + } + let onDisconnected: Todo + const onResponse = (res: Todo) => { + if (!tryMatch(res)) { return } + // clean up err handler + cleanup() + resolve(res) + } + + const onErrorResponse = (res: Todo) => { + if (!tryMatch(res)) { return } + // clean up success handler + cleanup() + const error = new Error(res.errorMessage) + // @ts-expect-error + error.code = res.errorCode + reject(error) + } + + cleanup = () => { + if (cancelTask) { cancelTask.catch(() => {}) } // ignore + connection.off('disconnected', onDisconnected) + connection.off(ControlMessage.TYPES.ErrorResponse, onErrorResponse) + types.forEach((type: Todo) => { + connection.off(type, onResponse) + }) + } + + types.forEach((type: Todo) => { + connection.on(type, onResponse) + }) + + connection.on(ControlMessage.TYPES.ErrorResponse, onErrorResponse) + + onDisconnected = () => { + cleanup() + // @ts-expect-error + resolve() // noop + } + + connection.once('disconnected', onDisconnected) + }) + + try { + const task = cancelTask ? Promise.race([ + matchTask, + cancelTask, + ]) : matchTask + + if (!timeout) { + return await task + } + + return await pTimeout(task, { + timeout, + message: timeoutMessage, + rejectOnTimeout, + }) + } finally { + cleanup() + } +} + +/** + * Wait for matching response types to requestId, or ErrorResponse. + */ + +export async function waitForResponse({ requestId, timeoutMessage = `Waiting for response to: ${requestId}.`, ...opts }: Todo) { + if (requestId == null) { + throw new Error(`requestId required, got: (${typeof requestId}) ${requestId}`) + } + + return waitForMatchingMessage({ + ...opts, + requestId, + timeoutMessage, + matchFn(res: Todo) { + return res.requestId === requestId + } + }) +} + +export async function waitForRequestResponse(client: StreamrClient, request: Todo, opts: Todo = {}) { + return waitForResponse({ + connection: client.connection, + types: PAIRS.get(request.type), + requestId: request.requestId, + ...opts, // e.g. timeout, rejectOnTimeout + }) +} diff --git a/src/subscribe/Decrypt.js b/src/subscribe/Decrypt.js new file mode 100644 index 000000000..c2c794927 --- /dev/null +++ b/src/subscribe/Decrypt.js @@ -0,0 +1,59 @@ +import { MessageLayer } from 'streamr-client-protocol' + +import PushQueue from '../utils/PushQueue' +import EncryptionUtil, { UnableToDecryptError } from '../stream/Encryption' +import { SubscriberKeyExchange } from '../stream/KeyExchange' + +const { StreamMessage } = MessageLayer + +export default function Decrypt(client, options = {}) { + if (!client.options.keyExchange) { + // noop unless message encrypted + return (streamMessage) => { + if (streamMessage.groupKeyId) { + throw new Error('No keyExchange configured, cannot decrypt message.') + } + + return streamMessage + } + } + + const requestKey = SubscriberKeyExchange(client, { + ...options, + groupKeys: { + ...client.options.groupKeys, + ...options.groupKeys, + } + }) + + async function* decrypt(src, onError = async (err) => { throw err }) { + yield* PushQueue.transform(src, async (streamMessage) => { + if (!streamMessage.groupKeyId) { + return streamMessage + } + + if (streamMessage.encryptionType !== StreamMessage.ENCRYPTION_TYPES.AES) { + return streamMessage + } + + try { + const groupKey = await requestKey(streamMessage) + if (!groupKey) { + throw new UnableToDecryptError(`Group key not found: ${streamMessage.groupKeyId}`, streamMessage) + } + await EncryptionUtil.decryptStreamMessage(streamMessage, groupKey) + return streamMessage + } catch (err) { + await onError(err, streamMessage) + } + + return streamMessage + }) + } + + return Object.assign(decrypt, { + stop() { + return requestKey.stop() + } + }) +} diff --git a/src/subscribe/OrderMessages.js b/src/subscribe/OrderMessages.js new file mode 100644 index 000000000..4da6226f0 --- /dev/null +++ b/src/subscribe/OrderMessages.js @@ -0,0 +1,112 @@ +import { Utils } from 'streamr-client-protocol' + +import { pipeline } from '../utils/iterators' +import PushQueue from '../utils/PushQueue' +import { validateOptions } from '../stream/utils' + +import resendStream from './resendStream' + +const { OrderingUtil } = Utils + +let ID = 0 + +/** + * Wraps OrderingUtil into a pipeline. + * Implements gap filling + */ + +export default function OrderMessages(client, options = {}) { + const { gapFillTimeout, retryResendAfter, maxGapRequests } = client.options + const { streamId, streamPartition, gapFill = true } = validateOptions(options) + const debug = client.debug.extend(`OrderMessages::${ID}`) + ID += 1 + + // output buffer + const outStream = new PushQueue([], { + autoEnd: false, + }) + + let done = false + const resendStreams = new Set() // holds outstanding resends for cleanup + + const orderingUtil = new OrderingUtil(streamId, streamPartition, (orderedMessage) => { + if (!outStream.isWritable() || done) { + return + } + outStream.push(orderedMessage) + }, async (from, to, publisherId, msgChainId) => { + if (done || !gapFill) { return } + debug('gap %o', { + streamId, streamPartition, publisherId, msgChainId, from, to, + }) + + // eslint-disable-next-line no-use-before-define + const resendMessageStream = resendStream(client, { + streamId, streamPartition, from, to, publisherId, msgChainId, + }) + + try { + if (done) { return } + resendStreams.add(resendMessageStream) + await resendMessageStream.subscribe() + if (done) { return } + + for await (const { streamMessage } of resendMessageStream) { + if (done) { return } + orderingUtil.add(streamMessage) + } + } finally { + resendStreams.delete(resendMessageStream) + await resendMessageStream.cancel() + } + }, gapFillTimeout, retryResendAfter, gapFill ? maxGapRequests : 0) + + const markMessageExplicitly = orderingUtil.markMessageExplicitly.bind(orderingUtil) + + let inputClosed = false + + function maybeClose() { + // we can close when: + // input has closed (i.e. all messages sent) + // AND + // no gaps are pending + // AND + // gaps have been filled or failed + // NOTE ordering util cannot have gaps if queue is empty + if (inputClosed && orderingUtil.isEmpty()) { + outStream.end() + } + } + + orderingUtil.on('drain', () => { + maybeClose() + }) + + orderingUtil.on('error', () => { + // TODO: handle gapfill errors without closing stream or logging + maybeClose() // probably noop + }) + + return Object.assign(pipeline([ + // eslint-disable-next-line require-yield + async function* WriteToOrderingUtil(src) { + for await (const msg of src) { + orderingUtil.add(msg) + // note no yield + // orderingUtil writes to outStream itself + } + inputClosed = true + maybeClose() + }, + outStream, // consumer gets outStream + ], async (err) => { + done = true + orderingUtil.clearGaps() + resendStreams.forEach((s) => s.cancel()) + resendStreams.clear() + await outStream.cancel(err) + orderingUtil.clearGaps() + }), { + markMessageExplicitly, + }) +} diff --git a/src/subscribe/Validator.js b/src/subscribe/Validator.js new file mode 100644 index 000000000..0a30b3c27 --- /dev/null +++ b/src/subscribe/Validator.js @@ -0,0 +1,79 @@ +import { inspect } from 'util' + +import { MessageLayer, Utils, Errors } from 'streamr-client-protocol' + +import { pOrderedResolve, CacheAsyncFn } from '../utils' +import { validateOptions } from '../stream/utils' + +const { StreamMessageValidator, SigningUtil } = Utils +const { ValidationError } = Errors +const { StreamMessage, GroupKeyErrorResponse } = MessageLayer + +const EMPTY_MESSAGE = { + serialize() {} +} + +export class SignatureRequiredError extends ValidationError { + constructor(streamMessage = EMPTY_MESSAGE) { + super(`Client requires data to be signed. Message: ${inspect(streamMessage)}`) + this.streamMessage = streamMessage + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor) + } + } +} + +/** + * Wrap StreamMessageValidator in a way that ensures it can validate in parallel but + * validation is guaranteed to resolve in the same order they were called + * Handles caching remote calls + */ + +export default function Validator(client, opts) { + const options = validateOptions(opts) + const validator = new StreamMessageValidator({ + getStream: client.cached.getStream.bind(client.cached), + async isPublisher(publisherId, _streamId) { + return client.cached.isStreamPublisher(_streamId, publisherId) + }, + async isSubscriber(ethAddress, _streamId) { + return client.cached.isStreamSubscriber(_streamId, ethAddress) + }, + verify: CacheAsyncFn(SigningUtil.verify.bind(SigningUtil), { + ...client.options.cache, + cachePromiseRejection: false, + cacheKey: (args) => args.join('|'), + }) + }) + + const validate = pOrderedResolve(async (msg) => { + if (msg.messageType === StreamMessage.MESSAGE_TYPES.GROUP_KEY_ERROR_RESPONSE) { + const res = GroupKeyErrorResponse.fromArray(msg.getParsedContent()) + const err = new ValidationError(`GroupKeyErrorResponse: ${res.errorMessage}`, msg) + err.code = res.errorCode + throw err + } + + // Check special cases controlled by the verifySignatures policy + if (client.options.verifySignatures === 'never' && msg.messageType === StreamMessage.MESSAGE_TYPES.MESSAGE) { + return msg // no validation required + } + + if (options.verifySignatures === 'always' && !msg.signature) { + throw new SignatureRequiredError(msg) + } + + // In all other cases validate using the validator + await validator.validate(msg) // will throw with appropriate validation failure + return msg + }) + + // return validation function that resolves in call order + return Object.assign(validate, { + clear(key) { + if (!key) { + validate.clear() + } + } + }) +} diff --git a/src/subscribe/api.js b/src/subscribe/api.js new file mode 100644 index 000000000..394a0cae8 --- /dev/null +++ b/src/subscribe/api.js @@ -0,0 +1,147 @@ +import { inspect } from 'util' + +import { ControlLayer, MessageLayer } from 'streamr-client-protocol' + +import { uuid } from '../utils' +import { waitForRequestResponse } from '../stream/utils' + +const { + SubscribeRequest, UnsubscribeRequest, + ResendLastRequest, ResendFromRequest, ResendRangeRequest, +} = ControlLayer + +const { MessageRef } = MessageLayer + +/** + * Subscribe Request + */ + +export async function subscribe(client, { streamId, streamPartition = 0 }) { + const sessionToken = await client.session.getSessionToken() + const request = new SubscribeRequest({ + streamId, + streamPartition, + sessionToken, + requestId: uuid('sub'), + }) + + const onResponse = waitForRequestResponse(client, request) + + await client.send(request) + return onResponse +} + +/** + * Unsubscribe Request + */ + +export async function unsubscribe(client, { streamId, streamPartition = 0 }) { // eslint-disable-line no-underscore-dangle + const { connection } = client + + // disconnection auto-unsubs + // if already disconnected/disconnecting no need to send unsub + const needsUnsubscribe = ( + connection.isConnectionValid() + && !connection.isDisconnected() + && !connection.isDisconnecting() + ) + + if (!needsUnsubscribe) { + return Promise.resolve() + } + + const sessionToken = await client.session.getSessionToken() + const request = new UnsubscribeRequest({ + streamId, + streamPartition, + sessionToken, + requestId: uuid('unsub'), + }) + + const onResponse = waitForRequestResponse(client, request).catch((err) => { + // noop if unsubscribe failed because we are already unsubscribed + if (err.message.contains('Not subscribed to stream')) { + return + } + + throw err + }) + + await client.send(request) + return onResponse +} + +/** + * Resend Request + */ + +function createResendRequest(resendOptions) { + const { + requestId = uuid('rs'), + streamId, + streamPartition = 0, + sessionToken, + ...options + } = resendOptions + + const { + from, + to, + last, + publisherId, + msgChainId, + } = { + ...options, + ...options.resend + } + + const commonOpts = { + streamId, + streamPartition, + requestId, + sessionToken, + } + + let request + + if (last > 0) { + request = new ResendLastRequest({ + ...commonOpts, + numberLast: last, + }) + } else if (from && !to) { + request = new ResendFromRequest({ + ...commonOpts, + fromMsgRef: new MessageRef(from.timestamp, from.sequenceNumber), + publisherId, + msgChainId, + }) + } else if (from && to) { + request = new ResendRangeRequest({ + ...commonOpts, + fromMsgRef: new MessageRef(from.timestamp, from.sequenceNumber), + toMsgRef: new MessageRef(to.timestamp, to.sequenceNumber), + publisherId, + msgChainId, + }) + } + + if (!request) { + throw new Error(`Can't _requestResend without resend options. Got: ${inspect(resendOptions)}`) + } + + return request +} + +export async function resend(client, options) { + const sessionToken = await client.session.getSessionToken() + const request = createResendRequest({ + ...options, + sessionToken, + }) + + const onResponse = waitForRequestResponse(client, request) + + await client.send(request) + return onResponse +} diff --git a/src/subscribe/index.ts b/src/subscribe/index.ts new file mode 100644 index 000000000..7cb1320f4 --- /dev/null +++ b/src/subscribe/index.ts @@ -0,0 +1,679 @@ +import Emitter from 'events' + +import { allSettledValues, AggregatedError, Scaffold, Defer, counterId } from '../utils' +import { pipeline } from '../utils/iterators' +import { validateOptions } from '../stream/utils' +import { ConnectionError } from '../Connection' + +import { subscribe, unsubscribe } from './api' +import MessagePipeline from './pipeline' +import Validator from './Validator' +import messageStream from './messageStream' +import resendStream from './resendStream' +import { Todo } from '../types' +import StreamrClient, { StreamPartDefinition, SubscribeOptions } from '..' + +export class Subscription extends Emitter { + + streamId: string + streamPartition: number + /** @internal */ + client: StreamrClient + /** @internal */ + options: Todo + /** @internal */ + key: Todo + /** @internal */ + id: Todo + /** @internal */ + _onDone: Todo + /** @internal */ + _onFinally: Todo + /** @internal */ + pipeline: Todo + /** @internal */ + msgStream: Todo + /** @internal */ + iterated?: Todo + + constructor(client: StreamrClient, opts: Todo, onFinally = () => {}) { + super() + this.client = client + this.options = validateOptions(opts) + this.key = this.options.key + this.id = counterId(`Subscription.${this.key}`) + this.streamId = this.options.streamId + this.streamPartition = this.options.streamPartition + + this._onDone = Defer() + this._onDone.catch(() => {}) // prevent unhandledrejection + this._onFinally = onFinally + + const validate = opts.validate || Validator(client, this.options) + this.onPipelineEnd = this.onPipelineEnd.bind(this) + this.pipeline = opts.pipeline || MessagePipeline(client, { + ...this.options, + validate, + onError: (err: Todo) => { + this.emit('error', err) + }, + // @ts-expect-error + }, this.onPipelineEnd) + + this.msgStream = this.pipeline.msgStream + } + + /** + * Expose cleanup + * @internal + */ + async onPipelineEnd(err: Todo) { + try { + await this._onFinally(err) + } finally { + this._onDone.handleErrBack(err) + } + } + + /** @internal */ + async onDone() { + return this._onDone + } + + /** + * Collect all messages into an array. + * Returns array when subscription is ended. + */ + async collect(n?: number) { + const msgs = [] + for await (const msg of this) { + if (n === 0) { + break + } + + msgs.push(msg.getParsedContent()) + if (msgs.length === n) { + break + } + } + + return msgs + } + + /** @internal */ + [Symbol.asyncIterator]() { + // only iterate sub once + if (this.iterated) { + throw new Error('cannot iterate subscription more than once. Cannot iterate if message handler function was passed to subscribe.') + } + + this.iterated = true + return this.pipeline + } + + /** @internal */ + async cancel(...args: Todo[]) { + return this.pipeline.cancel(...args) + } + + /** @internal */ + async return(...args: Todo[]) { + return this.pipeline.return(...args) + } + + /** @internal */ + async throw(...args: Todo[]) { + return this.pipeline.throw(...args) + } + + // TODO should we expose this to the user as no-args method? + async unsubscribe() { + return this.cancel() + } +} + +/** + * Emit event on all supplied emitters. + * Aggregates errors rather than throwing on first. + */ + +function multiEmit(emitters: Todo, ...args: Todo[]) { + let error: Todo + emitters.forEach((s: Todo) => { + try { + s.emit(...args) + } catch (err) { + AggregatedError.from(error, err, `Error emitting event: ${args[0]}`) + } + }) + + if (error) { + throw error + } +} + +/** + * Sends Subscribe/Unsubscribe requests as needed. + * Adds connection handles as needed. + */ + +class SubscriptionSession extends Emitter { + + client: StreamrClient + options: Todo + validate: Todo + subscriptions: Set + deletedSubscriptions: Set + step?: Todo + + constructor(client: StreamrClient, options: Todo) { + super() + this.client = client + this.options = validateOptions(options) + this.validate = Validator(client, this.options) + + this.subscriptions = new Set() // active subs + this.deletedSubscriptions = new Set() // hold so we can clean up + this._init() + } + + _init() { + const { key } = this.options + const { connection } = this.client + + let needsReset = false + const onDisconnected = async () => { + // see if we should reset then retry connecting + try { + if (!connection.isConnectionValid()) { + await this.step() + return + } + + needsReset = true + await this.step() + if (connection.isConnectionValid()) { + needsReset = false + await this.step() + } + } catch (err) { + this.emit('error', err) + } + } + + let deleted = new Set() + const check = () => { + return ( + connection.isConnectionValid() + && !needsReset + // has some active subscription + && this.count() + ) + } + + this.step = Scaffold([ + () => { + needsReset = false + return async () => { + // don't clean up if just resetting + if (needsReset) { return } + + try { + this.emit('unsubscribed') + } finally { + deleted.forEach((s) => { + this.deletedSubscriptions.delete(s) + }) + } + if (!connection.isConnectionValid()) { + await this.removeAll() + } + } + }, + // add handlers for connection close events + () => { + connection.on('done', onDisconnected) + connection.on('disconnected', onDisconnected) + connection.on('disconnecting', onDisconnected) + this.emit('subscribing') + + return () => { + connection.off('done', onDisconnected) + connection.off('disconnected', onDisconnected) + connection.off('disconnecting', onDisconnected) + } + }, + // open connection + async () => { + await connection.addHandle(key) + return async () => { + if (needsReset) { return } // don't close connection if just resetting + deleted = new Set(this.deletedSubscriptions) + await connection.removeHandle(key) + } + }, + // validate connected + async () => { + await connection.needsConnection(`Subscribe ${key}`) + }, + // subscribe + async () => { + await subscribe(this.client, this.options) + this.emit('subscribed') + + return async () => { + if (needsReset) { return } + this.emit('unsubscribing') + await unsubscribe(this.client, this.options) + } + } + // @ts-expect-error + ], check, { + onError(err) { + if (err instanceof ConnectionError && !check()) { + // ignore error if state changed + needsReset = true + return + } + throw err + } + }) + } + + has(sub: Todo) { + return this.subscriptions.has(sub) + } + + /** + * Emit message on every subscription, + * then on self. + */ + + emit(...args: Todo[]) { + const subs = this._getSubs() + try { + multiEmit(subs, ...args) + } catch (error) { + return super.emit('error', error) + } + // @ts-expect-error + return super.emit(...args) + } + + _getSubs() { + // all known subs + return new Set([ + ...this.deletedSubscriptions, + ...this.subscriptions, + ]) + } + + /** + * Add subscription & appropriate connection handle. + */ + + async add(sub: Todo) { + this.subscriptions.add(sub) + const { connection } = this.client + await connection.addHandle(`adding${sub.id}`) + try { + await connection.needsConnection(`Subscribe ${sub.id}`) + await this.step() + } finally { + await connection.removeHandle(`adding${sub.id}`) + } + } + + /** + * Remove subscription & appropriate connection handle. + */ + + async remove(sub: Todo) { + this.subscriptions.delete(sub) + + if (this.deletedSubscriptions.has(sub)) { + return + } + + const cancelTask = sub.cancel() + this.subscriptions.delete(sub) + this.deletedSubscriptions.add(sub) + await this.step() + await cancelTask + } + + /** + * Remove all subscriptions & subscription connection handles + */ + + async removeAll() { + const subs = this._getSubs() + return Promise.all([...subs].map((sub) => ( + this.remove(sub) + ))) + } + + /** + * How many subscriptions + */ + + count() { + return this.subscriptions.size + } +} + +/** + * Keeps track of subscriptions. + */ + +class Subscriptions { + + client: StreamrClient + subSessions: Map + + constructor(client: StreamrClient) { + this.client = client + this.subSessions = new Map() + } + + async add(opts: StreamPartDefinition, onFinally: Todo = async () => {}) { + const options = validateOptions(opts) + const { key } = options + + // get/create subscription session + // don't add SubscriptionSession to subSessions until after subscription successfully created + const subSession = this.subSessions.get(key) || new SubscriptionSession(this.client, options) + + // create subscription + const sub = new Subscription(this.client, { + ...options, + validate: subSession.validate, + // @ts-expect-error + }, async (err: Todo) => { + try { + await this.remove(sub) + } finally { + await onFinally(err) + } + }) + + // @ts-expect-error + sub.count = () => { + // sub.count() gives number of subs on same stream+partition + return this.count(sub.options) + } + + // sub didn't throw, add subsession + if (!this.subSessions.has(key)) { // double-check + this.subSessions.set(key, subSession) + } + + // add subscription to subSession + try { + await subSession.add(sub) + } catch (err) { + // clean up if fail + await this.remove(sub) + throw err + } + + return sub + } + + async remove(sub: Todo) { + const { key } = sub + let cancelTask + try { + cancelTask = sub.cancel() + const subSession = this.subSessions.get(key) + + if (subSession) { + await subSession.remove(sub) + // remove subSession if no more subscriptions + if (!subSession.count()) { + this.subSessions.delete(key) + } + } + } finally { + await cancelTask // only wait for cancel at end + } + } + + /** + * Remove all subscriptions, optionally only those matching options. + */ + async removeAll(options?: StreamPartDefinition) { + const subs = this.get(options) + return allSettledValues(subs.map((sub: Todo) => ( + this.remove(sub) + ))) + } + + /** + * Count all subscriptions. + */ + + countAll() { + let count = 0 + this.subSessions.forEach((s) => { + count += s.count() + }) + return count + } + + /** + * Count all matching subscriptions. + */ + + count(options?: StreamPartDefinition) { + if (options === undefined) { return this.countAll() } + return this.get(options).length + } + + /** + * Get all subscriptions. + */ + + getAll() { + return [...this.subSessions.values()].reduce((o, s) => { + o.push(...s.subscriptions) + return o + }, []) + } + + /** + * Get subscription session for matching sub options. + */ + + getSubscriptionSession(options: Todo) { + const { key } = validateOptions(options) + return this.subSessions.get(key) + } + + /** + * Get all subscriptions matching options. + */ + + get(options?: StreamPartDefinition) { + if (options === undefined) { return this.getAll() } + + const { key } = validateOptions(options) + const subSession = this.subSessions.get(key) + if (!subSession) { return [] } + + return [...subSession.subscriptions] + } +} + +/** + * Top-level user-facing interface for creating/destroying subscriptions. + */ +export class Subscriber { + + client: StreamrClient + subscriptions: Subscriptions + + constructor(client: StreamrClient) { + this.client = client + this.subscriptions = new Subscriptions(client) + } + + getSubscriptionSession(...args: Todo[]) { + // @ts-expect-error + return this.subscriptions.getSubscriptionSession(...args) + } + + getAll() { + return this.subscriptions.getAll() + } + + count(options?: StreamPartDefinition) { + return this.subscriptions.count(options) + } + + async subscribe(opts: StreamPartDefinition, onFinally?: Todo) { + return this.subscriptions.add(opts, onFinally) + } + + async unsubscribe(options: Subscription | StreamPartDefinition | { options: Subscription|StreamPartDefinition }): Promise { + if (options instanceof Subscription) { + const sub = options + return sub.cancel() + } + + // @ts-expect-error + if (options && options.options) { + // @ts-expect-error + return this.unsubscribe(options.options) + } + + // @ts-expect-error + return this.subscriptions.removeAll(options) + } + + async resend(opts: Todo) { + const resendMsgStream = resendStream(this.client, opts) + + const sub = new Subscription(this.client, { + msgStream: resendMsgStream, + ...opts, + }, async (...args) => { + sub.emit('resent') + await sub.cancel(...args) + }) + + await resendMsgStream.subscribe() + return sub + } + + async resendSubscribe(opts: SubscribeOptions & StreamPartDefinition, onMessage: Todo) { + // This works by passing a custom message stream to a subscription + // the custom message stream iterates resends, then iterates realtime + const options = validateOptions(opts) + + const resendMessageStream = resendStream(this.client, options) + // @ts-expect-error + const realtimeMessageStream = messageStream(this.client.connection, options) + + // cancel both streams on end + async function end(optionalErr: Todo) { + await Promise.all([ + resendMessageStream.cancel(optionalErr), + realtimeMessageStream.cancel(optionalErr), + ]) + + if (optionalErr) { + throw optionalErr + } + } + + let resendSubscribeSub: Todo + + let lastResentMsgId: Todo + let lastProcessedMsgId: Todo + const resendDone = Defer() + let isResendDone = false + let resentEmitted = false + + function messageIDString(msg: Todo) { + return msg.getMessageID().serialize() + } + + function maybeEmitResend() { + if (resentEmitted || !isResendDone) { return } + + // need to account for both cases: + // resent finished after last message got through pipeline + // resent finished before last message got through pipeline + if (!lastResentMsgId || lastProcessedMsgId === lastResentMsgId) { + lastResentMsgId = undefined + resentEmitted = true + resendSubscribeSub.emit('resent') + } + } + + const it = pipeline([ + async function* HandleResends() { + try { + // Inconvience here + // emitting the resent event is a bit tricky in this setup because the subscription + // doesn't know anything about the source of the messages + // can't emit resent immediately after resent stream end since + // the message is not yet through the message pipeline + let currentMsgId + try { + for await (const msg of resendSubscribeSub.resend) { + currentMsgId = messageIDString(msg.streamMessage) + yield msg + } + } finally { + lastResentMsgId = currentMsgId + } + } finally { + isResendDone = true + maybeEmitResend() + // @ts-expect-error + resendDone.resolve() + } + }, + async function* ResendThenRealtime(src: Todo) { + yield* src + await resendDone // ensure realtime doesn't start until resend ends + yield* resendSubscribeSub.realtime + }, + // @ts-expect-error + ], end) + + const resendTask = resendMessageStream.subscribe() + const realtimeTask = this.subscribe({ + ...options, + // @ts-expect-error + msgStream: it, + afterSteps: [ + async function* detectEndOfResend(src: Todo) { + for await (const msg of src) { + const id = messageIDString(msg) + try { + yield msg + } finally { + lastProcessedMsgId = id + maybeEmitResend() + } + } + }, + ], + }, onMessage) + + // eslint-disable-next-line semi-style + ;[resendSubscribeSub] = await Promise.all([ + realtimeTask, + resendTask, + ]) + + // attach additional utility functions + return Object.assign(resendSubscribeSub, { + realtime: realtimeMessageStream, + resend: resendMessageStream, + }) + } +} diff --git a/src/subscribe/messageStream.js b/src/subscribe/messageStream.js new file mode 100644 index 000000000..85dbcb082 --- /dev/null +++ b/src/subscribe/messageStream.js @@ -0,0 +1,57 @@ +import { ControlLayer } from 'streamr-client-protocol' + +import PushQueue from '../utils/PushQueue' + +const { ControlMessage } = ControlLayer + +function getIsMatchingStreamMessage({ streamId, streamPartition = 0 }) { + return function isMatchingStreamMessage({ streamMessage }) { + const msgStreamId = streamMessage.getStreamId() + if (streamId !== msgStreamId) { return false } + const msgPartition = streamMessage.getStreamPartition() + if (streamPartition !== msgPartition) { return false } + return true + } +} + +/** + * Listen for matching stream messages on connection. + * Returns a PushQueue that will fill with messages. + */ + +export default function messageStream(connection, { streamId, streamPartition, isUnicast, type }, onFinally = async () => {}) { + if (!type) { + // eslint-disable-next-line no-param-reassign + type = isUnicast ? ControlMessage.TYPES.UnicastMessage : ControlMessage.TYPES.BroadcastMessage + } + + const isMatchingStreamMessage = getIsMatchingStreamMessage({ + streamId, + streamPartition + }) + + let msgStream + // write matching messages to stream + const onMessage = (msg) => { + if (!isMatchingStreamMessage(msg)) { return } + msgStream.push(msg) + } + + // stream acts as buffer + msgStream = new PushQueue([], { + async onEnd(...args) { + // remove onMessage handler & clean up + connection.off(type, onMessage) + await onFinally(...args) + } + }) + + Object.assign(msgStream, { + streamId, + streamPartition, + }) + + connection.on(type, onMessage) + + return msgStream +} diff --git a/src/subscribe/pipeline.js b/src/subscribe/pipeline.js new file mode 100644 index 000000000..3e45d7c4b --- /dev/null +++ b/src/subscribe/pipeline.js @@ -0,0 +1,139 @@ +import { counterId } from '../utils' +import { pipeline } from '../utils/iterators' +import { validateOptions } from '../stream/utils' + +import Validator from './Validator' +import messageStream from './messageStream' +import OrderMessages from './OrderMessages' +import Decrypt from './Decrypt' + +export { SignatureRequiredError } from './Validator' + +async function collect(src) { + const msgs = [] + for await (const msg of src) { + msgs.push(msg.getParsedContent()) + } + + return msgs +} + +/** + * Subscription message processing pipeline + */ + +export default function MessagePipeline(client, opts = {}, onFinally = async () => {}) { + const options = validateOptions(opts) + const { key, afterSteps = [], beforeSteps = [], onError = (err) => { throw err } } = options + const id = counterId('MessagePipeline') + key + + /* eslint-disable object-curly-newline */ + const { + validate = Validator(client, options), + msgStream = messageStream(client.connection, options), + orderingUtil = OrderMessages(client, options), + decrypt = Decrypt(client, options), + } = options + /* eslint-enable object-curly-newline */ + + // re-order messages (ignore gaps) + const internalOrderingUtil = OrderMessages(client, { + ...options, + gapFill: false, + }) + + // collect messages that fail validation/parsing, do not push out of pipeline + // NOTE: we let failed messages be processed and only removed at end so they don't + // end up acting as gaps that we repeatedly try to fill. + const ignoreMessages = new WeakSet() + + const p = pipeline([ + // take messages + msgStream, + // custom pipeline steps + ...beforeSteps, + // unpack stream message + async function* getStreamMessage(src) { + for await (const { streamMessage } of src) { + yield streamMessage + } + }, + // order messages (fill gaps) + orderingUtil, + // validate + async function* ValidateMessages(src) { + for await (const streamMessage of src) { + try { + await validate(streamMessage) + } catch (err) { + ignoreMessages.add(streamMessage) + await onError(err) + } + yield streamMessage + } + }, + // decrypt + async function* DecryptMessages(src) { + yield* decrypt(src, async (err, streamMessage) => { + ignoreMessages.add(streamMessage) + await onError(err) + }) + }, + // parse content + async function* ParseMessages(src) { + for await (const streamMessage of src) { + try { + streamMessage.getParsedContent() + } catch (err) { + ignoreMessages.add(streamMessage) + await onError(err) + } + yield streamMessage + } + }, + // re-order messages (ignore gaps) + internalOrderingUtil, + // ignore any failed messages + async function* IgnoreMessages(src) { + for await (const streamMessage of src) { + if (ignoreMessages.has(streamMessage)) { + continue + } + yield streamMessage + } + }, + // special handling for bye message + async function* ByeMessageSpecialHandling(src) { + for await (const orderedMessage of src) { + yield orderedMessage + try { + if (orderedMessage.isByeMessage()) { + break + } + } catch (err) { + await onError(err) + } + } + }, + // custom pipeline steps + ...afterSteps + ], async (err, ...args) => { + await msgStream.cancel(err) + try { + if (err) { + await onError(err) + } + } finally { + await onFinally(err, ...args) + } + }) + + return Object.assign(p, { + id, + msgStream, + orderingUtil, + validate, + collect: collect.bind(null, p), + end: msgStream.end, + }) +} diff --git a/src/subscribe/resendStream.js b/src/subscribe/resendStream.js new file mode 100644 index 000000000..51c51439a --- /dev/null +++ b/src/subscribe/resendStream.js @@ -0,0 +1,72 @@ +import { ControlLayer } from 'streamr-client-protocol' + +import { counterId } from '../utils' +import { validateOptions, waitForResponse } from '../stream/utils' + +import { resend } from './api' +import messageStream from './messageStream' + +const { ControlMessage } = ControlLayer + +/** + * Stream of resent messages. + * Sends resend request, handles responses. + */ + +export default function resendStream(client, opts = {}, onFinally = async () => {}) { + const options = validateOptions(opts) + const { connection } = client + const requestId = counterId(`${options.key}-resend`) + const msgStream = messageStream(client.connection, { + ...options, + isUnicast: true, + }, async (...args) => { + try { + await connection.removeHandle(requestId) + } finally { + await onFinally(...args) + } + }) + + const onResendDone = waitForResponse({ // eslint-disable-line promise/catch-or-return + requestId, + connection: client.connection, + types: [ + ControlMessage.TYPES.ResendResponseResent, + ControlMessage.TYPES.ResendResponseNoResend, + ], + }).then(() => ( + msgStream.end() + ), async (err) => { + await msgStream.cancel(err) + throw err + }) + + // wait for resend complete message or resend request done + return Object.assign(msgStream, { + async subscribe() { + await connection.addHandle(requestId) + // wait for resend complete message or resend request done + let error + await Promise.race([ + resend(client, { + requestId, + ...options, + }).catch((err) => { + error = err + }), + onResendDone.catch((err) => { + error = err + }) + ]) + if (error) { + await msgStream.cancel(error) + throw error + } + return this + }, + async unsubscribe() { + return this.cancel() + } + }) +} diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 000000000..739afa588 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,7 @@ +import { F } from 'ts-toolbelt' + +export type EthereumAddress = string + +export type MaybeAsync = T | F.Promisify // Utility Type: make a function maybe async + +export type Todo = any diff --git a/src/user/index.js b/src/user/index.js new file mode 100644 index 000000000..925141ca0 --- /dev/null +++ b/src/user/index.js @@ -0,0 +1,50 @@ +import { computeAddress } from '@ethersproject/transactions' +import { Web3Provider } from '@ethersproject/providers' +import { hexlify } from '@ethersproject/bytes' +import { sha256 } from '@ethersproject/sha2' + +async function getUsername(client) { + const { options: { auth = {} } = {} } = client + if (auth.username) { return auth.username } + + const { username, id } = await client.cached.getUserInfo() + return ( + username + // edge case: if auth.apiKey is an anonymous key, userInfo.id is that anonymous key + || id + ) +} + +export async function getAddressFromOptions({ ethereum, privateKey } = {}) { + if (privateKey) { + return computeAddress(privateKey).toLowerCase() + } + + if (ethereum) { + const provider = new Web3Provider(ethereum) + const address = await provider.getSigner().getAddress() + return address.toLowerCase() + } + + throw new Error('Need either "privateKey" or "ethereum".') +} + +export async function getUserId(client) { + if (client.session.isUnauthenticated()) { + throw new Error('Need to be authenticated to getUserId.') + } + + const { options: { auth = {} } = {} } = client + if (auth.ethereum || auth.privateKey) { + return getAddressFromOptions(auth) + } + + const username = await getUsername(client) + + if (username != null) { + const hexString = hexlify(Buffer.from(username, 'utf8')) + return sha256(hexString) + } + + throw new Error('Need either "privateKey", "ethereum", "apiKey", "username"+"password" or "sessionToken" to derive the publisher Id.') +} diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index ec43d0da0..000000000 --- a/src/utils.js +++ /dev/null @@ -1,41 +0,0 @@ -import { v4 as uuidv4 } from 'uuid' -import uniqueId from 'lodash.uniqueid' - -import pkg from '../package.json' - -const UUID = uuidv4() - -export function uuid(label = '') { - return uniqueId(`${UUID}${label ? `.${label}` : ''}`) // incrementing + human readable uuid -} - -export function getVersionString() { - const isProduction = process.env.NODE_ENV === 'production' - return `${pkg.version}${!isProduction ? 'dev' : ''}` -} - -/** - * Converts a .once event listener into a promise. - * Rejects if an 'error' event is received before resolving. - */ - -export function waitFor(emitter, event) { - return new Promise((resolve, reject) => { - let onError - const onEvent = (value) => { - emitter.off('error', onError) - resolve(value) - } - onError = (error) => { - emitter.off(event, onEvent) - reject(error) - } - - emitter.once(event, onEvent) - emitter.once('error', onError) - }) -} - -export const getEndpointUrl = (baseUrl, ...pathParts) => { - return baseUrl + '/' + pathParts.map((part) => encodeURIComponent(part)).join('/') -} diff --git a/src/utils/AggregatedError.ts b/src/utils/AggregatedError.ts new file mode 100644 index 000000000..a68c5b942 --- /dev/null +++ b/src/utils/AggregatedError.ts @@ -0,0 +1,93 @@ +/** + * An Error of Errors + * Pass an array of errors + message to create + * Single error without throwing away other errors + * Specifically not using AggregateError name as this has slightly different API + * + * See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError + */ + +function joinMessages(msgs: (string | undefined)[]): string { + return msgs.filter(Boolean).join('\n') +} + +export default class AggregatedError extends Error { + errors: Set + ownMessage?: string + constructor(errors: Error[] = [], errorMessage = '') { + const message = joinMessages([ + errorMessage, + ...errors.map((err) => err.message) + ]) + super(message) + this.ownMessage = errorMessage + this.errors = new Set(errors) + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor) + } + } + + /** + * Combine any errors from Promise.allSettled into AggregatedError. + */ + static fromAllSettled(results = [], errorMessage = '') { + const errs = results.map(({ reason }) => reason).filter(Boolean) + if (!errs.length) { + return undefined + } + + return new this(errs, errorMessage) + } + + /** + * Combine any errors from Promise.allSettled into AggregatedError and throw it. + */ + static throwAllSettled(results = [], errorMessage = '') { + const err = this.fromAllSettled(results, errorMessage) + if (err) { + throw err + } + } + + /** + * Handles 'upgrading' an existing error to an AggregatedError when necesary. + */ + static from(oldErr?: Error | AggregatedError, newErr?: Error, msg?: string) { + if (!newErr) { + if (oldErr && msg) { + // copy message + oldErr.message = joinMessages([oldErr.message, msg]) // eslint-disable-line no-param-reassign + } + return oldErr + } + + // When no oldErr, just return newErr + if (!oldErr) { + if (newErr && msg) { + // copy message + newErr.message = joinMessages([newErr.message, msg]) // eslint-disable-line no-param-reassign + } + return newErr + } + + // When oldErr is an AggregatedError, extend it + if (oldErr instanceof AggregatedError) { + return oldErr.extend(newErr, msg, this) + } + + // Otherwise create new AggregatedError from oldErr and newErr + return new this([oldErr]).extend(newErr, msg) + } + + /** + * Create a new error that adds err to list of errors + */ + + extend(err: Error, message = '', baseClass = this.constructor): AggregatedError { + if (err === this || this.errors.has(err)) { + return this + } + const errors = [err, ...this.errors] + return new ( baseClass)(errors, joinMessages([message, this.ownMessage])) + } +} diff --git a/src/utils/PushQueue.js b/src/utils/PushQueue.js new file mode 100644 index 000000000..adab5e0a8 --- /dev/null +++ b/src/utils/PushQueue.js @@ -0,0 +1,345 @@ +import { CancelableGenerator } from './iterators' // eslint-disable-line import/no-cycle + +import { pOrderedResolve } from './index' + +export class AbortError extends Error { + constructor(msg = '', ...args) { + super(`The operation was aborted. ${msg}`, ...args) + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor) + } + } +} + +/** + * Async Iterable PushQueue + * On throw/abort any items in buffer will be flushed before iteration throws. + * Heavily based on (upcoming) events.on API in node: + * https://github.com/nodejs/node/blob/e36ffb72bebae55091304da51837ca204367dc16/lib/events.js#L707-L826 + * + * const queue = new PushQueue([item1], { + * signal: abortController.signal // optional + * }) + * queue.push(item2, item3) // supports pushing multiple at once + * setTimeout(() => { + * queue.push(item4) // push asynchronously, iterator will wait + * queue.return() // need to explicitly end iteration or it will continue forever + * queue.throw(err) // force the queue to throw + * abortController.abort() // alternative + * }) + * + * try { + * for await (const m of queue) { + * console.log(m) + * break // this calls await queue.return() + * } + * } catch (err) { + * // queue threw an error + * } finally { + * // run clean up after iteration success/error + * } + * + */ + +export default class PushQueue { + constructor(items = [], { signal, onEnd, timeout = 0, autoEnd = true } = {}) { + this.autoEnd = autoEnd + this.buffer = [...items] + this.finished = false + this.error = null // queued error + this.nextQueue = [] // queued promises for next() + this.pending = 0 + this._onEnd = onEnd + this.timeout = timeout + + this[Symbol.asyncIterator] = this[Symbol.asyncIterator].bind(this) + this.onAbort = this.onAbort.bind(this) + this.onEnd = this.onEnd.bind(this) + this.cancel = this.cancel.bind(this) + this.end = this.end.bind(this) + + // abort signal handling + this.signal = signal + if (signal) { + if (signal.aborted) { + this.onAbort() + } + + signal.addEventListener('abort', this.onAbort, { + once: true + }) + } + + this.iterator = this.iterate() + } + + static from(iterable, opts = {}) { + const queue = new PushQueue([], opts) + queue.from(iterable) + return queue + } + + static transform(src, fn, opts = {}) { + const buffer = new PushQueue([], opts) + const orderedFn = pOrderedResolve(fn) // push must be run in sequence + ;(async () => { // eslint-disable-line semi-style + const tasks = [] + for await (const value of src) { + // run in parallel + const task = orderedFn(value).then(() => ( + buffer.push(value) + )).catch((err) => { + buffer.throw(err) + }) + tasks.push(task) + } + await Promise.all(tasks) + if (buffer.autoEnd) { + buffer.end() + } + })().catch((err) => { + return buffer.throw(err) + }) // no await + + return buffer + } + + async from(iterable, { end = this.autoEnd } = {}) { + try { + // detect sync/async iterable and iterate appropriately + if (!iterable[Symbol.asyncIterator]) { + // sync iterables push into buffer immediately + for (const item of iterable) { + this.push(item) + } + } else { + for await (const item of iterable) { + this.push(item) + } + } + } catch (err) { + return this.throw(err) + } + + if (end) { + this.end() + } + + return Promise.resolve() + } + + onEnd(...args) { + if (this._onEndCalled || !this._onEnd) { + return Promise.resolve() + } + + this._onEndCalled = true + return this._onEnd(...args) + } + + /** + * signals no more data should be buffered + */ + + end(v) { + if (this.ended) { + return + } + + if (v != null) { + this.push(v) + } + + this.push(null) + this.ended = true + } + + onAbort() { + return this.throw(new AbortError()) + } + + async next(...args) { + return this.iterator.next(...args) + } + + isWritable() { + return !(this.finished || this.ended) + } + + isReadable() { + return !(this.finished || this.ended) + } + + async return() { + this.finished = true + await this._cleanup() + } + + async throw(err) { + this.finished = true + const p = this.nextQueue.shift() + if (p) { + p.reject(err) + } else { + // for next() + this.error = err + } + + return this.return() + } + + get length() { + const count = this.pending + this.buffer.length + return this.ended && count ? count - 1 : count + } + + _cleanup() { + this.finished = true + for (const p of this.nextQueue) { + p.resolve() + } + this.pending = 0 + this.buffer.length = 0 + return this.onEnd(this.error) + } + + push(...values) { + if (this.finished || this.ended) { + // do nothing if done + return + } + + // if values contains null, treat null as end + const nullIndex = values.findIndex((v) => v === null) + if (nullIndex !== -1) { + this.ended = true + // include null but trim rest + values = values.slice(0, nullIndex + 1) // eslint-disable-line no-param-reassign + } + + // resolve pending next calls + while (this.nextQueue.length && values.length) { + const p = this.nextQueue.shift() + p.resolve(values.shift()) + } + + // push any remaining values into buffer + if (values.length) { + this.buffer.push(...values) + } + } + + iterate() { // eslint-disable-line class-methods-use-this + const handleTerminalValues = (value) => { + // returns final task to perform before returning, or false + if (value === null) { + return this.return() + } + + if (value instanceof Error) { + return this.throw(value) + } + + return false + } + + const [cancel, itr] = CancelableGenerator(async function* iterate() { + while (true) { + /* eslint-disable no-await-in-loop */ + // feed from buffer first + const buffer = this.buffer.slice() + this.pending += buffer.length + this.buffer.length = 0 // prevent endless loop + while (buffer.length && !this.error && !this.finished) { + this.pending = Math.max(this.pending - 1, 0) + const value = buffer.shift() + const endTask = handleTerminalValues(value) + if (endTask) { + await endTask + break + } + + yield value + } + + // handle queued error + if (this.error) { + const err = this.error + this.error = null + throw err + } + + // done + if (this.finished) { + return + } + + // if more items have been buffered, continue loop + if (this.buffer.length) { + continue // eslint-disable-line no-continue + } + + const deferred = new Promise((resolve, reject) => { + // wait for next push + this.nextQueue.push({ + resolve, + reject, + }) + }) + + deferred.catch(() => {}) // prevent unhandledrejection + const value = await deferred + + // ignore value if finished + if (this.finished) { + return + } + + const endTask = handleTerminalValues(value) + if (endTask) { + await endTask + continue // eslint-disable-line no-continue + } + + yield value + /* eslint-enable no-await-in-loop */ + } + }.call(this), async (err) => { + return this.onEnd(err) + }, { + timeout: this.timeout, + }) + + return Object.assign(itr, { + cancel, + }) + } + + pipe(next, opts) { + return next.from(this, opts) + } + + async cancel(...args) { + this.finished = true + return this.iterator.cancel(...args) + } + + isCancelled(...args) { + return this.iterator.isCancelled(...args) + } + + async* [Symbol.asyncIterator]() { + // NOTE: consider throwing if trying to iterate after finished + // or maybe returning a new iterator? + try { + yield* this.iterator + } finally { + this.finished = true + if (this.signal) { + this.signal.removeEventListener('abort', this.onAbort, { + once: true, + }) + } + } + } +} diff --git a/src/utils/Scaffold.ts b/src/utils/Scaffold.ts new file mode 100644 index 000000000..1adc7ae16 --- /dev/null +++ b/src/utils/Scaffold.ts @@ -0,0 +1,190 @@ +import pLimit from 'p-limit' + +import { MaybeAsync } from '../types' +import AggregatedError from './AggregatedError' + +/** + * Takes a sequence of async steps & a check function. + * While check function is true, will execute steps in order until all done. + * Each step optionally returns a cleanup function. + * If/when check fails (or there's an error) cleanup functions will be executed in order. + * onChange fires when up/down direction changes. + * onDone fires when no more up/down steps to execute. + * onError fires when something errors. Rethrow in onError to keep error, don't rethrow to suppress. + * returns a function which should be called whenever something changes that could affect the check. + */ +type Step = StepUp | MaybeAsync<() => void> // possibly no StepDown +type StepUp = MaybeAsync<() => StepDown> +type StepDown = MaybeAsync<() => void> + +type ScaffoldOptions = { + onError?: (error: Error) => void + onDone?: MaybeAsync<(shouldUp: boolean, error?: Error) => void> + onChange?: MaybeAsync<(shouldUp: boolean) => void> +} + +const noop = () => {} + +export default function Scaffold( + sequence: Step[] = [], + _checkFn: () => Promise, + { onError, onDone, onChange }: ScaffoldOptions = {} +) { + let error: Error | undefined + // ignore error if check fails + + const nextSteps: StepUp[] = sequence.slice().reverse().map((fn) => ( + async () => { + const downFn = await fn() + return ( + typeof downFn === 'function' + ? downFn + : noop + ) + } + )) + + const prevSteps: StepUp[] = [] + const onDownSteps: StepDown[] = [] + const queue = pLimit(1) + + let isDone = false + let didStart = false + + function collectErrors(err: Error) { + try { + if (typeof onError === 'function') { + onError(err) // give option to suppress error + } else { + throw err // rethrow + } + } catch (newErr) { + error = AggregatedError.from(error, newErr) + } + } + + const checkShouldUp = async () => { + if (error) { return false } + try { + return await _checkFn() + } catch (err) { + collectErrors(err) + } + return false + } + + let shouldUp = false + let prevShouldUp = false + const innerQueue = pLimit(1) + + async function next(): Promise { + shouldUp = await checkShouldUp() + const didChange = prevShouldUp !== shouldUp + prevShouldUp = shouldUp + if (didChange && typeof onChange === 'function') { + try { + await onChange(shouldUp) + } catch (err) { + collectErrors(err) + } + return next() + } + + if (shouldUp) { + if (nextSteps.length) { + isDone = false + didStart = true + let onDownStep + const stepFn = nextSteps.pop() as StepUp + prevSteps.push(stepFn) + try { + onDownStep = await stepFn() + } catch (err) { + collectErrors(err) + } + onDownSteps.push(onDownStep || (() => {})) + return next() + } + } else if (onDownSteps.length) { + isDone = false + didStart = true + const stepFn = onDownSteps.pop() as StepDown // exists because checked onDownSteps.length + try { + await stepFn() + } catch (err) { + collectErrors(err) + } + nextSteps.push(prevSteps.pop() as StepUp) + return next() + } else if (error) { + const err = error + // eslint-disable-next-line require-atomic-updates + error = undefined + isDone = true + throw err + } + + isDone = true + + return Promise.resolve() + } + + function isActive() { + return !( + didStart + && isDone + && !queue.activeCount + && !queue.pendingCount + ) + } + + const nextDone = async () => { + await innerQueue(() => next()) + } + + let currentStep: Promise + const queuedNext = async () => { + let stepErr + try { + currentStep = queue(() => nextDone()) + await currentStep + } catch (err) { + stepErr = err + throw err + } finally { + if (!isActive()) { + didStart = false + if (typeof onDone === 'function') { + const err = stepErr + stepErr = undefined + await onDone(shouldUp, err) + } + } + } + } + + return Object.assign(queuedNext, { + next: nextDone, + isActive, + getCurrentStep() { + return currentStep + }, + get activeCount() { + return queue.activeCount + }, + get pendingCount() { + return queue.pendingCount + }, + setError(err: Error) { + error = AggregatedError.from(error, err) + }, + getError() { + return error + }, + clearError() { + const err = error + error = undefined + return err + } + }) +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 000000000..a0788f679 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,474 @@ +import { inspect } from 'util' +import EventEmitter from 'events' + +import { v4 as uuidv4 } from 'uuid' +import uniqueId from 'lodash.uniqueid' +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' +import Scaffold from './Scaffold' + +export { AggregatedError, Scaffold } + +const UUID = uuidv4() + +/* + * Incrementing + human readable uuid + */ + +export function uuid(label = '') { + return uniqueId(`${UUID}${label ? `.${label}` : ''}`) +} + +export function randomString(length = 20) { + // eslint-disable-next-line no-bitwise + return [...Array(length)].map(() => (~~(Math.random() * 36)).toString(36)).join('') +} + +/** + * Generates counter-based ids. + * Basically lodash.uniqueid but per-prefix. + * Not universally unique. + * Generally useful for tracking instances. + * + * Careful not to use too many prefixes since it needs to hold all prefixes in memory + * e.g. don't pass new uuid as a prefix + * + * counterId('test') => test.0 + * counterId('test') => test.1 + */ + +export const counterId = (() => { + const MAX_PREFIXES = 256 + let counts: { [prefix: string]: number } = {} // possible we could switch this to WeakMap and pass functions or classes. + let didWarn = false + const counterIdFn = (prefix = 'ID') => { + // pedantic: wrap around if count grows too large + counts[prefix] = (counts[prefix] + 1 || 0) % Number.MAX_SAFE_INTEGER + + // warn once if too many prefixes + if (!didWarn) { + const numTracked = Object.keys(counts).length + if (numTracked > MAX_PREFIXES) { + didWarn = true + console.warn(`counterId should not be used for a large number of unique prefixes: ${numTracked} > ${MAX_PREFIXES}`) + } + } + + return `${prefix}.${counts[prefix]}` + } + + /** + * Clears counts for prefix or all if no prefix supplied. + * + * @param {string?} prefix + */ + counterIdFn.clear = (...args: [string] | []) => { + // check length to differentiate between clear(undefined) & clear() + if (args.length) { + const [prefix] = args + delete counts[prefix] + } else { + // clear all + counts = {} + } + } + return counterIdFn +})() + +export function getVersionString() { + const isProduction = process.env.NODE_ENV === 'production' + return `${pkg.version}${!isProduction ? 'dev' : ''}` +} + +/** + * Converts a .once event listener into a promise. + * Rejects if an 'error' event is received before resolving. + */ + +export function waitFor(emitter: EventEmitter, event: Parameters[0]) { + return new Promise((resolve, reject) => { + let onError: (error: Error) => void + const onEvent = (value: any) => { + emitter.off('error', onError) + resolve(value) + } + onError = (error) => { + emitter.off(event, onEvent) + reject(error) + } + + emitter.once(event, onEvent) + emitter.once('error', onError) + }) +} + +export const getEndpointUrl = (baseUrl: string, ...pathParts: string[]) => { + return baseUrl + '/' + pathParts.map((part) => encodeURIComponent(part)).join('/') +} + +type Collection = { + keys: Map['keys'] + delete: Map['delete'] +} + +function clearMatching(cache: Collection, matchFn: (key: unknown) => boolean) { + for (const key of cache.keys()) { + if (matchFn(key)) { + cache.delete(key) + } + } +} + +/* eslint-disable object-curly-newline */ + +/** + * Returns a cached async fn, cached keyed on first argument passed. See documentation for mem/p-memoize. + * Caches into a LRU cache capped at options.maxSize + * Won't call asyncFn again until options.maxAge or options.maxSize exceeded, or cachedAsyncFn.clear() is called. + * Won't cache rejections by default. Override with options.cachePromiseRejection = true. + * + * ```js + * const cachedAsyncFn = CacheAsyncFn(asyncFn, options) + * await cachedAsyncFn(key) + * await cachedAsyncFn(key) + * cachedAsyncFn.clear() + * ``` + */ + +export function CacheAsyncFn(asyncFn: Parameters[0], { + maxSize = 10000, + maxAge = 30 * 60 * 1000, // 30 minutes + cachePromiseRejection = false, + onEviction = () => {}, + ...opts +} = {}) { + const cache = new LRU({ + maxSize, + maxAge, + onEviction, + }) + + const cachedFn = Object.assign(pMemoize(asyncFn, { + maxAge, + cachePromiseRejection, + cache, + ...opts, + }), { + clear: () => pMemoize.clear(cachedFn), + clearMatching: (...args: L.Tail>) => clearMatching(cache, ...args), + }) + + return cachedFn +} + +/** + * Returns a cached fn, cached keyed on first argument passed. See documentation for mem. + * Caches into a LRU cache capped at options.maxSize + * Won't call fn again until options.maxAge or options.maxSize exceeded, or cachedFn.clear() is called. + * + * ```js + * const cachedFn = CacheFn(fn, options) + * cachedFn(key) + * cachedFn(key) + * cachedFn(...args) + * cachedFn.clear() + * ``` + */ + +export function CacheFn(fn: Parameters[0], { + maxSize = 10000, + maxAge = 30 * 60 * 1000, // 30 minutes + onEviction = () => {}, + ...opts +} = {}) { + const cache = new LRU({ + maxSize, + maxAge, + onEviction, + }) + + const cachedFn = Object.assign(mem(fn, { + maxAge, + cache, + ...opts, + }), { + clear: () => mem.clear(cachedFn), + clearMatching: (...args: L.Tail>) => clearMatching(cache, ...args), + }) + + return cachedFn +} + +/* eslint-enable object-curly-newline */ + +/** + * Deferred promise allowing external control of resolve/reject. + * Returns a Promise with resolve/reject functions attached. + * Also has a wrap(fn) method that wraps a function to settle this promise + * Also has a wrapError(fn) method that wraps a function to settle this promise if error + * Defer optionally takes executor function ala `new Promise(executor)` + */ +type PromiseResolve = L.Compulsory['then']>>[0] +type PromiseReject = L.Compulsory['then']>>[1] + +export function Defer(executor: (...args: Parameters['then']>) => void = () => {}) { + let resolve: PromiseResolve = () => {} + let reject: PromiseReject = () => {} + // eslint-disable-next-line promise/param-names + const p = new Promise((_resolve, _reject) => { + resolve = _resolve + reject = _reject + executor(resolve, reject) + }) + + function wrap(fn: F.Function) { + return async (...args: unknown[]) => { + try { + return resolve(await fn(...args)) + } catch (err) { + reject(err) + } + return Promise.resolve() + } + } + + function wrapError(fn: F.Function) { + return async (...args: unknown[]) => { + try { + return await fn(...args) + } catch (err) { + reject(err) + } + return Promise.resolve() + } + } + + function handleErrBack(err: Error) { + if (err) { + reject(err) + } else { + resolve(undefined) + } + } + + return Object.assign(p, { + resolve, + reject, + wrap, + wrapError, + handleErrBack + }) +} + +/** + * Returns a limit function that limits concurrency per-key. + * + * ```js + * const limit = LimitAsyncFnByKey(1) + * limit('channel1', fn) + * limit('channel2', fn) + * limit('channel2', fn) + * ``` + */ + +export function LimitAsyncFnByKey(limit = 1) { + const pending = new Map() + const queueOnEmptyTasks = new Map() + const f = async (id: KeyType, fn: () => Promise) => { + const limitFn = pending.get(id) || pending.set(id, pLimit(limit)).get(id) + const onQueueEmpty = queueOnEmptyTasks.get(id) || queueOnEmptyTasks.set(id, Defer()).get(id) + try { + return await limitFn(fn) + } finally { + if (!limitFn.activeCount && !limitFn.pendingCount) { + if (pending.get(id) === limitFn) { + // clean up if no more active entries (if not cleared) + pending.delete(id) + } + queueOnEmptyTasks.delete(id) + onQueueEmpty.resolve() + } + } + } + + f.getOnQueueEmpty = async (id: KeyType) => { + return queueOnEmptyTasks.get(id) || pending.set(id, Defer()).get(id) + } + + f.clear = () => { + // note: does not cancel promises + pending.forEach((p) => p.clearQueue()) + pending.clear() + queueOnEmptyTasks.forEach((p) => p.resolve()) + queueOnEmptyTasks.clear() + } + return f +} + +/** + * Execute functions in parallel, but ensure they resolve in the order they were executed + */ + +export function pOrderedResolve(fn: F.Function) { + const queue = pLimit(1) + return async (...args: Parameters) => { + const d = Defer() + const done = queue(() => d) + // eslint-disable-next-line promise/catch-or-return + await Promise.resolve(fn(...args)).then(d.resolve, d.reject) + return done + } +} + +/** + * Returns a function that executes with limited concurrency. + */ + +export function pLimitFn(fn: F.Function, limit = 1) { + const queue = pLimit(limit) + return (...args: unknown[]) => queue(() => fn(...args)) +} + +/** + * Only allows one outstanding call. + * Returns same promise while task is executing. + */ + +export function pOne(fn: F.Function) { + let inProgress: Promise | undefined + return (...args: Parameters) => { + if (!inProgress) { + inProgress = Promise.resolve(fn(...args)).finally(() => { + inProgress = undefined + }) + } + + return inProgress + } +} + +export class TimeoutError extends Error { + timeout: number + constructor(msg = '', timeout = 0) { + super(`The operation timed out. ${timeout}ms. ${msg}`) + this.timeout = timeout + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor) + } + } +} + +/** + * Takes a promise and a timeout and an optional message for timeout errors. + * Returns a promise that rejects when timeout expires, or when promise settles, whichever comes first. + * + * Invoke with positional arguments for timeout & message: + * await pTimeout(promise, timeout, message) + * + * or using an options object for timeout, message & rejectOnTimeout: + * + * await pTimeout(promise, { timeout, message, rejectOnTimeout }) + * + * message and rejectOnTimeout are optional. + */ + +type pTimeoutOpts = { + timeout?: number, + message?: string, + rejectOnTimeout?: boolean, +} + +type pTimeoutArgs = [timeout?: number, message?: string] | [pTimeoutOpts] + +export async function pTimeout(promise: Promise, ...args: pTimeoutArgs) { + let opts: pTimeoutOpts = {} + if (args[0] && typeof args[0] === 'object') { + [opts] = args + } else { + [opts.timeout, opts.message] = args + } + + const { timeout = 0, message = '', rejectOnTimeout = true } = opts + + if (typeof timeout !== 'number') { + throw new Error(`timeout must be a number, got ${inspect(timeout)}`) + } + + let timedOut = false + let t: ReturnType + return Promise.race([ + Promise.resolve(promise).catch((err) => { + if (timedOut) { + // ignore errors after timeout + return + } + + throw err + }), + new Promise((resolve, reject) => { + t = setTimeout(() => { + timedOut = true + if (rejectOnTimeout) { + reject(new TimeoutError(message, timeout)) + } else { + resolve(undefined) + } + }, timeout) + }) + ]).finally(() => { + clearTimeout(t) + }) +} + +/** + * Convert allSettled results into a thrown Aggregate error if necessary. + */ + +export async function allSettledValues(items: Parameters, errorMessage = '') { + const result = await Promise.allSettled(items) + const errs = result + .filter(({ status }) => status === 'rejected') + .map((v) => (v as PromiseRejectedResult).reason) + if (errs.length) { + throw new AggregatedError(errs, errorMessage) + } + + return result + .map((v) => (v as PromiseFulfilledResult).value) +} + +export async function sleep(ms: number = 0) { + return new Promise((resolve) => { + setTimeout(resolve, ms) + }) +} + +/** + * Wait until a condition is true + * @param {function(): Promise|function(): boolean} condition wait until this callback function returns true + * @param {number} [timeOutMs=10000] stop waiting after that many milliseconds, -1 for disable + * @param {number} [pollingIntervalMs=100] check condition between so many milliseconds + */ +export async function until(condition: MaybeAsync<() => boolean>, timeOutMs = 10000, pollingIntervalMs = 100) { + let timeout = false + if (timeOutMs > 0) { + setTimeout(() => { timeout = true }, timeOutMs) + } + + // Promise wrapped condition function works for normal functions just the same as Promises + while (!await Promise.resolve().then(condition)) { // eslint-disable-line no-await-in-loop + if (timeout) { + throw new Error(`Timeout after ${timeOutMs} milliseconds`) + } + await sleep(pollingIntervalMs) // eslint-disable-line no-await-in-loop + } + return condition() +} diff --git a/src/utils/iterators.js b/src/utils/iterators.js new file mode 100644 index 000000000..bfb70ffba --- /dev/null +++ b/src/utils/iterators.js @@ -0,0 +1,406 @@ +import pMemoize from 'p-memoize' + +import { Defer, pTimeout, allSettledValues, AggregatedError } from './index' + +/** + * Allows injecting a function to execute after an iterator finishes. + * Executes finally function even if generator not started. + * Returns new generator. + */ + +export function iteratorFinally(iterable, onFinally) { + if (!onFinally) { + // noop if no onFinally + return iterable + } + + let started = false + let ended = false + let error + + // ensure finally only runs once + const onFinallyOnce = pMemoize(onFinally, { + cachePromiseRejection: true, // don't run again if failed + cacheKey: () => true // always same key + }) + + // wraps return/throw to call onFinally even if generator was never started + const handleFinally = (originalFn) => async (...args) => { + // Important to: + // * only await onFinally if not started + // * call original return/throw *immediately* in either case + // Otherwise: + // * if started, iterator won't stop until onFinally finishes + // * if not started, iterator can still be started before onFinally finishes + // This function handles both cases, but note here as a reminder. + ended = true + if (started) { + return originalFn(...args) + } + + // otherwise iteration can still start if finally function still pending + try { + return await originalFn(...args) + } catch (err) { + if (!error) { + error = err + } + throw err + } finally { + await onFinallyOnce(error) + } + } + + // wrap in generator to track if generator was started + const g = (async function* TrackStarted() { + started = true + try { + yield* iterable + } catch (err) { + if (!error) { + error = err + } + throw err + } finally { + await onFinallyOnce(error) + } + }()) + + const it = g[Symbol.asyncIterator].bind(g) + + // copy cancel api across if exists + if (iterable.cancel) { + g.cancel = (...args) => iterable.cancel(...args) + g.isCancelled = (...args) => iterable.isCancelled(...args) + } + + // replace generator methods + return Object.assign(g, { + return: handleFinally(g.return.bind(g)), + throw: handleFinally(g.throw.bind(g)), + [Symbol.asyncIterator]() { + // if ended before started + if (ended && !started) { + // return a generator that simply runs finally script (once) + return (async function* generatorRunFinally() { // eslint-disable-line require-yield + try { + if (typeof iterable.return === 'function') { + await iterable.return() // runs onFinally for nested iterable + } + } finally { + await onFinallyOnce() + } + }()) + } + + return it() + } + }) +} + +async function endGenerator(gtr, error) { + return error + ? gtr.throw(error).catch(() => {}) // ignore err + : gtr.return() +} + +function canCancel(gtr) { + return ( + gtr + && typeof gtr.cancel === 'function' + && typeof gtr.isCancelled === 'function' + && !gtr.isCancelled() + ) +} + +async function cancelGenerator(gtr, error) { + if (!canCancel(gtr)) { return } + await gtr.cancel(error) +} + +const endGeneratorTimeout = pMemoize(async (gtr, error, timeout = 250) => { + await pTimeout(endGenerator(gtr, error), { + timeout, + rejectOnTimeout: false, + }) + + if (canCancel(gtr)) { + await cancelGenerator(gtr, error) + } +}, { + cachePromiseRejection: true, +}) + +/** + * Creates a generator that can be cancelled and perform optional final cleanup. + * const [cancal, generator] = CancelableGenerator(iterable, onFinally) + */ + +export function CancelableGenerator(iterable, onFinally = () => {}, { timeout = 250 } = {}) { + let started = false + let cancelled = false + let finalCalled = false + let pendingNextCount = 0 + let error + + const onCancel = Defer() + const onDone = Defer() + + let iterator + + async function cancelIterable(err) { + // cancel inner if has cancel + await cancelGenerator(iterable, err) + await cancelGenerator(iterator, err) + } + + function collectErrors(value) { + if (!value || value === error) { return } + + if (!error) { + error = value + return + } + + error = error.extend + ? error.extend(value, value.message) + : new AggregatedError([value, error], value.message) + } + + function resolveCancel(value) { + if (value instanceof Error) { + collectErrors(value) + } + + if (error) { + onCancel.reject(error) + if (!started) { + onCancel.catch(() => {}) + } + } else { + onCancel.resolve({ + value, + done: true, + }) + } + } + + const cancel = (gtr) => async (value) => { + if (cancelled || finalCalled) { + // prevent recursion + return onDone + } + + cancelled = true + resolveCancel(value) + + // need to make sure we don't try return inside final otherwise we end up deadlocked + await endGeneratorTimeout(gtr, error, timeout) + return onDone + } + + async function* CancelableGeneratorFn() { + started = true + + // manually iterate + iterator = iterable[Symbol.asyncIterator]() + + // keep track of pending calls to next() + // so we can cancel early if nothing pending + async function next(...args) { + // use symbol instead of true so we can tell if called multiple times + // see === comparison below + pendingNextCount += 1 + try { + return await iterator.next(...args) + } finally { + pendingNextCount = Math.max(0, pendingNextCount - 1) // eslint-disable-line require-atomic-updates + } + } + + try { + yield* { + // here is the meat: + // each next() races against cancel promise + next: async (...args) => Promise.race([ + next(...args), + onCancel, + ]), + async throw(err) { + await endGeneratorTimeout(iterator, err, timeout) + throw err + }, + async return(v) { + await endGeneratorTimeout(iterator, error, timeout) + return { + value: v, + done: true, + } + }, + [Symbol.asyncIterator]() { + return this + }, + } + } finally { + // try end iterator + if (iterator) { + await endGeneratorTimeout(iterator, error, timeout) + } + } + } + + const cancelableGenerator = iteratorFinally(CancelableGeneratorFn(), async (err) => { + finalCalled = true + try { + // cancel inner if has cancel + await cancelIterable(err || error) + await onFinally(err || error) + } finally { + onDone.resolve() + } + + // error whole generator, for await of will reject. + if (error) { + throw error + } + + return onDone + }) + + const cancelFn = cancel(cancelableGenerator) + + Object.assign(cancelableGenerator, { + cancel: cancelFn, + timeout, + isCancelled: () => cancelled, + isDone: () => finalCalled, + }) + + return [ + cancelFn, + cancelableGenerator + ] +} + +/** + * Pipeline of async generators + */ + +const isPipeline = Symbol('isPipeline') + +const getIsStream = (item) => typeof item.from === 'function' + +export function pipeline(iterables = [], onFinally = () => {}, { end, ...opts } = {}) { + const cancelFns = new Set() + let cancelled = false + let error + let finallyCalled = false + const onCancelDone = Defer() + let pipelineValue + + const cancelAll = async (err) => { + if (cancelled) { + await onCancelDone + return + } + + cancelled = true + error = err + try { + // eslint-disable-next-line promise/no-promise-in-callback + await allSettledValues([...cancelFns].map(async ({ isCancelled, cancel }) => ( + isCancelled ? cancel(err) : undefined + ))) + } finally { + cancelFns.clear() + } + } + + const cancel = async (err) => { + if (finallyCalled) { + return + } + + try { + if (cancelled) { + await onCancelDone + return + } + + if (error) { + // eslint-disable-next-line promise/no-promise-in-callback + pipelineValue.throw(error).catch(() => {}) // ignore err + } else { + pipelineValue.return() + } + await cancelAll(err) + await onCancelDone + } finally { + await true + } + } + + let firstSrc + const setFirstSource = (v) => { + cancelFns.add(v) + firstSrc = v + } + + const last = iterables.reduce((_prev, next, index) => { + let prev + let nextIterable + + const [, it] = CancelableGenerator((async function* Gen() { + prev = index === 0 ? firstSrc : _prev + // take first "prev" from outer iterator, if one exists + nextIterable = typeof next === 'function' ? next(prev) : next + + if (prev && nextIterable[isPipeline]) { + nextIterable.setFirstSource(prev) + } + + if (nextIterable.cancel) { + cancelFns.add(nextIterable) + } + + if (prev && nextIterable && getIsStream(nextIterable)) { + prev.id = prev.id || 'inter-' + nextIterable.id + nextIterable.from(prev, { end }) + } + + yield* nextIterable + }()), async (err) => { + if (!error && err && error !== err) { + error = err + } + }, opts) + + cancelFns.add(it) + return it + }, undefined) + + pipelineValue = iteratorFinally(last, async () => { + if (!cancelled) { + await cancelAll(error) + } + cancelFns.clear() + try { + finallyCalled = true + await onFinally(error) + finallyCalled = false + if (error) { + throw error + } + } finally { + onCancelDone.resolve() + await onCancelDone + } + }) + + return Object.assign(pipelineValue, { + [isPipeline]: true, + isCancelled: () => cancelled, + setFirstSource, + cancel, + }) +} diff --git a/test/benchmarks/publish.js b/test/benchmarks/publish.js index 3da517663..131cca6b4 100644 --- a/test/benchmarks/publish.js +++ b/test/benchmarks/publish.js @@ -1,71 +1,142 @@ +const { format } = require('util') const { Benchmark } = require('benchmark') -const { ethers } = require('ethers') // eslint-disable-next-line import/no-unresolved -const StreamrClient = require('../../dist/streamr-client.nodejs.js') +const StreamrClient = require('../../dist') const config = require('../integration/config') -const client1 = new StreamrClient({ - auth: { - privateKey: ethers.Wallet.createRandom().privateKey, - }, - autoConnect: true, - ...config.clientOptions -}) - -const client2 = new StreamrClient({ - auth: { - apiKey: 'tester1-api-key' - }, - publishWithSignature: 'never', - autoConnect: true, - ...config.clientOptions -}) - -const msg = { - msg: 'test' +/* eslint-disable no-console */ + +let count = 100000 // pedantic: use large initial number so payload size is similar +const Msg = () => { + count += 1 + return { + msg: `msg${count}` + } } +function createClient(opts) { + return new StreamrClient({ + ...config.clientOptions, + ...opts, + }) +} + +async function setupClientAndStream(clientOpts, streamOpts) { + const client = createClient(clientOpts) + await client.connect() + await client.session.getSessionToken() + + const stream = await client.createStream({ + name: `test-stream.${client.id}`, + ...streamOpts, + }) + return [client, stream] +} + +const BATCH_SIZES = [ + 1, + 4, + 16, + 64 +] + +const log = (...args) => process.stderr.write(format(...args) + '\n') + async function run() { - const stream1 = await client1.getOrCreateStream({ - name: 'node-example-data', + const account1 = StreamrClient.generateEthereumAccount() + const [client1, stream1] = await setupClientAndStream({ + auth: { + privateKey: account1.privateKey, + }, + publishWithSignature: 'always', + }) + + const account2 = StreamrClient.generateEthereumAccount() + const [client2, stream2] = await setupClientAndStream({ + auth: { + privateKey: account2.privateKey, + }, + publishWithSignature: 'never', }) - const stream2 = await client2.getOrCreateStream({ - name: 'node-example-data', + const account3 = StreamrClient.generateEthereumAccount() + const [client3, stream3] = await setupClientAndStream({ + auth: { + privateKey: account3.privateKey, + }, + publishWithSignature: 'always', + }, { + requiresEncryption: true, }) const suite = new Benchmark.Suite() - suite.add('client publishing with signing', { - defer: true, - fn(deferred) { - // eslint-disable-next-line promise/catch-or-return - stream1.publish(msg).then(() => deferred.resolve(), () => deferred.resolve()) + + async function publish(stream, batchSize) { + const tasks = [] + for (let i = 0; i < batchSize; i++) { + tasks.push(stream.publish(Msg())) } + return Promise.all(tasks) + } + + BATCH_SIZES.forEach((batchSize) => { + suite.add(`client publishing in batches of ${batchSize} with signing`, { + defer: true, + fn(deferred) { + this.BATCH_SIZE = batchSize + // eslint-disable-next-line promise/catch-or-return + return publish(stream1, batchSize).then(() => deferred.resolve(), () => deferred.resolve()) + } + }) + + suite.add(`client publishing in batches of ${batchSize} without signing`, { + defer: true, + fn(deferred) { + this.BATCH_SIZE = batchSize + // eslint-disable-next-line promise/catch-or-return + return publish(stream2, batchSize).then(() => deferred.resolve(), () => deferred.resolve()) + } + }) + + suite.add(`client publishing in batches of ${batchSize} with encryption`, { + defer: true, + fn(deferred) { + this.BATCH_SIZE = batchSize + // eslint-disable-next-line promise/catch-or-return + return publish(stream3, batchSize).then(() => deferred.resolve(), () => deferred.resolve()) + } + }) }) - suite.add('client publishing without signing', { - defer: true, - fn(deferred) { - // eslint-disable-next-line promise/catch-or-return - stream2.publish(msg).then(() => deferred.resolve(), () => deferred.resolve()) + function toStringBench(bench) { + const { error, id, stats } = bench + let { hz } = bench + hz *= bench.BATCH_SIZE // adjust hz by batch size + const size = stats.sample.length + const pm = '\xb1' + let result = bench.name || (Number.isNaN(id) ? id : '') + if (error) { + return result + ' Error' } - }) + + result += ' x ' + Benchmark.formatNumber(hz.toFixed(hz < 100 ? 2 : 0)) + ' ops/sec ' + pm + + stats.rme.toFixed(2) + '% (' + size + ' run' + (size === 1 ? '' : 's') + ' sampled)' + return result + } suite.on('cycle', (event) => { - // eslint-disable-next-line no-console - console.log(String(event.target)) + log(toStringBench(event.target)) }) - suite.on('complete', async function onComplete() { - // eslint-disable-next-line no-console - console.log('Fastest is ' + this.filter('fastest').map('name')) - // eslint-disable-next-line no-console - console.log('Disconnecting clients') + suite.on('complete', async () => { + log('Disconnecting clients') await Promise.all([ - client1.ensureDisconnected(), - client2.ensureDisconnected(), + client1.disconnect(), + client2.disconnect(), + client3.disconnect(), ]) + log('Clients disconnected') }) suite.run() diff --git a/test/benchmarks/subscribe.js b/test/benchmarks/subscribe.js new file mode 100644 index 000000000..afbb911ef --- /dev/null +++ b/test/benchmarks/subscribe.js @@ -0,0 +1,151 @@ +const { format } = require('util') +const { Benchmark } = require('benchmark') + +// eslint-disable-next-line import/no-unresolved +const StreamrClient = require('../../dist') +const config = require('../integration/config') + +/* eslint-disable no-console */ + +let count = 100000 // pedantic: use large initial number so payload size is similar +const Msg = () => { + count += 1 + return { + value: `msg${count}` + } +} + +function createClient(opts) { + return new StreamrClient({ + ...config.clientOptions, + ...opts, + }) +} + +async function setupClientAndStream(clientOpts, streamOpts) { + const client = createClient(clientOpts) + await client.connect() + await client.session.getSessionToken() + + const stream = await client.createStream({ + name: `test-stream.${client.id}`, + ...streamOpts, + }) + return [client, stream] +} + +const BATCH_SIZES = [ + 1, + 32, + 512, + 1024, +] + +const log = (...args) => process.stderr.write(format(...args) + '\n') + +async function run() { + const account1 = StreamrClient.generateEthereumAccount() + const [client1, stream1] = await setupClientAndStream({ + auth: { + privateKey: account1.privateKey, + }, + publishWithSignature: 'always', + }) + + const account2 = StreamrClient.generateEthereumAccount() + const [client2, stream2] = await setupClientAndStream({ + auth: { + privateKey: account2.privateKey, + }, + publishWithSignature: 'never', + }) + + const account3 = StreamrClient.generateEthereumAccount() + const [client3, stream3] = await setupClientAndStream({ + auth: { + privateKey: account3.privateKey, + }, + publishWithSignature: 'always', + }, { + requiresEncryption: true, + }) + + const suite = new Benchmark.Suite() + + async function publish(stream, batchSize) { + const msgs = [] + for (let i = 0; i < batchSize; i++) { + msgs.push(Msg()) + } + + await Promise.all(msgs.map((msg) => stream.publish(msg))) + return msgs + } + + function test(client, stream, batchSize) { + return async function Fn(deferred) { + this.BATCH_SIZE = batchSize + const received = [] + let msgs + const sub = await client.subscribe(stream.id, (msg) => { + received.push(msg) + if (msgs && received.length === msgs.length) { + // eslint-disable-next-line promise/catch-or-return + sub.unsubscribe().then(() => deferred.resolve(), () => deferred.resolve()) + } + }) + msgs = await publish(stream, batchSize) + } + } + + BATCH_SIZES.forEach((batchSize) => { + suite.add(`client subscribing in batches of ${batchSize} with signing`, { + defer: true, + fn: test(client1, stream1, batchSize) + }) + + suite.add(`client subscribing in batches of ${batchSize} without signing`, { + defer: true, + fn: test(client2, stream2, batchSize) + }) + + suite.add(`client subscribing in batches of ${batchSize} with encryption`, { + defer: true, + fn: test(client3, stream3, batchSize) + }) + }) + + function toStringBench(bench) { + const { error, id, stats } = bench + let { hz } = bench + hz *= bench.BATCH_SIZE // adjust hz by batch size + const size = stats.sample.length + const pm = '\xb1' + let result = bench.name || (Number.isNaN(id) ? id : '') + if (error) { + return result + ' Error' + } + + result += ' x ' + Benchmark.formatNumber(hz.toFixed(hz < 100 ? 2 : 0)) + ' ops/sec ' + pm + + stats.rme.toFixed(2) + '% (' + size + ' run' + (size === 1 ? '' : 's') + ' sampled)' + return result + } + + suite.on('cycle', (event) => { + log(toStringBench(event.target)) + }) + + suite.on('complete', async () => { + log('Disconnecting clients') + await Promise.all([ + client1.disconnect(), + client2.disconnect(), + client3.disconnect(), + ]) + log('Clients disconnected') + }) + + suite.run() +} + +run() diff --git a/test/browser/browser.html b/test/browser/browser.html index 0c6d5f156..e1e0971a6 100644 --- a/test/browser/browser.html +++ b/test/browser/browser.html @@ -2,7 +2,7 @@ Test StreamrClient in Chrome Browser - + diff --git a/test/browser/browser.js b/test/browser/browser.js index 2735be549..1695f3a9e 100644 --- a/test/browser/browser.js +++ b/test/browser/browser.js @@ -9,6 +9,7 @@ describe('StreamrClient', () => { const url = process.env.WEBSOCKET_URL ? `&WEBSOCKET_URL=${encodeURIComponent(process.env.WEBSOCKET_URL)}` : '' const restUrl = process.env.REST_URL ? `&REST_URL=${encodeURIComponent(process.env.REST_URL)}` : '' const browserUrl = `http://localhost:8880?streamName=${streamName}${url}${restUrl}` + // eslint-disable-next-line no-console console.info(browserUrl) return browser.url(browserUrl) }) @@ -24,12 +25,35 @@ describe('StreamrClient', () => { .click('button[id=subscribe]') .assert.containsText('#result', 'subscribed') .click('button[id=publish]') - .assert.containsText('#result', '[{"msg":0},{"msg":1},{"msg":2},{"msg":3},{"msg":4},{"msg":5},{"msg":6},{"msg":7},{"msg":8},{"msg":9}]') .pause(3000) + .verify.containsText('#result', '{"msg":0}') + .verify.containsText('#result', '{"msg":1}') + .verify.containsText('#result', '{"msg":2}') + .verify.containsText('#result', '{"msg":3}') + .verify.containsText('#result', '{"msg":4}') + .verify.containsText('#result', '{"msg":5}') + .verify.containsText('#result', '{"msg":6}') + .verify.containsText('#result', '{"msg":7}') + .verify.containsText('#result', '{"msg":8}') + .verify.containsText('#result', '{"msg":9}') + .assert.containsText('#result', '[{"msg":0},{"msg":1},{"msg":2},{"msg":3},{"msg":4},{"msg":5},{"msg":6},{"msg":7},{"msg":8},{"msg":9}]') + .pause(6000) .click('button[id=resend]') .pause(6000) - // eslint-disable-next-line max-len - .assert.containsText('#result', 'Resend: [{"msg":0},{"msg":1},{"msg":2},{"msg":3},{"msg":4},{"msg":5},{"msg":6},{"msg":7},{"msg":8},{"msg":9}]') + .verify.containsText('#result', '{"msg":0}') + .verify.containsText('#result', '{"msg":1}') + .verify.containsText('#result', '{"msg":2}') + .verify.containsText('#result', '{"msg":3}') + .verify.containsText('#result', '{"msg":4}') + .verify.containsText('#result', '{"msg":5}') + .verify.containsText('#result', '{"msg":6}') + .verify.containsText('#result', '{"msg":7}') + .verify.containsText('#result', '{"msg":8}') + .verify.containsText('#result', '{"msg":9}') + .assert.containsText( + '#result', + 'Resend: [{"msg":0},{"msg":1},{"msg":2},{"msg":3},{"msg":4},{"msg":5},{"msg":6},{"msg":7},{"msg":8},{"msg":9}]', + ) .click('button[id=disconnect]') .assert.containsText('#result', 'disconnected') }) 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 new file mode 100644 index 000000000..60ceb263e --- /dev/null +++ b/test/flakey/EnvStressTest.test.js @@ -0,0 +1,86 @@ +import { pTimeout } from '../../src/utils' +import { StreamrClient } from '../../src/StreamrClient' +import { fakePrivateKey, uid } from '../utils' +import config from '../integration/config' + +const TEST_REPEATS = 6 +const MAX_CONCURRENCY = 24 +const TEST_TIMEOUT = 5000 +const INC_FACTOR = 1.5 + +/* eslint-disable require-atomic-updates, no-loop-func */ + +describe('EnvStressTest', () => { + let client + + const createClient = (opts = {}) => new StreamrClient({ + autoConnect: false, + autoDisconnect: false, + ...config.clientOptions, + ...opts, + }) + + describe('Stream Creation + Deletion', () => { + const nextConcurrency = (j) => { + if (j === MAX_CONCURRENCY) { + return j + 1 + } + + return Math.min(MAX_CONCURRENCY, Math.round(j * INC_FACTOR)) + } + + for (let j = 1; j <= MAX_CONCURRENCY; j = nextConcurrency(j)) { + describe(`Create ${j} streams`, () => { + let errors = [] + beforeAll(() => { + errors = [] + }) + + afterAll(() => { + expect(errors).toEqual([]) + }) + + for (let i = 0; i < TEST_REPEATS; i++) { + test(`Test ${i + 1} of ${TEST_REPEATS}`, async () => { + const testDesc = `with concurrency ${j} for test ${i + 1}` + client = createClient({ + auth: { + privateKey: fakePrivateKey(), + }, + }) + + await pTimeout(client.session.getSessionToken(), TEST_TIMEOUT, `Timeout getting session token ${testDesc}`) + + const names = [] + for (let k = 0; k < j; k++) { + names.push(uid(`stream ${k + 1} . `)) + } + + const streams = await Promise.all(names.map((name, index) => ( + pTimeout(client.createStream({ + name, + requireSignedData: true, + requireEncryptedData: false, + }), TEST_TIMEOUT * j * 0.2, `Timeout creating stream ${index + 1} ${testDesc}`) + ))) + + streams.forEach((createdStream, index) => { + try { + expect(createdStream.id).toBeTruthy() + expect(createdStream.name).toBe(names[index]) + expect(createdStream.requireSignedData).toBe(true) + } catch (err) { + errors.push(`Error with stream ${index + 1} in ${testDesc}: ${err.message}`) + throw err + } + }) + + await Promise.all(streams.map((s, index) => ( + pTimeout(s.delete(), TEST_TIMEOUT * j * 0.2, `Timeout deleting stream ${index + 1} ${testDesc}`) + ))) + }, TEST_TIMEOUT * j * 1.2) + } + }) + } + }) +}) diff --git a/test/integration/DataUnionEndpoints.test.js b/test/integration/DataUnionEndpoints.test.js deleted file mode 100644 index db3fd1f67..000000000 --- a/test/integration/DataUnionEndpoints.test.js +++ /dev/null @@ -1,284 +0,0 @@ -/* eslint-disable no-await-in-loop */ -import { Contract, providers, utils, Wallet } from 'ethers' -import debug from 'debug' -import { wait } from 'streamr-test-utils' - -import StreamrClient from '../../src' -import * as Token from '../../contracts/TestToken.json' -import { getEndpointUrl } from '../../src/utils' -import authFetch from '../../src/rest/authFetch' - -import config from './config' - -const log = debug('StreamrClient::DataUnionEndpoints::integration-test') - -describe('DataUnionEndPoints', () => { - let dataUnion - - let testProvider - let adminClient - let adminWallet - - const createProduct = async () => { - const DATA_UNION_VERSION = 1 - const properties = { - beneficiaryAddress: dataUnion.address, - type: 'DATAUNION', - dataUnionVersion: DATA_UNION_VERSION - } - const url = getEndpointUrl(config.clientOptions.restUrl, 'products') - return authFetch( - url, - adminClient.session, - { - method: 'POST', - body: JSON.stringify(properties) - } - ) - } - - beforeAll(async () => { - testProvider = new providers.JsonRpcProvider(config.ethereumServerUrl) - log(`Connecting to Ethereum network, config = ${JSON.stringify(config)}`) - - const network = await testProvider.getNetwork() - log('Connected to Ethereum network: ', JSON.stringify(network)) - - adminWallet = new Wallet(config.privateKey, testProvider) - adminClient = new StreamrClient({ - auth: { - privateKey: adminWallet.privateKey - }, - autoConnect: false, - autoDisconnect: false, - ...config.clientOptions, - }) - - log('beforeAll done') - }, 10000) - - beforeEach(async () => { - await adminClient.ensureConnected() - dataUnion = await adminClient.deployDataUnion({ - provider: testProvider, - }) - await dataUnion.deployed() - log(`Deployment done for ${dataUnion.address}`) - await dataUnion.isReady(2000, 200000) - log(`DataUnion ${dataUnion.address} is ready to roll`) - dataUnion.secret = await adminClient.createSecret(dataUnion.address, 'DataUnionEndpoints test secret') - await createProduct() - }, 300000) - - afterAll(async () => { - if (!adminClient) { return } - await adminClient.ensureDisconnected() - }) - - afterAll(async () => { - await testProvider.removeAllListeners() - }) - - describe('Admin', () => { - const memberAddressList = [ - '0x0000000000000000000000000000000000000001', - '0x0000000000000000000000000000000000000002', - '0x000000000000000000000000000000000000bEEF', - ] - - it('can add and remove members', async () => { - log('starting test') - await adminClient.dataUnionIsReady(dataUnion.address, log) - - await adminClient.addMembers(dataUnion.address, memberAddressList, testProvider) - await adminClient.hasJoined(dataUnion.address, memberAddressList[0]) - const res = await adminClient.getDataUnionStats(dataUnion.address) - expect(res.memberCount).toEqual({ - total: 3, active: 3, inactive: 0 - }) - - await adminClient.kick(dataUnion.address, memberAddressList.slice(1), testProvider) - await wait(1000) // TODO: instead of sleeping, find a way to check server has registered the parting - const res2 = await adminClient.getDataUnionStats(dataUnion.address) - expect(res2.memberCount).toEqual({ - total: 3, active: 1, inactive: 2 - }) - }, 300000) - - // separate test for adding and removing secrets? Adding secret is tested in member joins dataUnion test though. - }) - - describe('Members', () => { - let memberClient - const memberWallet = new Wallet('0x1000000000000000000000000000000000000000000000000000000000000001', testProvider) - - beforeAll(async () => { - memberClient = new StreamrClient({ - auth: { - privateKey: memberWallet.privateKey - }, - autoConnect: false, - autoDisconnect: false, - ...config.clientOptions, - }) - await memberClient.ensureConnected() - }) - - afterAll(async () => { - if (!memberClient) { return } - await memberClient.ensureDisconnected() - }) - - it('can join the dataUnion, and get their balances and stats, and check proof, and withdraw', async () => { - // send eth so the member can afford to send tx - await adminWallet.sendTransaction({ - to: memberWallet.address, - value: utils.parseEther('1'), - }) - - const res = await memberClient.joinDataUnion(dataUnion.address, dataUnion.secret) - await memberClient.hasJoined(dataUnion.address) - expect(res).toMatchObject({ - state: 'ACCEPTED', - memberAddress: memberWallet.address, - contractAddress: dataUnion.address, - }) - - // too much bother to check this in a separate test... TODO: split - const res2 = await memberClient.getMemberStats(dataUnion.address) - expect(res2).toEqual({ - active: true, - address: memberWallet.address, - earnings: '0', - recordedEarnings: '0', - withdrawableEarnings: '0', - frozenEarnings: '0' - }) - - // add revenue, just to see some action - const opWallet = new Wallet('0x5e98cce00cff5dea6b454889f359a4ec06b9fa6b88e9d69b86de8e1c81887da0', testProvider) - const opToken = new Contract(adminClient.options.tokenAddress, Token.abi, opWallet) - const tx = await opToken.mint(dataUnion.address, utils.parseEther('1')) - const tr = await tx.wait(2) - expect(tr.events[0].event).toBe('Transfer') - expect(tr.events[0].args.from).toBe('0x0000000000000000000000000000000000000000') - expect(tr.events[0].args.to).toBe(dataUnion.address) - expect(tr.events[0].args.value.toString()).toBe('1000000000000000000') - await wait(1000) - - // note: getMemberStats without explicit address => get stats of the authenticated StreamrClient - let res3 = await memberClient.getMemberStats(dataUnion.address) - while (!res3.withdrawableBlockNumber) { - await wait(4000) - res3 = await memberClient.getMemberStats(dataUnion.address) - } - expect(res3).toMatchObject({ - active: true, - address: memberWallet.address, - earnings: '1000000000000000000', - recordedEarnings: '1000000000000000000', - withdrawableEarnings: '1000000000000000000', - frozenEarnings: '0', - withdrawableBlockNumber: res3.withdrawableBlockNumber, - }) - - const isValid = await memberClient.validateProof(dataUnion.address, { - provider: testProvider - }) - expect(isValid).toBeTruthy() - - const walletBefore = await opToken.balanceOf(memberWallet.address) - await wait(80000) - const tr2 = await memberClient.withdraw(dataUnion.address, { - provider: testProvider - }) - expect(tr2.logs[0].address).toBe(adminClient.options.tokenAddress) - - const walletAfter = await opToken.balanceOf(memberWallet.address) - const diff = walletAfter.sub(walletBefore) - expect(diff.toString()).toBe(res3.withdrawableEarnings) - }, 600000) - - // TODO: test withdrawTo, withdrawFor, getBalance - }) - - describe('Anyone', () => { - const memberAddressList = [ - '0x0000000000000000000000000000000000000001', - '0x0000000000000000000000000000000000000002', - '0x000000000000000000000000000000000000bEEF', - ] - - let client - beforeAll(async () => { - client = new StreamrClient({ - auth: { - apiKey: 'tester1-api-key' - }, - autoConnect: false, - autoDisconnect: false, - ...config.clientOptions, - }) - }) - afterAll(async () => { - if (!client) { return } - await client.ensureDisconnected() - }) - - it('can get dataUnion stats, member list, and member stats', async () => { - await adminClient.addMembers(dataUnion.address, memberAddressList, testProvider) - await adminClient.hasJoined(dataUnion.address, memberAddressList[0]) - - // mint tokens to dataUnion to generate revenue - const opWallet = new Wallet('0x5e98cce00cff5dea6b454889f359a4ec06b9fa6b88e9d69b86de8e1c81887da0', testProvider) - const opToken = new Contract(adminClient.options.tokenAddress, Token.abi, opWallet) - const tx = await opToken.mint(dataUnion.address, utils.parseEther('1')) - const tr = await tx.wait(2) - expect(tr.events[0].event).toBe('Transfer') - expect(tr.events[0].args.from).toBe('0x0000000000000000000000000000000000000000') - expect(tr.events[0].args.to).toBe(dataUnion.address) - - await wait(1000) - let mstats = await client.getMemberStats(dataUnion.address, memberAddressList[0]) - while (!mstats.withdrawableBlockNumber) { - await wait(4000) - mstats = await client.getMemberStats(dataUnion.address, memberAddressList[0]) - } - - // TODO: clean up asserts - const cstats = await client.getDataUnionStats(dataUnion.address) - const mlist = await client.getMembers(dataUnion.address) - - expect(cstats.memberCount).toEqual({ - total: 3, active: 3, inactive: 0 - }) - expect(cstats.totalEarnings).toBe('1000000000000000000') - expect(cstats.latestWithdrawableBlock.memberCount).toBe(4) - expect(cstats.latestWithdrawableBlock.totalEarnings).toBe('1000000000000000000') - expect(mlist).toEqual([{ - active: true, - address: '0x0000000000000000000000000000000000000001', - earnings: '333333333333333333' - }, - { - active: true, - address: '0x0000000000000000000000000000000000000002', - earnings: '333333333333333333' - }, - { - active: true, - address: '0x000000000000000000000000000000000000bEEF', - earnings: '333333333333333333' - }]) - expect(mstats).toMatchObject({ - active: true, - address: '0x0000000000000000000000000000000000000001', - earnings: '333333333333333333', - recordedEarnings: '333333333333333333', - withdrawableEarnings: '333333333333333333', - frozenEarnings: '0', - withdrawableBlockNumber: cstats.latestWithdrawableBlock.blockNumber, - }) - }, 300000) - }) -}) diff --git a/test/integration/Encryption.test.js b/test/integration/Encryption.test.js new file mode 100644 index 000000000..8b4475760 --- /dev/null +++ b/test/integration/Encryption.test.js @@ -0,0 +1,548 @@ +import { wait } from 'streamr-test-utils' +import { MessageLayer } from 'streamr-client-protocol' + +import { fakePrivateKey, uid, Msg, getPublishTestMessages } from '../utils' +import { Defer } from '../../src/utils' +import { StreamrClient } from '../../src/StreamrClient' +import { GroupKey } from '../../src/stream/Encryption' +import Connection from '../../src/Connection' + +import config from './config' + +const TIMEOUT = 30 * 1000 + +const { StreamMessage } = MessageLayer + +describe('decryption', () => { + let publishTestMessages + let expectErrors = 0 // check no errors by default + let errors = [] + + const getOnError = (errs) => jest.fn((err) => { + errs.push(err) + }) + + let onError = jest.fn() + let client + let stream + + const createClient = (opts = {}) => { + const c = new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: fakePrivateKey(), + }, + autoConnect: false, + autoDisconnect: false, + disconnectDelay: 1, + publishAutoDisconnectDelay: 50, + maxRetries: 2, + ...opts, + }) + c.onError = jest.fn() + c.on('error', onError) + + return c + } + + function checkEncryptionMessages(testClient) { + const onSendTest = Defer() + testClient.connection.on('_send', onSendTest.wrapError((sendingMsg) => { + // check encryption is as expected + const { streamMessage } = sendingMsg + if (!streamMessage) { + return + } + + if (streamMessage.messageType === StreamMessage.MESSAGE_TYPES.MESSAGE) { + expect(streamMessage.encryptionType).toEqual(StreamMessage.ENCRYPTION_TYPES.AES) + } else if (streamMessage.messageType === StreamMessage.MESSAGE_TYPES.GROUP_KEY_RESPONSE) { + expect(streamMessage.encryptionType).toEqual(StreamMessage.ENCRYPTION_TYPES.RSA) + } else { + expect(streamMessage.encryptionType).toEqual(StreamMessage.ENCRYPTION_TYPES.NONE) + } + })) + return onSendTest + } + + beforeEach(() => { + errors = [] + expectErrors = 0 + onError = getOnError(errors) + }) + + afterEach(async () => { + await wait() + // ensure no unexpected errors + expect(errors).toHaveLength(expectErrors) + if (client) { + expect(client.onError).toHaveBeenCalledTimes(expectErrors) + } + }) + + afterEach(async () => { + await wait() + if (client) { + client.debug('disconnecting after test') + await client.disconnect() + } + + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + throw new Error(`sockets not closed: ${openSockets}`) + } + }) + + beforeEach(async () => { + client = createClient() + await Promise.all([ + client.session.getSessionToken(), + client.connect(), + ]) + + const name = uid('stream') + stream = await client.createStream({ + name, + requireEncryptedData: true, + }) + + publishTestMessages = getPublishTestMessages(client, { + stream + }) + }) + + it('client.subscribe can decrypt encrypted messages if it knows the group key', async () => { + const groupKey = GroupKey.generate() + const keys = { + [stream.id]: { + [groupKey.id]: groupKey, + } + } + const msg = Msg() + const done = Defer() + const sub = await client.subscribe({ + stream: stream.id, + groupKeys: keys, + }, done.wrap((parsedContent, streamMessage) => { + expect(parsedContent).toEqual(msg) + // Check signature stuff + expect(streamMessage.signatureType).toBe(StreamMessage.SIGNATURE_TYPES.ETH) + expect(streamMessage.getPublisherId()) + expect(streamMessage.signature) + })) + + client.once('error', done.reject) + client.setNextGroupKey(stream.id, groupKey) + // Publish after subscribed + await Promise.all([ + client.publish(stream.id, msg), + done, + ]) + // All good, unsubscribe + await client.unsubscribe(sub) + }) + + it('client.subscribe can get the group key and decrypt encrypted message using an RSA key pair', async () => { + const done = Defer() + const msg = Msg() + const groupKey = GroupKey.generate() + // subscribe without knowing the group key to decrypt stream messages + const sub = await client.subscribe({ + stream: stream.id, + }, done.wrap((parsedContent, streamMessage) => { + expect(parsedContent).toEqual(msg) + + // Check signature stuff + expect(streamMessage.signatureType).toBe(StreamMessage.SIGNATURE_TYPES.ETH) + expect(streamMessage.getPublisherId()) + expect(streamMessage.signature) + })) + sub.once('error', done.reject) + + await client.setNextGroupKey(stream.id, groupKey) + const onEncryptionMessageErr = checkEncryptionMessages(client) + + await Promise.all([ + client.publish(stream.id, msg), + done, + ]) + onEncryptionMessageErr.resolve() // will be ignored if errored + await onEncryptionMessageErr + // All good, unsubscribe + await client.unsubscribe(sub) + }, 2 * TIMEOUT) + + it('errors if rotating group key for no stream', async () => { + expect(async () => ( + client.rotateGroupKey() + )).rejects.toThrow('streamId') + }) + + it('errors if setting group key for no stream', async () => { + expect(async () => ( + client.setNextGroupKey(undefined, GroupKey.generate()) + )).rejects.toThrow('streamId') + }) + + it('allows other users to get group key', async () => { + let otherClient + let sub + try { + otherClient = createClient({ + autoConnect: true, + autoDisconnect: true, + }) + + const onEncryptionMessageErr = checkEncryptionMessages(client) + const onEncryptionMessageErr2 = checkEncryptionMessages(otherClient) + const otherUser = await otherClient.getUserInfo() + await stream.grantPermission('stream_get', otherUser.username) + await stream.grantPermission('stream_subscribe', otherUser.username) + + const done = Defer() + const msg = Msg() + // subscribe without knowing the group key to decrypt stream messages + sub = await otherClient.subscribe({ + stream: stream.id, + }, done.wrap((parsedContent, streamMessage) => { + expect(parsedContent).toEqual(msg) + + // Check signature stuff + expect(streamMessage.signatureType).toBe(StreamMessage.SIGNATURE_TYPES.ETH) + expect(streamMessage.getPublisherId()) + expect(streamMessage.signature) + })) + sub.once('error', done.reject) + + const groupKey = GroupKey.generate() + await client.setNextGroupKey(stream.id, groupKey) + + await Promise.all([ + client.publish(stream.id, msg), + done, + ]) + onEncryptionMessageErr.resolve() // will be ignored if errored + await onEncryptionMessageErr + onEncryptionMessageErr2.resolve() // will be ignored if errored + await onEncryptionMessageErr2 + } finally { + if (otherClient) { + if (sub) { + await otherClient.unsubscribe(sub) + } + await otherClient.disconnect() + await otherClient.logout() + } + } + }, 2 * TIMEOUT) + + it('does not encrypt messages in stream without groupkey', async () => { + const name = uid('stream') + const stream2 = await client.createStream({ + name, + requireEncryptedData: false, + }) + + let didFindStream2 = false + + function checkEncryptionMessagesPerStream(testClient) { + const onSendTest = Defer() + testClient.connection.on('_send', onSendTest.wrapError((sendingMsg) => { + // check encryption is as expected + const { streamMessage } = sendingMsg + if (!streamMessage) { + return + } + + if (streamMessage.getStreamId() === stream2.id) { + didFindStream2 = true + // stream2 always unencrypted + expect(streamMessage.encryptionType).toEqual(StreamMessage.ENCRYPTION_TYPES.NONE) + return + } + + if (streamMessage.messageType === StreamMessage.MESSAGE_TYPES.MESSAGE) { + expect(streamMessage.encryptionType).toEqual(StreamMessage.ENCRYPTION_TYPES.AES) + } else if (streamMessage.messageType === StreamMessage.MESSAGE_TYPES.GROUP_KEY_RESPONSE) { + expect(streamMessage.encryptionType).toEqual(StreamMessage.ENCRYPTION_TYPES.RSA) + } else { + expect(streamMessage.encryptionType).toEqual(StreamMessage.ENCRYPTION_TYPES.NONE) + } + })) + return onSendTest + } + + async function testSub(testStream) { + const NUM_MESSAGES = 5 + const done = Defer() + const received = [] + const sub = await client.subscribe({ + stream: testStream.id, + }, done.wrapError((parsedContent) => { + received.push(parsedContent) + if (received.length === NUM_MESSAGES) { + done.resolve() + } + })) + sub.once('error', done.reject) + + const published = await publishTestMessages(NUM_MESSAGES, { + stream: testStream, + }) + + await done + + expect(received).toEqual(published) + } + + const onEncryptionMessageErr = checkEncryptionMessagesPerStream(client) + + const groupKey = GroupKey.generate() + await client.setNextGroupKey(stream.id, groupKey) + + await Promise.all([ + testSub(stream), + testSub(stream2), + ]) + onEncryptionMessageErr.resolve() // will be ignored if errored + await onEncryptionMessageErr + expect(didFindStream2).toBeTruthy() + }, 2 * TIMEOUT) + + it('sets group key per-stream', async () => { + const name = uid('stream') + const stream2 = await client.createStream({ + name, + requireEncryptedData: true, + }) + + const groupKey = GroupKey.generate() + await client.setNextGroupKey(stream.id, groupKey) + const groupKey2 = GroupKey.generate() + await client.setNextGroupKey(stream2.id, groupKey2) + + function checkEncryptionMessagesPerStream(testClient) { + const onSendTest = Defer() + testClient.connection.on('_send', onSendTest.wrapError((sendingMsg) => { + // check encryption is as expected + const { streamMessage } = sendingMsg + if (!streamMessage) { + return + } + + if (streamMessage.getStreamId() === stream2.id) { + expect(streamMessage.groupKeyId).toEqual(groupKey2.id) + } + + if (streamMessage.getStreamId() === stream.id) { + expect(streamMessage.groupKeyId).toEqual(groupKey.id) + } + + if (streamMessage.messageType === StreamMessage.MESSAGE_TYPES.MESSAGE) { + expect(streamMessage.encryptionType).toEqual(StreamMessage.ENCRYPTION_TYPES.AES) + } else if (streamMessage.messageType === StreamMessage.MESSAGE_TYPES.GROUP_KEY_RESPONSE) { + expect(streamMessage.encryptionType).toEqual(StreamMessage.ENCRYPTION_TYPES.RSA) + } else { + expect(streamMessage.encryptionType).toEqual(StreamMessage.ENCRYPTION_TYPES.NONE) + } + })) + return onSendTest + } + + async function testSub(testStream) { + const NUM_MESSAGES = 5 + const done = Defer() + const received = [] + const sub = await client.subscribe({ + stream: testStream.id, + }, done.wrapError((parsedContent) => { + received.push(parsedContent) + if (received.length === NUM_MESSAGES) { + done.resolve() + } + })) + sub.once('error', done.reject) + + const published = await publishTestMessages(NUM_MESSAGES, { + stream: testStream, + }) + + await done + + expect(received).toEqual(published) + } + + const onEncryptionMessageErr = checkEncryptionMessagesPerStream(client) + + await Promise.all([ + testSub(stream), + testSub(stream2), + ]) + onEncryptionMessageErr.resolve() // will be ignored if errored + await onEncryptionMessageErr + }, 2 * TIMEOUT) + + it('client.subscribe can get the group key and decrypt multiple encrypted messages using an RSA key pair', async () => { + // subscribe without knowing the group key to decrypt stream messages + const sub = await client.subscribe({ + stream: stream.id, + }) + + const groupKey = GroupKey.generate() + await client.setNextGroupKey(stream.id, groupKey) + const published = await publishTestMessages() + + const received = [] + for await (const msg of sub) { + received.push(msg.getParsedContent()) + if (received.length === published.length) { + return + } + } + + expect(received).toEqual(published) + + // All good, unsubscribe + await client.unsubscribe(sub) + }, 2 * TIMEOUT) + + it('subscribe with changing group key', async () => { + // subscribe without knowing the group key to decrypt stream messages + const sub = await client.subscribe({ + stream: stream.id, + }) + + const published = await publishTestMessages(5, { + async beforeEach() { + await client.rotateGroupKey(stream.id) + } + }) + + const received = [] + for await (const msg of sub) { + received.push(msg.getParsedContent()) + if (received.length === published.length) { + return + } + } + + expect(received).toEqual(published) + + // All good, unsubscribe + await client.unsubscribe(sub) + }, 2 * TIMEOUT) + + it('client.resend last can get the historical keys for previous encrypted messages', async () => { + // Publish encrypted messages with different keys + const published = await publishTestMessages(5, { + waitForLast: true, + async beforeEach() { + await client.rotateGroupKey(stream.id) + } + }) + + // resend without knowing the historical keys + const sub = await client.resend({ + stream: stream.id, + resend: { + last: 2, + }, + }) + + const received = await sub.collect() + + expect(received).toEqual(published.slice(-2)) + await client.unsubscribe(sub) + }, 2 * TIMEOUT) + + it('client.subscribe with resend last can get the historical keys for previous encrypted messages', async () => { + // Publish encrypted messages with different keys + const published = await publishTestMessages(5, { + waitForLast: true, + async beforeEach() { + await client.rotateGroupKey(stream.id) + } + }) + + // subscribe with resend without knowing the historical keys + const sub = await client.subscribe({ + stream: stream.id, + resend: { + last: 2, + }, + }) + + const received = [] + for await (const msg of sub) { + received.push(msg.getParsedContent()) + if (received.length === 2) { + break + } + } + + expect(received).toEqual(published.slice(-2)) + await client.unsubscribe(sub) + }, 2 * TIMEOUT) + + it('fails gracefully if cannot decrypt', async () => { + const MAX_MESSAGES = 10 + const groupKey = GroupKey.generate() + const keys = { + [stream.id]: { + [groupKey.id]: groupKey, + } + } + + await client.setNextGroupKey(stream.id, groupKey) + + const BAD_INDEX = 6 + let count = 0 + const { parse } = client.connection + client.connection.parse = (...args) => { + const msg = parse.call(client.connection, ...args) + if (!msg.streamMessage) { + return msg + } + + if (count === BAD_INDEX) { + msg.streamMessage.groupKeyId = 'badgroupkey' + } + + count += 1 + return msg + } + + const sub = await client.subscribe({ + stream: stream.id, + groupKeys: keys, + }) + + const onSubError = jest.fn((err) => { + expect(err).toBeInstanceOf(Error) + expect(err.message).toMatch('decrypt') + }) + + sub.on('error', onSubError) + + // Publish after subscribed + const published = await publishTestMessages(MAX_MESSAGES, { + timestamp: 1111111, + }) + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === published.length - 1) { + break + } + } + + expect(received).toEqual([ + ...published.slice(0, BAD_INDEX), + ...published.slice(BAD_INDEX + 1, MAX_MESSAGES) + ]) + + expect(onSubError).toHaveBeenCalledTimes(1) + }) +}) + diff --git a/test/integration/GapFill.test.js b/test/integration/GapFill.test.js new file mode 100644 index 000000000..7eb7dc8fa --- /dev/null +++ b/test/integration/GapFill.test.js @@ -0,0 +1,314 @@ +import { wait } from 'streamr-test-utils' + +import { uid, fakePrivateKey, describeRepeats, getPublishTestMessages } from '../utils' +import { StreamrClient } from '../../src/StreamrClient' +import Connection from '../../src/Connection' + +import config from './config' + +const MAX_MESSAGES = 10 + +describeRepeats('GapFill with resends', () => { + let expectErrors = 0 // check no errors by default + let publishTestMessages + let onError = jest.fn() + let client + let stream + let subscriber + + const createClient = (opts = {}) => { + const c = new StreamrClient({ + auth: { + privateKey: fakePrivateKey(), + }, + autoConnect: false, + autoDisconnect: false, + maxRetries: 2, + ...config.clientOptions, + ...opts, + }) + c.onError = jest.fn() + c.on('error', onError) + return c + } + + async function setupClient(opts) { + // eslint-disable-next-line require-atomic-updates + client = createClient(opts) + subscriber = client.subscriber + client.debug('connecting before test >>') + await client.session.getSessionToken() + stream = await client.createStream({ + requireSignedData: true, + name: uid('stream') + }) + + client.debug('connecting before test <<') + publishTestMessages = getPublishTestMessages(client, stream.id) + return client + } + + beforeEach(async () => { + expectErrors = 0 + onError = jest.fn() + }) + + afterEach(() => { + if (!subscriber) { return } + expect(subscriber.count(stream.id)).toBe(0) + if (!client) { return } + expect(client.getSubscriptions(stream.id)).toEqual([]) + }) + + afterEach(async () => { + await wait() + // ensure no unexpected errors + expect(onError).toHaveBeenCalledTimes(expectErrors) + if (client) { + expect(client.onError).toHaveBeenCalledTimes(expectErrors) + } + }) + + afterEach(async () => { + await wait() + if (client) { + client.debug('disconnecting after test >>') + await client.disconnect() + client.debug('disconnecting after test <<') + } + + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + await Connection.closeOpen() + throw new Error(`sockets not closed: ${openSockets}`) + } + }) + + let subs = [] + + beforeEach(async () => { + const existingSubs = subs + subs = [] + await Promise.all(existingSubs.map((sub) => ( + sub.cancel() + ))) + }) + + describe('filling gaps', () => { + beforeEach(async () => { + await setupClient({ + gapFillTimeout: 200, + retryResendAfter: 200, + }) + await client.connect() + }) + + it('can fill single gap', async () => { + const sub = await client.subscribe(stream.id) + const { parse } = client.connection + let count = 0 + client.connection.parse = (...args) => { + const msg = parse.call(client.connection, ...args) + if (!msg.streamMessage) { + return msg + } + + count += 1 + if (count === 2) { + return null + } + + return msg + } + + expect(subscriber.count(stream.id)).toBe(1) + + const published = await publishTestMessages(MAX_MESSAGES, { + timestamp: 111111, + }) + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === published.length) { + break + } + } + expect(received).toEqual(published) + expect(client.connection.getState()).toBe('connected') + }, 10000) + + it('can fill gap of multiple messages', async () => { + const sub = await client.subscribe(stream.id) + const { parse } = client.connection + let count = 0 + client.connection.parse = (...args) => { + const msg = parse.call(client.connection, ...args) + if (!msg.streamMessage) { + return msg + } + + count += 1 + if (count > 1 && count < 5) { + return null + } + + return msg + } + + expect(subscriber.count(stream.id)).toBe(1) + + const published = await publishTestMessages(MAX_MESSAGES) + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === published.length) { + break + } + } + expect(received).toEqual(published) + expect(client.connection.getState()).toBe('connected') + }, 10000) + + it('can fill multiple gaps', async () => { + const sub = await client.subscribe(stream.id) + const { parse } = client.connection + let count = 0 + client.connection.parse = (...args) => { + const msg = parse.call(client.connection, ...args) + if (!msg.streamMessage) { + return msg + } + + count += 1 + if (count === 3 || count === 4 || count === 7) { + return null + } + + return msg + } + + expect(subscriber.count(stream.id)).toBe(1) + + const published = await publishTestMessages(MAX_MESSAGES) + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === published.length) { + break + } + } + expect(received).toEqual(published) + expect(client.connection.getState()).toBe('connected') + }, 15000) + + it('can fill gaps in resends', async () => { + const { parse } = client.connection + let count = 0 + client.connection.parse = (...args) => { + const msg = parse.call(client.connection, ...args) + if (!msg.streamMessage) { + return msg + } + + count += 1 + if (count === 3 || count === 4 || count === 7) { + return null + } + + return msg + } + + const published = await publishTestMessages(MAX_MESSAGES, { + timestamp: 111111, + waitForLast: true, + }) + + const sub = await client.resend({ + stream, + last: MAX_MESSAGES, + }) + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + // should not need to explicitly end + } + expect(received).toEqual(published) + expect(client.connection.getState()).toBe('connected') + }, 60000) + + it('can fill gaps in resends even if gap cannot be filled', async () => { + const { parse } = client.connection + let count = 0 + let droppedMsgRef + client.connection.parse = (...args) => { + const msg = parse.call(client.connection, ...args) + if (!msg.streamMessage) { + return msg + } + + count += 1 + if (count === 3) { + if (!droppedMsgRef) { + droppedMsgRef = msg.streamMessage.getMessageRef() + } + return null + } + + if (droppedMsgRef && msg.streamMessage.getMessageRef().compareTo(droppedMsgRef) === 0) { + return null + } + + return msg + } + + const published = await publishTestMessages(MAX_MESSAGES, { + waitForLast: true, + }) + + const sub = await client.resend({ + stream, + last: MAX_MESSAGES, + }) + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + // should not need to explicitly end + } + expect(received).toEqual(published.filter((_value, index) => index !== 2)) + expect(client.connection.getState()).toBe('connected') + }, 60000) + + it('can fill gaps between resend and realtime', async () => { + // publish 5 messages into storage + const published = await publishTestMessages(5, { + waitForLast: true, + waitForLastCount: 5, + }) + + // then simultaneously subscribe with resend & start publishing realtime messages + const [sub, publishedLater] = await Promise.all([ + client.subscribe({ + stream, + resend: { + last: 5 + } + }), + publishTestMessages(5) + ]) + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === (published.length + publishedLater.length)) { + break + } + } + + expect(received).toEqual([...published, ...publishedLater]) + await sub.unsubscribe() + }, 15000) + }) +}) diff --git a/test/integration/LoginEndpoints.test.js b/test/integration/LoginEndpoints.test.js index 13d17f783..ce4f94610 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' +import { StreamrClient } from '../../src/StreamrClient' import config from './config' @@ -10,10 +10,10 @@ describe('LoginEndpoints', () => { let client const createClient = (opts = {}) => new StreamrClient({ + ...config.clientOptions, apiKey: 'tester1-api-key', autoConnect: false, autoDisconnect: false, - ...config.clientOptions, ...opts, }) @@ -21,80 +21,63 @@ describe('LoginEndpoints', () => { client = createClient() }) - afterAll(async (done) => { - await client.ensureDisconnected() - done() + afterAll(async () => { + await client.disconnect() }) describe('Challenge generation', () => { - it('should retrieve a challenge', () => client.getChallenge('some-address') - .then((challenge) => { - assert(challenge) - assert(challenge.id) - assert(challenge.challenge) - assert(challenge.expires) - })) + it('should retrieve a challenge', async () => { + const challenge = await client.getChallenge('some-address') + assert(challenge) + assert(challenge.id) + assert(challenge.challenge) + assert(challenge.expires) + }) }) - async function assertThrowsAsync(fn, regExp) { - let f = () => {} - try { - await fn() - } catch (e) { - f = () => { - throw e - } - } finally { - assert.throws(f, regExp) - } - } - describe('Challenge response', () => { it('should fail to get a session token', async () => { - await assertThrowsAsync(async () => client.sendChallengeResponse( - { + await expect(async () => { + await client.sendChallengeResponse({ id: 'some-id', challenge: 'some-challenge', - }, - 'some-sig', - 'some-address', - ), /Error/) + }, 'some-sig', 'some-address') + }).rejects.toThrow() }) - it('should get a session token', () => { + + it('should get a session token', async () => { const wallet = ethers.Wallet.createRandom() - return client.getChallenge(wallet.address) - .then(async (challenge) => { - assert(challenge.challenge) - const signature = await wallet.signMessage(challenge.challenge) - return client.sendChallengeResponse(challenge, signature, wallet.address) - .then((sessionToken) => { - assert(sessionToken) - assert(sessionToken.token) - assert(sessionToken.expires) - }) - }) + const challenge = await client.getChallenge(wallet.address) + assert(challenge.challenge) + const signature = await wallet.signMessage(challenge.challenge) + const sessionToken = await client.sendChallengeResponse(challenge, signature, wallet.address) + assert(sessionToken) + assert(sessionToken.token) + assert(sessionToken.expires) }) - it('should get a session token with combined function', () => { + + it('should get a session token with combined function', async () => { const wallet = ethers.Wallet.createRandom() - return client.loginWithChallengeResponse((d) => wallet.signMessage(d), wallet.address) - .then((sessionToken) => { - assert(sessionToken) - assert(sessionToken.token) - assert(sessionToken.expires) - }) + const sessionToken = await client.loginWithChallengeResponse((d) => wallet.signMessage(d), wallet.address) + assert(sessionToken) + assert(sessionToken.token) + assert(sessionToken.expires) }) }) describe('API key login', () => { it('should fail to get a session token', async () => { - await assertThrowsAsync(async () => client.loginWithApiKey('apikey'), /Error/) + await expect(async () => { + await client.loginWithApiKey('apikey') + }).rejects.toThrow() + }) + + it('should get a session token', async () => { + const sessionToken = await client.loginWithApiKey('tester1-api-key') + assert(sessionToken) + assert(sessionToken.token) + assert(sessionToken.expires) }) - it('should get a session token', () => client.loginWithApiKey('tester1-api-key') - .then((sessionToken) => { - assert(sessionToken) - assert(sessionToken.token) - assert(sessionToken.expires) - })) }) describe('Username/password login', () => { @@ -106,10 +89,11 @@ describe('LoginEndpoints', () => { }) describe('UserInfo', () => { - it('should get user info', () => client.getUserInfo().then((userInfo) => { + it('should get user info', async () => { + const userInfo = await client.getUserInfo() assert(userInfo.name) assert(userInfo.username) - })) + }) }) describe('logout', () => { diff --git a/test/integration/MultipleClients.test.js b/test/integration/MultipleClients.test.js index 92b30d8ec..2869b92d5 100644 --- a/test/integration/MultipleClients.test.js +++ b/test/integration/MultipleClients.test.js @@ -1,107 +1,517 @@ -import { ethers } from 'ethers' import { wait } from 'streamr-test-utils' +import { ControlLayer } from 'streamr-client-protocol' -import { uid } from '../utils' -import StreamrClient from '../../src' +import { describeRepeats, uid, fakePrivateKey, getWaitForStorage, getPublishTestMessages, addAfterFn } from '../utils' +import { StreamrClient } from '../../src/StreamrClient' +import { counterId, Defer, pLimitFn } from '../../src/utils' +import Connection from '../../src/Connection' import config from './config' +const { ControlMessage } = ControlLayer + const createClient = (opts = {}) => new StreamrClient({ + ...config.clientOptions, auth: { - privateKey: ethers.Wallet.createRandom().privateKey, + privateKey: fakePrivateKey() }, autoConnect: false, autoDisconnect: false, - ...config.clientOptions, + // disconnectDelay: 1, + // publishAutoDisconnectDelay: 1, ...opts, }) -const throwError = (error) => { throw error } +const MAX_MESSAGES = 10 -describe('PubSub with multiple clients', () => { +describeRepeats('PubSub with multiple clients', () => { let stream let mainClient let otherClient let privateKey + let errors = [] - async function setup() { - privateKey = ethers.Wallet.createRandom().privateKey + const runAfterTest = addAfterFn() + + const getOnError = (errs) => jest.fn((err) => { + errs.push(err) + }) + + beforeEach(async () => { + errors = [] + privateKey = fakePrivateKey() mainClient = createClient({ auth: { privateKey } }) - mainClient.once('error', throwError) + mainClient.on('error', getOnError(errors)) stream = await mainClient.createStream({ name: uid('stream') }) - } - - async function teardown() { - if (stream) { - await stream.delete() - stream = undefined // eslint-disable-line require-atomic-updates - } + }) + afterEach(async () => { if (mainClient) { - await mainClient.ensureDisconnected() + mainClient.debug('disconnecting after test') + await mainClient.disconnect() } if (otherClient) { - await otherClient.ensureDisconnected() + otherClient.debug('disconnecting after test') + await otherClient.disconnect() } - } - beforeEach(async () => { - await setup() - }) + expect(errors).toEqual([]) - afterEach(async () => { - await teardown() + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + await Connection.closeOpen() + throw new Error(`sockets not closed: ${openSockets}`) + } }) - test('can get messages published from other client', async (done) => { - otherClient = createClient({ - auth: { - privateKey - } - }) - otherClient.once('error', done) - mainClient.once('error', done) - await otherClient.ensureConnected() - await mainClient.ensureConnected() - - const receivedMessagesOther = [] - const receivedMessagesMain = [] - // subscribe to stream from other client instance - await new Promise((resolve) => { - otherClient.subscribe({ + describe('can get messages published from other client', () => { + test('it works', async () => { + otherClient = createClient({ + auth: { + privateKey + } + }) + otherClient.on('error', getOnError(errors)) + await otherClient.connect() + await mainClient.connect() + + const receivedMessagesOther = [] + const receivedMessagesMain = [] + // subscribe to stream from other client instance + await otherClient.subscribe({ stream: stream.id, }, (msg) => { receivedMessagesOther.push(msg) - }).once('subscribed', resolve) - }) - // subscribe to stream from main client instance - await new Promise((resolve) => { - mainClient.subscribe({ + }) + // subscribe to stream from main client instance + await mainClient.subscribe({ stream: stream.id, }, (msg) => { receivedMessagesMain.push(msg) - }).once('subscribed', resolve) + }) + const message = { + msg: uid('message'), + } + await wait(5000) + // publish message on main client + await mainClient.publish(stream, message) + await wait(5000) + // messages should arrive on both clients? + expect(receivedMessagesMain).toEqual([message]) + expect(receivedMessagesOther).toEqual([message]) + }, 30000) + + describe('subscriber disconnects after each message', () => { + test('single subscriber', async () => { + const maxMessages = MAX_MESSAGES + Math.floor(Math.random() * MAX_MESSAGES * 0.25) + otherClient = createClient({ + auth: { + privateKey + } + }) + otherClient.on('error', getOnError(errors)) + await otherClient.connect() + await mainClient.connect() + + const receivedMessagesOther = [] + const msgs = receivedMessagesOther + const otherDone = Defer() + // subscribe to stream from other client instance + await otherClient.subscribe({ + stream: stream.id, + }, (msg) => { + otherClient.debug('other', msg.value) + receivedMessagesOther.push(msg) + + if (receivedMessagesOther.length === maxMessages) { + otherDone.resolve() + } + }) + let disconnecting = false + const disconnect = async () => { + if (msgs.length === maxMessages) { return } + + if (disconnecting) { return } + disconnecting = true + otherClient.debug('disconnecting...', msgs.length) + otherClient.connection.socket.close() + // wait for reconnection before possibly disconnecting again + try { + await otherClient.nextConnection() + otherClient.debug('reconnected...', msgs.length) + } finally { + // eslint-disable-next-line require-atomic-updates + disconnecting = false + } + } + + const onConnectionMessage = jest.fn(() => { + // disconnect after every message + disconnect() + }) + + otherClient.connection.on(ControlMessage.TYPES.BroadcastMessage, onConnectionMessage) + otherClient.connection.on(ControlMessage.TYPES.UnicastMessage, onConnectionMessage) + let t = 0 + const publishTestMessages = getPublishTestMessages(mainClient, { + stream, + delay: 600, + timestamp: () => { + t += 1 + return t + }, + waitForLast: true, + waitForLastTimeout: 10000, + waitForLastCount: maxMessages, + }) + + const published = await publishTestMessages(maxMessages) + await otherDone + + expect(receivedMessagesOther).toEqual(published) + }, 30000) + + test('publisher also subscriber', async () => { + const maxMessages = MAX_MESSAGES + Math.floor(Math.random() * MAX_MESSAGES * 0.25) + otherClient = createClient({ + auth: { + privateKey + } + }) + otherClient.on('error', getOnError(errors)) + await otherClient.connect() + await mainClient.connect() + + const receivedMessagesOther = [] + const msgs = receivedMessagesOther + const receivedMessagesMain = [] + const mainDone = Defer() + const otherDone = Defer() + // subscribe to stream from other client instance + await otherClient.subscribe({ + stream: stream.id, + }, (msg) => { + otherClient.debug('other', msg.value) + receivedMessagesOther.push(msg) + + if (receivedMessagesOther.length === maxMessages) { + otherDone.resolve() + } + }) + + const disconnect = pLimitFn(async () => { + if (msgs.length === maxMessages) { return } + otherClient.debug('disconnecting...', msgs.length) + otherClient.connection.socket.close() + // wait for reconnection before possibly disconnecting again + await otherClient.nextConnection() + otherClient.debug('reconnected...', msgs.length) + }) + + const onConnectionMessage = jest.fn(() => { + // disconnect after every message + disconnect() + }) + + otherClient.connection.on(ControlMessage.TYPES.BroadcastMessage, onConnectionMessage) + otherClient.connection.on(ControlMessage.TYPES.UnicastMessage, onConnectionMessage) + // subscribe to stream from main client instance + await mainClient.subscribe({ + stream: stream.id, + }, (msg) => { + mainClient.debug('main', msg.value) + receivedMessagesMain.push(msg) + if (receivedMessagesMain.length === maxMessages) { + mainDone.resolve() + } + }) + + let t = 0 + + const publishTestMessages = getPublishTestMessages(mainClient, { + stream, + delay: 600, + waitForLast: true, + waitForLastTimeout: 10000, + waitForLastCount: maxMessages, + timestamp: () => { + t += 1 + return t + }, + }) + const published = await publishTestMessages(maxMessages) + + await otherDone + await mainDone + + // messages should arrive on both clients? + expect(receivedMessagesMain).toEqual(published) + expect(receivedMessagesOther).toEqual(published) + }, 30000) }) - const message = { - msg: uid('message'), + }) + + describe('multiple publishers', () => { + async function createPublisher() { + const pubClient = createClient({ + auth: { + privateKey: fakePrivateKey(), + } + }) + runAfterTest(() => pubClient.disconnect()) + pubClient.on('error', getOnError(errors)) + const pubUser = await pubClient.getUserInfo() + await stream.grantPermission('stream_get', pubUser.username) + await stream.grantPermission('stream_publish', pubUser.username) + // needed to check last + await stream.grantPermission('stream_subscribe', pubUser.username) + await pubClient.session.getSessionToken() + await pubClient.connect() + + runAfterTest(async () => { + await pubClient.disconnect() + }) + return pubClient } - await wait(5000) - // publish message on main client - await mainClient.publish(stream, message) - await wait(5000) - // messages should arrive on both clients? - expect(receivedMessagesMain).toEqual([message]) - expect(receivedMessagesOther).toEqual([message]) - otherClient.removeListener('error', done) - mainClient.removeListener('error', done) - done() - }, 30000) + + // eslint-disable-next-line no-inner-declarations + function checkMessages(published, received) { + for (const [key, msgs] of Object.entries(published)) { + expect(received[key]).toEqual(msgs) + } + } + + test('works with multiple publishers on one stream', async () => { + // this creates two subscriber clients and multiple publisher clients + // all subscribing and publishing to same stream + await mainClient.session.getSessionToken() + await mainClient.connect() + + otherClient = createClient({ + auth: { + privateKey + } + }) + otherClient.on('error', getOnError(errors)) + await otherClient.session.getSessionToken() + const otherUser = await otherClient.getUserInfo() + await stream.grantPermission('stream_get', otherUser.username) + await stream.grantPermission('stream_subscribe', otherUser.username) + await otherClient.connect() + + const receivedMessagesOther = {} + const receivedMessagesMain = {} + // subscribe to stream from other client instance + await otherClient.subscribe({ + stream: stream.id, + }, (msg, streamMessage) => { + const msgs = receivedMessagesOther[streamMessage.getPublisherId()] || [] + msgs.push(msg) + receivedMessagesOther[streamMessage.getPublisherId()] = msgs + }) + + // subscribe to stream from main client instance + await mainClient.subscribe({ + stream: stream.id, + }, (msg, streamMessage) => { + const msgs = receivedMessagesMain[streamMessage.getPublisherId()] || [] + msgs.push(msg) + receivedMessagesMain[streamMessage.getPublisherId()] = msgs + }) + + /* eslint-disable no-await-in-loop */ + const publishers = [] + for (let i = 0; i < 3; i++) { + publishers.push(await createPublisher()) + } + /* eslint-enable no-await-in-loop */ + const published = {} + await Promise.all(publishers.map(async (pubClient) => { + const publisherId = (await pubClient.getPublisherId()).toLowerCase() + runAfterTest(() => { + counterId.clear(publisherId) // prevent overflows in counter + }) + const publishTestMessages = getPublishTestMessages(pubClient, { + stream, + delay: 500 + Math.random() * 1500, + waitForLast: true, + waitForLastTimeout: 10000, + waitForLastCount: MAX_MESSAGES, + createMessage: () => ({ + value: counterId(publisherId), + }), + }) + published[publisherId] = await publishTestMessages(MAX_MESSAGES) + })) + + checkMessages(published, receivedMessagesMain) + checkMessages(published, receivedMessagesOther) + }, 40000) + + test('works with multiple publishers on one stream with late subscriber', async () => { + // this creates two subscriber clients and multiple publisher clients + // all subscribing and publishing to same stream + // the otherClient subscribes after the 3rd message hits storage + await mainClient.session.getSessionToken() + await mainClient.connect() + + otherClient = createClient({ + auth: { + privateKey + } + }) + + runAfterTest(() => { + otherClient.disconnect() + }) + + otherClient.on('error', getOnError(errors)) + await otherClient.session.getSessionToken() + const otherUser = await otherClient.getUserInfo() + await stream.grantPermission('stream_get', otherUser.username) + await stream.grantPermission('stream_subscribe', otherUser.username) + await otherClient.connect() + + const receivedMessagesOther = {} + const receivedMessagesMain = {} + + // subscribe to stream from main client instance + const mainSub = await mainClient.subscribe({ + stream: stream.id, + }, (msg, streamMessage) => { + const msgs = receivedMessagesMain[streamMessage.getPublisherId()] || [] + msgs.push(msg) + receivedMessagesMain[streamMessage.getPublisherId()] = msgs + if (Object.values(receivedMessagesMain).every((m) => m.length === MAX_MESSAGES)) { + mainSub.unsubscribe() + } + }) + + /* eslint-disable no-await-in-loop */ + const publishers = [] + for (let i = 0; i < 3; i++) { + publishers.push(await createPublisher()) + } + + /* eslint-enable no-await-in-loop */ + let counter = 0 + const published = {} + await Promise.all(publishers.map(async (pubClient) => { + const waitForStorage = getWaitForStorage(pubClient, { + stream, + timeout: 10000, + count: MAX_MESSAGES, + }) + + const publisherId = (await pubClient.getPublisherId()).toLowerCase() + runAfterTest(() => { + counterId.clear(publisherId) // prevent overflows in counter + }) + const publishTestMessages = getPublishTestMessages(pubClient, { + stream, + waitForLast: true, + waitForLastTimeout: 10000, + waitForLastCount: MAX_MESSAGES, + delay: 500 + Math.random() * 1500, + createMessage: () => ({ + value: counterId(publisherId), + }), + }) + + published[publisherId] = await publishTestMessages(MAX_MESSAGES, { + async afterEach(_pubMsg, req) { + counter += 1 + if (counter === 3) { + // late subscribe to stream from other client instance + await waitForStorage(req) // make sure lastest message has hit storage + const lateSub = await otherClient.subscribe({ + stream: stream.id, + resend: { + last: 1000, + } + }, (msg, streamMessage) => { + const msgs = receivedMessagesOther[streamMessage.getPublisherId()] || [] + msgs.push(msg) + receivedMessagesOther[streamMessage.getPublisherId()] = msgs + }) + + runAfterTest(async () => { + await lateSub.unsubscribe() + }) + } + } + }) + })) + checkMessages(published, receivedMessagesMain) + checkMessages(published, receivedMessagesOther) + }, 60000) + }) + + test('disconnecting one client does not disconnect the other', async () => { + otherClient = createClient({ + auth: { + privateKey + } + }) + const onConnectedOther = jest.fn() + const onConnectedMain = jest.fn() + const onDisconnectedOther = jest.fn() + const onDisconnectedMain = jest.fn() + otherClient.on('disconnected', onDisconnectedOther) + mainClient.on('disconnected', onDisconnectedMain) + otherClient.on('connected', onConnectedOther) + mainClient.on('connected', onConnectedMain) + otherClient.on('error', getOnError(errors)) + + await otherClient.connect() + await mainClient.connect() + + otherClient.connection.socket.close() + expect(mainClient.connection.getState()).toBe('connected') + await otherClient.nextConnection() + expect(otherClient.connection.getState()).toBe('connected') + expect(onDisconnectedMain).toHaveBeenCalledTimes(0) + expect(onDisconnectedOther).toHaveBeenCalledTimes(1) + expect(onConnectedMain).toHaveBeenCalledTimes(1) + expect(onConnectedOther).toHaveBeenCalledTimes(2) + }) + + test('disconnecting one client does not disconnect the other: with autoConnect', async () => { + otherClient = createClient({ + auth: { + privateKey + } + }) + const onConnectedOther = jest.fn() + const onConnectedMain = jest.fn() + const onDisconnectedOther = jest.fn() + const onDisconnectedMain = jest.fn() + otherClient.on('disconnected', onDisconnectedOther) + mainClient.on('disconnected', onDisconnectedMain) + otherClient.on('connected', onConnectedOther) + mainClient.on('connected', onConnectedMain) + otherClient.on('error', getOnError(errors)) + + otherClient.enableAutoConnect() + mainClient.enableAutoConnect() + await otherClient.connection.addHandle(1) + await mainClient.connection.addHandle(2) + + otherClient.connection.socket.close() + expect(mainClient.connection.getState()).toBe('connected') + await otherClient.nextConnection() + expect(otherClient.connection.getState()).toBe('connected') + expect(onDisconnectedMain).toHaveBeenCalledTimes(0) + expect(onDisconnectedOther).toHaveBeenCalledTimes(1) + expect(onConnectedMain).toHaveBeenCalledTimes(1) + expect(onConnectedOther).toHaveBeenCalledTimes(2) + }) }) diff --git a/test/integration/ResendReconnect.test.js b/test/integration/ResendReconnect.test.js index 0d79942a5..a777acc22 100644 --- a/test/integration/ResendReconnect.test.js +++ b/test/integration/ResendReconnect.test.js @@ -1,22 +1,21 @@ -import { ethers } from 'ethers' +import { wait, waitForCondition } from 'streamr-test-utils' -import { uid } from '../utils' -import StreamrClient from '../../src' +import { uid, fakePrivateKey, getPublishTestMessages } from '../utils' +import { StreamrClient } from '../../src/StreamrClient' +import { Defer } from '../../src/utils' import config from './config' -const { wait } = require('streamr-test-utils') - const createClient = (opts = {}) => new StreamrClient({ - auth: { - privateKey: ethers.Wallet.createRandom().privateKey, - }, - autoConnect: false, - autoDisconnect: false, ...(config.clientOptions || { url: config.websocketUrl, restUrl: config.restUrl, }), + auth: { + privateKey: fakePrivateKey(), + }, + autoConnect: false, + autoDisconnect: false, ...opts, }) @@ -26,73 +25,95 @@ describe('resend/reconnect', () => { let client let stream let publishedMessages + let publishTestMessages beforeEach(async () => { client = createClient() - await client.ensureConnected() - - publishedMessages = [] + await client.connect() stream = await client.createStream({ name: uid('resends') }) - for (let i = 0; i < MAX_MESSAGES; i++) { - const message = { - msg: uid('message'), - } - - // eslint-disable-next-line no-await-in-loop - await client.publish(stream.id, message) - publishedMessages.push(message) - } + publishTestMessages = getPublishTestMessages(client, { + streamId: stream.id, + waitForLast: true, + }) - await wait(5000) // wait for messages to (hopefully) land in storage + publishedMessages = await publishTestMessages(MAX_MESSAGES) }, 10 * 1000) afterEach(async () => { - await client.ensureDisconnected() + await client.disconnect() }) - describe('reconnect after resend', () => { + describe('reconnect with resend', () => { + let shouldDisconnect = false let sub let messages = [] - beforeEach((done) => { - sub = client.subscribe({ + beforeEach(async () => { + const done = Defer() + messages = [] + sub = await client.subscribe({ stream: stream.id, resend: { last: MAX_MESSAGES, }, }, (message) => { messages.push(message) + if (shouldDisconnect) { + client.connection.socket.close() + } }) - sub.once('resent', () => { - done() - }) + + sub.once('resent', done.resolve) + await done + expect(messages).toEqual(publishedMessages.slice(-MAX_MESSAGES)) }, 15000) - it('can handle reconnection after disconnection', (done) => { - const newPublishedMessages = [] - client.connection.socket.once('close', () => { - // should reconnect - client.once('connected', async () => { - setTimeout(async () => { - // clear messsages - messages = [] - const message = { - msg: uid('newmessage'), - } - newPublishedMessages.push(message) - await client.publish(stream, message) - setTimeout(() => { - expect(messages).toEqual(newPublishedMessages) - done() - }, 3000) - }, 3000) - }) + it('can handle mixed resend/subscribe', async () => { + const prevMessages = messages.slice() + const newMessages = await publishTestMessages(3) + expect(messages).toEqual([...prevMessages, ...newMessages]) + }, 10000) + + it('can handle reconnection after unintentional disconnection 1', async () => { + const onClose = Defer() + + client.connection.socket.once('close', onClose.resolve) + client.connection.socket.close() + await onClose + // should reconnect and get new messages + const prevMessages = messages.slice() + const newMessages = await publishTestMessages(3) + await wait(6000) + expect(messages).toEqual([...prevMessages, ...newMessages]) + }, 11000) + + it('can handle reconnection after unintentional disconnection 2', async () => { + // should reconnect and get new messages + const prevMessages = messages.slice() + const newMessages = await publishTestMessages(3, { + waitForLast: false, }) + const onClose = Defer() + + client.connection.socket.once('close', onClose.resolve) client.connection.socket.close() - }, 110000) + await client.connection.nextConnection() + + await wait(6000) + expect(messages).toEqual([...prevMessages, ...newMessages]) + }, 11000) + + it('can handle reconnection after unintentional disconnection 3', async () => { + shouldDisconnect = true + const prevMessages = messages.slice() + const newMessages = await publishTestMessages(MAX_MESSAGES, { + waitForLast: false, + }) + await waitForCondition(() => messages.length === MAX_MESSAGES * 2, 10000) + expect(messages).toEqual([...prevMessages, ...newMessages]) + }, 21000) }) }) - diff --git a/test/integration/Resends.test.js b/test/integration/Resends.test.js index 1246adaea..836632117 100644 --- a/test/integration/Resends.test.js +++ b/test/integration/Resends.test.js @@ -1,288 +1,284 @@ -import { uid } from '../utils' -import StreamrClient from '../../src' +import { wait, waitForCondition, waitForEvent } from 'streamr-test-utils' -import config from './config' - -const { wait, waitForCondition } = require('streamr-test-utils') +import { uid, describeRepeats, fakePrivateKey, getPublishTestMessages } from '../utils' +import { StreamrClient } from '../../src/StreamrClient' +import { Defer, pTimeout } from '../../src/utils' +import Connection from '../../src/Connection' -const createClient = (opts = {}) => new StreamrClient({ - apiKey: 'tester1-api-key', - autoConnect: false, - autoDisconnect: false, - ...config.clientOptions, - ...opts, -}) +import config from './config' const MAX_MESSAGES = 10 -const TEST_REPEATS = 10 +const WAIT_FOR_STORAGE_TIMEOUT = 6000 + +/* eslint-disable no-await-in-loop */ describe('StreamrClient resends', () => { describe('resend', () => { + let expectErrors = 0 // check no errors by default + let onError = jest.fn() + + const createClient = (opts = {}) => { + const c = new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: fakePrivateKey(), + }, + autoConnect: false, + autoDisconnect: false, + maxRetries: 2, + ...opts, + }) + c.onError = jest.fn() + c.on('error', onError) + return c + } + let client let stream - let publishedMessages + let published + let publishTestMessages beforeEach(async () => { client = createClient() - await client.ensureConnected() - - publishedMessages = [] - - stream = await client.createStream({ - name: uid('resends') - }) - - for (let i = 0; i < MAX_MESSAGES; i++) { - const message = { - msg: uid('message'), - } - - // eslint-disable-next-line no-await-in-loop - await client.publish(stream.id, message) - publishedMessages.push(message) - } - - await wait(5000) // wait for messages to (hopefully) land in storage - }, 10 * 1000) + await client.connect() + expectErrors = 0 + onError = jest.fn() + }) afterEach(async () => { - await client.ensureDisconnected() + await wait() + // ensure no unexpected errors + expect(onError).toHaveBeenCalledTimes(expectErrors) + if (client) { + expect(client.onError).toHaveBeenCalledTimes(expectErrors) + } }) - describe('issue resend and subscribe at the same time', () => { - it('works with resend -> subscribe', async () => { - const resentMessages = [] - const realtimeMessages = [] - - const realtimeMessage = { - msg: uid('realtimeMessage'), - } - - await client.resend({ - stream: stream.id, - resend: { - last: MAX_MESSAGES, - }, - }, (message) => { - resentMessages.push(message) - }) - - client.subscribe({ - stream: stream.id, - }, (message) => { - realtimeMessages.push(message) - }) - - await waitForCondition(() => resentMessages.length === MAX_MESSAGES, 5000) - await Promise.all([ - client.publish(stream.id, realtimeMessage), - waitForCondition(() => realtimeMessages.length === 1, 10000) - ]) - expect(resentMessages).toStrictEqual(publishedMessages) - expect(realtimeMessages).toStrictEqual([realtimeMessage]) - }, 18000) - - it('works with subscribe -> resend', async () => { - const resentMessages = [] - const realtimeMessages = [] - - const realtimeMessage = { - msg: uid('realtimeMessage'), - } + afterEach(async () => { + await wait(500) + if (client) { + client.debug('disconnecting after test') + await client.disconnect() + } - client.subscribe({ - stream: stream.id, - }, (message) => { - realtimeMessages.push(message) - }) + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + await Connection.closeOpen() + throw new Error(`sockets not closed: ${openSockets}`) + } + }) - // resend after realtime subscribe - await client.resend({ - stream: stream.id, - resend: { - last: MAX_MESSAGES, - }, - }, (message) => { - resentMessages.push(message) + describe('short resend', () => { + beforeEach(async () => { + stream = await client.createStream({ + name: uid('resends') }) - await waitForCondition(() => resentMessages.length === MAX_MESSAGES, 5000) - await Promise.all([ - client.publish(stream.id, realtimeMessage), - waitForCondition(() => realtimeMessages.length === 1, 5000) - ]) - expect(resentMessages).toStrictEqual(publishedMessages) - expect(realtimeMessages).toStrictEqual([realtimeMessage]) - }, 15000) - - it('works with subscribe+resend -> subscribe', async () => { - const resentMessages = [] - const realtimeMessages = [] - - const realtimeMessage = { - msg: uid('realtimeMessage'), - } - - client.subscribe({ - stream: stream.id, - resend: { - last: MAX_MESSAGES, - }, - }, (message) => { - resentMessages.push(message) + publishTestMessages = getPublishTestMessages(client, { + stream }) - client.subscribe({ - stream: stream.id, - }, (message) => { - realtimeMessages.push(message) + published = await publishTestMessages(MAX_MESSAGES, { + waitForLast: true, + waitForLastTimeout: WAIT_FOR_STORAGE_TIMEOUT, }) + }, WAIT_FOR_STORAGE_TIMEOUT * 2) - await waitForCondition(() => resentMessages.length === MAX_MESSAGES, 5000) - await Promise.all([ - client.publish(stream.id, realtimeMessage), - waitForCondition(() => realtimeMessages.length === 1, 5000) - ]) - expect(resentMessages).toStrictEqual([...publishedMessages, realtimeMessage]) - expect(realtimeMessages).toStrictEqual([realtimeMessage]) - }, 15000) - - it('works with subscribe -> subscribe+resend', async () => { - const resentMessages = [] - const realtimeMessages = [] - - const realtimeMessage = { - msg: uid('realtimeMessage'), - } + describe('issue resend and subscribe at the same time', () => { + it('works with resend -> subscribe', async () => { + const resentMessages = [] + const realtimeMessages = [] - client.subscribe({ - stream: stream.id, - }, (message) => { - realtimeMessages.push(message) - }) + const realtimeMessage = { + msg: uid('realtimeMessage'), + } - // subscribe with resend after realtime subscribe - client.subscribe({ - stream: stream.id, - resend: { - last: MAX_MESSAGES, - }, - }, (message) => { - resentMessages.push(message) - }) + await client.resend({ + stream: stream.id, + resend: { + last: MAX_MESSAGES, + }, + }, (message) => { + resentMessages.push(message) + }) - await waitForCondition(() => resentMessages.length === MAX_MESSAGES, 5000) - await Promise.all([ - client.publish(stream.id, realtimeMessage), - waitForCondition(() => realtimeMessages.length === 1, 5000) - ]) - expect(resentMessages).toStrictEqual([...publishedMessages, realtimeMessage]) - expect(realtimeMessages).toStrictEqual([realtimeMessage]) - }, 15000) - }) + await client.subscribe({ + stream: stream.id, + }, (message) => { + realtimeMessages.push(message) + }) + + await waitForCondition(() => resentMessages.length === MAX_MESSAGES, 5000) + await Promise.all([ + client.publish(stream.id, realtimeMessage), + waitForCondition(() => realtimeMessages.length === 1, 10000) + ]) + expect(resentMessages).toStrictEqual(published) + expect(realtimeMessages).toStrictEqual([realtimeMessage]) + }, 18000) + + it('works with subscribe -> resend', async () => { + const resentMessages = [] + const realtimeMessages = [] + + const realtimeMessage = { + msg: uid('realtimeMessage'), + } - for (let i = 0; i < TEST_REPEATS; i++) { - // eslint-disable-next-line no-loop-func - it(`resend last using resend function on try ${i}`, async () => { - const receivedMessages = [] + await client.subscribe({ + stream: stream.id, + }, (message) => { + realtimeMessages.push(message) + }) - // eslint-disable-next-line no-await-in-loop - const sub = await client.resend( - { + // resend after realtime subscribe + await client.resend({ stream: stream.id, resend: { last: MAX_MESSAGES, }, - }, - (message) => { - receivedMessages.push(message) - }, - ) + }, (message) => { + resentMessages.push(message) + }) + + await waitForCondition(() => resentMessages.length === MAX_MESSAGES, 5000) + await Promise.all([ + client.publish(stream.id, realtimeMessage), + waitForCondition(() => realtimeMessages.length === 1, 5000) + ]) + expect(resentMessages).toStrictEqual(published) + expect(realtimeMessages).toStrictEqual([realtimeMessage]) + }, 15000) + + it('works with subscribe+resend -> subscribe', async () => { + const resentMessages = [] + const realtimeMessages = [] + + const realtimeMessage = { + msg: uid('realtimeMessage'), + } - // eslint-disable-next-line no-loop-func - sub.once('resent', () => { - expect(receivedMessages).toStrictEqual(publishedMessages) - }) + client.subscribe({ + stream: stream.id, + resend: { + last: MAX_MESSAGES, + }, + }, (message) => { + resentMessages.push(message) + }) - // eslint-disable-next-line no-await-in-loop - await waitForCondition(() => receivedMessages.length === MAX_MESSAGES, 10000) - }, 10000) - } + client.subscribe({ + stream: stream.id, + }, (message) => { + realtimeMessages.push(message) + }) + + await waitForCondition(() => resentMessages.length === MAX_MESSAGES, 5000) + await Promise.all([ + client.publish(stream.id, realtimeMessage), + waitForCondition(() => realtimeMessages.length === 1, 5000) + ]) + expect(resentMessages).toStrictEqual([...published, realtimeMessage]) + expect(realtimeMessages).toStrictEqual([realtimeMessage]) + }, 15000) + + it('works with subscribe -> subscribe+resend', async () => { + const resentMessages = [] + const realtimeMessages = [] + + const realtimeMessage = { + msg: uid('realtimeMessage'), + } - for (let i = 0; i < TEST_REPEATS; i++) { - // eslint-disable-next-line no-loop-func - it(`resend last using subscribe function on try ${i}`, async () => { - const receivedMessages = [] + client.subscribe({ + stream: stream.id, + }, (message) => { + realtimeMessages.push(message) + }) - // eslint-disable-next-line no-await-in-loop - const sub = client.subscribe( - { + // subscribe with resend after realtime subscribe + client.subscribe({ stream: stream.id, resend: { last: MAX_MESSAGES, }, - }, - (message) => { - receivedMessages.push(message) - }, - ) + }, (message) => { + resentMessages.push(message) + }) + + await waitForCondition(() => resentMessages.length === MAX_MESSAGES, 5000) + await Promise.all([ + client.publish(stream.id, realtimeMessage), + waitForCondition(() => realtimeMessages.length === 1, 5000) + ]) + expect(resentMessages).toStrictEqual([...published, realtimeMessage]) + expect(realtimeMessages).toStrictEqual([realtimeMessage]) + }, 15000) + }) + describeRepeats('resend repeats', () => { // eslint-disable-next-line no-loop-func - sub.once('resent', () => { - expect(receivedMessages).toStrictEqual(publishedMessages) - }) + test('resend last using resend function', async () => { + const receivedMessages = [] - // eslint-disable-next-line no-await-in-loop - await waitForCondition(() => receivedMessages.length === MAX_MESSAGES, 10000) - }, 10000) - } - - it('resend last using subscribe and publish messages after resend', async () => { - const receivedMessages = [] + // eslint-disable-next-line no-await-in-loop + const sub = await client.resend( + { + stream: stream.id, + resend: { + last: MAX_MESSAGES, + }, + }, + (message) => { + receivedMessages.push(message) + }, + ) - client.subscribe({ - stream: stream.id, - resend: { - last: MAX_MESSAGES, - }, - }, (message) => { - receivedMessages.push(message) - }) + // eslint-disable-next-line no-loop-func + sub.once('resent', () => { + expect(receivedMessages).toStrictEqual(published) + }) - // wait for resend MAX_MESSAGES - await waitForCondition(() => receivedMessages.length === MAX_MESSAGES, 20000) - expect(receivedMessages).toStrictEqual(publishedMessages) + // eslint-disable-next-line no-await-in-loop + await waitForCondition(() => receivedMessages.length === MAX_MESSAGES, 10000) + }, 10000 * 1.2) - // publish after resend, realtime subscription messages - for (let i = MAX_MESSAGES; i < MAX_MESSAGES * 2; i++) { - const message = { - msg: uid('message'), - } + // eslint-disable-next-line no-loop-func + test('resend last using subscribe function', async () => { + const receivedMessages = [] - // eslint-disable-next-line no-await-in-loop - await client.publish(stream.id, message) - publishedMessages.push(message) - } + // eslint-disable-next-line no-await-in-loop + const sub = await client.subscribe({ + stream: stream.id, + resend: { + last: MAX_MESSAGES, + }, + }, (message) => { + receivedMessages.push(message) + }) + // eslint-disable-next-line no-loop-func + await waitForEvent(sub, 'resent', 10000) + expect(receivedMessages).toStrictEqual(published) + }, 10000 * 1.2) + }) - await waitForCondition(() => receivedMessages.length === MAX_MESSAGES * 2, 10000) - expect(receivedMessages).toStrictEqual(publishedMessages) - }, 40000) + it('resend last using subscribe and publish messages after resend', async () => { + const receivedMessages = [] - it('resend last using subscribe and publish realtime messages', async () => { - const receivedMessages = [] + await client.subscribe({ + stream: stream.id, + resend: { + last: MAX_MESSAGES, + }, + }, (message) => { + receivedMessages.push(message) + }) - const sub = client.subscribe({ - stream: stream.id, - resend: { - last: MAX_MESSAGES, - }, - }, (message) => { - receivedMessages.push(message) - }) + // wait for resend MAX_MESSAGES + await waitForCondition(() => receivedMessages.length === MAX_MESSAGES, 20000) + expect(receivedMessages).toStrictEqual(published) - sub.once('resent', async () => { - expect(receivedMessages).toStrictEqual(publishedMessages) - expect(receivedMessages).toHaveLength(MAX_MESSAGES) + // publish after resend, realtime subscription messages for (let i = MAX_MESSAGES; i < MAX_MESSAGES * 2; i++) { const message = { msg: uid('message'), @@ -290,55 +286,94 @@ describe('StreamrClient resends', () => { // eslint-disable-next-line no-await-in-loop await client.publish(stream.id, message) - publishedMessages.push(message) + published.push(message) } - }) - await waitForCondition(() => receivedMessages.length === MAX_MESSAGES * 2, 20000) - expect(receivedMessages).toStrictEqual(publishedMessages) - }, 40000) + await waitForCondition(() => receivedMessages.length === MAX_MESSAGES * 2, 10000) + expect(receivedMessages).toStrictEqual(published) + }, 40000) - it('long resend', async (done) => { - const LONG_RESEND = 10000 - const publishedMessages2 = [] + it('resend last using subscribe and publish realtime messages', async () => { + const receivedMessages = [] - stream = await client.createStream({ - name: uid('resends') - }) + const sub = await client.subscribe({ + stream: stream.id, + resend: { + last: MAX_MESSAGES, + }, + }, (message) => { + receivedMessages.push(message) + }) - for (let i = 0; i < LONG_RESEND; i++) { - const message = { - msg: uid('message'), - } + sub.once('resent', async () => { + expect(receivedMessages).toStrictEqual(published) + expect(receivedMessages).toHaveLength(MAX_MESSAGES) + for (let i = MAX_MESSAGES; i < MAX_MESSAGES * 2; i++) { + const message = { + msg: uid('message'), + } + + // eslint-disable-next-line no-await-in-loop + await client.publish(stream.id, message) + published.push(message) + } + }) - // eslint-disable-next-line no-await-in-loop - await client.publish(stream.id, message) - publishedMessages2.push(message) - } + await waitForCondition(() => receivedMessages.length === MAX_MESSAGES * 2, 20000) + expect(receivedMessages).toStrictEqual(published) + }, 40000) + }) + + describe('long resend', () => { + const LONG_RESEND = 500 + + beforeEach(async () => { + stream = await client.createStream({ + name: uid('resends') + }) - await wait(30000) - await client.ensureDisconnected() + client.debug('CREATED') + publishTestMessages = getPublishTestMessages(client, { + stream + }) - // resend from LONG_RESEND messages - await client.ensureConnected() - const receivedMessages = [] + client.debug(`Publishing ${LONG_RESEND} messages...`) + published = await publishTestMessages(LONG_RESEND, { + waitForLast: true, + }) + client.debug(`Published ${LONG_RESEND} messages`) + await client.disconnect() + }, 300000) - const sub = await client.resend({ - stream: stream.id, - resend: { - from: { - timestamp: 0, + test('receives all messages', async () => { + // resend from LONG_RESEND messages + await client.connect() + + const receivedMessages = [] + const onGotFirstMessage = Defer() + const sub = await client.resend({ + stream: stream.id, + resend: { + from: { + timestamp: 0, + }, }, - }, - }, (message) => { - receivedMessages.push(message) - }) + }, (msg) => { + receivedMessages.push(msg) + if (receivedMessages.length === 1) { + onGotFirstMessage.resolve() + } + }) - sub.once('resent', () => { - expect(receivedMessages).toEqual(publishedMessages2) - expect(publishedMessages2.length).toBe(LONG_RESEND) - done() - }) + await pTimeout(onGotFirstMessage, 5000, 'waiting for first resent message') + client.debug('got first message') + client.debug('waiting for all messages') + await sub.onDone() + client.debug('subscription done') + + expect(receivedMessages).toEqual(published) + expect(published.length).toBe(LONG_RESEND) + }, 300000) }, 300000) }) }) diff --git a/test/integration/Sequencing.test.js b/test/integration/Sequencing.test.js new file mode 100644 index 000000000..f9ee621bd --- /dev/null +++ b/test/integration/Sequencing.test.js @@ -0,0 +1,302 @@ +import { wait, waitForCondition, waitForEvent } from 'streamr-test-utils' + +import { uid, fakePrivateKey, getWaitForStorage } from '../utils' +import { StreamrClient } from '../../src/StreamrClient' +import Connection from '../../src/Connection' + +import config from './config' + +const Msg = (opts) => ({ + value: uid('msg'), + ...opts, +}) + +function toSeq(requests, ts = Date.now()) { + return requests.map((m) => { + const { prevMsgRef } = m.streamMessage + return [ + [m.streamMessage.getTimestamp() - ts, m.streamMessage.getSequenceNumber()], + prevMsgRef ? [prevMsgRef.timestamp - ts, prevMsgRef.sequenceNumber] : null + ] + }) +} + +describe('Sequencing', () => { + let expectErrors = 0 // check no errors by default + let onError = jest.fn() + let client + let stream + + const createClient = (opts = {}) => { + const c = new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: fakePrivateKey(), + }, + autoConnect: false, + autoDisconnect: false, + maxRetries: 2, + ...opts, + }) + c.onError = jest.fn() + c.on('error', onError) + return c + } + + beforeEach(async () => { + expectErrors = 0 + onError = jest.fn() + client = createClient() + await client.connect() + + stream = await client.createStream({ + name: uid('stream') + }) + }) + + afterEach(async () => { + await wait() + // ensure no unexpected errors + expect(onError).toHaveBeenCalledTimes(expectErrors) + if (client) { + expect(client.onError).toHaveBeenCalledTimes(expectErrors) + } + }) + + afterEach(async () => { + await wait() + if (client) { + client.debug('disconnecting after test') + await client.disconnect() + } + + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + await Connection.closeOpen() + throw new Error(`sockets not closed: ${openSockets}`) + } + }) + + it('should sequence in order', async () => { + const ts = Date.now() + const msgsPublished = [] + const msgsReceieved = [] + + await client.subscribe(stream.id, (m) => msgsReceieved.push(m)) + + const nextMsg = () => { + const msg = Msg() + msgsPublished.push(msg) + return msg + } + + const requests = await Promise.all([ + // first 2 messages at ts + 0 + client.publish(stream, nextMsg(), ts), + client.publish(stream, nextMsg(), ts), + // next two messages at ts + 1 + client.publish(stream, nextMsg(), ts + 1), + client.publish(stream, nextMsg(), ts + 1), + ]) + const seq = toSeq(requests, ts) + expect(seq).toEqual([ + [[0, 0], null], + [[0, 1], [0, 0]], + [[1, 0], [0, 1]], + [[1, 1], [1, 0]], + ]) + + await waitForCondition(() => ( + msgsReceieved.length === msgsPublished.length + ), 8000).catch(() => {}) // ignore, tests will fail anyway + + expect(msgsReceieved).toEqual(msgsPublished) + }, 10000) + + it('should sequence in order even if some calls delayed', async () => { + const ts = Date.now() + const msgsPublished = [] + const msgsReceieved = [] + + let calls = 0 + const getStream = client.getStream.bind(client) + client.getStream = async (...args) => { + // delay getStream call + calls += 1 + if (calls === 2) { + const result = await getStream(...args) + // delay resolving this call + await wait(100) + return result + } + return getStream(...args) + } + + const nextMsg = () => { + const msg = Msg() + msgsPublished.push(msg) + return msg + } + + await client.subscribe(stream.id, (m) => msgsReceieved.push(m)) + const requests = await Promise.all([ + // first 2 messages at ts + 0 + client.publish(stream, nextMsg(), ts), + client.publish(stream, nextMsg(), ts), + // next two messages at ts + 1 + client.publish(stream, nextMsg(), ts + 1), + client.publish(stream, nextMsg(), ts + 1), + ]) + const seq = toSeq(requests, ts) + expect(seq).toEqual([ + [[0, 0], null], + [[0, 1], [0, 0]], + [[1, 0], [0, 1]], + [[1, 1], [1, 0]], + ]) + + await waitForCondition(() => ( + msgsReceieved.length === msgsPublished.length + ), 5000).catch(() => {}) // ignore, tests will fail anyway + + expect(msgsReceieved).toEqual(msgsPublished) + }, 10000) + + it.skip('should sequence in order even if publish requests backdated', async () => { + const ts = Date.now() + const msgsPublished = [] + const msgsReceieved = [] + + await client.subscribe(stream.id, (m) => msgsReceieved.push(m)) + + const nextMsg = (...args) => { + const msg = Msg(...args) + msgsPublished.push(msg) + return msg + } + + const requests = await Promise.all([ + // publish at ts + 0 + client.publish(stream, nextMsg(), ts), + // publish at ts + 1 + client.publish(stream, nextMsg(), ts + 1), + // backdate at ts + 0 + client.publish(stream, nextMsg({ + backdated: true, + }), ts), + // resume at ts + 2 + client.publish(stream, nextMsg(), ts + 2), + client.publish(stream, nextMsg(), ts + 2), + client.publish(stream, nextMsg(), ts + 3), + ]) + + await waitForCondition(() => ( + msgsReceieved.length === msgsPublished.length + ), 2000).catch(() => {}) // ignore, tests will fail anyway + + const lastRequest = requests[requests.length - 1] + const waitForStorage = getWaitForStorage(client, { + stream, + timeout: 6000, + }) + await waitForStorage(lastRequest) + const msgsResent = [] + const sub = await client.resend({ + stream: stream.id, + resend: { + from: { + timestamp: 0 + }, + }, + }, (m) => msgsResent.push(m)) + await waitForEvent(sub, 'resent') + + expect(msgsReceieved).toEqual(msgsResent) + // backdated messages disappear + expect(msgsReceieved).toEqual(msgsPublished.filter(({ backdated }) => !backdated)) + + const seq = toSeq(requests, ts) + client.debug(seq) + expect(seq).toEqual([ + [[0, 0], null], + [[1, 0], [0, 0]], + [[0, 0], [1, 0]], // bad message + [[2, 0], [1, 0]], + [[2, 1], [2, 0]], + [[3, 0], [2, 1]], + ]) + }, 10000) + + it.skip('should sequence in order even if publish requests backdated in sequence', async () => { + const ts = Date.now() + const msgsPublished = [] + const msgsReceieved = [] + + await client.subscribe(stream.id, (m) => msgsReceieved.push(m)) + + const nextMsg = (...args) => { + const msg = Msg(...args) + msgsPublished.push(msg) + return msg + } + + const requests = await Promise.all([ + // first 3 messages at ts + 0 + client.publish(stream, nextMsg(), ts), + client.publish(stream, nextMsg(), ts), + client.publish(stream, nextMsg(), ts), + // next two messages at ts + 1 + client.publish(stream, nextMsg(), ts + 1), + client.publish(stream, nextMsg(), ts + 1), + // backdate at ts + 0 + client.publish(stream, nextMsg({ + backdated: true, + }), ts), + // resume publishing at ts + 1 + client.publish(stream, nextMsg(), ts + 1), + client.publish(stream, nextMsg(), ts + 1), + client.publish(stream, nextMsg(), ts + 2), + client.publish(stream, nextMsg(), ts + 2), + ]) + + await waitForCondition(() => ( + msgsReceieved.length === msgsPublished.length + ), 2000).catch(() => {}) // ignore, tests will fail anyway + + const lastRequest = requests[requests.length - 1] + const waitForStorage = getWaitForStorage(client, { + stream, + timeout: 6000, + }) + await waitForStorage(lastRequest) + + const msgsResent = [] + const sub = await client.resend({ + stream: stream.id, + resend: { + from: { + timestamp: 0 + }, + }, + }, (m) => msgsResent.push(m)) + await waitForEvent(sub, 'resent') + + expect(msgsReceieved).toEqual(msgsResent) + // backdated messages disappear + expect(msgsReceieved).toEqual(msgsPublished.filter(({ backdated }) => !backdated)) + + const seq = toSeq(requests, ts) + expect(seq).toEqual([ + [[0, 0], null], + [[0, 1], [0, 0]], + [[0, 2], [0, 1]], + [[1, 0], [0, 2]], + [[1, 1], [1, 0]], + [[0, 0], [1, 1]], // bad message + [[1, 2], [1, 1]], + [[1, 3], [1, 2]], + [[2, 0], [1, 3]], + [[2, 1], [2, 0]], + ]) + }, 10000) +}) diff --git a/test/integration/Session.test.js b/test/integration/Session.test.js index 60d24cdef..bccd20182 100644 --- a/test/integration/Session.test.js +++ b/test/integration/Session.test.js @@ -1,6 +1,5 @@ -import { ethers } from 'ethers' - -import StreamrClient from '../../src' +import { StreamrClient } from '../../src/StreamrClient' +import { fakePrivateKey } from '../utils' import config from './config' @@ -37,11 +36,28 @@ describe('Session', () => { expect.assertions(1) await expect(createClient({ auth: { - privateKey: ethers.Wallet.createRandom().privateKey, + privateKey: fakePrivateKey(), }, }).session.getSessionToken()).resolves.toBeTruthy() }) + it('can handle multiple client instances', async () => { + expect.assertions(1) + const client1 = createClient({ + auth: { + privateKey: fakePrivateKey(), + }, + }) + const client2 = createClient({ + auth: { + privateKey: fakePrivateKey(), + }, + }) + const token1 = await client1.session.getSessionToken() + const token2 = await client2.session.getSessionToken() + expect(token1).not.toEqual(token2) + }) + it('fails if trying to get the token using username and password', async () => { expect.assertions(1) await expect(() => createClient({ diff --git a/test/integration/Stream.test.js b/test/integration/Stream.test.js new file mode 100644 index 000000000..19df708a3 --- /dev/null +++ b/test/integration/Stream.test.js @@ -0,0 +1,117 @@ +import { StreamrClient } from '../../src/StreamrClient' +import { uid, fakePrivateKey, getPublishTestMessages } from '../utils' + +import config from './config' + +const createClient = (opts = {}) => new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: fakePrivateKey(), + }, + autoConnect: false, + autoDisconnect: false, + ...opts, +}) + +describe('Stream', () => { + let client + let stream + + beforeEach(async () => { + client = createClient() + await client.connect() + + stream = await client.createStream({ + name: uid('stream-integration-test') + }) + }) + + afterEach(async () => { + await client.disconnect() + }) + + describe('detectFields()', () => { + it('does detect primitive types', async () => { + const msg = { + number: 123, + boolean: true, + object: { + k: 1, + v: 2, + }, + array: [1, 2, 3], + string: 'test', + } + const publishTestMessages = getPublishTestMessages(client, { + streamId: stream.id, + waitForLast: true, + createMessage: () => msg, + }) + await publishTestMessages(1) + + expect(stream.config.fields).toEqual([]) + await stream.detectFields() + const expectedFields = [ + { + name: 'number', + type: 'number', + }, + { + name: 'boolean', + type: 'boolean', + }, + { + name: 'object', + type: 'map', + }, + { + name: 'array', + type: 'list', + }, + { + name: 'string', + type: 'string', + }, + ] + + expect(stream.config.fields).toEqual(expectedFields) + const loadedStream = await client.getStream(stream.id) + expect(loadedStream.config.fields).toEqual(expectedFields) + }) + + it('skips unsupported types', async () => { + const msg = { + null: null, + empty: {}, + func: () => null, + nonexistent: undefined, + symbol: Symbol('test'), + // TODO: bigint: 10n, + } + const publishTestMessages = getPublishTestMessages(client, { + streamId: stream.id, + waitForLast: true, + createMessage: () => msg, + }) + await publishTestMessages(1) + + expect(stream.config.fields).toEqual([]) + await stream.detectFields() + const expectedFields = [ + { + name: 'null', + type: 'map', + }, + { + name: 'empty', + type: 'map', + }, + ] + + expect(stream.config.fields).toEqual(expectedFields) + + const loadedStream = await client.getStream(stream.id) + expect(loadedStream.config.fields).toEqual(expectedFields) + }) + }) +}) diff --git a/test/integration/StreamConnectionState.test.js b/test/integration/StreamConnectionState.test.js new file mode 100644 index 000000000..d8fcd8c4e --- /dev/null +++ b/test/integration/StreamConnectionState.test.js @@ -0,0 +1,427 @@ +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 { Defer, pLimitFn } from '../../src/utils' +import Connection from '../../src/Connection' + +import config from './config' + +const { ControlMessage } = ControlLayer +const MAX_MESSAGES = 5 + +describeRepeats('Connection State', () => { + let expectErrors = 0 // check no errors by default + let publishTestMessages + let onError = jest.fn() + let client + let stream + let subscriber + + const createClient = (opts = {}) => { + const c = new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: fakePrivateKey(), + }, + autoConnect: false, + autoDisconnect: false, + publishAutoDisconnectDelay: 250, + maxRetries: 2, + ...opts, + }) + c.onError = jest.fn() + c.on('error', onError) + return c + } + + async function setupClient(opts) { + // eslint-disable-next-line require-atomic-updates + client = createClient(opts) + subscriber = client.subscriber + client.debug('connecting before test >>') + await client.session.getSessionToken() + stream = await client.createStream({ + requireSignedData: true, + name: uid('stream') + }) + + client.debug('connecting before test <<') + publishTestMessages = getPublishTestMessages(client, stream.id) + return client + } + + beforeEach(async () => { + expectErrors = 0 + onError = jest.fn() + }) + + afterEach(() => { + if (!subscriber) { return } + expect(subscriber.count(stream.id)).toBe(0) + if (!client) { return } + expect(client.getSubscriptions(stream.id)).toEqual([]) + }) + + afterEach(async () => { + await wait() + // ensure no unexpected errors + expect(onError).toHaveBeenCalledTimes(expectErrors) + if (client) { + expect(client.onError).toHaveBeenCalledTimes(expectErrors) + } + }) + + afterEach(async () => { + await wait() + if (client) { + client.debug('disconnecting after test >>') + await client.disconnect() + client.debug('disconnecting after test <<') + } + + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + await Connection.closeOpen() + throw new Error(`sockets not closed: ${openSockets}`) + } + }) + + let subs = [] + + beforeEach(async () => { + const existingSubs = subs + subs = [] + await Promise.all(existingSubs.map((sub) => ( + sub.cancel() + ))) + }) + + describe('autoConnect/Disconnect enabled', () => { + beforeEach(async () => { + await setupClient({ // new client with autoConnect + autoConnect: true, + autoDisconnect: true, + }) + // don't explicitly connect + }) + + it('connects on subscribe, disconnects on end', async () => { + const sub = await subscriber.subscribe(stream.id) + expect(client.connection.getState()).toBe('connected') + expect(subscriber.count(stream.id)).toBe(1) + + const published = await publishTestMessages() + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === published.length) { + break + } + } + expect(received).toEqual(published) + expect(client.connection.getState()).toBe('disconnected') + }) + + it('connects on subscribe, disconnects on end with two subs', async () => { + const [sub1, sub2] = await Promise.all([ + subscriber.subscribe(stream.id), + subscriber.subscribe(stream.id), + ]) + + expect(client.connection.getState()).toBe('connected') + expect(subscriber.count(stream.id)).toBe(2) + + const published = await publishTestMessages() + + const received1 = [] + for await (const m of sub1) { + received1.push(m.getParsedContent()) + if (received1.length === published.length) { + break + } + } + + expect(received1).toEqual(published) + expect(client.connection.getState()).toBe('connected') + + const received2 = [] + for await (const m of sub2) { + received2.push(m) + if (received2.length === published.length) { + return + } + } + expect(client.connection.getState()).toBe('disconnected') + + expect(received2).toEqual(received1) + }) + + it('should receive messages if subscriber disconnects after each message', async () => { + const otherClient = createClient({ + auth: client.options.auth, + }) + + client.enableAutoConnect() + client.enableAutoDisconnect() + + const onConnected = jest.fn() + const onDisconnected = jest.fn() + const onConnectedOther = jest.fn() + const onDisconnectedOther = jest.fn() + otherClient.connection.on('connected', onConnectedOther) + otherClient.connection.on('disconnected', onDisconnectedOther) + client.connection.on('connected', onConnected) + client.connection.on('disconnected', onDisconnected) + + try { + await otherClient.connect() + await otherClient.session.getSessionToken() + + const done = Defer() + + const msgs = [] + const sockets = new Set() + await otherClient.subscribe({ + stream, + resend: { + last: 5 + } + }, (msg) => { + msgs.push(msg) + if (msgs.length === MAX_MESSAGES) { + // should eventually get here + done.resolve() + } + + // disconnect after every message + if (otherClient.connection.socket) { + sockets.add(otherClient.connection.socket) + otherClient.connection.socket.close() + } + }) + + const published = await publishTestMessages(MAX_MESSAGES, { + waitForStorage: true, + }) + + await done + + expect(msgs).toEqual(published) + + await wait(1000) // TODO: remove timeout + + // check disconnect/connect actually happened + expect(onConnected).toHaveBeenCalledTimes(1) + expect(onDisconnected).toHaveBeenCalledTimes(1) + expect(onConnectedOther).toHaveBeenCalledTimes(sockets.size + 1) + expect(onDisconnectedOther).toHaveBeenCalledTimes(sockets.size) + } finally { + await Promise.all([ + otherClient.disconnect(), + client.disconnect(), + ]) + } + }, 15000) + }) + + describe('autoConnect disabled', () => { + beforeEach(async () => { + await setupClient({ + autoConnect: false, + autoDisconnect: false, + }) + await client.connect() + }) + + it('should error subscribe if client disconnected', async () => { + await client.disconnect() + await expect(async () => { + await subscriber.subscribe(stream.id) + }).rejects.toThrow() + expect(subscriber.count(stream.id)).toBe(0) + expect(client.getSubscriptions(stream.id)).toEqual([]) + }) + + it('should reconnect subscriptions when connection disconnected before subscribed & reconnected', async () => { + const subTask = subscriber.subscribe(stream.id) + await true + client.connection.socket.close() + const published = await publishTestMessages(2) + const sub = await subTask + expect(client.getSubscriptions(stream.id)).toHaveLength(1) + subs.push(sub) + const received = [] + for await (const msg of sub) { + received.push(msg.getParsedContent()) + if (received.length === published.length) { + expect(received).toEqual(published) + } + break + } + expect(subscriber.count(stream.id)).toBe(0) + expect(client.getSubscriptions(stream.id)).toEqual([]) + }) + + it('should re-subscribe when subscribed then reconnected + fill gaps', async () => { + const sub = await subscriber.subscribe(stream.id) + subs.push(sub) + const published = await publishTestMessages(2) + const received = [] + for await (const msg of sub) { + received.push(msg.getParsedContent()) + if (received.length === 2) { + expect(received).toEqual(published) + client.connection.socket.close() + // this will cause a gap fill + published.push(...(await publishTestMessages(2))) + } + + if (received.length === 4) { + expect(received).toEqual(published) + break + } + } + expect(subscriber.count(stream.id)).toBe(0) + expect(client.getSubscriptions(stream.id)).toEqual([]) + }, 30000) + + it('should end when subscribed then disconnected', async () => { + const sub = await subscriber.subscribe(stream.id) + subs.push(sub) + const published = await publishTestMessages(2) + const received = [] + for await (const msg of sub) { + received.push(msg.getParsedContent()) + if (received.length === 1) { + expect(received).toEqual(published.slice(0, 1)) + client.disconnect() // should trigger break + // no await, should be immediate + } + } + expect(received).toEqual(published.slice(0, 1)) + expect(subscriber.count(stream.id)).toBe(0) + expect(client.getSubscriptions(stream.id)).toEqual([]) + }) + + it('should end when subscribed then disconnected then connected', async () => { + const sub = await subscriber.subscribe(stream.id) + expect(client.getSubscriptions(stream.id)).toHaveLength(1) + subs.push(sub) + + await publishTestMessages(2) + const received = [] + await client.disconnect() + expect(subscriber.count(stream.id)).toBe(0) + expect(client.getSubscriptions(stream.id)).toHaveLength(0) + for await (const msg of sub) { + received.push(msg.getParsedContent()) + } + expect(received).toEqual([]) + client.connect() // no await, should be ok + await wait(1000) + const sub2 = await subscriber.subscribe(stream.id) + subs.push(sub) + const published2 = await publishTestMessages(2) + const received2 = [] + expect(subscriber.count(stream.id)).toBe(1) + expect(client.getSubscriptions(stream.id)).toHaveLength(1) + for await (const msg of sub2) { + received2.push(msg.getParsedContent()) + if (received2.length === 1) { + await client.disconnect() + } + } + expect(received2).toEqual(published2.slice(0, 1)) + expect(subscriber.count(stream.id)).toBe(0) + expect(client.getSubscriptions(stream.id)).toEqual([]) + }) + + it('should just end subs when disconnected', async () => { + await client.connect() + const sub = await subscriber.subscribe(stream.id) + subs.push(sub) + await client.disconnect() + expect(subscriber.count(stream.id)).toBe(0) + }) + + describe('resubscribe on unexpected disconnection', () => { + let otherClient + + beforeEach(async () => { + otherClient = createClient({ + auth: client.options.auth, + }) + const tasks = [ + client.connect(), + client.session.getSessionToken(), + otherClient.connect(), + otherClient.session.getSessionToken(), + ] + await Promise.allSettled(tasks) + await Promise.all(tasks) // throw if there were an error + }) + + afterEach(async () => { + const tasks = [ + otherClient.disconnect(), + client.disconnect(), + ] + await Promise.allSettled(tasks) + await Promise.all(tasks) // throw if there were an error + }) + + it('should work', async () => { + const done = Defer() + + const msgs = [] + + await otherClient.subscribe(stream, (msg) => { + msgs.push(msg) + + if (msgs.length === MAX_MESSAGES) { + // should eventually get here + done.resolve() + } + }) + + const disconnect = pLimitFn(async () => { + if (msgs.length === MAX_MESSAGES) { return } + otherClient.connection.socket.close() + // wait for reconnection before possibly disconnecting again + await otherClient.nextConnection() + }) + + const onConnectionMessage = jest.fn(() => { + // disconnect after every message + disconnect() + }) + + otherClient.connection.on(ControlMessage.TYPES.BroadcastMessage, onConnectionMessage) + otherClient.connection.on(ControlMessage.TYPES.UnicastMessage, onConnectionMessage) + + const onConnected = jest.fn() + const onDisconnected = jest.fn() + otherClient.connection.on('connected', onConnected) + otherClient.connection.on('disconnected', onDisconnected) + + const published = await publishTestMessages(MAX_MESSAGES, { + delay: 1000, + }) + + await done + // wait for final re-connection after final message + await otherClient.connection.nextConnection() + + expect(msgs).toEqual(published) + + // check disconnect/connect actually happened + expect(onConnectionMessage.mock.calls.length).toBeGreaterThanOrEqual(published.length) + expect(onConnected.mock.calls.length).toBeGreaterThanOrEqual(published.length) + expect(onDisconnected.mock.calls.length).toBeGreaterThanOrEqual(published.length) + }, 30000) + }) + }) +}) diff --git a/test/integration/StreamEndpoints.test.js b/test/integration/StreamEndpoints.test.js deleted file mode 100644 index 3cd46d6f4..000000000 --- a/test/integration/StreamEndpoints.test.js +++ /dev/null @@ -1,225 +0,0 @@ -import assert from 'assert' - -import { ethers } from 'ethers' -import { wait } from 'streamr-test-utils' - -import StreamrClient from '../../src' - -import config from './config' - -/** - * These tests should be run in sequential order! - */ -describe('StreamEndpoints', () => { - const name = `StreamEndpoints-integration-${Date.now()}` - - let client - let createdStream - let wallet - - const createClient = (opts = {}) => new StreamrClient({ - autoConnect: false, - autoDisconnect: false, - ...config.clientOptions, - ...opts, - }) - - beforeAll(() => { - wallet = ethers.Wallet.createRandom() - client = createClient({ - auth: { - privateKey: wallet.privateKey, - }, - }) - }) - - describe('createStream', () => { - it('creates a stream with correct values', async () => { - const stream = await client.createStream({ - name, - requireSignedData: true, - requireEncryptedData: false, - }) - createdStream = stream - assert(createdStream.id) - assert.strictEqual(createdStream.name, name) - assert.strictEqual(createdStream.requireSignedData, true) - }) - }) - - describe('getStream', () => { - it('get an existing Stream', async () => { - const stream = await client.createStream() - const existingStream = await client.getStream(stream.id) - assert.strictEqual(existingStream.id, stream.id) - }) - - it('get a non-existing Stream', async () => { - const id = `${wallet.address}/StreamEndpoints-integration-nonexisting-${Date.now()}` - const stream = await client.getStream(id) - assert.strictEqual(stream, undefined) - }) - }) - - describe('getOrCreate', () => { - it('getOrCreate an existing Stream', async () => { - const stream = await client.createStream({ - name: `StreamEndpoints-integration-${Date.now()}`, - }) - - const existingStream = await client.getOrCreateStream({ - name: stream.name, - }) - assert.strictEqual(existingStream.id, stream.id) - assert.strictEqual(existingStream.name, stream.name) - }) - - it('getOrCreate a new Stream by name', async () => { - const newName = `StreamEndpoints-integration-${Date.now()}` - const newStream = await client.getOrCreateStream({ - name: newName, - }) - - assert.strictEqual(newStream.name, newName) - }) - - it('getOrCreate a new Stream by id', async () => { - const newId = `${wallet.address}/StreamEndpoints-integration-${Date.now()}` - const newStream = await client.getOrCreateStream({ - id: newId, - }) - - assert.strictEqual(newStream.id, newId) - }) - }) - - describe('listStreams', () => { - it('filters by given criteria (match)', async () => { - const stream = await client.createStream({ - name: `StreamEndpoints-integration-${Date.now()}`, - }) - - const result = await client.listStreams({ - name: stream.name, - }) - assert.strictEqual(result.length, 1) - assert.strictEqual(result[0].id, stream.id) - }) - - it('filters by given criteria (no match)', async () => { - const result = await client.listStreams({ - name: `non-existent-${Date.now()}`, - }) - assert.strictEqual(result.length, 0) - }) - }) - - describe('getStreamPublishers', () => { - it('retrieves a list of publishers', async () => { - const publishers = await client.getStreamPublishers(createdStream.id) - assert.deepStrictEqual(publishers, [(await client.signer.getAddress()).toLowerCase()]) - }) - }) - - describe('isStreamPublisher', () => { - it('returns true for valid publishers', async () => { - const valid = await client.isStreamPublisher(createdStream.id, (await client.signer.getAddress()).toLowerCase()) - assert(valid) - }) - it('returns false for invalid publishers', async () => { - const valid = await client.isStreamPublisher(createdStream.id, 'some-wrong-address') - assert(!valid) - }) - }) - - describe('getStreamSubscribers', () => { - it('retrieves a list of publishers', async () => { - const subscribers = await client.getStreamSubscribers(createdStream.id) - assert.deepStrictEqual(subscribers, [(await client.signer.getAddress()).toLowerCase()]) - }) - }) - - describe('isStreamSubscriber', () => { - it('returns true for valid subscribers', async () => { - const valid = await client.isStreamSubscriber(createdStream.id, (await client.signer.getAddress()).toLowerCase()) - assert(valid) - }) - it('returns false for invalid subscribers', async () => { - const valid = await client.isStreamSubscriber(createdStream.id, 'some-wrong-address') - assert(!valid) - }) - }) - - describe('getStreamValidationInfo', () => { - it('returns an object with expected fields', async () => { - const result = await client.getStreamValidationInfo(createdStream.id) - assert(result.partitions > 0) - assert(result.requireSignedData === true) - assert(result.requireEncryptedData === false) - }) - }) - - describe('Stream.update', () => { - it('can change stream name', async () => { - createdStream.name = 'New name' - await createdStream.update() - }) - }) - - describe('Stream configuration', () => { - it.skip('Stream.detectFields', async () => { - await client.ensureConnected() - await client.publish(createdStream.id, { - foo: 'bar', - count: 0, - }) - // Need time to propagate to storage - await wait(10000) - const stream = await createdStream.detectFields() - assert.deepStrictEqual( - stream.config.fields, - [ - { - name: 'foo', - type: 'string', - }, - { - name: 'count', - type: 'number', - }, - ], - ) - await client.ensureDisconnected() - }, 15000) - }) - - describe('Stream permissions', () => { - it('Stream.getPermissions', async () => { - const permissions = await createdStream.getPermissions() - // get, edit, delete, subscribe, publish, share - assert.strictEqual(permissions.length, 6, `Unexpected number of permissions: ${JSON.stringify(permissions)}`) - }) - - it('Stream.hasPermission', async () => { - assert(await createdStream.hasPermission('stream_share', wallet.address)) - }) - - it('Stream.grantPermission', async () => { - await createdStream.grantPermission('stream_subscribe', null) // public read - assert(await createdStream.hasPermission('stream_subscribe', null)) - }) - - it('Stream.revokePermission', async () => { - const publicRead = await createdStream.hasPermission('stream_subscribe', null) - await createdStream.revokePermission(publicRead.id) - assert(!(await createdStream.hasPermission('stream_subscribe', null))) - }) - }) - - describe('Stream deletion', () => { - it('Stream.delete', async () => { - await createdStream.delete() - assert.strictEqual(await client.getStream(createdStream.id), undefined) - }) - }) -}) diff --git a/test/integration/StreamEndpoints.test.ts b/test/integration/StreamEndpoints.test.ts new file mode 100644 index 000000000..ea4e2672a --- /dev/null +++ b/test/integration/StreamEndpoints.test.ts @@ -0,0 +1,267 @@ +import { ethers, Wallet } from 'ethers' +import { NotFoundError, ValidationError } from '../../src/rest/authFetch' +import { Stream, StreamOperation } from '../../src/stream' + +import { StreamrClient } from '../../src/StreamrClient' +import { uid } from '../utils' + +import config from './config' + +/** + * These tests should be run in sequential order! + */ + +function TestStreamEndpoints(getName: () => string) { + let client: StreamrClient + let wallet: Wallet + let createdStream: Stream + + const createClient = (opts = {}) => new StreamrClient({ + ...config.clientOptions, + autoConnect: false, + autoDisconnect: false, + ...opts, + } as any) + + beforeAll(() => { + wallet = ethers.Wallet.createRandom() + client = createClient({ + auth: { + privateKey: wallet.privateKey, + }, + }) + }) + + beforeAll(async () => { + createdStream = await client.createStream({ + name: getName(), + requireSignedData: true, + requireEncryptedData: false, + }) + }) + + describe('createStream', () => { + it('creates a stream with correct values', async () => { + const name = getName() + const stream = await client.createStream({ + name, + requireSignedData: true, + requireEncryptedData: true, + }) + expect(stream.id).toBeTruthy() + expect(stream.name).toBe(name) + expect(stream.requireSignedData).toBe(true) + expect(stream.requireEncryptedData).toBe(true) + }) + + it('invalid id', () => { + return expect(() => client.createStream({ id: 'invalid.eth/foobar' })).rejects.toThrow(ValidationError) + }) + }) + + describe('getStream', () => { + it('get an existing Stream', async () => { + const stream = await client.createStream() + const existingStream = await client.getStream(stream.id) + expect(existingStream.id).toEqual(stream.id) + }) + + it('get a non-existing Stream', async () => { + const id = `${wallet.address}/StreamEndpoints-integration-nonexisting-${Date.now()}` + return expect(() => client.getStream(id)).rejects.toThrow(NotFoundError) + }) + }) + + describe('getStreamByName', () => { + it('get an existing Stream', async () => { + const stream = await client.createStream() + const existingStream = await client.getStreamByName(stream.name) + expect(existingStream.id).toEqual(stream.id) + }) + + it('get a non-existing Stream', async () => { + const name = `${wallet.address}/StreamEndpoints-integration-nonexisting-${Date.now()}` + return expect(() => client.getStreamByName(name)).rejects.toThrow(NotFoundError) + }) + }) + + describe('getOrCreate', () => { + it('getOrCreate an existing Stream by name', async () => { + const existingStream = await client.getOrCreateStream({ + name: createdStream.name, + }) + expect(existingStream.id).toBe(createdStream.id) + expect(existingStream.name).toBe(createdStream.name) + }) + + it('getOrCreate an existing Stream by id', async () => { + const existingStream = await client.getOrCreateStream({ + id: createdStream.id, + }) + expect(existingStream.id).toBe(createdStream.id) + expect(existingStream.name).toBe(createdStream.name) + }) + + it('getOrCreate a new Stream by name', async () => { + const newName = uid('stream') + const newStream = await client.getOrCreateStream({ + name: newName, + }) + expect(newStream.name).toEqual(newName) + }) + + it('getOrCreate a new Stream by id', async () => { + const newId = `${wallet.address}/StreamEndpoints-integration-${Date.now()}` + const newStream = await client.getOrCreateStream({ + id: newId, + }) + expect(newStream.id).toEqual(newId) + }) + }) + + describe('listStreams', () => { + it('filters by given criteria (match)', async () => { + const result = await client.listStreams({ + name: createdStream.name, + }) + expect(result.length).toBe(1) + expect(result[0].id).toBe(createdStream.id) + }) + + it('filters by given criteria (no match)', async () => { + const result = await client.listStreams({ + name: `non-existent-${Date.now()}`, + }) + expect(result.length).toBe(0) + }) + }) + + describe('getStreamLast', () => { + it('does not error', async () => { + const result = await client.getStreamLast(createdStream.id) + expect(result).toEqual([]) + }) + }) + + describe('getStreamPublishers', () => { + it('retrieves a list of publishers', async () => { + const publishers = await client.getStreamPublishers(createdStream.id) + const address = await client.getUserId() + expect(publishers).toEqual([address]) + }) + }) + + describe('isStreamPublisher', () => { + it('returns true for valid publishers', async () => { + const address = await client.getUserId() + const valid = await client.isStreamPublisher(createdStream.id, address) + expect(valid).toBeTruthy() + }) + it('returns false for invalid publishers', async () => { + const valid = await client.isStreamPublisher(createdStream.id, 'some-wrong-address') + expect(!valid).toBeTruthy() + }) + }) + + describe('getStreamSubscribers', () => { + it('retrieves a list of publishers', async () => { + const subscribers = await client.getStreamSubscribers(createdStream.id) + const address = await client.getUserId() + expect(subscribers).toEqual([address]) + }) + }) + + describe('isStreamSubscriber', () => { + it('returns true for valid subscribers', async () => { + const address = await client.getUserId() + const valid = await client.isStreamSubscriber(createdStream.id, address) + expect(valid).toBeTruthy() + }) + it('returns false for invalid subscribers', async () => { + const valid = await client.isStreamSubscriber(createdStream.id, 'some-wrong-address') + expect(!valid).toBeTruthy() + }) + }) + + describe('getStreamValidationInfo', () => { + it('returns an object with expected fields', async () => { + const result = await client.getStreamValidationInfo(createdStream.id) + expect(result.partitions > 0).toBeTruthy() + expect(result.requireSignedData === true).toBeTruthy() + expect(result.requireEncryptedData === false).toBeTruthy() + }) + }) + + describe('Stream.update', () => { + it('can change stream name', async () => { + createdStream.name = 'New name' + await createdStream.update() + }) + }) + + describe('Stream permissions', () => { + it('Stream.getPermissions', async () => { + const permissions = await createdStream.getPermissions() + // get, edit, delete, subscribe, publish, share + expect(permissions.length).toBe(6) + }) + + it('Stream.hasPermission', async () => { + expect(await createdStream.hasPermission(StreamOperation.STREAM_SHARE, wallet.address)).toBeTruthy() + }) + + it('Stream.grantPermission', async () => { + await createdStream.grantPermission(StreamOperation.STREAM_SUBSCRIBE, undefined) // public read + expect(await createdStream.hasPermission(StreamOperation.STREAM_SUBSCRIBE, undefined)).toBeTruthy() + }) + + it('Stream.revokePermission', async () => { + const publicRead = await createdStream.hasPermission(StreamOperation.STREAM_SUBSCRIBE, undefined) + await createdStream.revokePermission(publicRead!.id) + expect(!(await createdStream.hasPermission(StreamOperation.STREAM_SUBSCRIBE, undefined))).toBeTruthy() + }) + }) + + describe('Stream deletion', () => { + it('Stream.delete', async () => { + await createdStream.delete() + return expect(() => client.getStream(createdStream.id)).rejects.toThrow(NotFoundError) + }) + }) + + describe('Storage node assignment', () => { + it('add', async () => { + const storageNodeAddress = ethers.Wallet.createRandom().address + const stream = await client.createStream() + await stream.addToStorageNode(storageNodeAddress) + const storageNodes = await stream.getStorageNodes() + expect(storageNodes.length).toBe(1) + expect(storageNodes[0].getAddress()).toBe(storageNodeAddress) + const storedStreamParts = await client.getStreamPartsByStorageNode(storageNodeAddress) + expect(storedStreamParts.length).toBe(1) + expect(storedStreamParts[0].getStreamId()).toBe(stream.id) + expect(storedStreamParts[0].getStreamPartition()).toBe(0) + }) + + it('remove', async () => { + const storageNodeAddress = ethers.Wallet.createRandom().address + const stream = await client.createStream() + await stream.addToStorageNode(storageNodeAddress) + await stream.removeFromStorageNode(storageNodeAddress) + const storageNodes = await stream.getStorageNodes() + expect(storageNodes).toHaveLength(0) + const storedStreamParts = await client.getStreamPartsByStorageNode(storageNodeAddress) + expect(storedStreamParts).toHaveLength(0) + }) + }) +} + +describe('StreamEndpoints', () => { + describe('using normal name', () => { + TestStreamEndpoints(() => uid('test-stream')) + }) + + describe('using name with slashes', () => { + TestStreamEndpoints(() => uid('test-stream/slashes')) + }) +}) diff --git a/test/integration/StreamrClient.test.js b/test/integration/StreamrClient.test.js index 584cc8688..3f22997b8 100644 --- a/test/integration/StreamrClient.test.js +++ b/test/integration/StreamrClient.test.js @@ -1,451 +1,427 @@ -import assert from 'assert' -import crypto from 'crypto' import fs from 'fs' import path from 'path' import fetch from 'node-fetch' import { ControlLayer, MessageLayer } from 'streamr-client-protocol' import { wait, waitForEvent } from 'streamr-test-utils' -import { ethers } from 'ethers' -import { uid } from '../utils' -import StreamrClient from '../../src' +import { describeRepeats, uid, fakePrivateKey, getWaitForStorage, getPublishTestMessages, Msg } from '../utils' +import { StreamrClient } from '../../src/StreamrClient' +import { Defer, pLimitFn } from '../../src/utils' +import Connection from '../../src/Connection' import config from './config' -const { StreamMessage } = MessageLayer const WebSocket = require('ws') -const { SubscribeRequest, UnsubscribeRequest, ResendLastRequest } = ControlLayer +const { StreamMessage } = MessageLayer +const { SubscribeRequest, UnsubscribeRequest, ResendLastRequest, ControlMessage } = ControlLayer -const createClient = (opts = {}) => new StreamrClient({ - auth: { - privateKey: ethers.Wallet.createRandom().privateKey, - }, - autoConnect: false, - autoDisconnect: false, - ...config.clientOptions, - ...opts, -}) +const MAX_MESSAGES = 20 -describe('StreamrClient Connection', () => { - describe('bad config.url', () => { - it('emits error without autoconnect', async () => { - const client = createClient({ - url: 'asdasd', - autoConnect: false, - autoDisconnect: false, - }) - client.onError = jest.fn() +describeRepeats('StreamrClient', () => { + let expectErrors = 0 // check no errors by default + let errors = [] - await expect(() => ( - client.connect() - )).rejects.toThrow() - expect(client.onError).toHaveBeenCalledTimes(1) - }) + const getOnError = (errs) => jest.fn((err) => { + errs.push(err) + }) - it('rejects on connect without autoconnect', async () => { - const client = createClient({ - url: 'asdasd', - autoConnect: false, - autoDisconnect: false, - }) - client.onError = jest.fn() + let onError = jest.fn() + let client - await expect(() => ( - client.connect() - )).rejects.toThrow() - expect(client.onError).toHaveBeenCalledTimes(1) + const createClient = (opts = {}) => { + const c = new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: fakePrivateKey(), + }, + autoConnect: false, + autoDisconnect: false, + // disconnectDelay: 500, + // publishAutoDisconnectDelay: 250, + maxRetries: 2, + ...opts, }) + c.onError = jest.fn() + c.on('error', onError) + return c + } - it('emits error with autoconnect after first call that triggers connect()', async () => { - const client = createClient({ - url: 'asdasd', - autoConnect: true, - autoDisconnect: true, - }) - const client2 = createClient({ - autoConnect: true, - autoDisconnect: true, - }) + async function checkConnection() { + const c = createClient() + // create a temp client before connecting ws + // so client generates correct options.url for us + try { + await Promise.all([ + Promise.race([ + fetch(c.options.restUrl), + wait(1000).then(() => { + throw new Error(`timed out connecting to: ${c.options.restUrl}`) + }) + ]), + Promise.race([ + new Promise((resolve, reject) => { + const ws = new WebSocket(c.options.url) + ws.once('open', () => { + c.debug('open', c.options.url) + resolve() + ws.close() + }) + ws.once('error', (err) => { + c.debug('err', c.options.url, err) + reject(err) + ws.terminate() + }) + }), + wait(1000).then(() => { + throw new Error(`timed out connecting to: ${c.options.url}`) + }) + ]), + ]) + } catch (e) { + if (e.errno === 'ENOTFOUND' || e.errno === 'ECONNREFUSED') { + throw new Error('Integration testing requires that engine-and-editor ' + + 'and data-api ("entire stack") are running in the background. ' + + 'Instructions: https://github.com/streamr-dev/streamr-docker-dev#running') + } else { + throw e + } + } + } - client.onError = jest.fn() - const onError = jest.fn() - client.on('error', onError) - - const stream = await client2.createStream({ - name: uid('stream') - }) // this will succeed because it uses restUrl config, not url - - // publish should trigger connect - await expect(() => ( - client.publish(stream, {}) - )).rejects.toThrow('Invalid URL') - // check error is emitted with same error before rejection - // not clear if emit or reject *should* occur first - expect(onError).toHaveBeenCalledTimes(1) - expect(client.onError).toHaveBeenCalledTimes(1) - }, 10000) + beforeEach(() => { + errors = [] + expectErrors = 0 + onError = getOnError(errors) }) - describe('bad config.restUrl', () => { - it('emits no error with no connection', async (done) => { - const client = createClient({ - restUrl: 'asdasd', - autoConnect: false, - autoDisconnect: false, - }) - client.onError = jest.fn() - client.once('error', done) - setTimeout(() => { - expect(client.onError).not.toHaveBeenCalled() - done() - }, 100) - }) + beforeAll(async () => { + await checkConnection() + }) - it('emits error with connection', async (done) => { - const client = createClient({ - restUrl: 'asdasd', - autoConnect: false, - autoDisconnect: false, - }) - client.onError = jest.fn() - client.once('error', (error) => { - expect(error).toBeTruthy() - expect(client.onError).toHaveBeenCalledTimes(1) - done() - }) - client.connect() - }) + afterEach(async () => { + await wait() + // ensure no unexpected errors + expect(errors).toHaveLength(expectErrors) + if (client) { + expect(client.onError).toHaveBeenCalledTimes(expectErrors) + } }) - it('can disconnect before connected', async () => { - const client = createClient() - client.onError = jest.fn() - client.once('error', (error) => { - expect(error).toMatchObject({ - message: 'Failed to send subscribe request: Error: WebSocket is not open: readyState 3 (CLOSED)', - }) + afterEach(async () => { + await wait() + if (client) { + client.debug('disconnecting after test') + await client.disconnect() + } - expect(client.onError).toHaveBeenCalledTimes(1) - }) - client.connect() - await client.ensureDisconnected() + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + throw new Error(`sockets not closed: ${openSockets}`) + } }) - describe('resend', () => { - let client - let stream + describe('Connection', () => { + describe('bad config.url', () => { + it('emits error without autoconnect', async () => { + client = createClient({ + url: 'asdasd', + autoConnect: false, + autoDisconnect: false, + }) - let timestamps = [] + await expect(() => ( + client.connect() + )).rejects.toThrow() + }) - beforeEach(async () => { - client = createClient() - await client.ensureConnected() + it('rejects on connect without autoconnect', async () => { + client = createClient({ + url: 'asdasd', + autoConnect: false, + autoDisconnect: false, + }) - stream = await client.createStream({ - name: uid('stream') + await expect(() => ( + client.connect() + )).rejects.toThrow() }) - timestamps = [] - for (let i = 0; i < 5; i++) { - const message = { - msg: `message${i}`, - } - - // eslint-disable-next-line no-await-in-loop - const rawMessage = await client.publish(stream.id, message) - timestamps.push(rawMessage.streamMessage.getTimestamp()) - // eslint-disable-next-line no-await-in-loop - await wait(100) // ensure timestamp increments for reliable resend response in test. - } + it('emits error with autoconnect after first call that triggers connect()', async () => { + expectErrors = 1 + + client = createClient({ + url: 'asdasd', + autoConnect: true, + autoDisconnect: true, + }) + const client2 = createClient({ + autoConnect: true, + autoDisconnect: true, + }) - await wait(5000) // wait for messages to (probably) land in storage - }, 10 * 1000) + const otherOnError = jest.fn() + client2.on('error', otherOnError) - afterEach(async () => { - await client.ensureDisconnected() + const stream = await client2.createStream({ + name: uid('stream') + }) // this will succeed because it uses restUrl config, not url + + // publish should trigger connect + await expect(() => ( + client.publish(stream, {}) + )).rejects.toThrow('Invalid URL') + // check error is emitted with same error before rejection + // not clear if emit or reject *should* occur first + expect(onError).toHaveBeenCalledTimes(1) + expect(client.onError).toHaveBeenCalledTimes(1) + expect(otherOnError).toHaveBeenCalledTimes(0) + }, 10000) }) - it('resend last', async () => { - const messages = [] + describe('bad config.restUrl', () => { + it('emits no error with no connection', async () => { + client = createClient({ + restUrl: 'asdasd', + autoConnect: false, + autoDisconnect: false, + }) - const sub = await client.resend({ - stream: stream.id, - resend: { - last: 3, - }, - }, (message) => { - messages.push(message) + await wait(100) }) - await waitForEvent(sub, 'resent') - expect(messages).toHaveLength(3) - expect(messages).toEqual([{ - msg: 'message2', - }, { - msg: 'message3', - }, { - msg: 'message4', - }]) - }, 15000) - - it('resend from', async () => { - const messages = [] - - const sub = await client.resend( - { - stream: stream.id, - resend: { - from: { - timestamp: timestamps[3], - }, - }, - }, - (message) => { - messages.push(message) - }, - ) - - await waitForEvent(sub, 'resent') - expect(messages).toEqual([ - { - msg: 'message3', - }, - { - msg: 'message4', - }, - ]) - }, 10000) - - it('resend range', async () => { - const messages = [] - - const sub = await client.resend( - { - stream: stream.id, - resend: { - from: { - timestamp: timestamps[0], - }, - to: { - timestamp: timestamps[3] - 1, - }, - }, - }, - (message) => { - messages.push(message) - }, - ) - - await waitForEvent(sub, 'resent') - expect(messages).toEqual([ - { - msg: 'message0', - }, - { - msg: 'message1', - }, - { - msg: 'message2', - }, - ]) - }, 10000) - }) - - describe('ensureConnected', () => { - it('connects the client', async () => { - const client = createClient() - await client.ensureConnected() - expect(client.isConnected()).toBeTruthy() - // no error if already connected - await client.ensureConnected() - expect(client.isConnected()).toBeTruthy() - await client.disconnect() + it('does not emit error with connect', async () => { + // error will come through when getting session + client = createClient({ + restUrl: 'asdasd', + autoConnect: false, + autoDisconnect: false, + }) + await client.connect() + await wait(100) + }) }) - it('does not error if connecting', async (done) => { - const client = createClient() - client.connection.once('connecting', async () => { - await client.ensureConnected() + describe('connect handling', () => { + it('connects the client', async () => { + client = createClient() + await client.connect() + expect(client.isConnected()).toBeTruthy() + // no error if already connected + await client.connect() expect(client.isConnected()).toBeTruthy() await client.disconnect() - done() }) - await client.connect() - }) + it('does not error if connecting', async () => { + client = createClient() + const done = Defer() + client.connection.once('connecting', done.wrap(async () => { + await client.connect() + expect(client.isConnected()).toBeTruthy() + })) - it('connects if disconnecting', async (done) => { - const client = createClient() - client.connection.once('disconnecting', async () => { - await client.ensureConnected() + await client.connect() + await done expect(client.isConnected()).toBeTruthy() - await client.disconnect() - done() }) - await client.connect() - await client.disconnect() - }) - }) - - describe('ensureDisconnected', () => { - it('disconnects the client', async () => { - const client = createClient() - // no error if already disconnected - await client.ensureDisconnected() - await client.connect() - await client.ensureDisconnected() - expect(client.isDisconnected()).toBeTruthy() - }) + it('connects if disconnecting', async () => { + const done = Defer() + client = createClient() + client.connection.once('disconnecting', done.wrap(async () => { + await client.connect() + expect(client.isConnected()).toBeTruthy() + await client.disconnect() + })) - it('does not error if disconnecting', async (done) => { - const client = createClient() - client.connection.once('disconnecting', async () => { - await client.ensureDisconnected() - expect(client.isDisconnected()).toBeTruthy() - done() + await client.connect() + await expect(async () => { + await client.disconnect() + }).rejects.toThrow() + await done }) - await client.connect() - await client.disconnect() }) - it('disconnects if connecting', async (done) => { - const client = createClient() - client.connection.once('connecting', async () => { - await client.ensureDisconnected() + describe('disconnect handling', () => { + it('disconnects the client', async () => { + client = createClient() + // no error if already disconnected + await client.disconnect() + await client.connect() + await client.disconnect() expect(client.isDisconnected()).toBeTruthy() - done() }) - await client.connect() - }) - it('clear _reconnectTimeout when disconnecting client', async (done) => { - const client = createClient() - await client.ensureConnected() + it('does not error if disconnecting', async () => { + client = createClient() + const done = Defer() + client.connection.once('disconnecting', done.wrap(async () => { + await client.disconnect() + expect(client.isDisconnected()).toBeTruthy() + })) + await client.connect() + await client.disconnect() + await done + }) - client.once('disconnected', async () => { - await client.ensureDisconnected() - setTimeout(() => { + it('disconnects if connecting', async () => { + const done = Defer() + client = createClient() + client.connection.once('connecting', done.wrap(async () => { + await client.disconnect() expect(client.isDisconnected()).toBeTruthy() - done() - }, 2500) + })) + await expect(async () => { + await client.connect() + }).rejects.toThrow() + await done }) - client.connection.socket.close() - }) - }) + it('does not reconnect after purposeful disconnect', async () => { + client = createClient() + await client.connect() + const done = Defer() - describe('connect during disconnect', () => { - let client - async function teardown() { - if (client) { - client.removeAllListeners('error') - await client.ensureDisconnected() - } - } + client.once('disconnected', done.wrap(async () => { + await client.disconnect() + })) - beforeEach(async () => { - await teardown() + client.connection.socket.close() + await done + await wait(2500) + expect(client.isDisconnected()).toBeTruthy() + }) }) - afterEach(async () => { - await teardown() - }) + describe('connect during disconnect', () => { + it('can connect after disconnect', async () => { + const done = Defer() + client = createClient() + client.once('connected', done.wrapError(async () => { + await expect(async () => { + await client.disconnect() + }).rejects.toThrow() + })) + client.once('disconnected', done.wrapError(async () => { + client.once('connected', done.wrapError(async () => { + await client.disconnect() + done.resolve() + })) + + await expect(async () => { + await client.connect() + }).rejects.toThrow() + })) + await expect(async () => { + await client.connect() + }).rejects.toThrow() + await done + }) - it('can reconnect after disconnect', (done) => { - client = createClient() - client.once('error', done) - client.connect() - client.once('connected', async () => { + it('can disconnect before connected', async () => { + client = createClient() + + const t = expect(async () => { + await client.connect() + }).rejects.toThrow() await client.disconnect() + await t }) - client.once('disconnected', () => { - client.connect() - client.once('connected', async () => { - await client.disconnect() - done() - }) + + it('can disconnect before connected', async () => { + client = createClient() + const t = expect(async () => { + await client.connect() + }).rejects.toThrow() + await client.disconnect() + await t }) - }) - it('can disconnect before connected', async (done) => { - client = createClient() - client.once('error', done) - client.connect() - await client.disconnect() - done() - }) + it('can connect', async () => { + client = createClient() + const done = Defer() + await client.connect() - it('can connect', async (done) => { - client = createClient() - await client.connect() + client.connection.once('disconnecting', done.wrap(async () => { + await client.connect() + await client.disconnect() + })) - client.connection.once('disconnecting', async () => { - await client.connect() - await client.disconnect() - done() + await expect(async () => { + await client.disconnect() + }).rejects.toThrow() + await done }) - await client.disconnect() - }, 5000) + it('can reconnect on unexpected close', async () => { + client = createClient() + await client.connect() - it('will resolve original disconnect', async (done) => { - client = createClient() + client.connection.socket.close() + expect(client.isConnected()).not.toBeTruthy() + await client.connection.nextConnection() + expect(client.isConnected()).toBeTruthy() + }) - await client.connect() + it('will resolve original disconnect', async () => { + const done = Defer() + client = createClient() - client.connection.once('disconnecting', async () => { await client.connect() - }) - await client.disconnect() - done() // ok if it ever gets here - }, 5000) - it('has connection state transitions in correct order', async (done) => { - client = createClient() - const connectionEventSpy = jest.spyOn(client.connection, 'emit') + client.connection.once('disconnecting', done.wrap(async () => { + await client.connect() + })) + await expect(async () => { + await client.disconnect() + }).rejects.toThrow() + await done + }) - await client.connect() + it('has connection state transitions in correct order', async () => { + client = createClient() + const done = Defer() + const connectionEventSpy = jest.spyOn(client.connection, 'emit') - client.connection.once('disconnecting', async () => { await client.connect() - const eventNames = connectionEventSpy.mock.calls.map(([eventName]) => eventName) - expect(eventNames).toEqual([ - 'connecting', - 'connected', - 'disconnecting', - 'disconnected', // should disconnect before re-connecting - 'connecting', - 'connected', - ]) - done() - }) - await client.disconnect() - }, 5000) - it('should not subscribe to unsubscribed streams on reconnect', async (done) => { - client = createClient() - await client.ensureConnected() - const sessionToken = await client.session.getSessionToken() + client.connection.once('disconnecting', done.wrap(async () => { + await client.connect() + const eventNames = connectionEventSpy.mock.calls.map(([eventName]) => eventName) + expect(eventNames).toEqual([ + 'connecting', + 'connected', + 'disconnecting', + ]) + expect(client.isConnected()).toBeTruthy() + })) + + await expect(async () => { + await client.disconnect() + }).rejects.toThrow() + await done + }, 5000) - const stream = await client.createStream({ - name: uid('stream') - }) + it('should not subscribe to unsubscribed streams on reconnect', async () => { + client = createClient() + await client.connect() + const sessionToken = await client.session.getSessionToken() - const connectionEventSpy = jest.spyOn(client.connection, 'send') - const sub = client.subscribe(stream.id, () => {}) + const stream = await client.createStream({ + name: uid('stream') + }) - sub.once('subscribed', async () => { + const connectionEventSpy = jest.spyOn(client.connection, '_send') + const sub = await client.subscribe(stream.id, () => {}) await wait(100) - client.unsubscribe(sub) - }) - - sub.once('unsubscribed', async () => { - await client.ensureDisconnected() - await client.ensureConnected() - await client.ensureDisconnected() + await client.unsubscribe(sub) + await client.disconnect() + await client.connect() + await client.disconnect() + // key exchange stream subscription should not have been sent yet + expect(connectionEventSpy.mock.calls).toHaveLength(2) // check whole list of calls after reconnect and disconnect expect(connectionEventSpy.mock.calls[0]).toEqual([new SubscribeRequest({ @@ -461,633 +437,787 @@ describe('StreamrClient Connection', () => { sessionToken, requestId: connectionEventSpy.mock.calls[1][0].requestId, })]) - - // key exchange stream subscription should not have been sent yet - expect(connectionEventSpy.mock.calls.length).toEqual(2) - done() }) - }) - it('should not subscribe after resend() on reconnect', async (done) => { - client = createClient() - await client.ensureConnected() - const sessionToken = await client.session.getSessionToken() + it('should not subscribe after resend() on reconnect', async () => { + client = createClient() + await client.connect() + const sessionToken = await client.session.getSessionToken() - const stream = await client.createStream({ - name: uid('stream') - }) + const stream = await client.createStream({ + name: uid('stream') + }) - const connectionEventSpy = jest.spyOn(client.connection, 'send') - const sub = await client.resend({ - stream: stream.id, - resend: { - last: 10 - } - }, () => {}) - - sub.once('initial_resend_done', () => { - setTimeout(async () => { - await client.pause() // simulates a disconnection at the websocket level, not on the client level. - await client.ensureConnected() - await client.ensureDisconnected() - - // check whole list of calls after reconnect and disconnect - expect(connectionEventSpy.mock.calls[0]).toEqual([new ResendLastRequest({ - streamId: stream.id, - streamPartition: 0, - sessionToken, - numberLast: 10, - requestId: connectionEventSpy.mock.calls[0][0].requestId, - })]) - - // key exchange stream subscription should not have been sent yet - expect(connectionEventSpy.mock.calls.length).toEqual(1) - done() - }, 2000) - }) - }, 5000) + const connectionEventSpy = jest.spyOn(client.connection, 'send') + const sub = await client.resend({ + stream: stream.id, + resend: { + last: 10 + } + }) - it('does not try to reconnect', async (done) => { - client = createClient() - client.once('error', done) - await client.connect() + const msgs = await sub.collect() + + await wait(2000) + await client.connection.socket.close() + await client.connection.nextConnection() - client.connection.once('disconnecting', async () => { + // check whole list of calls after reconnect and disconnect + expect(connectionEventSpy.mock.calls[0]).toEqual([new ResendLastRequest({ + streamId: stream.id, + streamPartition: 0, + sessionToken, + numberLast: 10, + requestId: connectionEventSpy.mock.calls[0][0].requestId, + })]) + expect(msgs).toEqual([]) + + // key exchange stream subscription should not have been sent yet + expect(connectionEventSpy.mock.calls.length).toEqual(1) + await client.disconnect() + }, 10000) + + it('does not try to reconnect', async () => { + client = createClient() await client.connect() + const onConnectAfterDisconnecting = Defer() // should not try connecting after disconnect (or any other reason) - const onConnecting = () => { - done(new Error('should not be connecting')) - } - client.once('connecting', onConnecting) + client.connection.once('disconnecting', onConnectAfterDisconnecting.wrap(async () => { + await client.connect() + })) + await expect(async () => { + await client.disconnect() + }).rejects.toThrow() + await onConnectAfterDisconnecting + expect(client.isConnected()).toBe(true) await client.disconnect() + const onConnecting = jest.fn() + client.once('connecting', onConnecting) // wait for possible reconnections - setTimeout(() => { - client.off('connecting', onConnecting) - expect(client.isConnected()).toBe(false) - done() - }, 2000) + await wait(2000) + expect(onConnecting).toHaveBeenCalledTimes(0) + expect(client.isConnected()).toBe(false) + }, 10000) + }) + + describe('publish/subscribe connection handling', () => { + describe('publish', () => { + it('will connect if not connected if autoconnect set', async () => { + const done = Defer() + client = createClient({ + autoConnect: true, + autoDisconnect: true, + }) + + const stream = await client.createStream({ + name: uid('stream') + }) + expect(client.isDisconnected()).toBeTruthy() + + const message = { + id2: uid('msg') + } + + client.once('connected', done.wrap(() => {})) + await client.publish(stream.id, message) + await done + // wait in case of delayed errors + await wait(250) + }) + + it('errors if disconnected autoconnect set', async () => { + client = createClient({ + autoConnect: true, + autoDisconnect: true, + }) + + await client.connect() + const stream = await client.createStream({ + name: uid('stream') + }) + + const message = { + id1: uid('msg') + } + const p = client.publish(stream.id, message) + await wait() + await client.disconnect() // start async disconnect after publish started + await expect(p).rejects.toThrow() + expect(client.isDisconnected()).toBeTruthy() + // wait in case of delayed errors + await wait(250) + }) + + it('errors if disconnected autoconnect not set', async () => { + client = createClient({ + autoConnect: false, + autoDisconnect: true, + }) + + await client.connect() + const stream = await client.createStream({ + name: uid('stream') + }) + + const message = { + id1: uid('msg') + } + const p = client.publish(stream.id, message) + await wait() + await client.disconnect() // start async disconnect after publish started + await expect(p).rejects.toThrow() + expect(client.isDisconnected()).toBeTruthy() + // wait in case of delayed errors + await wait(500) + }, 10000) }) - await client.disconnect() - }, 6000) + + describe('subscribe', () => { + it('does not error if disconnect after subscribe', async () => { + client = createClient({ + autoConnect: true, + autoDisconnect: true, + }) + + await client.connect() + const stream = await client.createStream({ + name: uid('stream') + }) + + await client.subscribe({ + stream: stream.id, + }, () => {}) + + await client.disconnect() + }) + + it('does not error if disconnect after subscribe with resend', async () => { + client = createClient({ + autoConnect: true, + autoDisconnect: true, + }) + + await client.connect() + const stream = await client.createStream({ + name: uid('stream') + }) + + await client.subscribe({ + stream: stream.id, + resend: { + from: { + timestamp: 0, + }, + }, + }, () => {}) + + await client.disconnect() + }) + }) + }) }) - describe('publish/subscribe connection handling', () => { - let client - async function teardown() { - if (!client) { return } - client.removeAllListeners('error') - await client.ensureDisconnected() - client = undefined + describe('StreamrClient', () => { + let stream + let waitForStorage + let publishTestMessages + + // These tests will take time, especially on Travis + const TIMEOUT = 30 * 1000 + + const attachSubListeners = (sub) => { + const onSubscribed = jest.fn() + sub.on('subscribed', onSubscribed) + const onResent = jest.fn() + sub.on('resent', onResent) + const onUnsubscribed = jest.fn() + sub.on('unsubscribed', onUnsubscribed) + return { + onSubscribed, + onUnsubscribed, + onResent, + } + } + + const createStream = async ({ requireSignedData = true, ...opts } = {}) => { + const name = uid('stream') + const s = await client.createStream({ + name, + requireSignedData, + ...opts, + }) + + expect(s.id).toBeTruthy() + expect(s.name).toEqual(name) + expect(s.requireSignedData).toBe(requireSignedData) + return s } beforeEach(async () => { - await teardown() + client = createClient() + await Promise.all([ + client.session.getSessionToken(), + client.connect(), + ]) + stream = await createStream() + publishTestMessages = getPublishTestMessages(client, { + stream, + }) + waitForStorage = getWaitForStorage(client, { + stream, + }) + expect(onError).toHaveBeenCalledTimes(0) }) afterEach(async () => { - await teardown() + await wait() + // ensure no unexpected errors + expect(onError).toHaveBeenCalledTimes(expectErrors) }) - describe('publish', () => { - it('will connect if not connected if autoconnect set', async (done) => { - client = createClient({ - autoConnect: true, - autoDisconnect: true, - }) + afterEach(async () => { + await wait() - client.once('error', done) + if (client) { + client.debug('disconnecting after test') + await client.disconnect() + } - const stream = await client.createStream({ - name: uid('stream') - }) - await client.ensureDisconnected() + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + await Connection.closeOpen() + throw new Error(`sockets not closed: ${openSockets}`) + } + }) - const message = { - id2: uid('msg') - } - client.once('connected', () => { - // wait in case of delayed errors - setTimeout(() => done(), 500) - }) - await client.publish(stream.id, message) - }) + it('is stream publisher', async () => { + const publisherId = await client.getUserId() + const res = await client.isStreamPublisher(stream.id, publisherId) + expect(res).toBe(true) + }) - it('will connect if disconnecting & autoconnect set', async (done) => { - client = createClient({ - autoConnect: true, - autoDisconnect: true, + describe('Pub/Sub', () => { + it('client.publish does not error', async () => { + await client.publish(stream.id, { + test: 'client.publish', }) + await wait(TIMEOUT * 0.2) + }, TIMEOUT) - client.once('error', done) - await client.ensureConnected() - const stream = await client.createStream({ - name: uid('stream') + it('Stream.publish does not error', async () => { + await stream.publish({ + test: 'Stream.publish', }) + await wait(TIMEOUT * 0.2) + }, TIMEOUT) - const message = { - id1: uid('msg') - } - const p = client.publish(stream.id, message) - setTimeout(async () => { - await client.disconnect() // start async disconnect after publish started + it('client.publish with Stream object as arg', async () => { + await client.publish(stream, { + test: 'client.publish.Stream.object', }) - await p - // wait in case of delayed errors - setTimeout(() => done(), 500) - }) + await wait(TIMEOUT * 0.2) + }, TIMEOUT) - it('will error if disconnecting & autoconnect not set', async (done) => { - client = createClient({ - autoConnect: false, - autoDisconnect: false, + describe('subscribe/unsubscribe', () => { + beforeEach(() => { + expect(client.getSubscriptions(stream.id)).toHaveLength(0) }) - client.onError = jest.fn() - client.once('error', done) - await client.ensureConnected() - const stream = await client.createStream({ - name: uid('stream') - }) + it('client.subscribe then unsubscribe after subscribed', async () => { + const sub = await client.subscribe({ + stream: stream.id, + }, () => {}) - const message = { - id1: uid('msg') - } + const events = attachSubListeners(sub) - client.publish(stream.id, message).catch((err) => { - expect(err).toBeTruthy() - setTimeout(() => { - // wait in case of delayed errors - expect(client.onError).not.toHaveBeenCalled() - done() - }) - }) // don't wait + expect(client.getSubscriptions(stream.id)).toHaveLength(1) // has subscription immediately + expect(client.getSubscriptions(stream.id)).toHaveLength(1) + await client.unsubscribe(sub) + expect(client.getSubscriptions(stream.id)).toHaveLength(0) + expect(events.onUnsubscribed).toHaveBeenCalledTimes(1) + }, TIMEOUT) + + it('client.subscribe then unsubscribe before subscribed', async () => { + client.connection.enableAutoDisconnect(false) + const subTask = client.subscribe({ + stream: stream.id, + }, () => {}) + + const events = attachSubListeners(client.subscriber.getSubscriptionSession(stream)) + + expect(client.getSubscriptions(stream.id)).toHaveLength(1) + + const unsubTask = client.unsubscribe(stream) + + expect(client.getSubscriptions(stream.id)).toHaveLength(0) // lost subscription immediately + await unsubTask + await subTask + await wait(TIMEOUT * 0.2) + expect(events.onResent).toHaveBeenCalledTimes(0) + expect(events.onSubscribed).toHaveBeenCalledTimes(0) + expect(events.onUnsubscribed).toHaveBeenCalledTimes(0) + }, TIMEOUT) - setTimeout(() => { - client.disconnect() // start async disconnect after publish started + it('client.subscribe then unsubscribe before subscribed after started subscribing', async () => { + client.connection.enableAutoDisconnect(false) + const subTask = client.subscribe({ + stream: stream.id, + }, () => {}) + const subSession = client.subscriber.getSubscriptionSession(stream) + const events = attachSubListeners(subSession) + let unsubTask + const startedSubscribing = Defer() + subSession.once('subscribing', startedSubscribing.wrap(() => { + unsubTask = client.unsubscribe(stream) + })) + + await Promise.all([ + startedSubscribing, + unsubTask, + subTask, + ]) + expect(client.getSubscriptions(stream.id)).toHaveLength(0) // lost subscription immediately + await wait(TIMEOUT * 0.2) + expect(events.onResent).toHaveBeenCalledTimes(0) + expect(events.onSubscribed).toHaveBeenCalledTimes(0) + expect(events.onUnsubscribed).toHaveBeenCalledTimes(1) + }, TIMEOUT) + + describe('with resend', () => { + it('client.subscribe then unsubscribe before subscribed', async () => { + client.connection.enableAutoDisconnect(false) + const subTask = client.subscribe({ + stream: stream.id, + resend: { + from: { + timestamp: 0, + }, + }, + }, () => {}) + + const events = attachSubListeners(client.subscriber.getSubscriptionSession(stream)) + + expect(client.getSubscriptions(stream.id)).toHaveLength(1) + + const unsubTask = client.unsubscribe(stream) + + expect(client.getSubscriptions(stream.id)).toHaveLength(0) // lost subscription immediately + await unsubTask + await subTask + await wait(TIMEOUT * 0.2) + expect(events.onResent).toHaveBeenCalledTimes(0) + expect(events.onSubscribed).toHaveBeenCalledTimes(0) + expect(events.onUnsubscribed).toHaveBeenCalledTimes(0) + }, TIMEOUT) + + it('client.subscribe then unsubscribe ignores messages with resend', async () => { + const onMessage = jest.fn() + const subTask = client.subscribe({ + stream: stream.id, + resend: { + from: { + timestamp: 0, + }, + }, + }, onMessage) + + const events = attachSubListeners(client.subscriber.getSubscriptionSession(stream)) + const unsubTask = client.unsubscribe(stream) + expect(client.getSubscriptions(stream.id)).toHaveLength(0) // lost subscription immediately + + const msg = Msg() + const publishReq = await stream.publish(msg) + await waitForStorage(publishReq) + + await unsubTask + await subTask + await wait(TIMEOUT * 0.2) + expect(events.onResent).toHaveBeenCalledTimes(0) + expect(events.onSubscribed).toHaveBeenCalledTimes(0) + expect(events.onUnsubscribed).toHaveBeenCalledTimes(0) + expect(onMessage).toHaveBeenCalledTimes(0) + }, TIMEOUT) }) + + it('client.subscribe then unsubscribe ignores messages', async () => { + const onMessage = jest.fn() + const sub = await client.subscribe({ + stream: stream.id, + }, onMessage) + + expect(client.getSubscriptions(stream.id)).toHaveLength(1) + const events = attachSubListeners(sub) + const t = client.unsubscribe(sub) + await stream.publish(Msg()) + await t + expect(client.getSubscriptions(stream.id)).toHaveLength(0) // lost subscription immediately + await wait(TIMEOUT * 0.2) + expect(events.onResent).toHaveBeenCalledTimes(0) + expect(events.onSubscribed).toHaveBeenCalledTimes(0) + expect(events.onUnsubscribed).toHaveBeenCalledTimes(1) + }, TIMEOUT) }) - }) - describe('subscribe', () => { - it('does not error if disconnect after subscribe', async (done) => { - client = createClient({ - autoConnect: true, - autoDisconnect: true, - }) - client.onError = jest.fn() - client.once('error', done) - await client.ensureConnected() - const stream = await client.createStream({ - name: uid('stream') + it('client.subscribe (realtime)', async () => { + const id = Date.now() + const done = Defer() + const sub = await client.subscribe({ + stream: stream.id, + }, done.wrap(async (parsedContent, streamMessage) => { + expect(parsedContent.id).toBe(id) + + // Check signature stuff + expect(streamMessage.signatureType).toBe(StreamMessage.SIGNATURE_TYPES.ETH) + expect(streamMessage.getPublisherId()).toBeTruthy() + expect(streamMessage.signature).toBeTruthy() + })) + + // Publish after subscribed + await stream.publish({ + id, }) + await done + // All good, unsubscribe + await client.unsubscribe(sub) + }) - const sub = client.subscribe({ + it('client.subscribe with onMessage & collect', async () => { + const onMessageMsgs = [] + const sub = await client.subscribe({ stream: stream.id, - resend: { - from: { - timestamp: 0, - }, - }, - }, () => {}) - sub.once('subscribed', async () => { - await client.disconnect() - // wait in case of delayed errors - setTimeout(() => { - expect(client.onError).not.toHaveBeenCalled() - done() - }, 100) + }, async (msg) => { + onMessageMsgs.push(msg) }) + + const published = await publishTestMessages(MAX_MESSAGES) + await expect(async () => sub.collect(1)).rejects.toThrow('iterate') + expect(onMessageMsgs).toEqual(published) }) - }) - }) -}) -describe('StreamrClient', () => { - let client - let stream + describe('resubscribe on unexpected disconnection', () => { + let otherClient - // These tests will take time, especially on Travis - const TIMEOUT = 5 * 1000 + beforeEach(async () => { + otherClient = createClient({ + auth: client.options.auth, + }) + const tasks = [ + client.connect(), + client.session.getSessionToken(), + otherClient.connect(), + otherClient.session.getSessionToken(), + ] + await Promise.allSettled(tasks) + await Promise.all(tasks) // throw if there were an error + }) - const createStream = async () => { - const name = `StreamrClient-integration-${Date.now()}` - assert(client.isConnected()) + afterEach(async () => { + otherClient.debug('disconnecting after test') + const tasks = [ + otherClient.disconnect(), + client.disconnect(), + ] + await Promise.allSettled(tasks) + await Promise.all(tasks) // throw if there were an error + }) - const s = await client.createStream({ - name, - requireSignedData: true, - }) + it('should work', async () => { + const done = Defer() + const msgs = [] - assert(s.id) - assert.equal(s.name, name) - assert.strictEqual(s.requireSignedData, true) - return s - } + await otherClient.subscribe(stream, (msg) => { + msgs.push(msg) - beforeEach(async () => { - client = createClient() - // create client before connecting ws - // so client generates correct options.url for us + otherClient.debug('got msg %d of %d', msgs.length, MAX_MESSAGES) + if (msgs.length === MAX_MESSAGES) { + // should eventually get here + done.resolve() + } + }) - try { - await Promise.all([ - fetch(config.clientOptions.restUrl), - new Promise((resolve, reject) => { - const ws = new WebSocket(client.options.url) - ws.once('open', () => { - resolve() - ws.close() + const disconnect = pLimitFn(async () => { + if (msgs.length === MAX_MESSAGES) { return } + otherClient.debug('disconnecting...', msgs.length) + otherClient.connection.socket.close() + // wait for reconnection before possibly disconnecting again + await otherClient.nextConnection() + otherClient.debug('reconnected...', msgs.length) }) - ws.once('error', (err) => { - reject(err) - ws.terminate() + + const onConnectionMessage = jest.fn(() => { + // disconnect after every message + disconnect() }) - }), - ]) - } catch (e) { - if (e.errno === 'ENOTFOUND' || e.errno === 'ECONNREFUSED') { - throw new Error('Integration testing requires that engine-and-editor ' - + 'and data-api ("entire stack") are running in the background. ' - + 'Instructions: https://github.com/streamr-dev/streamr-docker-dev#running') - } else { - throw e - } - } - await client.ensureConnected() - stream = await createStream() - const publisherId = await client.getPublisherId() - const res = await client.isStreamPublisher(stream.id, publisherId.toLowerCase()) - assert.strictEqual(res, true) - }) - afterEach(async () => { - if (client) { - client.removeAllListeners('error') - await client.ensureDisconnected() - } - }) + otherClient.connection.on(ControlMessage.TYPES.BroadcastMessage, onConnectionMessage) + otherClient.connection.on(ControlMessage.TYPES.UnicastMessage, onConnectionMessage) - describe('Pub/Sub', () => { - it('client.publish', async (done) => { - client.once('error', done) - await client.publish(stream.id, { - test: 'client.publish', - }) - setTimeout(() => done(), TIMEOUT * 0.8) - }, TIMEOUT) + const onConnected = jest.fn() + const onDisconnected = jest.fn() + otherClient.connection.on('connected', onConnected) + otherClient.connection.on('disconnected', onDisconnected) + const published = await publishTestMessages(MAX_MESSAGES, { + delay: 600, + }) + await done + // wait for final re-connection after final message + await otherClient.connection.nextConnection() + + expect(msgs).toEqual(published) - it('Stream.publish', async (done) => { - client.once('error', done) - await stream.publish({ - test: 'Stream.publish', + // check disconnect/connect actually happened + expect(onConnectionMessage.mock.calls.length).toBeGreaterThanOrEqual(published.length) + expect(onConnected.mock.calls.length).toBeGreaterThanOrEqual(published.length) + expect(onDisconnected.mock.calls.length).toBeGreaterThanOrEqual(published.length) + }, 30000) }) - setTimeout(() => done(), TIMEOUT * 0.8) - }, TIMEOUT) - it('client.publish with Stream object as arg', async (done) => { - client.once('error', done) - await client.publish(stream, { - test: 'client.publish.Stream.object', + it('publish and subscribe a sequence of messages', async () => { + client.enableAutoConnect() + const done = Defer() + const received = [] + const sub = await client.subscribe({ + stream: stream.id, + }, done.wrapError((parsedContent, streamMessage) => { + received.push(parsedContent) + // Check signature stuff + expect(streamMessage.signatureType).toBe(StreamMessage.SIGNATURE_TYPES.ETH) + expect(streamMessage.getPublisherId()).toBeTruthy() + expect(streamMessage.signature).toBeTruthy() + if (received.length === MAX_MESSAGES) { + done.resolve(client.unsubscribe(sub)) + } + })) + + // Publish after subscribed + const published = await publishTestMessages(MAX_MESSAGES, { + wait: 100, + }) + + await done + expect(received).toEqual(published) }) - setTimeout(() => done(), TIMEOUT * 0.8) - }, TIMEOUT) - - it('client.subscribe with resend from', (done) => { - client.once('error', done) - // Publish message - client.publish(stream.id, { - test: 'client.subscribe with resend', + + test('publish does not disconnect after each message with autoDisconnect', async () => { + await client.disconnect() + const onConnected = jest.fn() + const onDisconnected = jest.fn() + client.on('disconnected', onDisconnected) + client.on('connected', onConnected) + + client.options.publishAutoDisconnectDelay = 1000 // eslint-disable-line require-atomic-updates + + client.enableAutoConnect() + client.enableAutoDisconnect() + await publishTestMessages(3, { + delay: 150, + }) + + await wait(client.options.publishAutoDisconnectDelay * 1.5) + + expect(onConnected).toHaveBeenCalledTimes(1) + expect(onDisconnected).toHaveBeenCalledTimes(1) }) - // Check that we're not subscribed yet - assert.strictEqual(client.getSubscriptions()[stream.id], undefined) + it('client.subscribe with resend from', async () => { + const done = Defer() + const published = await publishTestMessages(MAX_MESSAGES, { + waitForLast: true, + }) - // Add delay: this test needs some time to allow the message to be written to Cassandra - setTimeout(() => { - const sub = client.subscribe({ + const received = [] + + const sub = await client.subscribe({ stream: stream.id, resend: { from: { timestamp: 0, }, }, - }, async (parsedContent, streamMessage) => { - // Check message content - assert.strictEqual(parsedContent.test, 'client.subscribe with resend') + }, done.wrapError(async (parsedContent, streamMessage) => { + received.push(parsedContent) // Check signature stuff - // WARNING: digging into internals - const subStream = client._getSubscribedStreamPartition(stream.id, 0) // eslint-disable-line no-underscore-dangle - const publishers = await subStream.getPublishers() - const map = {} - map[(await client.signer.getAddress()).toLowerCase()] = true - assert.deepStrictEqual(publishers, map) - assert.strictEqual(streamMessage.signatureType, StreamMessage.SIGNATURE_TYPES.ETH) - assert(streamMessage.getPublisherId()) - assert(streamMessage.signature) - - // All good, unsubscribe - client.unsubscribe(sub) - sub.once('unsubscribed', () => { - assert.strictEqual(client.getSubscriptions(stream.id).length, 0) - done() - }) + expect(streamMessage.signatureType).toBe(StreamMessage.SIGNATURE_TYPES.ETH) + expect(streamMessage.getPublisherId()).toBeTruthy() + expect(streamMessage.signature).toBeTruthy() + if (received.length === published.length) { + done.resolve() + } + })) + + await done + expect(received).toEqual(published) + // All good, unsubscribe + await client.unsubscribe(sub) + expect(client.getSubscriptions(stream.id)).toHaveLength(0) + }, TIMEOUT) + + it('client.subscribe with resend last', async () => { + const done = Defer() + const published = await publishTestMessages(MAX_MESSAGES, { + waitForLast: true, }) - }, TIMEOUT * 0.8) - }, TIMEOUT) - - it('client.subscribe with resend last', (done) => { - client.once('error', done) - // Publish message - client.publish(stream.id, { - test: 'client.subscribe with resend', - }) - // Check that we're not subscribed yet - assert.strictEqual(client.getSubscriptions(stream.id).length, 0) + const received = [] - // Add delay: this test needs some time to allow the message to be written to Cassandra - setTimeout(() => { - const sub = client.subscribe({ + const sub = await client.subscribe({ stream: stream.id, resend: { - last: 1, + last: 2 }, - }, async (parsedContent, streamMessage) => { - // Check message content - assert.strictEqual(parsedContent.test, 'client.subscribe with resend') - + }, done.wrapError(async (parsedContent, streamMessage) => { + received.push(parsedContent) // Check signature stuff - // WARNING: digging into internals - const subStream = client._getSubscribedStreamPartition(stream.id, 0) // eslint-disable-line no-underscore-dangle - const publishers = await subStream.getPublishers() - const map = {} - map[(await client.signer.getAddress()).toLowerCase()] = true - assert.deepStrictEqual(publishers, map) - assert.strictEqual(streamMessage.signatureType, StreamMessage.SIGNATURE_TYPES.ETH) - assert(streamMessage.getPublisherId()) - assert(streamMessage.signature) - - // All good, unsubscribe - client.unsubscribe(sub) - sub.once('unsubscribed', () => { - assert.strictEqual(client.getSubscriptions(stream.id).length, 0) - done() - }) - }) - }, TIMEOUT * 0.8) - }, TIMEOUT) - - it('client.subscribe (realtime)', (done) => { - client.once('error', done) - const id = Date.now() - const sub = client.subscribe({ - stream: stream.id, - }, (parsedContent, streamMessage) => { - assert.equal(parsedContent.id, id) - - // Check signature stuff - assert.strictEqual(streamMessage.signatureType, StreamMessage.SIGNATURE_TYPES.ETH) - assert(streamMessage.getPublisherId()) - assert(streamMessage.signature) + expect(streamMessage.signatureType).toBe(StreamMessage.SIGNATURE_TYPES.ETH) + expect(streamMessage.getPublisherId()).toBeTruthy() + expect(streamMessage.signature).toBeTruthy() + if (received.length === 2) { + done.resolve() + } + })) + await done // All good, unsubscribe - client.unsubscribe(sub) - sub.once('unsubscribed', () => { - done() + await client.unsubscribe(sub) + expect(received).toEqual(published.slice(-2)) + expect(client.getSubscriptions(stream.id)).toHaveLength(0) + }, TIMEOUT) + + it('client.subscribe (realtime with resend)', async () => { + const done = Defer() + const published = await publishTestMessages(MAX_MESSAGES, { + waitForLast: true, }) - }) - // Publish after subscribed - sub.once('subscribed', () => { - stream.publish({ - id, - }) - }) + const received = [] + + const sub = await client.subscribe({ + stream: stream.id, + resend: { + last: 2 + }, + }, done.wrapError(async (parsedContent, streamMessage) => { + received.push(parsedContent) + // Check signature stuff + expect(streamMessage.signatureType).toBe(StreamMessage.SIGNATURE_TYPES.ETH) + expect(streamMessage.getPublisherId()).toBeTruthy() + expect(streamMessage.signature).toBeTruthy() + if (received.length === 3) { + done.resolve() + } + })) + + const [msg] = await publishTestMessages(1) + + await done + // All good, unsubscribe + await client.unsubscribe(sub) + expect(received).toEqual([...published.slice(-2), msg]) + expect(client.getSubscriptions(stream.id)).toHaveLength(0) + }, TIMEOUT) }) - it('publish and subscribe a sequence of messages', (done) => { - client.options.autoConnect = true - const nbMessages = 20 - const intervalMs = 500 - let counter = 1 - const sub = client.subscribe({ - stream: stream.id, - }, (parsedContent, streamMessage) => { - assert.strictEqual(parsedContent.i, counter) - counter += 1 - - // Check signature stuff - assert.strictEqual(streamMessage.signatureType, StreamMessage.SIGNATURE_TYPES.ETH) - assert(streamMessage.getPublisherId()) - assert(streamMessage.signature) - - if (counter === nbMessages) { - // All good, unsubscribe - client.unsubscribe(sub) - sub.once('unsubscribed', async () => { - await client.disconnect() - setTimeout(done, 1000) - }) - } - }) + describe('resend', () => { + let timestamps = [] + let published = [] - const sleep = (ms) => { - return new Promise((resolve) => setTimeout(resolve, ms)) - } - const f = async (index) => { - await sleep(intervalMs) - await stream.publish({ - i: index, + beforeEach(async () => { + publishTestMessages = getPublishTestMessages(client, { + stream, + waitForLast: true, + waitForLastTimeout: 9000, }) - } - // Publish after subscribed - sub.once('subscribed', () => { - let i - const loop = async () => { - for (i = 1; i <= nbMessages; i++) { - await f(i) // eslint-disable-line no-await-in-loop - } - } - return loop() - }) - }, 20000) - - it('client.subscribe (realtime with resend)', (done) => { - client.once('error', done) - - const id = Date.now() - const sub = client.subscribe({ - stream: stream.id, - resend: { - last: 1, - }, - }, (parsedContent, streamMessage) => { - assert.equal(parsedContent.id, id) - - // Check signature stuff - assert.strictEqual(streamMessage.signatureType, StreamMessage.SIGNATURE_TYPES.ETH) - assert(streamMessage.getPublisherId()) - assert(streamMessage.signature) - - sub.once('unsubscribed', () => { - done() - }) - // All good, unsubscribe - client.unsubscribe(sub) + const publishedRaw = await publishTestMessages.raw(5) + timestamps = publishedRaw.map(([, raw]) => raw.streamMessage.getTimestamp()) + published = publishedRaw.map(([msg]) => msg) }) - // Publish after subscribed - sub.once('subscribed', () => { - stream.publish({ - id, + it('resend last', async () => { + const sub = await client.resend({ + stream: stream.id, + resend: { + last: 3, + }, }) + + expect(await sub.collect()).toEqual(published.slice(-3)) }) - }, 30000) - describe.skip('decryption', () => { - it('client.subscribe can decrypt encrypted messages if it knows the group key', async (done) => { - client.once('error', done) - const id = Date.now() - const publisherId = await client.getPublisherId() - const groupKey = crypto.randomBytes(32) - const keys = {} - keys[publisherId] = groupKey - const sub = client.subscribe({ + it('resend from', async () => { + const sub = await client.resend({ stream: stream.id, - groupKeys: keys, - }, (parsedContent, streamMessage) => { - assert.equal(parsedContent.id, id) - - // Check signature stuff - assert.strictEqual(streamMessage.signatureType, StreamMessage.SIGNATURE_TYPES.ETH) - assert(streamMessage.getPublisherId()) - assert(streamMessage.signature) - - // All good, unsubscribe - client.unsubscribe(sub) - sub.once('unsubscribed', () => { - done() - }) + resend: { + from: { + timestamp: timestamps[3], + }, + }, }) - // Publish after subscribed - sub.once('subscribed', () => { - client.publish(stream.id, { - id, - }, Date.now(), null, groupKey) - }) + expect(await sub.collect()).toEqual(published.slice(3)) }) - it('client.subscribe can get the group key and decrypt encrypted messages using an RSA key pair', async (done) => { - client.once('error', done) - const id = Date.now() - const groupKey = crypto.randomBytes(32) - // subscribe without knowing the group key to decrypt stream messages - const sub = client.subscribe({ + it('resend range', async () => { + const sub = await client.resend({ stream: stream.id, - }, (parsedContent, streamMessage) => { - assert.equal(parsedContent.id, id) + resend: { + from: { + timestamp: timestamps[0], + }, + to: { + timestamp: timestamps[3] - 1, + }, + }, + }) - // Check signature stuff - assert.strictEqual(streamMessage.signatureType, StreamMessage.SIGNATURE_TYPES.ETH) - assert(streamMessage.getPublisherId()) - assert(streamMessage.signature) + expect(await sub.collect()).toEqual(published.slice(0, 3)) + }) - // Now the subscriber knows the group key - assert.deepStrictEqual(sub.groupKeys[streamMessage.getPublisherId().toLowerCase()], groupKey) + it('works with message handler + resent event', async () => { + const messages = [] + const sub = await client.resend({ + stream: stream.id, + resend: { + last: 3, + }, + }, (msg) => { + messages.push(msg) + }) - sub.once('unsubscribed', () => { - done() - }) + await waitForEvent(sub, 'resent') + expect(messages).toEqual(published.slice(-3)) + }) + }, 10000) - // All good, unsubscribe - client.unsubscribe(sub) + describe('utf-8 encoding', () => { + it('decodes realtime messages correctly', async () => { + const publishedMessage = Msg({ + content: fs.readFileSync(path.join(__dirname, 'utf8Example.txt'), 'utf8') }) + const sub = await client.subscribe(stream.id) + await client.publish(stream.id, publishedMessage) + const messages = await sub.collect(1) + expect(messages).toEqual([publishedMessage]) + }) - // Publish after subscribed - sub.once('subscribed', () => { - client.publish(stream.id, { - id, - }, Date.now(), null, groupKey) + it('decodes resent messages correctly', async () => { + const publishedMessage = Msg({ + content: fs.readFileSync(path.join(__dirname, 'utf8Example.txt'), 'utf8') }) - }, 2 * TIMEOUT) - - it('client.subscribe with resend last can get the historical keys for previous encrypted messages', (done) => { - client.once('error', done) - // Publish encrypted messages with different keys - const groupKey1 = crypto.randomBytes(32) - const groupKey2 = crypto.randomBytes(32) - client.publish(stream.id, { - test: 'resent msg 1', - }, Date.now(), null, groupKey1) - client.publish(stream.id, { - test: 'resent msg 2', - }, Date.now(), null, groupKey2) - - // Add delay: this test needs some time to allow the message to be written to Cassandra - let receivedFirst = false - setTimeout(() => { - // subscribe with resend without knowing the historical keys - const sub = client.subscribe({ - stream: stream.id, - resend: { - last: 2, - }, - }, async (parsedContent) => { - // Check message content - if (!receivedFirst) { - assert.strictEqual(parsedContent.test, 'resent msg 1') - receivedFirst = true - } else { - assert.strictEqual(parsedContent.test, 'resent msg 2') - } - - sub.once('unsubscribed', () => { - // TODO: fix this hack in other PR - assert.strictEqual(client.subscribedStreamPartitions[stream.id + '0'], undefined) - done() - }) - - // All good, unsubscribe - client.unsubscribe(sub) - }) - }, TIMEOUT * 0.8) - }, 2 * TIMEOUT) - }) - }) - - describe('utf-8 encoding', () => { - const publishedMessage = { - content: fs.readFileSync(path.join(__dirname, 'utf8Example.txt'), 'utf8') - } - - it('decodes realtime messages correctly', async (done) => { - client.once('error', done) - const sub = client.subscribe(stream.id, (msg) => { - expect(msg).toStrictEqual(publishedMessage) - done() - }).once('subscribed', () => { - client.publish(stream.id, publishedMessage) - }) + const publishReq = await client.publish(stream.id, publishedMessage) + await waitForStorage(publishReq) + const sub = await client.resend({ + stream: stream.id, + resend: { + last: 3, + }, + }) + const messages = await sub.collect() + expect(messages).toEqual([publishedMessage]) + }, 10000) }) - - it('decodes resent messages correctly', async (done) => { - client.once('error', done) - await client.publish(stream.id, publishedMessage) - await wait(5000) - await client.resend({ - stream: stream.id, - resend: { - last: 3, - }, - }, (msg) => { - expect(msg).toStrictEqual(publishedMessage) - done() - }) - }, 10000) }) }) diff --git a/test/integration/Subscriber.test.js b/test/integration/Subscriber.test.js new file mode 100644 index 000000000..55800d3eb --- /dev/null +++ b/test/integration/Subscriber.test.js @@ -0,0 +1,571 @@ +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 { Defer } from '../../src/utils' +import Connection from '../../src/Connection' + +import config from './config' + +const { ControlMessage } = ControlLayer + +const MAX_ITEMS = 2 + +describeRepeats('StreamrClient Stream', () => { + let expectErrors = 0 // check no errors by default + let onError = jest.fn() + let client + let stream + let M + let publishTestMessages + + const createClient = (opts = {}) => { + const c = new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: fakePrivateKey(), + }, + autoConnect: false, + autoDisconnect: false, + maxRetries: 2, + ...opts, + }) + c.onError = jest.fn() + c.on('error', onError) + return c + } + + beforeEach(async () => { + expectErrors = 0 + onError = jest.fn() + }) + + beforeEach(async () => { + // eslint-disable-next-line require-atomic-updates + client = createClient() + M = client.subscriber + client.debug('connecting before test >>') + await Promise.all([ + client.connect(), + client.session.getSessionToken(), + ]) + stream = await client.createStream({ + name: uid('stream') + }) + client.debug('connecting before test <<') + publishTestMessages = getPublishTestMessages(client, { + stream + }) + }) + + afterEach(() => { + expect(M.count(stream.id)).toBe(0) + }) + + afterEach(async () => { + await wait() + // ensure no unexpected errors + expect(onError).toHaveBeenCalledTimes(expectErrors) + if (client) { + expect(client.onError).toHaveBeenCalledTimes(expectErrors) + } + }) + + afterEach(async () => { + await wait() + if (client) { + client.debug('disconnecting after test >>') + await client.disconnect() + client.debug('disconnecting after test <<') + } + + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + await Connection.closeOpen() + throw new Error(`sockets not closed: ${openSockets}`) + } + }) + + it('attaches listener at subscribe time', async () => { + const beforeCount = client.connection.listenerCount(ControlMessage.TYPES.BroadcastMessage) + const sub = await M.subscribe(stream.id) + const afterCount = client.connection.listenerCount(ControlMessage.TYPES.BroadcastMessage) + expect(afterCount).toBeGreaterThan(beforeCount) + expect(M.count(stream.id)).toBe(1) + await sub.cancel() + }) + + describe('basics', () => { + it('works when passing stream', async () => { + const sub = await M.subscribe(stream) + expect(M.count(stream.id)).toBe(1) + + const published = await publishTestMessages() + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === published.length) { + break + } + } + expect(received).toEqual(published) + }) + + it('works when passing { stream: stream }', async () => { + const sub = await M.subscribe({ + stream, + }) + expect(M.count(stream.id)).toBe(1) + + const published = await publishTestMessages() + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === published.length) { + break + } + } + expect(received).toEqual(published) + }) + + it('can subscribe to stream and get updates then auto unsubscribe', async () => { + const sub = await M.subscribe(stream.id) + expect(M.count(stream.id)).toBe(1) + + const published = await publishTestMessages() + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === published.length) { + break + } + } + expect(received).toEqual(published) + }) + + it('subscribes immediately', async () => { + const sub = await M.subscribe(stream.id) + + expect(M.count(stream.id)).toBe(1) + + const published = await publishTestMessages() + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === published.length) { + break + } + } + + expect(received).toEqual(published) + }) + + it('errors if not connected', async () => { + await client.disconnect() + await expect(() => ( + M.subscribe(stream) + )).rejects.toThrow('connect') + expect(M.count(stream.id)).toBe(0) + }) + + it('errors if iterating twice', async () => { + const sub = await M.subscribe(stream) + const c1 = sub.collect() + + await expect(async () => ( + sub.collect() + )).rejects.toThrow('iterate') + + const [, m] = await Promise.all([ + sub.cancel(), + c1, + ]) + + expect(m).toEqual([]) + + expect(M.count(stream.id)).toBe(0) + }) + }) + + describe('ending a subscription', () => { + it('can kill stream using async end', async () => { + const unsubscribeEvents = [] + client.connection.on(ControlMessage.TYPES.UnsubscribeResponse, (m) => { + unsubscribeEvents.push(m) + }) + + const sub = await M.subscribe(stream.id) + expect(M.count(stream.id)).toBe(1) + + await publishTestMessages() + let t + let expectedLength + const received = [] + try { + for await (const m of sub) { + received.push(m.getParsedContent()) + // after first message schedule end + if (received.length === 1) { + // eslint-disable-next-line no-loop-func + t = setTimeout(() => { + expectedLength = received.length + // should not see any more messages after end + sub.cancel() + }) + } + } + } finally { + clearTimeout(t) + } + // gets some messages but not all + expect(received).toHaveLength(expectedLength) + expect(unsubscribeEvents).toHaveLength(1) + }) + + it('can kill stream with throw', async () => { + const unsubscribeEvents = [] + client.connection.on(ControlMessage.TYPES.UnsubscribeResponse, (m) => { + unsubscribeEvents.push(m) + }) + + const sub = await M.subscribe(stream.id) + expect(M.count(stream.id)).toBe(1) + + await publishTestMessages() + + const err = new Error('expected error') + const received = [] + await expect(async () => { + for await (const m of sub) { + received.push(m.getParsedContent()) + // after first message schedule end + if (received.length === 1) { + throw err + } + } + }).rejects.toThrow(err) + // gets some messages but not all + expect(received).toHaveLength(1) + expect(unsubscribeEvents).toHaveLength(1) + }) + + it('can subscribe to stream multiple times, get updates then unsubscribe', async () => { + const send = jest.spyOn(M.client.connection, 'send') + const sub1 = await M.subscribe(stream.id) + const sub2 = await M.subscribe(stream.id) + + expect(M.count(stream.id)).toBe(2) + + const published = await publishTestMessages() + + const [received1, received2] = await Promise.all([ + collect(sub1, async ({ received, iterator }) => { + if (received.length === published.length) { + await iterator.return() + } + }), + collect(sub2, async ({ received, iterator }) => { + if (received.length === published.length) { + await iterator.return() + } + }) + ]) + + expect(received1).toEqual(published) + expect(received2).toEqual(received1) + + // subscribed once + expect(send.mock.calls.filter(([msg]) => ( + msg.type === ControlMessage.TYPES.SubscribeRequest + ))).toHaveLength(1) + }) + + it('can subscribe to stream multiple times in parallel, get updates then unsubscribe', async () => { + const send = jest.spyOn(M.client.connection, 'send') + const [sub1, sub2] = await Promise.all([ + M.subscribe(stream.id), + M.subscribe(stream.id), + ]) + + expect(M.count(stream.id)).toBe(2) + const published = await publishTestMessages() + + const [received1, received2] = await Promise.all([ + collect(sub1, async ({ received, iterator }) => { + if (received.length === published.length) { + await iterator.return() + } + }), + collect(sub2, async ({ received, iterator }) => { + if (received.length === published.length) { + await iterator.return() + } + }) + ]) + + expect(received1).toEqual(published) + expect(received2).toEqual(received1) + + // subscribed once + expect(send.mock.calls.filter(([msg]) => ( + msg.type === ControlMessage.TYPES.SubscribeRequest + ))).toHaveLength(1) + }) + + it('can subscribe to stream and get some updates then unsubscribe mid-stream with end', async () => { + const sub = await M.subscribe(stream.id) + expect(M.count(stream.id)).toBe(1) + + const published = await publishTestMessages() + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === 1) { + await sub.cancel() + } + } + + expect(received).toEqual(published.slice(0, 1)) + expect(M.count(stream.id)).toBe(0) + }) + + it('finishes unsubscribe before returning', async () => { + const unsubscribeEvents = [] + client.connection.on(ControlMessage.TYPES.UnsubscribeResponse, (m) => { + unsubscribeEvents.push(m) + }) + + const sub = await M.subscribe(stream.id) + + const published = await publishTestMessages() + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === MAX_ITEMS) { + expect(unsubscribeEvents).toHaveLength(0) + await sub.return() + expect(unsubscribeEvents).toHaveLength(1) + expect(M.count(stream.id)).toBe(0) + } + } + expect(received).toHaveLength(MAX_ITEMS) + expect(received).toEqual(published.slice(0, MAX_ITEMS)) + }) + + it('finishes unsubscribe before returning from cancel', async () => { + const unsubscribeEvents = [] + client.connection.on(ControlMessage.TYPES.UnsubscribeResponse, (m) => { + unsubscribeEvents.push(m) + }) + + const sub = await M.subscribe(stream.id) + + const published = await publishTestMessages() + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === MAX_ITEMS) { + expect(unsubscribeEvents).toHaveLength(0) + await sub.cancel() + expect(unsubscribeEvents).toHaveLength(1) + expect(M.count(stream.id)).toBe(0) + } + } + expect(received).toHaveLength(MAX_ITEMS) + expect(received).toEqual(published.slice(0, MAX_ITEMS)) + }) + + it('can cancel + return and it will wait for unsubscribe', async () => { + const unsubscribeEvents = [] + client.connection.on(ControlMessage.TYPES.UnsubscribeResponse, (m) => { + unsubscribeEvents.push(m) + }) + + const sub = await M.subscribe(stream.id) + + const published = await publishTestMessages() + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === MAX_ITEMS) { + expect(unsubscribeEvents).toHaveLength(0) + const tasks = [ + sub.return(), + sub.cancel(), + ] + await Promise.race(tasks) + expect(unsubscribeEvents).toHaveLength(1) + await Promise.all(tasks) + expect(unsubscribeEvents).toHaveLength(1) + expect(M.count(stream.id)).toBe(0) + } + } + expect(received).toHaveLength(MAX_ITEMS) + expect(received).toEqual(published.slice(0, MAX_ITEMS)) + }) + + it('can cancel multiple times and it will wait for unsubscribe', async () => { + const unsubscribeEvents = [] + client.connection.on(ControlMessage.TYPES.UnsubscribeResponse, (m) => { + unsubscribeEvents.push(m) + }) + + const sub = await M.subscribe(stream.id) + + const published = await publishTestMessages() + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === MAX_ITEMS) { + expect(unsubscribeEvents).toHaveLength(0) + const tasks = [ + sub.cancel(), + sub.cancel(), + sub.cancel(), + ] + await Promise.race(tasks) + expect(unsubscribeEvents).toHaveLength(1) + await Promise.all(tasks) + expect(unsubscribeEvents).toHaveLength(1) + expect(M.count(stream.id)).toBe(0) + } + } + expect(received).toHaveLength(MAX_ITEMS) + expect(received).toEqual(published.slice(0, MAX_ITEMS)) + }) + + it('will clean up if iterator returned before start', async () => { + const unsubscribeEvents = [] + client.connection.on(ControlMessage.TYPES.UnsubscribeResponse, (m) => { + unsubscribeEvents.push(m) + }) + + const sub = await M.subscribe(stream.id) + expect(M.count(stream.id)).toBe(1) + await sub.return() + expect(M.count(stream.id)).toBe(0) + + await publishTestMessages() + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + } + expect(received).toHaveLength(0) + expect(unsubscribeEvents).toHaveLength(1) + + expect(M.count(stream.id)).toBe(0) + }) + + it('can subscribe then unsubscribe in parallel', async () => { + const unsubscribeEvents = [] + client.connection.on(ControlMessage.TYPES.UnsubscribeResponse, (m) => { + unsubscribeEvents.push(m) + }) + + const [sub] = await Promise.all([ + M.subscribe(stream.id), + M.unsubscribe(stream.id), + ]) + + expect(M.count(stream.id)).toBe(0) + + await publishTestMessages() + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + } + + // shouldn't get any messages + expect(received).toHaveLength(0) + expect(unsubscribeEvents).toHaveLength(0) + expect(M.count(stream.id)).toBe(0) + }) + }) + + describe('mid-stream stop methods', () => { + let sub1 + let sub2 + let published + + beforeEach(async () => { + sub1 = await M.subscribe(stream.id) + sub2 = await M.subscribe(stream.id) + published = await publishTestMessages(5) + }) + + it('can subscribe to stream multiple times then unsubscribe all mid-stream', async () => { + let sub1Received + let sub1ReceivedAtUnsubscribe + const gotOne = Defer() + const [received1, received2] = await Promise.all([ + collect(sub1, async ({ received }) => { + sub1Received = received + gotOne.resolve() + }), + collect(sub2, async ({ received }) => { + await gotOne + if (received.length === MAX_ITEMS) { + sub1ReceivedAtUnsubscribe = sub1Received.slice() + await M.unsubscribe(stream.id) + } + }), + ]) + expect(received2).toEqual(published.slice(0, MAX_ITEMS)) + expect(received1).toEqual(published.slice(0, sub1ReceivedAtUnsubscribe.length)) + expect(sub1ReceivedAtUnsubscribe).toEqual(sub1Received) + expect(M.count(stream.id)).toBe(0) + }) + + it('can subscribe to stream multiple times then unsubscribe one mid-stream', async () => { + let sub2ReceivedAtUnsubscribe + const [received1, received2] = await Promise.all([ + collect(sub1, async ({ received, iterator }) => { + if (received.length === published.length) { + await iterator.return() + } + }), + collect(sub2, async ({ received }) => { + if (received.length === MAX_ITEMS) { + sub2ReceivedAtUnsubscribe = received.slice() + await sub2.unsubscribe() + } + }), + ]) + expect(received2).toEqual(published.slice(0, MAX_ITEMS)) + expect(received1).toEqual(published) + expect(sub2ReceivedAtUnsubscribe).toEqual(received2) + expect(M.count(stream.id)).toBe(0) + }) + + it('can subscribe to stream multiple times then return mid-stream', async () => { + const [received1, received2] = await Promise.all([ + collect(sub1, async ({ received, iterator }) => { + if (received.length === MAX_ITEMS - 1) { + await iterator.return() + } + }), + collect(sub2, async ({ received, iterator }) => { + if (received.length === MAX_ITEMS) { + await iterator.return() + } + }), + ]) + + expect(received1).toEqual(published.slice(0, MAX_ITEMS - 1)) + expect(received2).toEqual(published.slice(0, MAX_ITEMS)) + expect(M.count(stream.id)).toBe(0) + }) + }) +}) diff --git a/test/integration/SubscriberResends.test.js b/test/integration/SubscriberResends.test.js new file mode 100644 index 000000000..5193dcfe9 --- /dev/null +++ b/test/integration/SubscriberResends.test.js @@ -0,0 +1,497 @@ +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 Connection from '../../src/Connection' +import { Defer } from '../../src/utils' + +import config from './config' + +const { ControlMessage } = ControlLayer + +/* eslint-disable no-await-in-loop */ + +const WAIT_FOR_STORAGE_TIMEOUT = process.env.CI ? 12000 : 6000 +const MAX_MESSAGES = 5 + +describeRepeats('resends', () => { + let expectErrors = 0 // check no errors by default + let onError = jest.fn() + let client + let stream + let published + let publishedRequests + let publishTestMessages + let waitForStorage + let subscriber + + const createClient = (opts = {}) => { + const c = new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: fakePrivateKey(), + }, + publishAutoDisconnectDelay: 10, + autoConnect: false, + autoDisconnect: false, + maxRetries: 2, + ...opts, + }) + c.onError = jest.fn() + c.on('error', onError) + return c + } + + beforeAll(async () => { + client = createClient() + subscriber = client.subscriber + + // eslint-disable-next-line require-atomic-updates + client.debug('connecting before test >>') + await Promise.all([ + client.connect(), + client.session.getSessionToken(), + ]) + stream = await client.createStream({ + name: uid('stream') + }) + client.debug('connecting before test <<') + + publishTestMessages = getPublishTestMessages(client, { + stream, + }) + + waitForStorage = getWaitForStorage(client, { + stream, + timeout: WAIT_FOR_STORAGE_TIMEOUT, + }) + }, WAIT_FOR_STORAGE_TIMEOUT * 2) + + beforeEach(async () => { + await client.connect() + expectErrors = 0 + onError = jest.fn() + }) + + afterEach(async () => { + await wait() + // ensure no unexpected errors + expect(onError).toHaveBeenCalledTimes(expectErrors) + if (client) { + expect(client.onError).toHaveBeenCalledTimes(expectErrors) + } + }) + + afterEach(async () => { + await wait(500) + if (client) { + client.debug('disconnecting after test') + await client.disconnect() + } + + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + await Connection.closeOpen() + throw new Error(`sockets not closed: ${openSockets}`) + } + }) + + describe('no data', () => { + let emptyStream + + it('throws error if bad stream id', async () => { + await expect(async () => { + await subscriber.resend({ + streamId: 'badstream', + last: 5, + }) + }).rejects.toThrow('badstream') + }) + + it('throws error if no resend config', async () => { + emptyStream = await client.createStream({ + name: uid('stream') + }) + await expect(async () => { + await subscriber.resend({ + streamId: emptyStream.id, + resend: {}, + }) + }).rejects.toThrow('without resend options') + }) + + it('handles nothing to resend', async () => { + emptyStream = await client.createStream({ + name: uid('stream') + }) + + const sub = await subscriber.resend({ + streamId: emptyStream.id, + last: 5, + }) + + const onResent = jest.fn() + sub.on('resent', onResent) + + const receivedMsgs = await sub.collect() + expect(receivedMsgs).toHaveLength(0) + expect(onResent).toHaveBeenCalledTimes(1) + expect(subscriber.count(emptyStream.id)).toBe(0) + }) + + it('resendSubscribe with nothing to resend', async () => { + emptyStream = await client.createStream({ + name: uid('stream') + }) + + const sub = await subscriber.resendSubscribe({ + streamId: emptyStream.id, + last: 5, + }) + + const onResent = jest.fn() + sub.on('resent', onResent) + + expect(subscriber.count(emptyStream.id)).toBe(1) + const msg = Msg() + // eslint-disable-next-line no-await-in-loop + await client.publish(emptyStream.id, msg) + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + setTimeout(() => { + sub.cancel() + }, 250) + } + + expect(onResent).toHaveBeenCalledTimes(1) + expect(received).toEqual([msg]) + expect(subscriber.count(emptyStream.id)).toBe(0) + }) + }) + + describe('with resend data', () => { + beforeAll(async () => { + await client.connect() + }) + + beforeAll(async () => { + const results = await publishTestMessages.raw(MAX_MESSAGES, { + waitForLast: true, + }) + published = results.map(([msg]) => msg) + publishedRequests = results.map(([, req]) => req) + }, WAIT_FOR_STORAGE_TIMEOUT * 2) + + beforeEach(async () => { + await client.connect() + // ensure last message is in storage + const lastRequest = publishedRequests[publishedRequests.length - 1] + await waitForStorage(lastRequest) + }, WAIT_FOR_STORAGE_TIMEOUT * 1.2) + + it('requests resend', async () => { + const sub = await subscriber.resend({ + streamId: stream.id, + last: published.length, + }) + + const onResent = jest.fn() + sub.on('resent', onResent) + + const receivedMsgs = await sub.collect() + expect(receivedMsgs).toHaveLength(published.length) + expect(receivedMsgs).toEqual(published) + expect(subscriber.count(stream.id)).toBe(0) + expect(onResent).toHaveBeenCalledTimes(1) + }) + + it('requests resend number', async () => { + const sub = await subscriber.resend({ + streamId: stream.id, + last: 2, + }) + + const onResent = jest.fn() + sub.on('resent', onResent) + + const receivedMsgs = await sub.collect() + expect(receivedMsgs).toHaveLength(2) + expect(receivedMsgs).toEqual(published.slice(-2)) + expect(subscriber.count(stream.id)).toBe(0) + expect(onResent).toHaveBeenCalledTimes(1) + }) + + it('closes stream', async () => { + const sub = await subscriber.resend({ + streamId: stream.id, + last: published.length, + }) + + const onResent = jest.fn() + sub.on('resent', onResent) + + const received = [] + for await (const m of sub) { + received.push(m) + } + + expect(received).toHaveLength(published.length) + expect(subscriber.count(stream.id)).toBe(0) + expect(sub.msgStream.isReadable()).toBe(false) + expect(onResent).toHaveBeenCalledTimes(1) + }) + + it('closes connection with autoDisconnect', async () => { + client.connection.enableAutoConnect() + client.connection.enableAutoDisconnect(0) // set 0 delay + const sub = await subscriber.resend({ + streamId: stream.id, + last: published.length, + }) + + const onResent = jest.fn() + sub.on('resent', onResent) + + const received = [] + for await (const m of sub) { + received.push(m) + } + + await wait(100) // wait for publish delay + + expect(client.connection.getState()).toBe('disconnected') + expect(subscriber.count(stream.id)).toBe(0) + expect(sub.msgStream.isReadable()).toBe(false) + expect(received).toHaveLength(published.length) + expect(onResent).toHaveBeenCalledTimes(1) + }) + + describe('resendSubscribe', () => { + it('sees resends and realtime', async () => { + const sub = await subscriber.resendSubscribe({ + streamId: stream.id, + last: published.length, + }) + + const onResent = Defer() + const publishedBefore = published.slice() + const receivedMsgs = [] + + sub.on('resent', onResent.wrap(() => { + expect(receivedMsgs).toEqual(publishedBefore) + })) + + const newMessage = Msg() + // eslint-disable-next-line no-await-in-loop + const req = await client.publish(stream.id, newMessage) // should be realtime + published.push(newMessage) + publishedRequests.push(req) + let t + for await (const msg of sub) { + receivedMsgs.push(msg.getParsedContent()) + if (receivedMsgs.length === published.length) { + await sub.return() + clearTimeout(t) + t = setTimeout(() => { + // await wait() // give resent event a chance to fire + onResent.reject(new Error('resent never called')) + }, 250) + } + } + + await onResent + clearTimeout(t) + + expect(receivedMsgs).toHaveLength(published.length) + expect(receivedMsgs).toEqual(published) + expect(subscriber.count(stream.id)).toBe(0) + expect(sub.realtime.isReadable()).toBe(false) + expect(sub.realtime.isWritable()).toBe(false) + expect(sub.resend.isReadable()).toBe(false) + expect(sub.resend.isWritable()).toBe(false) + }) + + it('sees resends and realtime again', async () => { + const sub = await subscriber.resendSubscribe({ + streamId: stream.id, + last: published.length, + }) + + const onResent = jest.fn() + sub.on('resent', onResent) + + const message = Msg() + // eslint-disable-next-line no-await-in-loop + const req = await client.publish(stream.id, message) // should be realtime + published.push(message) + publishedRequests.push(req) + const receivedMsgs = await collect(sub, async ({ received }) => { + if (received.length === published.length) { + await sub.return() + } + }) + + const msgs = receivedMsgs + expect(msgs).toHaveLength(published.length) + expect(msgs).toEqual(published) + expect(subscriber.count(stream.id)).toBe(0) + expect(sub.realtime.isReadable()).toBe(false) + expect(sub.realtime.isWritable()).toBe(false) + expect(sub.resend.isReadable()).toBe(false) + expect(sub.resend.isWritable()).toBe(false) + expect(onResent).toHaveBeenCalledTimes(1) + }) + + it('sees resends when no realtime', async () => { + const sub = await subscriber.resendSubscribe({ + streamId: stream.id, + last: published.length, + }) + + const onResent = Defer() + const publishedBefore = published.slice() + const receivedMsgs = [] + + sub.once('resent', onResent.wrap(() => { + expect(receivedMsgs).toEqual(publishedBefore) + })) + + for await (const msg of sub) { + receivedMsgs.push(msg.getParsedContent()) + if (receivedMsgs.length === published.length) { + await sub.return() + } + } + + await onResent + + expect(receivedMsgs).toHaveLength(published.length) + expect(receivedMsgs).toEqual(published) + expect(subscriber.count(stream.id)).toBe(0) + expect(sub.realtime.isReadable()).toBe(false) + expect(sub.realtime.isWritable()).toBe(false) + expect(sub.resend.isReadable()).toBe(false) + expect(sub.resend.isWritable()).toBe(false) + }) + + it('ends resend if unsubscribed', async () => { + const sub = await subscriber.resendSubscribe({ + streamId: stream.id, + last: published.length, + }) + + const message = Msg() + // eslint-disable-next-line no-await-in-loop + const req = await client.publish(stream.id, message) // should be realtime + published.push(message) + publishedRequests.push(req) + const receivedMsgs = await collect(sub, async ({ received }) => { + if (received.length === published.length) { + await sub.return() + } + }) + + const msgs = receivedMsgs + expect(msgs).toHaveLength(published.length) + expect(msgs).toEqual(published) + expect(subscriber.count(stream.id)).toBe(0) + expect(sub.realtime.isReadable()).toBe(false) + expect(sub.realtime.isWritable()).toBe(false) + expect(sub.resend.isReadable()).toBe(false) + expect(sub.resend.isWritable()).toBe(false) + }) + + it('can return before start', async () => { + const sub = await subscriber.resendSubscribe({ + streamId: stream.id, + last: published.length, + }) + + expect(subscriber.count(stream.id)).toBe(1) + const message = Msg() + + await sub.return() + // eslint-disable-next-line no-await-in-loop + const req = await client.publish(stream.id, message) // should be realtime + published.push(message) + publishedRequests.push(req) + const received = [] + for await (const m of sub) { + received.push(m) + } + + expect(received).toHaveLength(0) + expect(subscriber.count(stream.id)).toBe(0) + expect(sub.realtime.isReadable()).toBe(false) + expect(sub.resend.isWritable()).toBe(false) + }) + + it('can end asynchronously', async () => { + const sub = await subscriber.resendSubscribe({ + streamId: stream.id, + last: published.length, + }) + + const message = Msg() + // eslint-disable-next-line no-await-in-loop + const req = await client.publish(stream.id, message) // should be realtime + published.push(message) + publishedRequests.push(req) + + let t + let receivedMsgs + try { + receivedMsgs = await collect(sub, async ({ received }) => { + if (received.length === published.length) { + t = setTimeout(() => { + sub.cancel() + }) + } + }) + } finally { + clearTimeout(t) + } + + const msgs = receivedMsgs + expect(msgs).toHaveLength(published.length) + expect(msgs).toEqual(published) + expect(subscriber.count(stream.id)).toBe(0) + expect(sub.realtime.isReadable()).toBe(false) + expect(sub.resend.isWritable()).toBe(false) + }) + + it('can end inside resend', async () => { + const unsubscribeEvents = [] + client.connection.on(ControlMessage.TYPES.UnsubscribeResponse, (m) => { + unsubscribeEvents.push(m) + }) + const sub = await subscriber.resendSubscribe({ + streamId: stream.id, + last: published.length, + }) + + const message = Msg() + // eslint-disable-next-line no-await-in-loop + const req = await client.publish(stream.id, message) // should be realtime + published.push(message) + publishedRequests.push(req) + const END_AFTER = 3 + const receivedMsgs = await collect(sub, async ({ received }) => { + if (received.length === END_AFTER) { + await sub.cancel() + expect(unsubscribeEvents).toHaveLength(1) + } + }) + const msgs = receivedMsgs + expect(msgs).toHaveLength(END_AFTER) + expect(msgs).toEqual(published.slice(0, END_AFTER)) + expect(subscriber.count(stream.id)).toBe(0) + expect(sub.realtime.isReadable()).toBe(false) + expect(sub.resend.isWritable()).toBe(false) + }) + }) + }) +}) diff --git a/test/integration/Subscription.test.js b/test/integration/Subscription.test.js index 2c4209898..bdcd8dd17 100644 --- a/test/integration/Subscription.test.js +++ b/test/integration/Subscription.test.js @@ -1,23 +1,20 @@ -import { ethers } from 'ethers' -import { wait } from 'streamr-test-utils' +import { wait, waitForEvent } from 'streamr-test-utils' -import { uid } from '../utils' -import StreamrClient from '../../src' +import { uid, fakePrivateKey } from '../utils' +import { StreamrClient } from '../../src/StreamrClient' import config from './config' const createClient = (opts = {}) => new StreamrClient({ + ...config.clientOptions, auth: { - privateKey: ethers.Wallet.createRandom().privateKey, + privateKey: fakePrivateKey(), }, autoConnect: false, autoDisconnect: false, - ...config.clientOptions, ...opts, }) -const throwError = (error) => { throw error } - const RESEND_ALL = { from: { timestamp: 0, @@ -28,31 +25,11 @@ describe('Subscription', () => { let stream let client let subscription + let errors = [] + let expectedErrors = 0 - async function setup() { - client = createClient() - client.on('error', throwError) - stream = await client.createStream({ - name: uid('stream') - }) - } - - async function teardown() { - if (subscription) { - await client.unsubscribe(subscription) - subscription = undefined - } - - if (stream) { - await stream.delete() - stream = undefined - } - - if (client && client.isConnected()) { - await client.disconnect() - client.off('error', throwError) - client = undefined - } + function onError(err) { + errors.push(err) } /** @@ -60,10 +37,10 @@ describe('Subscription', () => { * Needs to create subscription at same time in order to track message events. */ - function createMonitoredSubscription(opts = {}) { + async function createMonitoredSubscription(opts = {}) { if (!client) { throw new Error('No client') } const events = [] - subscription = client.subscribe({ + subscription = await client.subscribe({ stream: stream.id, resend: RESEND_ALL, ...opts, @@ -71,9 +48,7 @@ describe('Subscription', () => { events.push(message) }) subscription.on('subscribed', () => events.push('subscribed')) - subscription.on('resending', () => events.push('resending')) subscription.on('resent', () => events.push('resent')) - subscription.on('no_resend', () => events.push('no_resend')) subscription.on('unsubscribed', () => events.push('unsubscribed')) subscription.on('error', () => events.push('error')) return events @@ -88,69 +63,72 @@ describe('Subscription', () => { } beforeEach(async () => { - await teardown() - await setup() + errors = [] + expectedErrors = 0 + client = createClient() + client.on('error', onError) + stream = await client.createStream({ + name: uid('stream') + }) + await client.connect() + }) + + afterEach(async () => { + expect(errors).toHaveLength(expectedErrors) }) afterEach(async () => { - await teardown() + if (!client) { return } + client.off('error', onError) + client.debug('disconnecting after test') + await client.disconnect() }) describe('subscribe/unsubscribe events', () => { - it('fires events in correct order', async (done) => { - const subscriptionEvents = createMonitoredSubscription() - subscription.on('subscribed', async () => { - subscription.on('unsubscribed', () => { - expect(subscriptionEvents).toEqual([ - 'subscribed', - 'unsubscribed', - ]) - done() - }) - await client.unsubscribe(subscription) - }) + it('fires events in correct order 1', async () => { + const subscriptionEvents = await createMonitoredSubscription() + await waitForEvent(subscription, 'resent') + await client.unsubscribe(stream) + expect(subscriptionEvents).toEqual([ + 'resent', + 'unsubscribed', + ]) + }) - await client.connect() + it('fires events in correct order 2', async () => { + const subscriptionEvents = await createMonitoredSubscription({ + resend: undefined, + }) + await client.unsubscribe(stream) + expect(subscriptionEvents).toEqual([ + 'unsubscribed', + ]) }) }) describe('resending/no_resend events', () => { - it('fires events in correct order', async (done) => { - const subscriptionEvents = createMonitoredSubscription() - subscription.on('no_resend', async () => { - await wait(0) - expect(subscriptionEvents).toEqual([ - 'subscribed', - 'no_resend', - ]) - done() - }) - - await client.connect() + it('fires events in correct order 1', async () => { + const subscriptionEvents = await createMonitoredSubscription() + await waitForEvent(subscription, 'resent') + expect(subscriptionEvents).toEqual([ + 'resent', + ]) }) }) describe('resending/resent events', () => { - it('fires events in correct order', async (done) => { - await client.connect() + it('fires events in correct order 1', async () => { const message1 = await publishMessage() const message2 = await publishMessage() await wait(5000) // wait for messages to (probably) land in storage - const subscriptionEvents = createMonitoredSubscription() - subscription.on('resent', async () => { - await wait(500) // wait in case messages appear after resent event - expect(subscriptionEvents).toEqual([ - 'subscribed', - 'resending', - message1, - message2, - 'resent', - ]) - done() - }) - subscription.on('no_resend', () => { - done('error: got no_resend, expected: resent') - }) + const subscriptionEvents = await createMonitoredSubscription() + await waitForEvent(subscription, 'resent') + await wait(500) // wait in case messages appear after resent event + expect(subscriptionEvents).toEqual([ + message1, + message2, + 'resent', + ]) }, 20 * 1000) }) }) diff --git a/test/integration/Validation.test.js b/test/integration/Validation.test.js new file mode 100644 index 000000000..bcefc8b0f --- /dev/null +++ b/test/integration/Validation.test.js @@ -0,0 +1,210 @@ +import { wait } from 'streamr-test-utils' + +import { uid, fakePrivateKey, describeRepeats, getPublishTestMessages } from '../utils' +import { StreamrClient } from '../../src/StreamrClient' +import Connection from '../../src/Connection' + +import config from './config' + +const MAX_MESSAGES = 10 + +describeRepeats('Validation', () => { + let expectErrors = 0 // check no errors by default + let publishTestMessages + let onError = jest.fn() + let client + let stream + let subscriber + + const createClient = (opts = {}) => { + const c = new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: fakePrivateKey(), + }, + autoConnect: false, + autoDisconnect: false, + maxRetries: 2, + ...opts, + }) + c.onError = jest.fn() + c.on('error', onError) + return c + } + + async function setupClient(opts) { + // eslint-disable-next-line require-atomic-updates + client = createClient(opts) + subscriber = client.subscriber + client.debug('connecting before test >>') + await client.session.getSessionToken() + stream = await client.createStream({ + requireSignedData: client.options.publishWithSignature !== 'never', + name: uid('stream') + }) + + client.debug('connecting before test <<') + publishTestMessages = getPublishTestMessages(client, stream.id) + return client + } + + beforeEach(async () => { + expectErrors = 0 + onError = jest.fn() + }) + + afterEach(() => { + if (!subscriber) { return } + expect(subscriber.count(stream.id)).toBe(0) + if (!client) { return } + expect(client.getSubscriptions(stream.id)).toEqual([]) + }) + + afterEach(async () => { + await wait() + // ensure no unexpected errors + expect(onError).toHaveBeenCalledTimes(expectErrors) + if (client) { + expect(client.onError).toHaveBeenCalledTimes(expectErrors) + } + }) + + afterEach(async () => { + await wait() + if (client) { + client.debug('disconnecting after test >>') + await client.disconnect() + client.debug('disconnecting after test <<') + } + + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + await Connection.closeOpen() + throw new Error(`sockets not closed: ${openSockets}`) + } + }) + + let subs = [] + + beforeEach(async () => { + const existingSubs = subs + subs = [] + await Promise.all(existingSubs.map((sub) => ( + sub.cancel() + ))) + }) + + describe('signature validation', () => { + beforeEach(async () => { + await setupClient({ + gapFillTimeout: 1000, + retryResendAfter: 1000, + }) + await client.connect() + }) + + it('subscribe fails gracefully when signature bad', async () => { + const sub = await client.subscribe(stream.id) + const onSubError = jest.fn((err) => { + expect(err).toBeInstanceOf(Error) + expect(err.message).toMatch('signature') + }) + sub.on('error', onSubError) + const { parse } = client.connection + let count = 0 + const BAD_INDEX = 2 + client.connection.parse = (...args) => { + const msg = parse.call(client.connection, ...args) + if (!msg.streamMessage) { + return msg + } + + if (count === BAD_INDEX) { + msg.streamMessage.signature = 'badsignature' + } + + count += 1 + return msg + } + + const published = await publishTestMessages(MAX_MESSAGES, { + timestamp: 111111, + }) + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === published.length - 1) { + break + } + } + const expectedMessages = [ + // remove bad message + ...published.slice(0, BAD_INDEX), + ...published.slice(BAD_INDEX + 1, MAX_MESSAGES) + ] + + expect(received).toEqual(expectedMessages) + expect(client.connection.getState()).toBe('connected') + expect(onSubError).toHaveBeenCalledTimes(1) + }, 10000) + }) + + describe('content parsing', () => { + beforeEach(async () => { + await setupClient({ + gapFillTimeout: 1000, + retryResendAfter: 1000, + publishWithSignature: 'never', + }) + await client.connect() + }) + + it('subscribe fails gracefully when content bad', async () => { + await client.connect() + const sub = await client.subscribe(stream.id) + const onSubError = jest.fn((err) => { + expect(err).toBeInstanceOf(Error) + expect(err.message).toMatch('JSON') + }) + + sub.on('error', onSubError) + const { parse } = client.connection + let count = 0 + const BAD_INDEX = 2 + client.connection.parse = (...args) => { + const msg = parse.call(client.connection, ...args) + if (!msg.streamMessage) { + return msg + } + + if (count === BAD_INDEX) { + msg.streamMessage.serializedContent = '{ badcontent' + } + + count += 1 + return msg + } + + const published = await publishTestMessages(MAX_MESSAGES, { + stream, + timestamp: 1111111, + }) + + const received = [] + for await (const m of sub) { + received.push(m.getParsedContent()) + if (received.length === published.length - 1) { + break + } + } + + expect(received).toEqual([ + ...published.slice(0, BAD_INDEX), + ...published.slice(BAD_INDEX + 1, MAX_MESSAGES) + ]) + expect(client.connection.getState()).toBe('connected') + expect(onSubError).toHaveBeenCalledTimes(1) + }, 10000) + }) +}) diff --git a/test/integration/authFetch.test.js b/test/integration/authFetch.test.js index 12caec830..bb699a7c2 100644 --- a/test/integration/authFetch.test.js +++ b/test/integration/authFetch.test.js @@ -1,9 +1,9 @@ jest.mock('node-fetch') -import { ethers } from 'ethers' import fetch from 'node-fetch' -import StreamrClient from '../../src' +import { StreamrClient } from '../../src/StreamrClient' +import { fakePrivateKey } from '../utils' import config from './config' @@ -27,7 +27,7 @@ describe('authFetch', () => { fetch.mockImplementation(realFetch) client = new StreamrClient({ auth: { - privateKey: ethers.Wallet.createRandom().privateKey, + privateKey: fakePrivateKey() }, autoConnect: false, autoDisconnect: false, diff --git a/test/integration/config.js b/test/integration/config.js index 27550eb05..72a4d7f86 100644 --- a/test/integration/config.js +++ b/test/integration/config.js @@ -1,12 +1,30 @@ module.exports = { clientOptions: { + // ganache 1: 0x4178baBE9E5148c6D5fd431cD72884B07Ad855a0 + auth: { + privateKey: process.env.ETHEREUM_PRIVATE_KEY || '0xe5af7834455b7239881b85be89d905d6881dcb4751063897f12be1b0dd546bdb', + }, url: process.env.WEBSOCKET_URL || 'ws://localhost/api/v1/ws', restUrl: process.env.REST_URL || 'http://localhost/api/v1', + streamrNodeAddress: '0xFCAd0B19bB29D4674531d6f115237E16AfCE377c', tokenAddress: process.env.TOKEN_ADDRESS || '0xbAA81A0179015bE47Ad439566374F2Bae098686F', - streamrNodeAddress: process.env.STREAMR_NODE_ADDRESS || '0xFCAd0B19bB29D4674531d6f115237E16AfCE377c', - streamrOperatorAddress: process.env.OPERATOR_ADDRESS || '0xa3d1F77ACfF0060F7213D7BF3c7fEC78df847De1', + tokenAddressSidechain: process.env.TOKEN_ADDRESS_SIDECHAIN || '0x73Be21733CC5D08e1a14Ea9a399fb27DB3BEf8fF', + 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, + }, + mainnet: { + url: process.env.ETHEREUM_SERVER_URL || 'http://10.200.10.1:8545', + timeout: process.env.TEST_TIMEOUT, + }, + autoConnect: false, + autoDisconnect: false, }, - ethereumServerUrl: process.env.ETHEREUM_SERVER_URL || 'http://localhost:8545', - // ganache 1: 0x4178baBE9E5148c6D5fd431cD72884B07Ad855a0 - privateKey: process.env.ETHEREUM_PRIVATE_KEY || '0xe5af7834455b7239881b85be89d905d6881dcb4751063897f12be1b0dd546bdb', + tokenAdminPrivateKey: '0x5e98cce00cff5dea6b454889f359a4ec06b9fa6b88e9d69b86de8e1c81887da0', } diff --git a/test/integration/dataunion/adminFee.test.ts b/test/integration/dataunion/adminFee.test.ts new file mode 100644 index 000000000..d4c273a0e --- /dev/null +++ b/test/integration/dataunion/adminFee.test.ts @@ -0,0 +1,80 @@ +import { Contract, providers, Wallet } from 'ethers' +import { parseEther, formatEther } from 'ethers/lib/utils' +import debug from 'debug' + +import { StreamrClient } from '../../../src/StreamrClient' +import * as Token from '../../../contracts/TestToken.json' +import config from '../config' + +const log = debug('StreamrClient::DataUnion::integration-test-adminFee') + +// @ts-expect-error +const providerSidechain = new providers.JsonRpcProvider(config.clientOptions.sidechain) +// @ts-expect-error +const providerMainnet = new providers.JsonRpcProvider(config.clientOptions.mainnet) +const adminWalletMainnet = new Wallet(config.clientOptions.auth.privateKey, providerMainnet) + +describe('DataUnion admin fee', () => { + let adminClient: StreamrClient + + const tokenAdminWallet = new Wallet(config.tokenAdminPrivateKey, providerMainnet) + const tokenMainnet = new Contract(config.clientOptions.tokenAddress, Token.abi, tokenAdminWallet) + + beforeAll(async () => { + log(`Connecting to Ethereum networks, config = ${JSON.stringify(config)}`) + const network = await providerMainnet.getNetwork() + log('Connected to "mainnet" network: ', JSON.stringify(network)) + const network2 = await providerSidechain.getNetwork() + log('Connected to sidechain network: ', JSON.stringify(network2)) + log(`Minting 100 tokens to ${adminWalletMainnet.address}`) + const tx1 = await tokenMainnet.mint(adminWalletMainnet.address, parseEther('100')) + await tx1.wait() + adminClient = new StreamrClient(config.clientOptions as any) + }, 10000) + + afterAll(() => { + providerMainnet.removeAllListeners() + providerSidechain.removeAllListeners() + }) + + it('can set admin fee', async () => { + const dataUnion = await adminClient.deployDataUnion() + const oldFee = await dataUnion.getAdminFee() + log(`DU owner: ${await dataUnion.getAdminAddress()}`) + log(`Sending tx from ${await adminClient.getAddress()}`) + const tr = await dataUnion.setAdminFee(0.1) + log(`Transaction receipt: ${JSON.stringify(tr)}`) + const newFee = await dataUnion.getAdminFee() + expect(oldFee).toEqual(0) + expect(newFee).toEqual(0.1) + }, 150000) + + it('receives admin fees', async () => { + const dataUnion = await adminClient.deployDataUnion() + const tr = await dataUnion.setAdminFee(0.1) + log(`Transaction receipt: ${JSON.stringify(tr)}`) + + const amount = parseEther('2') + // eslint-disable-next-line no-underscore-dangle + const contract = await dataUnion._getContract() + const tokenAddress = await contract.token() + const adminTokenMainnet = new Contract(tokenAddress, Token.abi, adminWalletMainnet) + + log(`Transferring ${amount} token-wei ${adminWalletMainnet.address}->${dataUnion.getAddress()}`) + const txTokenToDU = await adminTokenMainnet.transfer(dataUnion.getAddress(), amount) + await txTokenToDU.wait() + + const balance1 = await adminTokenMainnet.balanceOf(adminWalletMainnet.address) + log(`Token balance of ${adminWalletMainnet.address}: ${formatEther(balance1)} (${balance1.toString()})`) + + log(`Transferred ${formatEther(amount)} tokens, next sending to bridge`) + const tx2 = await contract.sendTokensToBridge() + await tx2.wait() + + const balance2 = await adminTokenMainnet.balanceOf(adminWalletMainnet.address) + log(`Token balance of ${adminWalletMainnet.address}: ${formatEther(balance2)} (${balance2.toString()})`) + + expect(formatEther(balance2.sub(balance1))).toEqual('0.2') + }, 150000) + +}) diff --git a/test/integration/dataunion/calculate.test.ts b/test/integration/dataunion/calculate.test.ts new file mode 100644 index 000000000..cba46a0e4 --- /dev/null +++ b/test/integration/dataunion/calculate.test.ts @@ -0,0 +1,51 @@ +import { providers, Wallet } from 'ethers' +import debug from 'debug' + +import { StreamrClient } from '../../../src/StreamrClient' +import config from '../config' +import { createClient, expectInvalidAddress } from '../../utils' + +const log = debug('StreamrClient::DataUnion::integration-test-calculate') + +// @ts-expect-error +const providerSidechain = new providers.JsonRpcProvider(config.clientOptions.sidechain) +// @ts-expect-error +const providerMainnet = new providers.JsonRpcProvider(config.clientOptions.mainnet) +const adminWalletMainnet = new Wallet(config.clientOptions.auth.privateKey, providerMainnet) + +// This test will fail when new docker images are pushed with updated DU smart contracts +// -> generate new codehashes for getDataUnionMainnetAddress() and getDataUnionSidechainAddress() + +describe('DataUnion calculate', () => { + + afterAll(() => { + providerMainnet.removeAllListeners() + providerSidechain.removeAllListeners() + }) + + it('calculate DU address before deployment', async () => { + log(`Connecting to Ethereum networks, config = ${JSON.stringify(config)}`) + const network = await providerMainnet.getNetwork() + log('Connected to "mainnet" network: ', JSON.stringify(network)) + const network2 = await providerSidechain.getNetwork() + log('Connected to sidechain network: ', JSON.stringify(network2)) + + const adminClient = new StreamrClient(config.clientOptions as any) + + const dataUnionName = 'test-' + Date.now() + // eslint-disable-next-line no-underscore-dangle + const dataUnionPredicted = adminClient._getDataUnionFromName({ dataUnionName, deployerAddress: adminWalletMainnet.address }) + + const dataUnionDeployed = await adminClient.deployDataUnion({ dataUnionName }) + const version = await dataUnionDeployed.getVersion() + + expect(dataUnionPredicted.getAddress()).toBe(dataUnionDeployed.getAddress()) + expect(dataUnionPredicted.getSidechainAddress()).toBe(dataUnionDeployed.getSidechainAddress()) + expect(version).toBe(2) + }, 60000) + + it('get DataUnion: invalid address', () => { + const client = createClient(providerSidechain) + return expectInvalidAddress(async () => client.getDataUnion('invalid-address')) + }) +}) diff --git a/test/integration/dataunion/deploy.test.ts b/test/integration/dataunion/deploy.test.ts new file mode 100644 index 000000000..123f273fa --- /dev/null +++ b/test/integration/dataunion/deploy.test.ts @@ -0,0 +1,52 @@ +import { providers } from 'ethers' +import debug from 'debug' + +import { StreamrClient } from '../../../src/StreamrClient' +import config from '../config' +import { createMockAddress } from '../../utils' + +const log = debug('StreamrClient::DataUnion::integration-test-deploy') + +// @ts-expect-error +const providerSidechain = new providers.JsonRpcProvider(config.clientOptions.sidechain) +// @ts-expect-error +const providerMainnet = new providers.JsonRpcProvider(config.clientOptions.mainnet) + +describe('DataUnion deploy', () => { + + let adminClient: StreamrClient + + beforeAll(async () => { + log(`Connecting to Ethereum networks, config = ${JSON.stringify(config)}`) + const network = await providerMainnet.getNetwork() + log('Connected to "mainnet" network: ', JSON.stringify(network)) + const network2 = await providerSidechain.getNetwork() + log('Connected to sidechain network: ', JSON.stringify(network2)) + adminClient = new StreamrClient(config.clientOptions as any) + }, 60000) + + afterAll(() => { + providerMainnet.removeAllListeners() + providerSidechain.removeAllListeners() + }) + + describe('owner', () => { + + it('not specified: defaults to deployer', async () => { + const dataUnion = await adminClient.deployDataUnion() + expect(await dataUnion.getAdminAddress()).toBe(await adminClient.getAddress()) + }, 60000) + + it('specified', async () => { + const owner = createMockAddress() + const dataUnion = await adminClient.deployDataUnion({ owner }) + expect(await dataUnion.getAdminAddress()).toBe(owner) + }, 60000) + + it('invalid', () => { + return expect(() => adminClient.deployDataUnion({ owner: 'foobar' })).rejects.toThrow('invalid address') + }, 60000) + + }) +}) + diff --git a/test/integration/dataunion/member.test.ts b/test/integration/dataunion/member.test.ts new file mode 100644 index 000000000..53c445e4e --- /dev/null +++ b/test/integration/dataunion/member.test.ts @@ -0,0 +1,110 @@ +import { providers, Wallet } from 'ethers' +import debug from 'debug' + +import { StreamrClient } from '../../../src/StreamrClient' +import config from '../config' +import { DataUnion, JoinRequestState } from '../../../src/dataunion/DataUnion' +import { createMockAddress, expectInvalidAddress, fakePrivateKey } from '../../utils' +import authFetch from '../../../src/rest/authFetch' +import { getEndpointUrl } from '../../../src/utils' + +const log = debug('StreamrClient::DataUnion::integration-test-member') + +// @ts-expect-error +const providerSidechain = new providers.JsonRpcProvider(config.clientOptions.sidechain) +// @ts-expect-error +const providerMainnet = new providers.JsonRpcProvider(config.clientOptions.mainnet) + +const joinMember = async (memberWallet: Wallet, secret: string|undefined, dataUnionAddress: string) => { + const memberClient = new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: memberWallet.privateKey, + } + } as any) + return memberClient.getDataUnion(dataUnionAddress).join(secret) +} + +describe('DataUnion member', () => { + + let dataUnion: DataUnion + let secret: string + + beforeAll(async () => { + log(`Connecting to Ethereum networks, config = ${JSON.stringify(config)}`) + const network = await providerMainnet.getNetwork() + log('Connected to "mainnet" network: ', JSON.stringify(network)) + const network2 = await providerSidechain.getNetwork() + log('Connected to sidechain network: ', JSON.stringify(network2)) + const adminClient = new StreamrClient(config.clientOptions as any) + dataUnion = await adminClient.deployDataUnion() + // product is needed for join requests to analyze the DU version + const createProductUrl = getEndpointUrl(config.clientOptions.restUrl, 'products') + await authFetch( + createProductUrl, + adminClient.session, + { + method: 'POST', + body: JSON.stringify({ + beneficiaryAddress: dataUnion.getAddress(), + type: 'DATAUNION', + dataUnionVersion: 2 + }) + } + ) + secret = await dataUnion.createSecret() + }, 60000) + + afterAll(() => { + providerMainnet.removeAllListeners() + providerSidechain.removeAllListeners() + }) + + it('random user is not a member', async () => { + const userAddress = createMockAddress() + const isMember = await dataUnion.isMember(userAddress) + expect(isMember).toBe(false) + }, 60000) + + it('join with valid secret', async () => { + const memberWallet = new Wallet(fakePrivateKey()) + await joinMember(memberWallet, secret, dataUnion.getAddress()) + const isMember = await dataUnion.isMember(memberWallet.address) + expect(isMember).toBe(true) + }, 60000) + + it('join with invalid secret', async () => { + const memberWallet = new Wallet(fakePrivateKey()) + return expect(() => joinMember(memberWallet, 'invalid-secret', dataUnion.getAddress())).rejects.toThrow('Incorrect data union secret') + }, 60000) + + it('join without secret', async () => { + const memberWallet = new Wallet(fakePrivateKey()) + const response = await joinMember(memberWallet, undefined, dataUnion.getAddress()) + expect(response.id).toBeDefined() + expect(response.state).toBe(JoinRequestState.PENDING) + }, 60000) + + it('add', async () => { + const userAddress = createMockAddress() + await dataUnion.addMembers([userAddress]) + const isMember = await dataUnion.isMember(userAddress) + expect(isMember).toBe(true) + }, 60000) + + it('remove', async () => { + const userAddress = createMockAddress() + await dataUnion.addMembers([userAddress]) + await dataUnion.removeMembers([userAddress]) + const isMember = await dataUnion.isMember(userAddress) + expect(isMember).toBe(false) + }, 60000) + + it('invalid address', () => { + return Promise.all([ + expectInvalidAddress(() => dataUnion.addMembers(['invalid-address'])), + expectInvalidAddress(() => dataUnion.removeMembers(['invalid-address'])), + expectInvalidAddress(() => dataUnion.isMember('invalid-address')) + ]) + }) +}) diff --git a/test/integration/dataunion/signature.test.ts b/test/integration/dataunion/signature.test.ts new file mode 100644 index 000000000..9f655e856 --- /dev/null +++ b/test/integration/dataunion/signature.test.ts @@ -0,0 +1,78 @@ +import { Contract, providers, Wallet } from 'ethers' +import { parseEther } from 'ethers/lib/utils' +import debug from 'debug' + +import { getEndpointUrl } from '../../../src/utils' +import { StreamrClient } from '../../../src/StreamrClient' +import * as Token from '../../../contracts/TestToken.json' +import * as DataUnionSidechain from '../../../contracts/DataUnionSidechain.json' +import config from '../config' +import authFetch from '../../../src/rest/authFetch' + +const log = debug('StreamrClient::DataUnion::integration-test-signature') + +// @ts-expect-error +const providerSidechain = new providers.JsonRpcProvider(config.clientOptions.sidechain) +const adminWalletSidechain = new Wallet(config.clientOptions.auth.privateKey, providerSidechain) + +describe('DataUnion signature', () => { + + afterAll(() => { + providerSidechain.removeAllListeners() + }) + + it('check validity', async () => { + const adminClient = new StreamrClient(config.clientOptions as any) + const dataUnion = await adminClient.deployDataUnion() + const secret = await dataUnion.createSecret('test secret') + log(`DataUnion ${dataUnion.getAddress()} is ready to roll`) + + const memberWallet = new Wallet(`0x100000000000000000000000000000000000000012300000001${Date.now()}`, providerSidechain) + const member2Wallet = new Wallet(`0x100000000000000000000000000000000000000012300000002${Date.now()}`, providerSidechain) + + const memberClient = new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: memberWallet.privateKey + } + } as any) + + // product is needed for join requests to analyze the DU version + const createProductUrl = getEndpointUrl(config.clientOptions.restUrl, 'products') + await authFetch(createProductUrl, adminClient.session, { + method: 'POST', + body: JSON.stringify({ + beneficiaryAddress: dataUnion.getAddress(), + type: 'DATAUNION', + dataUnionVersion: 2 + }) + }) + await memberClient.getDataUnion(dataUnion.getAddress()).join(secret) + + // eslint-disable-next-line no-underscore-dangle + const contract = await dataUnion._getContract() + const sidechainContract = new Contract(contract.sidechain.address, DataUnionSidechain.abi, adminWalletSidechain) + const tokenSidechain = new Contract(config.clientOptions.tokenAddressSidechain, Token.abi, adminWalletSidechain) + + const signature = await memberClient.getDataUnion(dataUnion.getAddress()).signWithdrawAllTo(member2Wallet.address) + const signature2 = await memberClient + .getDataUnion(dataUnion.getAddress()) + .signWithdrawAmountTo(member2Wallet.address, parseEther('1')) + const signature3 = await memberClient + .getDataUnion(dataUnion.getAddress()) + .signWithdrawAmountTo(member2Wallet.address, 3000000000000000) // 0.003 tokens + + const isValid = await sidechainContract.signatureIsValid(memberWallet.address, member2Wallet.address, '0', signature) // '0' = all earnings + const isValid2 = await sidechainContract.signatureIsValid(memberWallet.address, member2Wallet.address, parseEther('1'), signature2) + const isValid3 = await sidechainContract.signatureIsValid(memberWallet.address, member2Wallet.address, '3000000000000000', signature3) + log(`Signature for all tokens ${memberWallet.address} -> ${member2Wallet.address}: ${signature}, checked ${isValid ? 'OK' : '!!!BROKEN!!!'}`) + log(`Signature for 1 token ${memberWallet.address} -> ${member2Wallet.address}: ${signature2}, checked ${isValid2 ? 'OK' : '!!!BROKEN!!!'}`) + // eslint-disable-next-line max-len + log(`Signature for 0.003 tokens ${memberWallet.address} -> ${member2Wallet.address}: ${signature3}, checked ${isValid3 ? 'OK' : '!!!BROKEN!!!'}`) + log(`sidechainDU(${sidechainContract.address}) token bal ${await tokenSidechain.balanceOf(sidechainContract.address)}`) + + expect(isValid).toBe(true) + expect(isValid2).toBe(true) + expect(isValid3).toBe(true) + }, 100000) +}) diff --git a/test/integration/dataunion/stats.test.ts b/test/integration/dataunion/stats.test.ts new file mode 100644 index 000000000..786181d35 --- /dev/null +++ b/test/integration/dataunion/stats.test.ts @@ -0,0 +1,103 @@ +import { providers } from 'ethers' +import debug from 'debug' + +import { StreamrClient } from '../../../src/StreamrClient' +import config from '../config' +import { DataUnion, MemberStatus } from '../../../src/dataunion/DataUnion' +import { createClient, createMockAddress, expectInvalidAddress } from '../../utils' +import { BigNumber } from '@ethersproject/bignumber' + +const log = debug('StreamrClient::DataUnion::integration-test-stats') + +// @ts-expect-error +const providerSidechain = new providers.JsonRpcProvider(config.clientOptions.sidechain) +// @ts-expect-error +const providerMainnet = new providers.JsonRpcProvider(config.clientOptions.mainnet) + +describe('DataUnion stats', () => { + + let adminClient: StreamrClient + let dataUnion: DataUnion + let queryClient: StreamrClient + const nonce = Date.now() + const activeMemberAddressList = [ + `0x100000000000000000000000000${nonce}`, + `0x200000000000000000000000000${nonce}`, + `0x300000000000000000000000000${nonce}`, + ] + const inactiveMember = createMockAddress() + + beforeAll(async () => { + log(`Connecting to Ethereum networks, config = ${JSON.stringify(config)}`) + const network = await providerMainnet.getNetwork() + log('Connected to "mainnet" network: ', JSON.stringify(network)) + const network2 = await providerSidechain.getNetwork() + log('Connected to sidechain network: ', JSON.stringify(network2)) + adminClient = new StreamrClient(config.clientOptions as any) + dataUnion = await adminClient.deployDataUnion() + await dataUnion.addMembers(activeMemberAddressList.concat([inactiveMember])) + await dataUnion.removeMembers([inactiveMember]) + queryClient = createClient(providerSidechain) + }, 60000) + + afterAll(() => { + providerMainnet.removeAllListeners() + providerSidechain.removeAllListeners() + }) + + it('DataUnion stats', async () => { + const stats = await queryClient.getDataUnion(dataUnion.getAddress()).getStats() + expect(stats.activeMemberCount).toEqual(BigNumber.from(3)) + expect(stats.inactiveMemberCount).toEqual(BigNumber.from(1)) + expect(stats.joinPartAgentCount).toEqual(BigNumber.from(2)) + expect(stats.totalEarnings).toEqual(BigNumber.from(0)) + expect(stats.totalWithdrawable).toEqual(BigNumber.from(0)) + expect(stats.lifetimeMemberEarnings).toEqual(BigNumber.from(0)) + }, 150000) + + it('member stats', async () => { + const memberStats = await Promise.all( + activeMemberAddressList + .concat([inactiveMember]) + .map((m) => queryClient.getDataUnion(dataUnion.getAddress()).getMemberStats(m)) + ) + + const ZERO = BigNumber.from(0) + expect(memberStats).toMatchObject([{ + status: MemberStatus.ACTIVE, + earningsBeforeLastJoin: ZERO, + totalEarnings: ZERO, + withdrawableEarnings: ZERO, + }, { + status: MemberStatus.ACTIVE, + earningsBeforeLastJoin: ZERO, + totalEarnings: ZERO, + withdrawableEarnings: ZERO, + }, { + status: MemberStatus.ACTIVE, + earningsBeforeLastJoin: ZERO, + totalEarnings: ZERO, + withdrawableEarnings: ZERO, + }, { + status: MemberStatus.INACTIVE, + earningsBeforeLastJoin: ZERO, + totalEarnings: ZERO, + withdrawableEarnings: ZERO, + }]) + }, 150000) + + it('member stats: no member', async () => { + const memberStats = await queryClient.getDataUnion(dataUnion.getAddress()).getMemberStats(createMockAddress()) + const ZERO = BigNumber.from(0) + expect(memberStats).toMatchObject({ + status: MemberStatus.NONE, + earningsBeforeLastJoin: ZERO, + totalEarnings: ZERO, + withdrawableEarnings: ZERO + }) + }) + + it('member stats: invalid address', () => { + return expectInvalidAddress(() => dataUnion.getMemberStats('invalid-address')) + }) +}) diff --git a/test/integration/dataunion/withdraw.test.ts b/test/integration/dataunion/withdraw.test.ts new file mode 100644 index 000000000..2b5cf0278 --- /dev/null +++ b/test/integration/dataunion/withdraw.test.ts @@ -0,0 +1,221 @@ +import { BigNumber, Contract, providers, Wallet } from 'ethers' +import { formatEther, parseEther } from 'ethers/lib/utils' +import { TransactionReceipt } from '@ethersproject/providers' +import debug from 'debug' + +import { getEndpointUrl, until } from '../../../src/utils' +import { StreamrClient } from '../../../src/StreamrClient' +import * as Token from '../../../contracts/TestToken.json' +import * as DataUnionSidechain from '../../../contracts/DataUnionSidechain.json' +import config from '../config' +import authFetch from '../../../src/rest/authFetch' +import { createClient, createMockAddress, expectInvalidAddress } from '../../utils' +import { MemberStatus } from '../../../src/dataunion/DataUnion' + +const log = debug('StreamrClient::DataUnion::integration-test-withdraw') + +// @ts-expect-error +const providerSidechain = new providers.JsonRpcProvider(config.clientOptions.sidechain) +// @ts-expect-error +const providerMainnet = new providers.JsonRpcProvider(config.clientOptions.mainnet) +const adminWalletMainnet = new Wallet(config.clientOptions.auth.privateKey, providerMainnet) +const adminWalletSidechain = new Wallet(config.clientOptions.auth.privateKey, providerSidechain) + +const tokenAdminWallet = new Wallet(config.tokenAdminPrivateKey, providerMainnet) +const tokenMainnet = new Contract(config.clientOptions.tokenAddress, Token.abi, tokenAdminWallet) + +const testWithdraw = async ( + getBalanceBefore: (memberWallet: Wallet, adminTokenMainnet: Contract) => Promise, + withdraw: ( + dataUnionAddress: string, + memberClient: StreamrClient, + memberWallet: Wallet, + adminClient: StreamrClient + ) => Promise, + getBalanceAfter: (memberWallet: Wallet, adminTokenMainnet: Contract) => Promise, + requiresMainnetETH: boolean +) => { + log(`Connecting to Ethereum networks, config = ${JSON.stringify(config)}`) + const network = await providerMainnet.getNetwork() + log('Connected to "mainnet" network: ', JSON.stringify(network)) + const network2 = await providerSidechain.getNetwork() + log('Connected to sidechain network: ', JSON.stringify(network2)) + + log(`Minting 100 tokens to ${adminWalletMainnet.address}`) + const tx1 = await tokenMainnet.mint(adminWalletMainnet.address, parseEther('100')) + await tx1.wait() + + const adminClient = new StreamrClient(config.clientOptions as any) + + const dataUnion = await adminClient.deployDataUnion() + const secret = await dataUnion.createSecret('test secret') + log(`DataUnion ${dataUnion.getAddress()} is ready to roll`) + // dataUnion = await adminClient.getDataUnionContract({dataUnion: "0xd778CfA9BB1d5F36E42526B2BAFD07B74b4066c0"}) + + const memberWallet = new Wallet(`0x100000000000000000000000000000000000000012300000001${Date.now()}`, providerSidechain) + const sendTx = await adminWalletSidechain.sendTransaction({ to: memberWallet.address, value: parseEther('0.1') }) + await sendTx.wait() + log(`Sent 0.1 sidechain-ETH to ${memberWallet.address}`) + + if (requiresMainnetETH) { + const send2Tx = await adminWalletMainnet.sendTransaction({ to: memberWallet.address, value: parseEther('0.1') }) + await send2Tx.wait() + log(`Sent 0.1 mainnet-ETH to ${memberWallet.address}`) + } + + const memberClient = new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: memberWallet.privateKey + } + } as any) + + // product is needed for join requests to analyze the DU version + const createProductUrl = getEndpointUrl(config.clientOptions.restUrl, 'products') + await authFetch(createProductUrl, adminClient.session, { + method: 'POST', + body: JSON.stringify({ + beneficiaryAddress: dataUnion.getAddress(), + type: 'DATAUNION', + dataUnionVersion: 2 + }) + }) + const res = await memberClient.getDataUnion(dataUnion.getAddress()).join(secret) + // await adminClient.addMembers([memberWallet.address], { dataUnion }) + log(`Member joined data union: ${JSON.stringify(res)}`) + + // eslint-disable-next-line no-underscore-dangle + const contract = await dataUnion._getContract() + const tokenAddress = await contract.token() + log(`Token address: ${tokenAddress}`) + const adminTokenMainnet = new Contract(tokenAddress, Token.abi, adminWalletMainnet) + + const amount = parseEther('1') + const duSidechainEarningsBefore = await contract.sidechain.totalEarnings() + + const duBalance1 = await adminTokenMainnet.balanceOf(dataUnion.getAddress()) + log(`Token balance of ${dataUnion.getAddress()}: ${formatEther(duBalance1)} (${duBalance1.toString()})`) + const balance1 = await adminTokenMainnet.balanceOf(adminWalletMainnet.address) + log(`Token balance of ${adminWalletMainnet.address}: ${formatEther(balance1)} (${balance1.toString()})`) + + log(`Transferring ${amount} token-wei ${adminWalletMainnet.address}->${dataUnion.getAddress()}`) + const txTokenToDU = await adminTokenMainnet.transfer(dataUnion.getAddress(), amount) + await txTokenToDU.wait() + + const duBalance2 = await adminTokenMainnet.balanceOf(dataUnion.getAddress()) + log(`Token balance of ${dataUnion.getAddress()}: ${formatEther(duBalance2)} (${duBalance2.toString()})`) + const balance2 = await adminTokenMainnet.balanceOf(adminWalletMainnet.address) + log(`Token balance of ${adminWalletMainnet.address}: ${formatEther(balance2)} (${balance2.toString()})`) + + log(`DU member count: ${await contract.sidechain.activeMemberCount()}`) + + log(`Transferred ${formatEther(amount)} tokens, next sending to bridge`) + const tx2 = await contract.sendTokensToBridge() + await tx2.wait() + + log(`Sent to bridge, waiting for the tokens to appear at ${contract.sidechain.address} in sidechain`) + const tokenSidechain = new Contract(config.clientOptions.tokenAddressSidechain, Token.abi, adminWalletSidechain) + await until(async () => !(await tokenSidechain.balanceOf(contract.sidechain.address)).eq('0'), 300000, 3000) + log(`Confirmed tokens arrived, DU balance: ${duSidechainEarningsBefore} -> ${await contract.sidechain.totalEarnings()}`) + + // make a "full" sidechain contract object that has all functions, not just those required by StreamrClient + const sidechainContract = new Contract(contract.sidechain.address, DataUnionSidechain.abi, adminWalletSidechain) + const tx3 = await sidechainContract.refreshRevenue() + const tr3 = await tx3.wait() + log(`refreshRevenue returned ${JSON.stringify(tr3)}`) + log(`DU balance: ${await contract.sidechain.totalEarnings()}`) + + const duBalance3 = await adminTokenMainnet.balanceOf(dataUnion.getAddress()) + log(`Token balance of ${dataUnion.getAddress()}: ${formatEther(duBalance3)} (${duBalance3.toString()})`) + const balance3 = await adminTokenMainnet.balanceOf(adminWalletMainnet.address) + log(`Token balance of ${adminWalletMainnet.address}: ${formatEther(balance3)} (${balance3.toString()})`) + + const stats = await memberClient.getDataUnion(dataUnion.getAddress()).getMemberStats(memberWallet.address) + log(`Stats: ${JSON.stringify(stats)}`) + + const balanceBefore = await getBalanceBefore(memberWallet, adminTokenMainnet) + log(`Balance before: ${balanceBefore}. Withdrawing tokens...`) + + const withdrawTr = await withdraw(dataUnion.getAddress(), memberClient, memberWallet, adminClient) + log(`Tokens withdrawn, sidechain tx receipt: ${JSON.stringify(withdrawTr)}`) + const balanceAfter = await getBalanceAfter(memberWallet, adminTokenMainnet) + const balanceIncrease = balanceAfter.sub(balanceBefore) + + expect(stats).toMatchObject({ + status: MemberStatus.ACTIVE, + earningsBeforeLastJoin: BigNumber.from(0), + totalEarnings: BigNumber.from('1000000000000000000'), + withdrawableEarnings: BigNumber.from('1000000000000000000') + }) + expect(withdrawTr.logs[0].address).toBe(config.clientOptions.tokenAddressSidechain) + expect(balanceIncrease.toString()).toBe(amount.toString()) +} + +describe('DataUnion withdraw', () => { + + afterAll(() => { + providerMainnet.removeAllListeners() + providerSidechain.removeAllListeners() + }) + + describe('Member', () => { + + it('by member itself', () => { + const getBalanceBefore = async (memberWallet: Wallet, adminTokenMainnet: Contract) => adminTokenMainnet.balanceOf(memberWallet.address) + const withdraw = async (dataUnionAddress: string, memberClient: StreamrClient) => ( + memberClient.getDataUnion(dataUnionAddress).withdrawAll() + ) + const getBalanceAfter = async (memberWallet: Wallet, adminTokenMainnet: Contract) => adminTokenMainnet.balanceOf(memberWallet.address) + return testWithdraw(getBalanceBefore, withdraw, getBalanceAfter, true) + }, 300000) + + it('from member to any address', () => { + const outsiderWallet = new Wallet(`0x100000000000000000000000000000000000000012300000002${Date.now()}`, providerSidechain) + const getBalanceBefore = (_: Wallet, adminTokenMainnet: Contract) => adminTokenMainnet.balanceOf(outsiderWallet.address) + const withdraw = (dataUnionAddress: string, memberClient: StreamrClient) => ( + memberClient.getDataUnion(dataUnionAddress).withdrawAllTo(outsiderWallet.address) + ) + const getBalanceAfter = (_: Wallet, adminTokenMainnet: Contract) => adminTokenMainnet.balanceOf(outsiderWallet.address) + return testWithdraw(getBalanceBefore, withdraw, getBalanceAfter, true) + }, 300000) + + }) + + describe('Admin', () => { + it('non-signed', async () => { + const getBalanceBefore = (memberWallet: Wallet, adminTokenMainnet: Contract) => adminTokenMainnet.balanceOf(memberWallet.address) + const withdraw = (dataUnionAddress: string, _: StreamrClient, memberWallet: Wallet, adminClient: StreamrClient) => ( + adminClient.getDataUnion(dataUnionAddress).withdrawAllToMember(memberWallet.address) + ) + const getBalanceAfter = (memberWallet: Wallet, adminTokenMainnet: Contract) => adminTokenMainnet.balanceOf(memberWallet.address) + return testWithdraw(getBalanceBefore, withdraw, getBalanceAfter, false) + }, 300000) + + it('signed', async () => { + const member2Wallet = new Wallet(`0x100000000000000000000000000000000000000012300000002${Date.now()}`, providerSidechain) + const getBalanceBefore = (_: Wallet, adminTokenMainnet: Contract) => adminTokenMainnet.balanceOf(member2Wallet.address) + const withdraw = async (dataUnionAddress: string, memberClient: StreamrClient, memberWallet: Wallet, adminClient: StreamrClient) => { + const signature = await memberClient.getDataUnion(dataUnionAddress).signWithdrawAllTo(member2Wallet.address) + const withdrawTr = await adminClient + .getDataUnion(dataUnionAddress) + .withdrawAllToSigned(memberWallet.address, member2Wallet.address, signature) + return withdrawTr + } + const getBalanceAfter = (_: Wallet, adminTokenMainnet: Contract) => adminTokenMainnet.balanceOf(member2Wallet.address) + return testWithdraw(getBalanceBefore, withdraw, getBalanceAfter, false) + }, 300000) + }) + + it('Validate address', async () => { + const client = createClient(providerSidechain) + const dataUnion = client.getDataUnion(createMockAddress()) + return Promise.all([ + expectInvalidAddress(() => dataUnion.getWithdrawableEarnings('invalid-address')), + expectInvalidAddress(() => dataUnion.withdrawAllTo('invalid-address')), + expectInvalidAddress(() => dataUnion.signWithdrawAllTo('invalid-address')), + expectInvalidAddress(() => dataUnion.signWithdrawAmountTo('invalid-address', '123')), + expectInvalidAddress(() => dataUnion.withdrawAllToMember('invalid-address')), + expectInvalidAddress(() => dataUnion.withdrawAllToSigned('invalid-address', 'invalid-address', 'mock-signature')) + ]) + }) +}) diff --git a/test/unit/CombinedSubscription.test.js b/test/legacy/CombinedSubscription.test.js similarity index 86% rename from test/unit/CombinedSubscription.test.js rename to test/legacy/CombinedSubscription.test.js index 2d729a5a3..c53aa374f 100644 --- a/test/unit/CombinedSubscription.test.js +++ b/test/legacy/CombinedSubscription.test.js @@ -27,9 +27,16 @@ const msg1 = createMsg() describe('CombinedSubscription', () => { it('handles real time gap that occurred during initial resend', (done) => { const msg4 = createMsg(4, undefined, 3) - const sub = new CombinedSubscription(msg1.getStreamId(), msg1.getStreamPartition(), sinon.stub(), { - last: 1 - }, {}, 100, 100) + const sub = new CombinedSubscription({ + streamId: msg1.getStreamId(), + streamPartition: msg1.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1 + }, + propagationTimeout: 100, + resendTimeout: 100, + }) sub.on('error', done) sub.addPendingResendRequestId('requestId') sub.on('gap', (from, to, publisherId) => { diff --git a/test/unit/HistoricalSubscription.test.js b/test/legacy/HistoricalSubscription.test.js similarity index 63% rename from test/unit/HistoricalSubscription.test.js rename to test/legacy/HistoricalSubscription.test.js index 883ebec7f..582dc880d 100644 --- a/test/unit/HistoricalSubscription.test.js +++ b/test/legacy/HistoricalSubscription.test.js @@ -1,11 +1,8 @@ -import crypto from 'crypto' - import sinon from 'sinon' import { ControlLayer, MessageLayer, Errors } from 'streamr-client-protocol' import { wait } from 'streamr-test-utils' import HistoricalSubscription from '../../src/HistoricalSubscription' -import EncryptionUtil from '../../src/EncryptionUtil' import Subscription from '../../src/Subscription' const { StreamMessage, MessageIDStrict, MessageRef } = MessageLayer @@ -36,11 +33,16 @@ describe('HistoricalSubscription', () => { describe('message handling', () => { describe('handleBroadcastMessage()', () => { it('calls the message handler', () => { - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), (content, receivedMsg) => { - expect(content).toEqual(msg.getParsedContent()) - expect(msg).toEqual(receivedMsg) - }, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: (content, receivedMsg) => { + expect(content).toEqual(msg.getParsedContent()) + expect(msg).toEqual(receivedMsg) + }, + options: { + last: 1, + }, }) return sub.handleResentMessage(msg, 'requestId', sinon.stub().resolves(true)) }) @@ -51,8 +53,14 @@ describe('HistoricalSubscription', () => { beforeEach(() => { const msgHandler = () => { throw new Error('should not be called!') } - sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), msgHandler, { - last: 1, + + sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: msgHandler, + options: { + last: 1, + }, }) stdError = console.error console.error = sinon.stub() @@ -101,14 +109,19 @@ describe('HistoricalSubscription', () => { const received = [] - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), (content, receivedMsg) => { - received.push(receivedMsg) - if (received.length === 5) { - expect(msgs).toEqual(received) - done() - } - }, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: (content, receivedMsg) => { + received.push(receivedMsg) + if (received.length === 5) { + expect(msgs).toEqual(received) + done() + } + }, + options: { + last: 1, + }, }) return Promise.all(msgs.map((m) => sub.handleResentMessage(m, 'requestId', sinon.stub().resolves(true)))) @@ -122,14 +135,19 @@ describe('HistoricalSubscription', () => { const received = [] - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), (content, receivedMsg) => { - received.push(receivedMsg) - if (received.length === 5) { - expect(received).toEqual(msgs) - done() - } - }, { - last: 5, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: (content, receivedMsg) => { + received.push(receivedMsg) + if (received.length === 5) { + expect(received).toEqual(msgs) + done() + } + }, + options: { + last: 5, + }, }) return Promise.all(msgs.map((m, index, arr) => sub.handleResentMessage(m, 'requestId', async () => { @@ -152,19 +170,24 @@ describe('HistoricalSubscription', () => { resolveLastMessageValidation = resolve }) - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), (content, receivedMsg) => { - received.push(receivedMsg) - if (received.length === 4) { - // only resolve last message when 4th message received - resolveLastMessageValidation() - } + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: (content, receivedMsg) => { + received.push(receivedMsg) + if (received.length === 4) { + // only resolve last message when 4th message received + resolveLastMessageValidation() + } - if (received.length === 5) { - expect(received).toEqual(msgs) - done() + if (received.length === 5) { + expect(received).toEqual(msgs) + done() + } + }, + options: { + last: 5, } - }, { - last: 5, }) return Promise.all(msgs.map((m, index, arr) => sub.handleResentMessage(m, 'requestId', async () => { @@ -181,8 +204,13 @@ describe('HistoricalSubscription', () => { describe('duplicate handling', () => { it('ignores re-received messages', async () => { const handler = sinon.stub() - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), handler, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + options: { + last: 1, + } }) await sub.handleResentMessage(msg, 'requestId', sinon.stub().resolves(true)) @@ -197,9 +225,17 @@ describe('HistoricalSubscription', () => { const msg1 = msg const msg4 = createMsg(4, undefined, 3) - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, - }, {}, 100, 100) + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, + propagationTimeout: 100, + resendTimeout: 100, + }) + sub.on('gap', (from, to, publisherId) => { expect(from.timestamp).toEqual(1) expect(from.sequenceNumber).toEqual(1) @@ -216,29 +252,33 @@ describe('HistoricalSubscription', () => { sub.handleResentMessage(msg4, 'requestId', sinon.stub().resolves(true)) }) - it( - 'emits second "gap" after the first one if no missing message is received in between', - (done) => { - const msg1 = msg - const msg4 = createMsg(4, undefined, 3) + it('emits second "gap" after the first one if no missing message is received in between', (done) => { + const msg1 = msg + const msg4 = createMsg(4, undefined, 3) - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { last: 1, - }, {}, 100, 100) - sub.on('gap', (from, to, publisherId) => { - sub.on('gap', (from2, to2, publisherId2) => { - expect(from).toStrictEqual(from2) - expect(to).toStrictEqual(to2) - expect(publisherId).toStrictEqual(publisherId2) - sub.stop() - done() - }) + }, + propagationTimeout: 100, + resendTimeout: 100, + }) + sub.once('gap', (from, to, publisherId) => { + sub.once('gap', (from2, to2, publisherId2) => { + expect(from).toStrictEqual(from2) + expect(to).toStrictEqual(to2) + expect(publisherId).toStrictEqual(publisherId2) + sub.stop() + done() }) + }) - sub.handleResentMessage(msg1, 'requestId', sinon.stub().resolves(true)) - sub.handleResentMessage(msg4, 'requestId', sinon.stub().resolves(true)) - } - ) + sub.handleResentMessage(msg1, 'requestId', sinon.stub().resolves(true)) + sub.handleResentMessage(msg4, 'requestId', sinon.stub().resolves(true)) + }) it('does not emit second "gap" after the first one if the missing messages are received in between', (done) => { const msg1 = msg @@ -246,9 +286,17 @@ describe('HistoricalSubscription', () => { const msg3 = createMsg(3, undefined, 2) const msg4 = createMsg(4, undefined, 3) - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, - }, {}, 100, 100) + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, + propagationTimeout: 100, + resendTimeout: 100, + }) + sub.once('gap', () => { sub.handleResentMessage(msg2, 'requestId', sinon.stub().resolves(true)) sub.handleResentMessage(msg3, 'requestId', sinon.stub().resolves(true)).then(() => {}) @@ -267,9 +315,17 @@ describe('HistoricalSubscription', () => { const msg1 = msg const msg4 = createMsg(4, undefined, 3) - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, - }, {}, 100, 100) + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, + propagationTimeout: 100, + resendTimeout: 100, + }) + sub.once('gap', () => { sub.emit('unsubscribed') sub.once('gap', () => { throw new Error('should not emit second gap') }) @@ -286,10 +342,16 @@ describe('HistoricalSubscription', () => { it('does not emit second "gap" if gets disconnected', async (done) => { const msg1 = msg const msg4 = createMsg(4, undefined, 3) - - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, - }, {}, 100, 100) + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, + propagationTimeout: 100, + resendTimeout: 100, + }) sub.once('gap', () => { sub.emit('disconnected') sub.once('gap', () => { throw new Error('should not emit second gap') }) @@ -307,9 +369,17 @@ describe('HistoricalSubscription', () => { const msg1 = msg const msg1b = createMsg(1, 0, undefined, 0, {}, 'anotherPublisherId') - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, + propagationTimeout: 100, + resendTimeout: 100, }) + sub.on('gap', () => { throw new Error('unexpected gap') }) @@ -322,9 +392,17 @@ describe('HistoricalSubscription', () => { const msg1 = msg const msg4 = createMsg(1, 4, 1, 3) - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, - }, {}, 100, 100) + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, + propagationTimeout: 100, + resendTimeout: 100, + }) + sub.once('gap', (from, to, publisherId) => { expect(from.timestamp).toEqual(1) // cannot know the first missing message so there will be a duplicate received expect(from.sequenceNumber).toEqual(1) @@ -345,8 +423,15 @@ describe('HistoricalSubscription', () => { const msg1 = msg const msg2 = createMsg(2, undefined, 1) - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, + propagationTimeout: 100, + resendTimeout: 100, }) sub.on('gap', sinon.stub().throws()) @@ -358,9 +443,17 @@ describe('HistoricalSubscription', () => { const msg1 = msg const msg2 = createMsg(1, 1, 1, 0) - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, + propagationTimeout: 100, + resendTimeout: 100, }) + sub.once('gap', sinon.stub().throws()) sub.handleResentMessage(msg1, 'requestId', sinon.stub().resolves(true)) @@ -375,11 +468,20 @@ describe('HistoricalSubscription', () => { const msg4 = createMsg(4, 0, 3, 0) const received = [] - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), (content, receivedMsg) => { - received.push(receivedMsg) - }, { - last: 1, - }, {}, 100, 100, false) + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: (content, receivedMsg) => { + received.push(receivedMsg) + }, + options: { + last: 1, + }, + propagationTimeout: 100, + resendTimeout: 100, + orderMessages: false, + }) + sub.on('gap', sinon.stub().throws()) await sub.handleResentMessage(msg1, 'requestId', sinon.stub().resolves(true)) @@ -399,10 +501,18 @@ describe('HistoricalSubscription', () => { const msg4 = createMsg(4, 0, 3, 0) const received = [] - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), (content, receivedMsg) => { - received.push(receivedMsg) - }, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: (content, receivedMsg) => { + received.push(receivedMsg) + }, + options: { + last: 1, + }, + propagationTimeout: 100, + resendTimeout: 100, + orderMessages: true, }) await sub.handleResentMessage(msg1, 'requestId', sinon.stub().resolves(true)) @@ -421,200 +531,38 @@ describe('HistoricalSubscription', () => { const byeMsg = createMsg(1, undefined, null, null, { _bye: true, }) + const handler = sinon.stub() - const sub = new HistoricalSubscription(byeMsg.getStreamId(), byeMsg.getStreamPartition(), handler, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: byeMsg.getStreamId(), + streamPartition: byeMsg.getStreamPartition(), + callback: handler, + options: { + last: 1, + }, + propagationTimeout: 100, + resendTimeout: 100, }) - sub.on('done', () => { + sub.once('done', () => { expect(handler.calledOnce).toBeTruthy() done() }) sub.handleResentMessage(byeMsg, 'requestId', sinon.stub().resolves(true)) }) - - describe('decryption', () => { - let sub - - afterEach(() => { - sub.stop() - }) - - it('should read clear text content without trying to decrypt', (done) => { - const msg1 = createMsg(1, 0, null, 0, { - foo: 'bar', - }) - sub = new HistoricalSubscription(msg1.getStreamId(), msg1.getStreamPartition(), (content) => { - expect(content).toStrictEqual(msg1.getParsedContent()) - done() - }, { - last: 1, - }) - return sub.handleResentMessage(msg1, 'requestId', sinon.stub().resolves(true)) - }) - - it('should decrypt encrypted content with the correct key', (done) => { - const groupKey = crypto.randomBytes(32) - const data = { - foo: 'bar', - } - const msg1 = createMsg(1, 0, null, 0, data) - EncryptionUtil.encryptStreamMessage(msg1, groupKey) - sub = new HistoricalSubscription(msg1.getStreamId(), msg1.getStreamPartition(), (content) => { - expect(content).toStrictEqual(data) - done() - }, { - last: 1, - }, { - publisherId: groupKey, - }) - return sub.handleResentMessage(msg1, 'requestId', sinon.stub().resolves(true)) - }) - - it('should emit "groupKeyMissing" with range when no historical group keys are set', (done) => { - const correctGroupKey = crypto.randomBytes(32) - const msg1 = createMsg(1, 0, null, 0, { - foo: 'bar', - }) - EncryptionUtil.encryptStreamMessage(msg1, correctGroupKey) - sub = new HistoricalSubscription(msg1.getStreamId(), msg1.getStreamPartition(), sinon.stub(), { - last: 1, - }) - sub.on('groupKeyMissing', (publisherId, start, end) => { - expect(publisherId).toBe(msg1.getPublisherId()) - expect(start).toBe(msg1.getTimestamp()) - expect(end).toBeTruthy() - done() - }) - return sub.handleResentMessage(msg1, 'requestId', sinon.stub().resolves(true)) - }) - - it('should queue messages when not able to decrypt and handle them once the keys are set', async () => { - const groupKey1 = crypto.randomBytes(32) - const groupKey2 = crypto.randomBytes(32) - const data1 = { - test: 'data1', - } - const data2 = { - test: 'data2', - } - const msg1 = createMsg(1, 0, null, 0, data1) - const msg2 = createMsg(2, 0, 1, 0, data2) - EncryptionUtil.encryptStreamMessage(msg1, groupKey1) - EncryptionUtil.encryptStreamMessage(msg2, groupKey2) - let received1 = null - let received2 = null - sub = new HistoricalSubscription(msg1.getStreamId(), msg1.getStreamPartition(), (content) => { - if (!received1) { - received1 = content - } else { - received2 = content - } - }, { - last: 1, - }) - // cannot decrypt msg1, queues it and emits "groupKeyMissing" (should send group key request). - await sub.handleResentMessage(msg1, 'requestId', sinon.stub().resolves(true)) - // cannot decrypt msg2, queues it. - await sub.handleResentMessage(msg2, 'requestId', sinon.stub().resolves(true)) - // faking the reception of the group key response - sub.setGroupKeys('publisherId', [groupKey1, groupKey2]) - // try again to decrypt the queued messages but this time with the correct key - expect(received1).toStrictEqual(data1) - expect(received2).toStrictEqual(data2) - }) - - it('should call "onUnableToDecrypt" when not able to decrypt with historical keys set', async () => { - const correctGroupKey = crypto.randomBytes(32) - const wrongGroupKey = crypto.randomBytes(32) - const data1 = { - test: 'data1', - } - const data2 = { - test: 'data2', - } - const msg1 = createMsg(1, 0, null, 0, data1) - const msg2 = createMsg(2, 0, 1, 0, data2) - EncryptionUtil.encryptStreamMessage(msg1, correctGroupKey) - EncryptionUtil.encryptStreamMessage(msg2, correctGroupKey) - let undecryptableMsg = null - sub = new HistoricalSubscription(msg1.getStreamId(), msg1.getStreamPartition(), () => { - throw new Error('should not call the handler') - }, { - last: 1, - }, {}, 5000, 5000, true, (error) => { - undecryptableMsg = error.streamMessage - }) - // cannot decrypt msg1, emits "groupKeyMissing" (should send group key request). - await sub.handleResentMessage(msg1, 'requestId', sinon.stub().resolves(true)) - // cannot decrypt msg2, queues it. - await sub.handleResentMessage(msg2, 'requestId', sinon.stub().resolves(true)) - // faking the reception of the group key response - sub.setGroupKeys('publisherId', [wrongGroupKey]) - - expect(undecryptableMsg).toStrictEqual(msg2) - }) - - it('should queue messages when not able to decrypt and handle them once the keys are set (multiple publishers)', async () => { - const groupKey1 = crypto.randomBytes(32) - const groupKey2 = crypto.randomBytes(32) - const groupKey3 = crypto.randomBytes(32) - const data1 = { - test: 'data1', - } - const data2 = { - test: 'data2', - } - const data3 = { - test: 'data3', - } - const data4 = { - test: 'data4', - } - const msg1 = createMsg(1, 0, null, 0, data1, 'publisherId1') - const msg2 = createMsg(2, 0, 1, 0, data2, 'publisherId1') - const msg3 = createMsg(1, 0, null, 0, data3, 'publisherId2') - const msg4 = createMsg(2, 0, 1, 0, data4, 'publisherId2') - EncryptionUtil.encryptStreamMessage(msg1, groupKey1) - EncryptionUtil.encryptStreamMessage(msg2, groupKey2) - EncryptionUtil.encryptStreamMessage(msg3, groupKey3) - EncryptionUtil.encryptStreamMessage(msg4, groupKey3) - const received = [] - sub = new HistoricalSubscription(msg1.getStreamId(), msg1.getStreamPartition(), (content) => { - received.push(content) - }, { - last: 1, - }) - // cannot decrypt msg1, queues it and emits "groupKeyMissing" (should send group key request). - await sub.handleResentMessage(msg1, 'requestId', sinon.stub().resolves(true)) - // cannot decrypt msg2, queues it. - await sub.handleResentMessage(msg2, 'requestId', sinon.stub().resolves(true)) - // cannot decrypt msg3, queues it and emits "groupKeyMissing" (should send group key request). - await sub.handleResentMessage(msg3, 'requestId', sinon.stub().resolves(true)) - // cannot decrypt msg4, queues it. - await sub.handleResentMessage(msg4, 'requestId', sinon.stub().resolves(true)) - // faking the reception of the group key response - sub.setGroupKeys('publisherId2', [groupKey3]) - sub.setGroupKeys('publisherId1', [groupKey1, groupKey2]) - // try again to decrypt the queued messages but this time with the correct key - expect(received[0]).toStrictEqual(data3) - expect(received[1]).toStrictEqual(data4) - expect(received[2]).toStrictEqual(data1) - expect(received[3]).toStrictEqual(data2) - }) - }) }) describe('handleError()', () => { it('emits an error event', (done) => { const err = new Error('Test error') - const sub = new HistoricalSubscription( - msg.getStreamId(), - msg.getStreamPartition(), - sinon.stub().throws('Msg handler should not be called!'), { + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub().throws('Msg handler should not be called!'), + options: { last: 1, - } - ) + }, + }) sub.onError = jest.fn() sub.once('error', (thrown) => { expect(thrown).toBe(err) @@ -625,13 +573,18 @@ describe('HistoricalSubscription', () => { }) it('marks the message as received if an InvalidJsonError occurs, and continue normally on next message', async (done) => { - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), (content, receivedMsg) => { - if (receivedMsg.getTimestamp() === 3) { - sub.stop() - done() - } - }, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: (content, receivedMsg) => { + if (receivedMsg.getTimestamp() === 3) { + sub.stop() + done() + } + }, + options: { + last: 1, + }, }) sub.onError = jest.fn() @@ -654,9 +607,16 @@ describe('HistoricalSubscription', () => { }) it('if an InvalidJsonError AND a gap occur, does not mark it as received and emits gap at the next message', async (done) => { - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, - }, {}, 100, 100) + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, + propagationTimeout: 100, + resendTimeout: 100, + }) sub.onError = jest.fn() @@ -691,16 +651,26 @@ describe('HistoricalSubscription', () => { describe('setState()', () => { it('updates the state', () => { - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, }) sub.setState(Subscription.State.subscribed) expect(sub.getState()).toEqual(Subscription.State.subscribed) }) it('fires an event', (done) => { - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, }) sub.once(Subscription.State.subscribed, done) sub.setState(Subscription.State.subscribed) @@ -709,8 +679,13 @@ describe('HistoricalSubscription', () => { describe('handleResending()', () => { it('emits the resending event', async () => { - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, }) sub.addPendingResendRequestId('requestId') const onResending = new Promise((resolve) => sub.once('resending', resolve)) @@ -726,8 +701,13 @@ describe('HistoricalSubscription', () => { describe('handleResent()', () => { it('emits the "resent" + "initial_resend_done" events on last message (message handler completes BEFORE resent)', async (done) => { const handler = sinon.stub() - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), handler, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + options: { + last: 1, + }, }) sub.addPendingResendRequestId('requestId') @@ -742,8 +722,13 @@ describe('HistoricalSubscription', () => { it('arms the Subscription to emit the resent event on last message (message handler completes AFTER resent)', async () => { const handler = sinon.stub() - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), handler, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + options: { + last: 1, + }, }) sub.addPendingResendRequestId('requestId') const onResent = new Promise((resolve) => sub.once('resent', resolve)) @@ -758,8 +743,13 @@ describe('HistoricalSubscription', () => { it('should not emit "initial_resend_done" after receiving "resent" if there are still pending resend requests', async () => { const handler = sinon.stub() - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), handler, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + options: { + last: 1, + }, }) sub.addPendingResendRequestId('requestId1') sub.addPendingResendRequestId('requestId2') @@ -778,8 +768,13 @@ describe('HistoricalSubscription', () => { it('emits 2 "resent" and 1 "initial_resend_done" after receiving 2 pending resend response', async (done) => { const handler = sinon.stub() - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), handler, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + options: { + last: 1, + }, }) sub.addPendingResendRequestId('requestId1') sub.addPendingResendRequestId('requestId2') @@ -807,8 +802,13 @@ describe('HistoricalSubscription', () => { it('can handle a second resend while in the middle of resending', async (done) => { const handler = sinon.stub() - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), handler, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + options: { + last: 1, + }, }) sub.addPendingResendRequestId('requestId1') sub.addPendingResendRequestId('requestId2') @@ -829,8 +829,13 @@ describe('HistoricalSubscription', () => { describe('handleNoResend()', () => { it('emits the no_resend event and then the initial_resend_done event', (done) => { - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), sinon.stub(), { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: sinon.stub(), + options: { + last: 1, + }, }) sub.addPendingResendRequestId('requestId') sub.once('no_resend', () => sub.once('initial_resend_done', () => done())) @@ -843,8 +848,13 @@ describe('HistoricalSubscription', () => { it('should not emit "initial_resend_done" after receiving "no resend" if there are still pending resend requests', async (done) => { const handler = sinon.stub() - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), handler, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + options: { + last: 1, + }, }) sub.addPendingResendRequestId('requestId1') sub.addPendingResendRequestId('requestId2') @@ -862,8 +872,13 @@ describe('HistoricalSubscription', () => { it('emits 2 "resent" and 1 "initial_resend_done" after receiving 2 pending resend response', async (done) => { const handler = sinon.stub() - const sub = new HistoricalSubscription(msg.getStreamId(), msg.getStreamPartition(), handler, { - last: 1, + const sub = new HistoricalSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + options: { + last: 1, + }, }) sub.addPendingResendRequestId('requestId1') sub.addPendingResendRequestId('requestId2') diff --git a/test/legacy/MessageCreationUtil.test.js b/test/legacy/MessageCreationUtil.test.js new file mode 100644 index 000000000..66c77bb8e --- /dev/null +++ b/test/legacy/MessageCreationUtil.test.js @@ -0,0 +1,279 @@ +import sinon from 'sinon' +import { ethers } from 'ethers' +import { wait } from 'streamr-test-utils' +import { MessageLayer } from 'streamr-client-protocol' + +import { MessageCreationUtil, StreamPartitioner } from '../../src/Publisher' +import { Stream } from '../../src/stream' + +// eslint-disable-next-line import/no-named-as-default-member +import StubbedStreamrClient from './StubbedStreamrClient' + +const { StreamMessage, MessageID, MessageRef } = MessageLayer + +describe('MessageCreationUtil', () => { + let client + let msgCreationUtil + const hashedUsername = '0x16F78A7D6317F102BBD95FC9A4F3FF2E3249287690B8BDAD6B7810F82B34ACE3'.toLowerCase() + + const createClient = (opts = {}) => { + return new StubbedStreamrClient({ + auth: { + username: 'username', + }, + autoConnect: false, + autoDisconnect: false, + maxRetries: 2, + ...opts, + }) + } + + afterEach(async () => { + if (msgCreationUtil) { + msgCreationUtil.stop() + } + + if (client) { + await client.disconnect() + } + }) + + describe('getPublisherId', () => { + it('uses address for privateKey auth', async () => { + const wallet = ethers.Wallet.createRandom() + client = createClient({ + auth: { + privateKey: wallet.privateKey, + }, + }) + msgCreationUtil = new MessageCreationUtil(client) + const publisherId = await msgCreationUtil.getPublisherId() + expect(publisherId).toBe(wallet.address.toLowerCase()) + }) + + it('uses hash of username for apiKey auth', async () => { + client = createClient({ + auth: { + apiKey: 'apiKey', + }, + }) + msgCreationUtil = new MessageCreationUtil(client) + const publisherId = await msgCreationUtil.getPublisherId() + expect(publisherId).toBe(hashedUsername) + }) + + it('uses hash of username for username auth', async () => { + client = createClient({ + auth: { + username: 'username', + }, + }) + msgCreationUtil = new MessageCreationUtil(client) + const publisherId = await msgCreationUtil.getPublisherId() + expect(publisherId).toBe(hashedUsername) + }) + + it('uses hash of username for sessionToken auth', async () => { + client = createClient({ + auth: { + sessionToken: 'session-token', + }, + }) + msgCreationUtil = new MessageCreationUtil(client) + const publisherId = await msgCreationUtil.getPublisherId() + expect(publisherId).toBe(hashedUsername) + }) + }) + + describe('StreamPartitioner', () => { + let streamPartitioner + + beforeAll(() => { + client = createClient() + }) + + beforeEach(() => { + streamPartitioner = new StreamPartitioner(client) + }) + + it('should throw if partition count is not defined', () => { + expect(() => { + streamPartitioner.computeStreamPartition(undefined, 'foo') + }).toThrow() + }) + + it('should always return partition 0 for all keys if partition count is 1', () => { + for (let i = 0; i < 100; i++) { + expect(streamPartitioner.computeStreamPartition(1, `foo${i}`)).toEqual(0) + } + }) + + it('should use md5 partitioner and produce same results as crypto.createHash(md5).update(string).digest()', () => { + const keys = [] + for (let i = 0; i < 100; i++) { + keys.push(`key-${i}`) + } + // Results must be the same as those produced by md5 + const correctResults = [6, 7, 4, 4, 9, 1, 8, 0, 6, 6, 7, 6, 7, 3, 2, 2, 0, 9, 4, 9, 9, 5, 5, + 1, 7, 3, 0, 6, 5, 6, 3, 6, 3, 5, 6, 2, 3, 6, 7, 2, 1, 3, 2, 7, 1, 1, 5, 1, 4, 0, 1, 9, 7, + 4, 2, 3, 2, 9, 7, 7, 4, 3, 5, 4, 5, 3, 9, 0, 4, 8, 1, 7, 4, 8, 1, 2, 9, 9, 5, 3, 5, 0, 9, + 4, 3, 9, 6, 7, 8, 6, 4, 6, 0, 1, 1, 5, 8, 3, 9, 7] + + expect(correctResults.length).toEqual(keys.length) + + for (let i = 0; i < keys.length; i++) { + const partition = streamPartitioner.computeStreamPartition(10, keys[i]) + expect(correctResults[i]).toStrictEqual(partition) + } + }) + }) + + describe('createStreamMessage()', () => { + const pubMsg = { + foo: 'bar', + } + + let stream + + beforeAll(() => { + client = createClient({ + auth: { + username: 'username', + }, + }) + }) + + beforeEach(() => { + stream = new Stream(null, { + id: 'streamId', + partitions: 1, + }) + client.getStream = sinon.stub().resolves(stream) + msgCreationUtil = new MessageCreationUtil(client) + }) + + function getStreamMessage(streamId, timestamp, sequenceNumber, prevMsgRef) { + return new StreamMessage({ + messageId: new MessageID(streamId, 0, timestamp, sequenceNumber, hashedUsername, msgCreationUtil.msgChainer.msgChainId), + prevMsgRef, + content: pubMsg, + messageType: StreamMessage.MESSAGE_TYPES.MESSAGE, + encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, + }) + } + + it('should create messages with increasing sequence numbers', async () => { + const ts = Date.now() + let prevMsgRef = null + for (let i = 0; i < 10; i++) { + // eslint-disable-next-line no-await-in-loop + const streamMessage = await msgCreationUtil.createStreamMessage(stream, { + content: pubMsg, timestamp: ts, + }) + expect(streamMessage).toStrictEqual(getStreamMessage('streamId', ts, i, prevMsgRef)) + prevMsgRef = new MessageRef(ts, i) + } + }) + + it('should create messages with sequence number 0 if different timestamp', async () => { + const ts = Date.now() + let prevMsgRef = null + for (let i = 0; i < 10; i++) { + // eslint-disable-next-line no-await-in-loop + const streamMessage = await msgCreationUtil.createStreamMessage(stream, { + content: pubMsg, timestamp: ts + i, + }) + expect(streamMessage).toStrictEqual(getStreamMessage('streamId', ts + i, 0, prevMsgRef)) + prevMsgRef = new MessageRef(ts + i, 0) + } + }) + + it('should sequence in order even if async dependencies resolve out of order', async () => { + const ts = Date.now() + let calls = 0 + const getStreamPartitions = msgCreationUtil.partitioner.getStreamPartitions.bind(msgCreationUtil.partitioner) + msgCreationUtil.partitioner.getStreamPartitions = async (...args) => { + calls += 1 + if (calls === 2) { + const result = await getStreamPartitions(...args) + // delay resolving this call + await wait(100) + return result + } + return getStreamPartitions(...args) + } + + // simultaneously publish 3 messages, but the second item's dependencies will resolve late. + // this shouldn't affect the sequencing + const messages = await Promise.all([ + msgCreationUtil.createStreamMessage(stream, { + content: pubMsg, timestamp: ts, + }), + msgCreationUtil.createStreamMessage(stream, { + content: pubMsg, timestamp: ts, + }), + msgCreationUtil.createStreamMessage(stream, { + content: pubMsg, timestamp: ts, + }) + ]) + const sequenceNumbers = messages.map((m) => m.getSequenceNumber()) + expect(sequenceNumbers).toEqual([0, 1, 2]) + }) + + it('should handle old timestamps', async () => { + const ts = Date.now() + const streamMessage1 = await msgCreationUtil.createStreamMessage(stream, { + content: pubMsg, timestamp: ts, + }) + const streamMessage2 = await msgCreationUtil.createStreamMessage(stream, { + content: pubMsg, timestamp: ts + 1, + }) + const streamMessage3 = await msgCreationUtil.createStreamMessage(stream, { + content: pubMsg, timestamp: ts, + }) + const sequenceNumbers = [streamMessage1, streamMessage2, streamMessage3].map((m) => m.getSequenceNumber()) + expect(sequenceNumbers).toEqual([0, 0, 0]) + }) + + it('should publish messages with sequence number 0 (different streams)', async () => { + const ts = Date.now() + const stream2 = new Stream(null, { + id: 'streamId2', + partitions: 1, + }) + const stream3 = new Stream(null, { + id: 'streamId3', + partitions: 1, + }) + + const msg1 = await msgCreationUtil.createStreamMessage(stream, { + content: pubMsg, timestamp: ts + }) + const msg2 = await msgCreationUtil.createStreamMessage(stream2, { + content: pubMsg, timestamp: ts + }) + const msg3 = await msgCreationUtil.createStreamMessage(stream3, { + content: pubMsg, timestamp: ts + }) + + expect(msg1).toEqual(getStreamMessage('streamId', ts, 0, null)) + expect(msg2).toEqual(getStreamMessage('streamId2', ts, 0, null)) + expect(msg3).toEqual(getStreamMessage('streamId3', ts, 0, null)) + }) + + it.skip('should sign messages if signer is defined', async () => { + const msg1 = await msgCreationUtil.createStreamMessage(stream, { + content: pubMsg, timestamp: Date.now() + }) + expect(msg1.signature).toBe('signature') + }) + + it('should create message from a stream id by fetching the stream', async () => { + const ts = Date.now() + const streamMessage = await msgCreationUtil.createStreamMessage(stream.id, { + content: pubMsg, timestamp: ts + }) + expect(streamMessage).toEqual(getStreamMessage(stream.id, ts, 0, null)) + }) + }) +}) diff --git a/test/unit/RealTimeSubscription.test.js b/test/legacy/RealTimeSubscription.test.js similarity index 54% rename from test/unit/RealTimeSubscription.test.js rename to test/legacy/RealTimeSubscription.test.js index 8f7f5c727..c303dbd4f 100644 --- a/test/unit/RealTimeSubscription.test.js +++ b/test/legacy/RealTimeSubscription.test.js @@ -1,11 +1,8 @@ -import crypto from 'crypto' - import { ControlLayer, MessageLayer, Errors } from 'streamr-client-protocol' +import { wait } from 'streamr-test-utils' import RealTimeSubscription from '../../src/RealTimeSubscription' -import EncryptionUtil from '../../src/EncryptionUtil' import Subscription from '../../src/Subscription' -import AbstractSubscription from '../../src/AbstractSubscription' const { StreamMessage, MessageIDStrict, MessageRef } = MessageLayer @@ -34,11 +31,15 @@ describe('RealTimeSubscription', () => { it('calls the message handler', async (done) => { const handler = jest.fn(async () => true) - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), (content, receivedMsg) => { - expect(content).toStrictEqual(msg.getParsedContent()) - expect(msg).toStrictEqual(receivedMsg) - expect(handler).toHaveBeenCalledTimes(1) - done() + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: (content, receivedMsg) => { + expect(content).toStrictEqual(msg.getParsedContent()) + expect(msg).toStrictEqual(receivedMsg) + expect(handler).toHaveBeenCalledTimes(1) + done() + }, }) await sub.handleBroadcastMessage(msg, handler) }) @@ -47,7 +48,11 @@ describe('RealTimeSubscription', () => { let sub beforeEach(() => { - sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => { throw new Error('should not be called!') }) + sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => { throw new Error('should not be called!') }, + }) sub.onError = jest.fn() }) @@ -95,11 +100,15 @@ describe('RealTimeSubscription', () => { const received = [] - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), (content, receivedMsg) => { - received.push(receivedMsg) - if (received.length === 5) { - expect(msgs).toStrictEqual(received) - done() + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: (content, receivedMsg) => { + received.push(receivedMsg) + if (received.length === 5) { + expect(msgs).toStrictEqual(received) + done() + } } }) @@ -110,7 +119,11 @@ describe('RealTimeSubscription', () => { describe('handleResentMessage()', () => { it('processes messages if resending is true', async () => { const handler = jest.fn() - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), handler) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + }) sub.setResending(true) await sub.handleResentMessage(msg, 'requestId', async () => true) @@ -121,8 +134,12 @@ describe('RealTimeSubscription', () => { let sub beforeEach(() => { - sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => { - throw new Error('should not be called!') + sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => { + throw new Error('should not be called!') + }, }) sub.setResending(true) }) @@ -171,7 +188,11 @@ describe('RealTimeSubscription', () => { describe('duplicate handling', () => { it('ignores re-received messages', async () => { const handler = jest.fn() - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), handler) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + }) await sub.handleBroadcastMessage(msg, async () => true) await sub.handleBroadcastMessage(msg, async () => true) @@ -181,7 +202,11 @@ describe('RealTimeSubscription', () => { it('ignores re-received messages if they come from resend', async () => { const handler = jest.fn() - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), handler) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + }) sub.setResending(true) await sub.handleBroadcastMessage(msg, async () => true) @@ -194,8 +219,13 @@ describe('RealTimeSubscription', () => { it('emits "gap" if a gap is detected', (done) => { const msg1 = msg const msg4 = createMsg(4, undefined, 3) - - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}, {}, 100, 100) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + propagationTimeout: 100, + resendTimeout: 100, + }) sub.once('gap', (from, to, publisherId) => { expect(from.timestamp).toEqual(1) // cannot know the first missing message so there will be a duplicate received expect(from.sequenceNumber).toEqual(1) @@ -216,7 +246,14 @@ describe('RealTimeSubscription', () => { const msg1 = msg const msg4 = createMsg(4, undefined, 3) - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}, {}, 100, 100) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + propagationTimeout: 100, + resendTimeout: 100, + }) + sub.once('gap', (from, to, publisherId) => { sub.once('gap', (from2, to2, publisherId2) => { expect(from).toStrictEqual(from2) @@ -237,7 +274,14 @@ describe('RealTimeSubscription', () => { const msg3 = createMsg(3, undefined, 2) const msg4 = createMsg(4, undefined, 3) - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}, {}, 100, 100) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + propagationTimeout: 100, + resendTimeout: 100, + }) + sub.once('gap', () => { sub.handleBroadcastMessage(msg2, async () => true) sub.handleBroadcastMessage(msg3, async () => true) @@ -256,7 +300,14 @@ describe('RealTimeSubscription', () => { const msg1 = msg const msg4 = createMsg(4, undefined, 3) - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}, {}, 100, 100) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + propagationTimeout: 100, + resendTimeout: 100, + }) + sub.once('gap', () => { sub.emit('unsubscribed') sub.once('gap', () => { throw new Error('should not emit second gap') }) @@ -274,7 +325,14 @@ describe('RealTimeSubscription', () => { const msg1 = msg const msg4 = createMsg(4, undefined, 3) - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}, {}, 100, 100) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + propagationTimeout: 100, + resendTimeout: 100, + }) + sub.once('gap', () => { sub.emit('disconnected') sub.once('gap', () => { throw new Error('should not emit second gap') }) @@ -288,24 +346,37 @@ describe('RealTimeSubscription', () => { sub.handleBroadcastMessage(msg4, async () => true) }) - it('does not emit "gap" if different publishers', () => { + it('does not emit "gap" if different publishers', async () => { const msg1 = msg const msg1b = createMsg(1, 0, undefined, 0, {}, 'anotherPublisherId') - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + propagationTimeout: 100, + resendTimeout: 100, + }) sub.once('gap', () => { throw new Error('unexpected gap') }) sub.handleBroadcastMessage(msg1, async () => true) sub.handleBroadcastMessage(msg1b, async () => true) + await wait(100) }) it('emits "gap" if a gap is detected (same timestamp but different sequenceNumbers)', (done) => { const msg1 = msg const msg4 = createMsg(1, 4, 1, 3) - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}, {}, 100, 100) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + propagationTimeout: 100, + resendTimeout: 100, + }) sub.once('gap', (from, to, publisherId) => { expect(from.timestamp).toEqual(1) // cannot know the first missing message so there will be a duplicate received expect(from.sequenceNumber).toEqual(1) @@ -322,26 +393,39 @@ describe('RealTimeSubscription', () => { sub.handleBroadcastMessage(msg4, async () => true) }) - it('does not emit "gap" if a gap is not detected', () => { + it('does not emit "gap" if a gap is not detected', async () => { const msg1 = msg const msg2 = createMsg(2, undefined, 1) - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + propagationTimeout: 100, + resendTimeout: 100, + }) sub.once('gap', () => { throw new Error() }) sub.handleBroadcastMessage(msg1, async () => true) sub.handleBroadcastMessage(msg2, async () => true) }) - it('does not emit "gap" if a gap is not detected (same timestamp but different sequenceNumbers)', () => { + it('does not emit "gap" if a gap is not detected (same timestamp but different sequenceNumbers)', async () => { const msg1 = msg const msg2 = createMsg(1, 1, 1, 0) - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + propagationTimeout: 100, + resendTimeout: 100, + }) sub.once('gap', () => { throw new Error() }) sub.handleBroadcastMessage(msg1, async () => true) sub.handleBroadcastMessage(msg2, async () => true) + await wait(100) }) }) @@ -352,10 +436,16 @@ describe('RealTimeSubscription', () => { const msg3 = createMsg(3, 0, 2, 0) const msg4 = createMsg(4, 0, 3, 0) const received = [] - - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), (content, receivedMsg) => { - received.push(receivedMsg) - }, {}, 100, 100, false) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: (content, receivedMsg) => { + received.push(receivedMsg) + }, + propagationTimeout: 100, + resendTimeout: 100, + orderMessages: false, + }) sub.once('gap', () => { throw new Error() }) await sub.handleBroadcastMessage(msg1, async () => true) @@ -375,8 +465,15 @@ describe('RealTimeSubscription', () => { const msg4 = createMsg(4, 0, 3, 0) const received = [] - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), (content, receivedMsg) => { - received.push(receivedMsg) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: (content, receivedMsg) => { + received.push(receivedMsg) + }, + propagationTimeout: 100, + resendTimeout: 100, + orderMessages: true, }) await sub.handleBroadcastMessage(msg1, async () => true) @@ -395,7 +492,11 @@ describe('RealTimeSubscription', () => { _bye: true, }) const handler = jest.fn() - const sub = new RealTimeSubscription(byeMsg.getStreamId(), byeMsg.getStreamPartition(), handler) + const sub = new RealTimeSubscription({ + streamId: byeMsg.getStreamId(), + streamPartition: byeMsg.getStreamPartition(), + callback: handler, + }) sub.once('done', () => { expect(handler).toHaveBeenCalledTimes(1) done() @@ -403,311 +504,18 @@ describe('RealTimeSubscription', () => { sub.handleBroadcastMessage(byeMsg, async () => true) }) - - describe('decryption', () => { - let sub - afterEach(() => { - sub.stop() - }) - - it('should read clear text content without trying to decrypt', (done) => { - const msg1 = createMsg(1, 0, null, 0, { - foo: 'bar', - }) - sub = new RealTimeSubscription(msg1.getStreamId(), msg1.getStreamPartition(), (content) => { - expect(content).toStrictEqual(msg1.getParsedContent()) - done() - }) - return sub.handleBroadcastMessage(msg1, async () => true) - }) - - it('should decrypt encrypted content with the correct key', (done) => { - const groupKey = crypto.randomBytes(32) - const data = { - foo: 'bar', - } - const msg1 = createMsg(1, 0, null, 0, data) - EncryptionUtil.encryptStreamMessage(msg1, groupKey) - sub = new RealTimeSubscription(msg1.getStreamId(), msg1.getStreamPartition(), (content) => { - expect(content).toStrictEqual(data) - done() - }, { - publisherId: groupKey, - }) - return sub.handleBroadcastMessage(msg1, async () => true) - }) - - it('should emit "groupKeyMissing" when not able to decrypt with the wrong key', (done) => { - const correctGroupKey = crypto.randomBytes(32) - const wrongGroupKey = crypto.randomBytes(32) - const msg1 = createMsg(1, 0, null, 0, { - foo: 'bar', - }) - EncryptionUtil.encryptStreamMessage(msg1, correctGroupKey) - sub = new RealTimeSubscription(msg1.getStreamId(), msg1.getStreamPartition(), () => {}, { - publisherId: wrongGroupKey, - }) - sub.once('groupKeyMissing', (publisherId) => { - expect(publisherId).toBe(msg1.getPublisherId()) - done() - }) - return sub.handleBroadcastMessage(msg1, async () => true) - }) - - it('emits "groupKeyMissing" multiple times before response received', (done) => { - const correctGroupKey = crypto.randomBytes(32) - const wrongGroupKey = crypto.randomBytes(32) - let counter = 0 - const msg1 = createMsg(1, 0, null, 0, { - foo: 'bar', - }) - EncryptionUtil.encryptStreamMessage(msg1, correctGroupKey) - sub = new RealTimeSubscription(msg1.getStreamId(), msg1.getStreamPartition(), () => {}, { - publisherId: wrongGroupKey, - }, 200) - sub.on('groupKeyMissing', (publisherId) => { - if (counter < 3) { - expect(publisherId).toBe(msg1.getPublisherId()) - counter += 1 - } else { - // fake group key response after 3 requests - sub.setGroupKeys(publisherId, [correctGroupKey]) - setTimeout(() => { - if (counter > 3) { - throw new Error('Sent additional group key request after response received.') - } - done() - }, 1000) - } - }) - return sub.handleBroadcastMessage(msg1, async () => true) - }) - - it('emits "groupKeyMissing" MAX_NB_GROUP_KEY_REQUESTS times before response received', (done) => { - const correctGroupKey = crypto.randomBytes(32) - const wrongGroupKey = crypto.randomBytes(32) - let counter = 0 - const msg1 = createMsg(1, 0, null, 0, { - foo: 'bar', - }) - const timeout = 200 - EncryptionUtil.encryptStreamMessage(msg1, correctGroupKey) - sub = new RealTimeSubscription(msg1.getStreamId(), msg1.getStreamPartition(), () => {}, { - publisherId: wrongGroupKey, - }, timeout) - let t - sub.on('groupKeyMissing', (publisherId) => { - expect(publisherId).toBe(msg1.getPublisherId()) - counter += 1 - clearTimeout(t) - t = setTimeout(() => { - expect(counter).toBe(AbstractSubscription.MAX_NB_GROUP_KEY_REQUESTS) - done() - }, timeout * (AbstractSubscription.MAX_NB_GROUP_KEY_REQUESTS + 2)) - }) - return sub.handleBroadcastMessage(msg1, async () => true) - }) - - it('should queue messages when not able to decrypt and handle them once the key is updated', async () => { - const correctGroupKey = crypto.randomBytes(32) - const wrongGroupKey = crypto.randomBytes(32) - const data1 = { - test: 'data1', - } - const data2 = { - test: 'data2', - } - const msg1 = createMsg(1, 0, null, 0, data1) - const msg2 = createMsg(2, 0, 1, 0, data2) - EncryptionUtil.encryptStreamMessage(msg1, correctGroupKey) - EncryptionUtil.encryptStreamMessage(msg2, correctGroupKey) - let received1 = null - let received2 = null - sub = new RealTimeSubscription(msg1.getStreamId(), msg1.getStreamPartition(), (content) => { - if (!received1) { - received1 = content - } else { - received2 = content - } - }, { - publisherId: wrongGroupKey, - }) - // cannot decrypt msg1, queues it and emits "groupKeyMissing" (should send group key request). - await sub.handleBroadcastMessage(msg1, async () => true) - // cannot decrypt msg2, queues it. - await sub.handleBroadcastMessage(msg2, async () => true) - // faking the reception of the group key response - sub.setGroupKeys('publisherId', [correctGroupKey]) - // try again to decrypt the queued messages but this time with the correct key - expect(received1).toStrictEqual(data1) - expect(received2).toStrictEqual(data2) - }) - - it('should queue messages when not able to decrypt and handle them once the keys are updated (multiple publishers)', async () => { - const groupKey1 = crypto.randomBytes(32) - const groupKey2 = crypto.randomBytes(32) - const wrongGroupKey = crypto.randomBytes(32) - const data1 = { - test: 'data1', - } - const data2 = { - test: 'data2', - } - const data3 = { - test: 'data3', - } - const data4 = { - test: 'data4', - } - const msg1 = createMsg(1, 0, null, 0, data1, 'publisherId1') - const msg2 = createMsg(2, 0, 1, 0, data2, 'publisherId1') - const msg3 = createMsg(1, 0, null, 0, data3, 'publisherId2') - const msg4 = createMsg(2, 0, 1, 0, data4, 'publisherId2') - EncryptionUtil.encryptStreamMessage(msg1, groupKey1) - EncryptionUtil.encryptStreamMessage(msg2, groupKey1) - EncryptionUtil.encryptStreamMessage(msg3, groupKey2) - EncryptionUtil.encryptStreamMessage(msg4, groupKey2) - const received = [] - sub = new RealTimeSubscription(msg1.getStreamId(), msg1.getStreamPartition(), (content) => { - received.push(content) - }, { - publisherId1: wrongGroupKey, - }) - // cannot decrypt msg1, queues it and emits "groupKeyMissing" (should send group key request). - await sub.handleBroadcastMessage(msg1, async () => true) - // cannot decrypt msg2, queues it. - await sub.handleBroadcastMessage(msg2, async () => true) - // cannot decrypt msg3, queues it and emits "groupKeyMissing" (should send group key request). - await sub.handleBroadcastMessage(msg3, async () => true) - // cannot decrypt msg4, queues it. - await sub.handleBroadcastMessage(msg4, async () => true) - // faking the reception of the group key response - sub.setGroupKeys('publisherId2', [groupKey2]) - sub.setGroupKeys('publisherId1', [groupKey1]) - // try again to decrypt the queued messages but this time with the correct key - expect(received[0]).toStrictEqual(data3) - expect(received[1]).toStrictEqual(data4) - expect(received[2]).toStrictEqual(data1) - expect(received[3]).toStrictEqual(data2) - }) - - it('should queue messages when cannot decrypt and handle them once the keys are updated (multiple publishers interleaved)', async () => { - const groupKey1 = crypto.randomBytes(32) - const groupKey2 = crypto.randomBytes(32) - const wrongGroupKey = crypto.randomBytes(32) - const data1 = { - test: 'data1', - } - const data2 = { - test: 'data2', - } - const data3 = { - test: 'data3', - } - const data4 = { - test: 'data4', - } - const data5 = { - test: 'data5', - } - const msg1Pub1 = createMsg(1, 0, null, 0, data1, 'publisherId1') - const msg2Pub1 = createMsg(2, 0, 1, 0, data2, 'publisherId1') - const msg3Pub1 = createMsg(3, 0, 2, 0, data3, 'publisherId1') - const msg1Pub2 = createMsg(1, 0, null, 0, data4, 'publisherId2') - const msg2Pub2 = createMsg(2, 0, 1, 0, data5, 'publisherId2') - EncryptionUtil.encryptStreamMessage(msg1Pub1, groupKey1) - EncryptionUtil.encryptStreamMessage(msg2Pub1, groupKey1) - EncryptionUtil.encryptStreamMessage(msg1Pub2, groupKey2) - EncryptionUtil.encryptStreamMessage(msg2Pub2, groupKey2) - const received = [] - sub = new RealTimeSubscription(msg1Pub1.getStreamId(), msg1Pub1.getStreamPartition(), (content) => { - received.push(content) - }, { - publisherId1: wrongGroupKey, - }) - await sub.handleBroadcastMessage(msg1Pub1, async () => true) - await sub.handleBroadcastMessage(msg1Pub2, async () => true) - await sub.handleBroadcastMessage(msg2Pub1, async () => true) - sub.setGroupKeys('publisherId1', [groupKey1]) - await sub.handleBroadcastMessage(msg3Pub1, async () => true) - await sub.handleBroadcastMessage(msg2Pub2, async () => true) - sub.setGroupKeys('publisherId2', [groupKey2]) - - // try again to decrypt the queued messages but this time with the correct key - expect(received[0]).toStrictEqual(data1) - expect(received[1]).toStrictEqual(data2) - expect(received[2]).toStrictEqual(data3) - expect(received[3]).toStrictEqual(data4) - expect(received[4]).toStrictEqual(data5) - }) - - it('should call "onUnableToDecrypt" when not able to decrypt for the second time', async () => { - const correctGroupKey = crypto.randomBytes(32) - const wrongGroupKey = crypto.randomBytes(32) - const otherWrongGroupKey = crypto.randomBytes(32) - const msg1 = createMsg(1, 0, null, 0, { - test: 'data1', - }) - const msg2 = createMsg(2, 0, 1, 0, { - test: 'data2', - }) - EncryptionUtil.encryptStreamMessage(msg1, correctGroupKey) - EncryptionUtil.encryptStreamMessage(msg2, correctGroupKey) - let undecryptableMsg = null - sub = new RealTimeSubscription(msg1.getStreamId(), msg1.getStreamPartition(), () => { - throw new Error('should not call the handler') - }, { - publisherId: wrongGroupKey, - }, 5000, 5000, true, (error) => { - undecryptableMsg = error.streamMessage - }) - // cannot decrypt msg1, emits "groupKeyMissing" (should send group key request). - await sub.handleBroadcastMessage(msg1, async () => true) - // cannot decrypt msg2, queues it. - await sub.handleBroadcastMessage(msg2, async () => true) - // faking the reception of the group key response - sub.setGroupKeys('publisherId', [otherWrongGroupKey]) - expect(undecryptableMsg).toStrictEqual(msg2) - }) - - it('should decrypt first content, update key and decrypt second content', async (done) => { - const groupKey1 = crypto.randomBytes(32) - const groupKey2 = crypto.randomBytes(32) - const data1 = { - test: 'data1', - } - const data2 = { - test: 'data2', - } - const msg1 = createMsg(1, 0, null, 0, data1) - const msg2 = createMsg(2, 0, 1, 0, data2) - EncryptionUtil.encryptStreamMessageAndNewKey(groupKey2, msg1, groupKey1) - EncryptionUtil.encryptStreamMessage(msg2, groupKey2) - let test1Ok = false - sub = new RealTimeSubscription(msg1.getStreamId(), msg1.getStreamPartition(), (content) => { - if (JSON.stringify(content) === JSON.stringify(data1)) { - expect(sub.groupKeys[msg1.getPublisherId().toLowerCase()]).toStrictEqual(groupKey2) - test1Ok = true - } else if (test1Ok && JSON.stringify(content) === JSON.stringify(data2)) { - done() - } - }, { - publisherId: groupKey1, - }) - await sub.handleBroadcastMessage(msg1, async () => true) - return sub.handleBroadcastMessage(msg2, async () => true) - }) - }) }) describe('handleError()', () => { it('emits an error event', (done) => { const err = new Error('Test error') - const sub = new RealTimeSubscription( - msg.getStreamId(), - msg.getStreamPartition(), - () => { throw new Error('Msg handler should not be called!') }, - ) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => { + throw new Error('Msg handler should not be called!') + }, + }) sub.onError = jest.fn() sub.once('error', (thrown) => { expect(err === thrown).toBeTruthy() @@ -717,11 +525,15 @@ describe('RealTimeSubscription', () => { }) it('marks the message as received if an InvalidJsonError occurs, and continue normally on next message', async (done) => { - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), (content, receivedMsg) => { - if (receivedMsg.getTimestamp() === 3) { - sub.stop() - done() - } + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: (content, receivedMsg) => { + if (receivedMsg.getTimestamp() === 3) { + sub.stop() + done() + } + }, }) sub.onError = jest.fn() @@ -742,7 +554,13 @@ describe('RealTimeSubscription', () => { }) it('if an InvalidJsonError AND a gap occur, does not mark it as received and emits gap at the next message', async (done) => { - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}, {}, 100, 100) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + propagationTimeout: 100, + resendTimeout: 100, + }) sub.onError = jest.fn() sub.once('gap', (from, to, publisherId) => { @@ -774,12 +592,20 @@ describe('RealTimeSubscription', () => { describe('setState()', () => { it('updates the state', () => { - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + }) sub.setState(Subscription.State.subscribed) expect(sub.getState()).toEqual(Subscription.State.subscribed) }) it('fires an event', (done) => { - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + }) sub.once(Subscription.State.subscribed, done) sub.setState(Subscription.State.subscribed) }) @@ -787,7 +613,11 @@ describe('RealTimeSubscription', () => { describe('handleResending()', () => { it('emits the resending event', (done) => { - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + }) sub.addPendingResendRequestId('requestId') sub.once('resending', () => done()) sub.setResending(true) @@ -802,7 +632,11 @@ describe('RealTimeSubscription', () => { describe('handleResent()', () => { it('arms the Subscription to emit the resent event on last message (message handler completes BEFORE resent)', async (done) => { const handler = jest.fn() - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), handler) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + }) sub.addPendingResendRequestId('requestId') sub.once('resent', () => { expect(handler).toHaveBeenCalledTimes(1) @@ -819,7 +653,11 @@ describe('RealTimeSubscription', () => { it('arms the Subscription to emit the resent event on last message (message handler completes AFTER resent)', async (done) => { const handler = jest.fn() - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), handler) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: handler, + }) sub.addPendingResendRequestId('requestId') sub.once('resent', () => { expect(handler).toHaveBeenCalledTimes(1) @@ -842,7 +680,11 @@ describe('RealTimeSubscription', () => { }) it('cleans up the resend if event handler throws', async () => { - sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}) + sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + }) sub.onError = jest.fn() const error = new Error('test error, ignore') sub.addPendingResendRequestId('requestId') @@ -862,7 +704,11 @@ describe('RealTimeSubscription', () => { describe('handleNoResend()', () => { it('emits the no_resend event', async () => { - const sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}) + const sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + }) sub.addPendingResendRequestId('requestId') const onNoResent = new Promise((resolve) => sub.once('no_resend', resolve)) sub.setResending(true) @@ -883,7 +729,11 @@ describe('RealTimeSubscription', () => { }) it('cleans up the resend if event handler throws', async () => { - sub = new RealTimeSubscription(msg.getStreamId(), msg.getStreamPartition(), () => {}) + sub = new RealTimeSubscription({ + streamId: msg.getStreamId(), + streamPartition: msg.getStreamPartition(), + callback: () => {}, + }) sub.onError = jest.fn() const error = new Error('test error, ignore') sub.addPendingResendRequestId('requestId') diff --git a/test/unit/StreamrClient.test.js b/test/legacy/StreamrClient.test.js similarity index 60% rename from test/unit/StreamrClient.test.js rename to test/legacy/StreamrClient.test.js index 851f30f6a..1ff9bd221 100644 --- a/test/unit/StreamrClient.test.js +++ b/test/legacy/StreamrClient.test.js @@ -1,22 +1,19 @@ -import crypto from 'crypto' - -import EventEmitter from 'eventemitter3' import sinon from 'sinon' -import debug from 'debug' import { Wallet } from 'ethers' import { ControlLayer, MessageLayer, Errors } from 'streamr-client-protocol' -import { wait } from 'streamr-test-utils' +import { wait, waitForEvent } from 'streamr-test-utils' +import Debug from 'debug' import FailedToPublishError from '../../src/errors/FailedToPublishError' -import Connection from '../../src/Connection' import Subscription from '../../src/Subscription' -import KeyExchangeUtil from '../../src/KeyExchangeUtil' -// import StreamrClient from '../../src/StreamrClient' +import Connection from '../../src/Connection' import { uid } from '../utils' // eslint-disable-next-line import/no-named-as-default-member import StubbedStreamrClient from './StubbedStreamrClient' +/* eslint-disable no-underscore-dangle */ + const { ControlMessage, BroadcastMessage, @@ -35,64 +32,17 @@ const { } = ControlLayer const { StreamMessage, MessageRef, MessageID, MessageIDStrict } = MessageLayer -const { getKeyExchangeStreamId } = KeyExchangeUtil -const mockDebug = debug('mock') + +console.log = Debug('Streamr:: CONSOLE ') describe('StreamrClient', () => { let client let connection - let asyncs = [] let requests = [] const streamPartition = 0 const sessionToken = 'session-token' - function async(func) { - const me = setTimeout(() => { - expect(me).toEqual(asyncs[0]) - asyncs.shift() - func() - }, 0) - asyncs.push(me) - } - - function clearAsync() { - asyncs.forEach((it) => { - clearTimeout(it) - }) - asyncs = [] - } - - function setupSubscription( - streamId, emitSubscribed = true, subscribeOptions = {}, handler = sinon.stub(), - expectSubscribeRequest = !client.getSubscriptions(streamId).length, - ) { - expect(client.isConnected()).toBeTruthy() - const requestId = uid('request') - - if (expectSubscribeRequest) { - connection.expect(new SubscribeRequest({ - requestId, - streamId, - streamPartition, - sessionToken, - })) - } - const sub = client.subscribe({ - stream: streamId, - ...subscribeOptions, - }, handler) - - if (emitSubscribed) { - connection.emitMessage(new SubscribeResponse({ - streamId: sub.streamId, - requestId, - streamPartition, - })) - } - return sub - } - function getStreamMessage(streamId = 'stream1', content = {}, publisherId = '') { const timestamp = Date.now() return new StreamMessage({ @@ -107,41 +57,19 @@ describe('StreamrClient', () => { } function createConnectionMock() { - const c = new EventEmitter() - c.state = Connection.State.DISCONNECTED + const c = new Connection({}) c.expectedMessagesToSend = [] - c.connect = () => new Promise((resolve) => { - mockDebug('Connection mock: connecting') - c.state = Connection.State.CONNECTING - async(() => { - mockDebug('Connection mock: connected') - c.state = Connection.State.CONNECTED - c.emit('connected') - resolve() - }) - }) - - c.clearReconnectTimeout = () => {} - - c.disconnect = () => new Promise((resolve) => { - mockDebug('Connection mock: disconnecting') - c.state = Connection.State.DISCONNECTING - async(() => { - mockDebug('Connection mock: disconnected') - c.state = Connection.State.DISCONNECTED - c.emit('disconnected') - resolve() - }) - }) - - c.send = jest.fn(async (request) => { + c._send = jest.fn(async (request) => { requests.push(request) }) c.emitMessage = (message) => { - c.emit(message.type, message) + c.emit('message', { + type: 'message', + data: message.serialize(), + }) } return c @@ -153,14 +81,13 @@ describe('StreamrClient', () => { errors.push(error) } - function mockSubscription(...opts) { - let sub - connection.send = jest.fn(async (request) => { + async function mockSubscription(...opts) { + connection._send = jest.fn(async (request) => { requests.push(request) await wait() if (request.type === ControlMessage.TYPES.SubscribeRequest) { connection.emitMessage(new SubscribeResponse({ - streamId: sub.streamId, + streamId: request.streamId, requestId: request.requestId, streamPartition: request.streamPartition, })) @@ -168,88 +95,124 @@ describe('StreamrClient', () => { if (request.type === ControlMessage.TYPES.UnsubscribeRequest) { connection.emitMessage(new UnsubscribeResponse({ - streamId: sub.streamId, + streamId: request.streamId, requestId: request.requestId, streamPartition: request.streamPartition, })) } }) - sub = client.subscribe(...opts).on('error', onError) - return sub + return client.subscribe(...opts) } const STORAGE_DELAY = 2000 beforeEach(() => { - clearAsync() + errors = [] + requests = [] connection = createConnectionMock() client = new StubbedStreamrClient({ autoConnect: false, autoDisconnect: false, verifySignatures: 'never', retryResendAfter: STORAGE_DELAY, + url: 'wss://echo.websocket.org/', auth: { sessionToken: 'session-token', }, }, connection) - errors = [] - requests = [] + + connection.options = client.options client.on('error', onError) }) - afterEach(async () => { + afterEach(() => { client.removeListener('error', onError) - await client.ensureDisconnected() expect(errors[0]).toBeFalsy() expect(errors).toHaveLength(0) }) + afterEach(async () => { + await client.disconnect() + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + throw new Error(`sockets not closed: ${openSockets}`) + } + }) + afterAll(async () => { await wait(3000) // give tests a few more moments to clean up }) describe('connecting behaviour', () => { - it('connected event should emit an event on client', (done) => { - client.once('connected', () => { - done() - }) - client.connect() + it('connected event should emit an event on client', async () => { + const onConnected = jest.fn() + client.once('connected', onConnected) + await client.connect() + expect(onConnected).toHaveBeenCalledTimes(1) }) it('should not send anything if not subscribed to anything', async () => { - await client.ensureConnected() - expect(connection.send).not.toHaveBeenCalled() + await client.connect() + expect(connection._send).not.toHaveBeenCalled() }) it('should send pending subscribes', async () => { - client.subscribe('stream1', () => {}).on('error', onError) + const t = mockSubscription('stream1', () => {}) - await client.ensureConnected() + await client.connect() await wait() - expect(connection.send.mock.calls).toHaveLength(1) - expect(connection.send.mock.calls[0][0]).toMatchObject({ + await t + expect(connection._send.mock.calls).toHaveLength(1) + expect(connection._send.mock.calls[0][0]).toMatchObject({ streamId: 'stream1', streamPartition, sessionToken, }) }) - it('should send pending subscribes when disconnected and then reconnected', async () => { - client.subscribe('stream1', () => {}).on('error', onError) - await client.ensureConnected() - await connection.disconnect() - await client.ensureConnected() - await wait(100) - expect(connection.send.mock.calls).toHaveLength(2) + it('should reconnect subscriptions when connection disconnected before subscribed & reconnected', async () => { + await client.connect() + let subscribed = false + const t = mockSubscription('stream1', () => {}).then((v) => { + subscribed = true + return v + }) + connection.socket.close() + expect(subscribed).toBe(false) // shouldn't have subscribed yet + // no connect necessary should connect and subscribe + await t + expect(connection._send.mock.calls).toHaveLength(2) // On connect - expect(connection.send.mock.calls[0][0]).toMatchObject({ + expect(connection._send.mock.calls[0][0]).toMatchObject({ streamId: 'stream1', streamPartition, sessionToken, }) // On reconnect - expect(connection.send.mock.calls[1][0]).toMatchObject({ + expect(connection._send.mock.calls[1][0]).toMatchObject({ + streamId: 'stream1', + streamPartition, + sessionToken, + }) + }) + + it('should re-subscribe when subscribed then reconnected', async () => { + await client.connect() + await mockSubscription('stream1', () => {}) + connection.socket.close() + await client.nextConnection() + // no connect necessary should auto-reconnect and subscribe + expect(connection._send.mock.calls).toHaveLength(2) + // On connect + expect(connection._send.mock.calls[0][0]).toMatchObject({ + streamId: 'stream1', + streamPartition, + sessionToken, + }) + + // On reconnect + expect(connection._send.mock.calls[1][0]).toMatchObject({ streamId: 'stream1', streamPartition, sessionToken, @@ -258,125 +221,123 @@ describe('StreamrClient', () => { // TODO convert and move all super mocked tests to integration }) - describe('disconnection behaviour', () => { - beforeEach(async () => client.ensureConnected()) + describe('promise subscribe behaviour', () => { + beforeEach(async () => client.connect()) + + it('works', async () => { + const sub = await mockSubscription('stream1', () => {}) + expect(sub).toBeTruthy() + expect(sub.streamId).toBe('stream1') + await client.unsubscribe(sub) + expect(client.getSubscriptions(sub.streamId)).toEqual([]) + }) + }) + + describe.only('disconnection behaviour', () => { + beforeEach(async () => client.connect()) it('emits disconnected event on client', async (done) => { - client.once('disconnected', done) + client.once('disconnected', () => done()) await connection.disconnect() }) - it('does not remove subscriptions', async () => { - const sub = client.subscribe('stream1', () => {}).on('error', onError) - await connection.disconnect() - expect(client.getSubscriptions(sub.streamId)).toEqual([sub]) + it('removes subscriptions', async () => { + const sub = await mockSubscription('stream1', () => {}) + await client.disconnect() + expect(client.getSubscriptions(sub.streamId)).toEqual([]) + }) + + it('does not remove subscriptions if disconnected accidentally', async () => { + const sub = await mockSubscription('stream1', () => {}) + client.connection.socket.close() + await waitForEvent(client, 'disconnected') + expect(client.getSubscriptions(sub.streamId)).toHaveLength(1) + expect(sub.getState()).toEqual(Subscription.State.unsubscribed) + await client.connect() + expect(client.getSubscriptions(sub.streamId)).toHaveLength(1) + // re-subscribes + expect(sub.getState()).toEqual(Subscription.State.subscribing) }) it('sets subscription state to unsubscribed', async () => { - const sub = client.subscribe('stream1', () => {}).on('error', onError) + const sub = await mockSubscription('stream1', () => {}) await connection.disconnect() expect(sub.getState()).toEqual(Subscription.State.unsubscribed) }) }) describe('SubscribeResponse', () => { - beforeEach(async () => client.ensureConnected()) + beforeEach(async () => client.connect()) - it('marks Subscriptions as subscribed', async (done) => { - const sub = mockSubscription('stream1', () => {}) - sub.once('subscribed', () => { - expect(sub.getState()).toEqual(Subscription.State.subscribed) - done() - }) + it('marks Subscriptions as subscribed', async () => { + const sub = await mockSubscription('stream1', () => {}) + expect(sub.getState()).toEqual(Subscription.State.subscribed) }) - it('generates a requestId without resend', (done) => { - const sub = mockSubscription({ + it('generates a requestId without resend', async () => { + await mockSubscription({ stream: 'stream1', }, () => {}) - sub.once('subscribed', () => { - const { requestId } = requests[0] - expect(requestId).toBeTruthy() - done() - }) + const { requestId } = requests[0] + expect(requestId).toBeTruthy() }) - it('emits a resend request if resend options were given. No second resend if a message is received.', (done) => { - const sub = mockSubscription({ + it('emits a resend request if resend options were given. No second resend if a message is received.', async () => { + const sub = await mockSubscription({ stream: 'stream1', resend: { last: 1, }, }, () => {}) - sub.once('subscribed', async () => { - await wait(100) - const { requestId } = requests[requests.length - 1] - const streamMessage = getStreamMessage(sub.streamId, {}) - connection.emitMessage(new UnicastMessage({ - requestId, - streamMessage, - })) - await wait(STORAGE_DELAY) - sub.stop() - await wait() - expect(connection.send.mock.calls).toHaveLength(2) // sub + resend - expect(connection.send.mock.calls[1][0]).toMatchObject({ - type: ControlMessage.TYPES.ResendLastRequest, - streamId: sub.streamId, - streamPartition: sub.streamPartition, - requestId, - numberLast: 1, - sessionToken: 'session-token' - }) - done() + await wait(100) + const { requestId, type } = requests[requests.length - 1] + expect(type).toEqual(ControlMessage.TYPES.ResendLastRequest) + const streamMessage = getStreamMessage(sub.streamId, {}) + connection.emitMessage(new UnicastMessage({ + requestId, + streamMessage, + })) + await wait(STORAGE_DELAY) + sub.stop() + await wait() + expect(connection._send.mock.calls).toHaveLength(2) // sub + resend + expect(connection._send.mock.calls[1][0]).toMatchObject({ + type: ControlMessage.TYPES.ResendLastRequest, + streamId: sub.streamId, + streamPartition: sub.streamPartition, + requestId, + numberLast: 1, + sessionToken: 'session-token' }) }, STORAGE_DELAY + 1000) - it('emits multiple resend requests as per multiple subscriptions. No second resends if messages are received.', async (done) => { - const sub1 = mockSubscription({ - stream: 'stream1', - resend: { - last: 2, - }, - }, () => {}) - const sub2 = mockSubscription({ - stream: 'stream1', - resend: { - last: 1, - }, - }, () => {}) - - let requestId1 - let requestId2 - - await Promise.all([ - new Promise((resolve) => { - sub1.once('subscribed', async () => { - await wait(200) - requestId1 = requests[requests.length - 2].requestId - const streamMessage = getStreamMessage(sub1.streamId, {}) - connection.emitMessage(new UnicastMessage({ - requestId: requestId1, - streamMessage, - })) - resolve() - }) - }), - new Promise((resolve) => { - sub2.once('subscribed', async () => { - await wait(200) - requestId2 = requests[requests.length - 1].requestId - const streamMessage = getStreamMessage(sub2.streamId, {}) - connection.emitMessage(new UnicastMessage({ - requestId: requestId2, - streamMessage, - })) - resolve() - }) - }) + it('emits multiple resend requests as per multiple subscriptions. No second resends if messages are received.', async () => { + const [sub1, sub2] = await Promise.all([ + mockSubscription({ + stream: 'stream1', + resend: { + last: 2, + }, + }, () => {}), + mockSubscription({ + stream: 'stream1', + resend: { + last: 1, + }, + }, () => {}) ]) + const requestId1 = requests.find((r) => r.numberLast === 2).requestId + connection.emitMessage(new UnicastMessage({ + requestId: requestId1, + streamMessage: getStreamMessage(sub1.streamId, {}) + })) + + const requestId2 = requests.find((r) => r.numberLast === 1).requestId + connection.emitMessage(new UnicastMessage({ + requestId: requestId2, + streamMessage: getStreamMessage(sub2.streamId, {}) + })) - await wait(STORAGE_DELAY + 400) sub1.stop() sub2.stop() @@ -396,8 +357,10 @@ describe('StreamrClient', () => { sessionToken: 'session-token', }) ] - // eslint-disable-next-line semi-style - ;[connection.send.mock.calls[1][0], connection.send.mock.calls[2][0]].forEach((actual, index) => { + + const calls = connection._send.mock.calls.filter(([o]) => [requestId1, requestId2].includes(o.requestId)) + expect(calls).toHaveLength(2) + calls.forEach(([actual], index) => { const expected = expectedResponses[index] expect(actual).toMatchObject({ requestId: expected.requestId, @@ -407,28 +370,24 @@ describe('StreamrClient', () => { sessionToken: expected.sessionToken, }) }) - done() }, STORAGE_DELAY + 1000) }) describe('UnsubscribeResponse', () => { // Before each test, client is connected, subscribed, and unsubscribe() is called let sub - beforeEach(async (done) => { - await client.ensureConnected() - sub = mockSubscription('stream1', () => {}) - sub.once('subscribed', () => done()) + beforeEach(async () => { + await client.connect() + sub = await mockSubscription('stream1', () => {}) }) it('removes the subscription', async () => { - client.unsubscribe(sub) - await wait() + await client.unsubscribe(sub) expect(client.getSubscriptions(sub.streamId)).toEqual([]) }) it('sets Subscription state to unsubscribed', async () => { - client.unsubscribe(sub) - await wait() + await client.unsubscribe(sub) expect(sub.getState()).toEqual(Subscription.State.unsubscribed) }) @@ -439,10 +398,8 @@ describe('StreamrClient', () => { }) it('calls connection.disconnect() when no longer subscribed to any streams', async () => { - const disconnect = jest.spyOn(connection, 'disconnect') - client.unsubscribe(sub) - await wait(100) - expect(disconnect).toHaveBeenCalled() + await client.unsubscribe(sub) + expect(client.isDisconnected()).toBeTruthy() }) }) @@ -452,10 +409,8 @@ describe('StreamrClient', () => { }) it('should not disconnect if autoDisconnect is set to false', async () => { - const disconnect = jest.spyOn(connection, 'disconnect') - client.unsubscribe(sub) - await wait(100) - expect(disconnect).not.toHaveBeenCalled() + await client.unsubscribe(sub) + expect(client.isConnected()).toBeTruthy() }) }) }) @@ -466,13 +421,13 @@ describe('StreamrClient', () => { beforeEach(async () => { await client.connect() - sub = mockSubscription('stream1', () => {}) + sub = await mockSubscription('stream1', () => {}) }) - it('should call the message handler of each subscription', () => { + it('should call the message handler of each subscription', async () => { sub.handleBroadcastMessage = jest.fn() - const sub2 = setupSubscription('stream1') + const sub2 = await mockSubscription('stream1', () => {}) sub2.handleBroadcastMessage = jest.fn() const requestId = uid('broadcastMessage') const msg1 = new BroadcastMessage({ @@ -482,6 +437,7 @@ describe('StreamrClient', () => { connection.emitMessage(msg1) expect(sub.handleBroadcastMessage).toHaveBeenCalledWith(msg1.streamMessage, expect.any(Function)) + expect(sub2.handleBroadcastMessage).toHaveBeenCalledWith(msg1.streamMessage, expect.any(Function)) }) it('should not crash if messages are received for unknown streams', () => { @@ -493,14 +449,14 @@ describe('StreamrClient', () => { connection.emitMessage(msg1) }) - it('should ensure that the promise returned by the verification function is cached and returned for all handlers', (done) => { + it('should ensure that the promise returned by the verification function is cached and returned for all handlers', async (done) => { let firstResult sub.handleBroadcastMessage = (message, verifyFn) => { firstResult = verifyFn() expect(firstResult).toBeInstanceOf(Promise) expect(verifyFn()).toBe(firstResult) } - const sub2 = mockSubscription('stream1', () => {}) + const sub2 = await mockSubscription('stream1', () => {}) sub2.handleBroadcastMessage = (message, verifyFn) => { firstResult = verifyFn() expect(firstResult).toBeInstanceOf(Promise) @@ -523,15 +479,14 @@ describe('StreamrClient', () => { describe('UnicastMessage', () => { let sub - beforeEach(async (done) => { + beforeEach(async () => { await client.connect() - sub = mockSubscription({ + sub = await mockSubscription({ stream: 'stream1', resend: { last: 5, }, }, () => {}) - .once('subscribed', () => done()) }) it('should call the message handler of specified Subscription', async () => { @@ -539,7 +494,6 @@ describe('StreamrClient', () => { sub.handleResentMessage = jest.fn() const { requestId } = requests[requests.length - 1] expect(requestId).toBeTruthy() - // this sub's handler must not be called const sub2 = mockSubscription('stream1', () => {}) sub2.handleResentMessage = jest.fn() @@ -593,15 +547,14 @@ describe('StreamrClient', () => { describe('ResendResponseResending', () => { let sub - beforeEach(async (done) => { + beforeEach(async () => { await client.connect() - sub = mockSubscription({ + sub = await mockSubscription({ stream: 'stream1', resend: { last: 5, }, }, () => {}) - .once('subscribed', () => done()) }) it('emits event on associated subscription', async () => { @@ -639,14 +592,14 @@ describe('StreamrClient', () => { describe('ResendResponseNoResend', () => { let sub - beforeEach(async (done) => { + beforeEach(async () => { await client.connect() - sub = mockSubscription({ + sub = await mockSubscription({ stream: 'stream1', resend: { last: 5, }, - }, () => {}).once('subscribed', () => done()) + }, () => {}) }) it('calls event handler on subscription', () => { @@ -683,14 +636,14 @@ describe('StreamrClient', () => { describe('ResendResponseResent', () => { let sub - beforeEach(async (done) => { + beforeEach(async () => { await client.connect() - sub = mockSubscription({ + sub = await mockSubscription({ stream: 'stream1', resend: { last: 5, }, - }, () => {}).once('subscribed', () => done()) + }, () => {}) }) it('calls event handler on subscription', () => { @@ -725,14 +678,14 @@ describe('StreamrClient', () => { }) describe('ErrorResponse', () => { - beforeEach(async (done) => { + beforeEach(async () => { await client.connect() - mockSubscription({ + await mockSubscription({ stream: 'stream1', resend: { last: 5, } - }, () => {}).once('subscribed', () => done()) + }, () => {}) }) it('emits an error event on client', (done) => { @@ -744,7 +697,7 @@ describe('StreamrClient', () => { errorCode: 'error code' }) - client.once('error', async (err) => { + client.once('error', (err) => { errors.pop() expect(err.message).toEqual(errorResponse.errorMessage) expect(client.onError).toHaveBeenCalled() @@ -757,9 +710,9 @@ describe('StreamrClient', () => { describe('error', () => { let sub - beforeEach(async (done) => { + beforeEach(async () => { await client.connect() - sub = mockSubscription('stream1', () => {}).once('subscribed', () => done()) + sub = await mockSubscription('stream1', () => {}) }) it('reports InvalidJsonErrors to subscriptions', (done) => { @@ -771,7 +724,7 @@ describe('StreamrClient', () => { ) sub.handleError = async (err) => { - expect(err).toBe(jsonError) + expect(err && err.message).toMatch(jsonError.message) done() } connection.emit('error', jsonError) @@ -781,14 +734,12 @@ describe('StreamrClient', () => { client.onError = jest.fn() const testError = new Error('This is a test error message, ignore') - client.once('error', async (err) => { - expect(err).toBe(testError) + client.once('error', (err) => { + errors.pop() + expect(err.message).toMatch(testError.message) expect(client.onError).toHaveBeenCalled() done() }) - client.once('error', () => { - errors.pop() - }) connection.emit('error', testError) }) }) @@ -799,83 +750,42 @@ describe('StreamrClient', () => { expect(result).toBeInstanceOf(Promise) await result }) - - it('should call connection.connect()', () => { - connection.connect = jest.fn(async () => {}) - client.connect() - expect(connection.connect).toHaveBeenCalledTimes(1) - }) - - it('should reject promise while connecting', async (done) => { - client.onError = jest.fn() - connection.state = Connection.State.CONNECTING - client.once('error', (err) => { - errors.pop() - expect(err).toMatchObject({ - message: 'Already connecting!' - }) - expect(client.onError).toHaveBeenCalledTimes(1) - done() - }) - await expect(() => ( - client.connect() - )).rejects.toThrow() - }) - - it('should reject promise when connected', async (done) => { - client.onError = jest.fn() - connection.state = Connection.State.CONNECTED - client.once('error', (err) => { - errors.pop() - expect(err).toMatchObject({ - message: 'Already connected!' - }) - expect(client.onError).toHaveBeenCalledTimes(1) - done() - }) - await expect(() => ( - client.connect() - )).rejects.toThrow() - }) }) describe('resend()', () => { - async function mockResend(...opts) { - let sub - connection.send = jest.fn(async (request) => { - requests.push(request) - await wait() - if (request.type === ControlMessage.TYPES.SubscribeRequest) { - connection.emitMessage(new SubscribeResponse({ - streamId: sub.streamId, - requestId: request.requestId, - streamPartition, - })) - } + beforeEach(() => { + client.options.autoConnect = true + }) - if (request.type === ControlMessage.TYPES.UnsubscribeRequest) { - connection.emitMessage(new UnsubscribeResponse({ - streamId: sub.streamId, - requestId: request.requestId, - streamPartition, - })) - } - }) - sub = await client.resend(...opts) + async function mockResend(...opts) { + const sub = await client.resend(...opts) sub.on('error', onError) return sub } - it('should not send SubscribeRequest on reconnection', async () => { + it('should reject if cannot send', async () => { + client.options.autoConnect = false + await expect(async () => { + await mockResend({ + stream: 'stream1', + resend: { + last: 10 + } + }, () => {}) + }).rejects.toThrow() + }) + + it('should not send SubscribeRequest/ResendRequest on reconnection', async () => { await mockResend({ stream: 'stream1', resend: { last: 10 } }, () => {}) - await client.pause() - await client.connect() - expect(connection.send.mock.calls.filter(([arg]) => arg.type === ControlMessage.TYPES.SubscribeRequest)).toHaveLength(0) + client.connection.socket.close() + await client.nextConnection() + client.debug(connection._send.mock.calls) + expect(connection._send.mock.calls.filter(([arg]) => arg.type === ControlMessage.TYPES.SubscribeRequest)).toHaveLength(0) }) it('should not send SubscribeRequest after ResendResponseNoResend on reconnection', async () => { @@ -885,6 +795,7 @@ describe('StreamrClient', () => { last: 10 } }, () => {}) + const { requestId } = requests[requests.length - 1] const resendResponse = new ResendResponseNoResend({ streamId: sub.streamId, @@ -892,9 +803,9 @@ describe('StreamrClient', () => { requestId, }) connection.emitMessage(resendResponse) - await client.pause() - await client.connect() - expect(connection.send.mock.calls.filter(([arg]) => arg.type === ControlMessage.TYPES.SubscribeRequest)).toHaveLength(0) + client.connection.socket.close() + await client.nextConnection() + expect(connection._send.mock.calls.filter(([arg]) => arg.type === ControlMessage.TYPES.SubscribeRequest)).toHaveLength(0) }) it('should not send SubscribeRequest after ResendResponseResent on reconnection', async () => { @@ -917,94 +828,71 @@ describe('StreamrClient', () => { requestId, }) connection.emitMessage(resendResponse) - await client.pause() + connection.socket.close() await client.connect() expect(requests.filter((req) => req.type === ControlMessage.TYPES.SubscribeRequest)).toHaveLength(0) }) }) describe('subscribe()', () => { - it('should call client.connect() if autoConnect is set to true', (done) => { + it('should connect if autoConnect is set to true', async () => { client.options.autoConnect = true - client.once('connected', done) - - client.subscribe('stream1', () => {}) + await mockSubscription('stream1', () => {}) }) describe('when connected', () => { beforeEach(() => client.connect()) it('throws an error if no options are given', () => { - expect(() => { + expect(() => ( client.subscribe(undefined, () => {}) - }).toThrow() + )).rejects.toThrow() }) it('throws an error if options is wrong type', () => { - expect(() => { + expect(() => ( client.subscribe(['streamId'], () => {}) - }).toThrow() + )).rejects.toThrow() }) it('throws an error if no callback is given', () => { - expect(() => { + expect(() => ( client.subscribe('stream1') - }).toThrow() + )).rejects.toThrow() }) - it('sends a subscribe request', (done) => { - const sub = mockSubscription('stream1', () => {}) - sub.once('subscribed', () => { - const lastRequest = requests[requests.length - 1] - expect(lastRequest).toEqual(new SubscribeRequest({ - streamId: sub.streamId, - streamPartition: sub.streamPartition, - requestId: lastRequest.requestId, - sessionToken: 'session-token' - })) - done() - }) - }) - - it('sets the group keys if passed as arguments', () => { - const groupKey = crypto.randomBytes(32) - const sub = client.subscribe({ - stream: 'stream1', - groupKeys: { - publisherId: groupKey - } - }, () => {}) - expect(client.options.subscriberGroupKeys).toHaveProperty('stream1.publisherId.start') - expect(client.options.subscriberGroupKeys.stream1.publisherId.groupKey).toEqual(groupKey) - expect(sub.groupKeys['publisherId'.toLowerCase()]).toEqual(groupKey) + it('sends a subscribe request', async () => { + const sub = await mockSubscription('stream1', () => {}) + const lastRequest = requests[requests.length - 1] + expect(lastRequest).toEqual(new SubscribeRequest({ + streamId: sub.streamId, + streamPartition: sub.streamPartition, + requestId: lastRequest.requestId, + sessionToken: 'session-token' + })) }) - it('sends a subscribe request for a given partition', (done) => { - const sub = mockSubscription({ + it('sends a subscribe request for a given partition', async () => { + const sub = await mockSubscription({ stream: 'stream1', partition: 5, - }, () => {}).once('subscribed', () => { - const lastRequest = requests[requests.length - 1] - expect(lastRequest).toEqual(new SubscribeRequest({ - streamId: sub.streamId, - streamPartition: 5, - requestId: lastRequest.requestId, - sessionToken, - })) - done() - }) + }, () => {}) + const lastRequest = requests[requests.length - 1] + expect(lastRequest).toEqual(new SubscribeRequest({ + streamId: sub.streamId, + streamPartition: 5, + requestId: lastRequest.requestId, + sessionToken, + })) }) it('sends subscribe request for each subscribed partition', async () => { const tasks = [] for (let i = 0; i < 3; i++) { - tasks.push(new Promise((resolve) => { - const s = mockSubscription({ - stream: 'stream1', - partition: i, - }, () => {}) - .once('subscribed', () => resolve(s)) - })) + tasks.push(mockSubscription({ + stream: 'stream1', + partition: i, + }, () => {})) } const subs = await Promise.all(tasks) @@ -1031,12 +919,10 @@ describe('StreamrClient', () => { })) }) - it('sends only one subscribe request to server even if there are multiple subscriptions for same stream', async () => { - const sub = mockSubscription('stream1', () => {}) - const sub2 = mockSubscription('stream1', () => {}) - await Promise.all([ - new Promise((resolve) => sub.once('subscribed', resolve)), - new Promise((resolve) => sub2.once('subscribed', resolve)) + it('sends just one subscribe request to server even if there are multiple subscriptions for same stream', async () => { + const [sub, sub2] = await Promise.all([ + mockSubscription('stream1', () => {}), + mockSubscription('stream1', () => {}) ]) expect(requests).toHaveLength(1) const request = requests[0] @@ -1052,9 +938,9 @@ describe('StreamrClient', () => { }) describe('with resend options', () => { - it('supports resend.from', (done) => { + it('supports resend.from', async () => { const ref = new MessageRef(5, 0) - const sub = mockSubscription({ + const sub = await mockSubscription({ stream: 'stream1', resend: { from: { @@ -1064,71 +950,65 @@ describe('StreamrClient', () => { publisherId: 'publisherId', }, }, () => {}) - sub.once('subscribed', async () => { - await wait(200) - const lastRequest = requests[requests.length - 1] - expect(lastRequest).toEqual(new ResendFromRequest({ - streamId: sub.streamId, - streamPartition: sub.streamPartition, - requestId: lastRequest.requestId, - publisherId: 'publisherId', - fromMsgRef: ref, - sessionToken, - })) - const streamMessage = getStreamMessage(sub.streamId, {}) - connection.emitMessage(new UnicastMessage({ - requestId: lastRequest.requestId, - streamMessage, - })) - // TODO validate message - await wait(STORAGE_DELAY + 200) - sub.stop() - done() - }) + await wait(200) + const lastRequest = requests[requests.length - 1] + expect(lastRequest).toEqual(new ResendFromRequest({ + streamId: sub.streamId, + streamPartition: sub.streamPartition, + requestId: lastRequest.requestId, + publisherId: 'publisherId', + fromMsgRef: ref, + sessionToken, + })) + const streamMessage = getStreamMessage(sub.streamId, {}) + connection.emitMessage(new UnicastMessage({ + requestId: lastRequest.requestId, + streamMessage, + })) + // TODO validate message + await wait(STORAGE_DELAY + 200) + sub.stop() }, STORAGE_DELAY + 1000) - it('supports resend.last', (done) => { - const sub = mockSubscription({ + it('supports resend.last', async () => { + const sub = await mockSubscription({ stream: 'stream1', resend: { last: 5, }, }, () => {}) - sub.once('subscribed', async () => { - await wait(200) - const lastRequest = requests[requests.length - 1] - expect(lastRequest).toEqual(new ResendLastRequest({ - streamId: sub.streamId, - streamPartition: sub.streamPartition, - requestId: lastRequest.requestId, - numberLast: 5, - sessionToken, - })) - const streamMessage = getStreamMessage(sub.streamId, {}) - connection.emitMessage(new UnicastMessage({ - requestId: lastRequest.requestId, - streamMessage, - })) - // TODO validate message - await wait(STORAGE_DELAY + 200) - sub.stop() - done() - }) + await wait(200) + const lastRequest = requests[requests.length - 1] + expect(lastRequest).toEqual(new ResendLastRequest({ + streamId: sub.streamId, + streamPartition: sub.streamPartition, + requestId: lastRequest.requestId, + numberLast: 5, + sessionToken, + })) + const streamMessage = getStreamMessage(sub.streamId, {}) + connection.emitMessage(new UnicastMessage({ + requestId: lastRequest.requestId, + streamMessage, + })) + // TODO validate message + await wait(STORAGE_DELAY + 200) + sub.stop() }, STORAGE_DELAY + 1000) it('sends a ResendLastRequest if no StreamMessage received and a ResendResponseNoResend received', async () => { - const sub = client.subscribe({ + const t = client.subscribe({ stream: 'stream1', resend: { last: 5, }, }, () => {}) - connection.send = async (request) => { + connection._send = async (request) => { requests.push(request) await wait() if (request.type === ControlMessage.TYPES.SubscribeRequest) { connection.emitMessage(new SubscribeResponse({ - streamId: sub.streamId, + streamId: request.streamId, requestId: request.requestId, streamPartition: request.streamPartition, })) @@ -1136,8 +1016,8 @@ describe('StreamrClient', () => { if (request.type === ControlMessage.TYPES.ResendLastRequest) { const resendResponse = new ResendResponseNoResend({ - streamId: sub.streamId, - streamPartition: sub.streamPartition, + streamId: request.streamId, + streamPartition: request.streamPartition, requestId: request.requestId }) connection.emitMessage(resendResponse) @@ -1145,6 +1025,7 @@ describe('StreamrClient', () => { } await wait(STORAGE_DELAY + 200) + const sub = await t sub.stop() expect(requests).toHaveLength(2) const lastRequest = requests[requests.length - 1] @@ -1158,7 +1039,7 @@ describe('StreamrClient', () => { }, STORAGE_DELAY + 1000) it('throws if multiple resend options are given', () => { - expect(() => { + expect(() => ( client.subscribe({ stream: 'stream1', resend: { @@ -1169,95 +1050,85 @@ describe('StreamrClient', () => { last: 5, }, }, () => {}) - }).toThrow() + )).rejects.toThrow() }) }) describe('Subscription event handling', () => { describe('gap', () => { - it('sends resend request', (done) => { - const sub = mockSubscription('streamId', () => {}) - sub.once('subscribed', async () => { - await wait() - const fromRef = new MessageRef(1, 0) - const toRef = new MessageRef(5, 0) - - const fromRefObject = { - timestamp: fromRef.timestamp, - sequenceNumber: fromRef.sequenceNumber, - } - const toRefObject = { - timestamp: toRef.timestamp, - sequenceNumber: toRef.sequenceNumber, - } - sub.emit('gap', fromRefObject, toRefObject, 'publisherId', 'msgChainId') - await wait(100) - - expect(requests).toHaveLength(2) - const lastRequest = requests[requests.length - 1] - expect(lastRequest).toEqual(new ResendRangeRequest({ - streamId: sub.streamId, - streamPartition: sub.streamPartition, - requestId: lastRequest.requestId, - fromMsgRef: fromRef, - toMsgRef: toRef, - msgChainId: lastRequest.msgChainId, - publisherId: lastRequest.publisherId, - sessionToken, - })) - done() - }) + it('sends resend request', async () => { + const sub = await mockSubscription('streamId', () => {}) + const fromRef = new MessageRef(1, 0) + const toRef = new MessageRef(5, 0) + + const fromRefObject = { + timestamp: fromRef.timestamp, + sequenceNumber: fromRef.sequenceNumber, + } + const toRefObject = { + timestamp: toRef.timestamp, + sequenceNumber: toRef.sequenceNumber, + } + sub.emit('gap', fromRefObject, toRefObject, 'publisherId', 'msgChainId') + await wait(100) + + expect(requests).toHaveLength(2) + const lastRequest = requests[requests.length - 1] + expect(lastRequest).toEqual(new ResendRangeRequest({ + streamId: sub.streamId, + streamPartition: sub.streamPartition, + requestId: lastRequest.requestId, + fromMsgRef: fromRef, + toMsgRef: toRef, + msgChainId: lastRequest.msgChainId, + publisherId: lastRequest.publisherId, + sessionToken, + })) }) - it('does not send another resend request while resend is in progress', (done) => { - const sub = mockSubscription('streamId', () => {}) - sub.once('subscribed', async () => { - await wait() - const fromRef = new MessageRef(1, 0) - const toRef = new MessageRef(5, 0) - const fromRefObject = { - timestamp: fromRef.timestamp, - sequenceNumber: fromRef.sequenceNumber, - } - const toRefObject = { - timestamp: toRef.timestamp, - sequenceNumber: toRef.sequenceNumber, - } - sub.emit('gap', fromRefObject, toRefObject, 'publisherId', 'msgChainId') - sub.emit('gap', fromRefObject, { - timestamp: 10, - sequenceNumber: 0, - }, 'publisherId', 'msgChainId') - await wait() - expect(requests).toHaveLength(2) - const lastRequest = requests[requests.length - 1] - expect(lastRequest).toEqual(new ResendRangeRequest({ - streamId: sub.streamId, - streamPartition: sub.streamPartition, - requestId: lastRequest.requestId, - fromMsgRef: fromRef, - toMsgRef: toRef, - msgChainId: lastRequest.msgChainId, - publisherId: lastRequest.publisherId, - sessionToken, - })) - done() - }) + it('does not send another resend request while resend is in progress', async () => { + const sub = await mockSubscription('streamId', () => {}) + const fromRef = new MessageRef(1, 0) + const toRef = new MessageRef(5, 0) + const fromRefObject = { + timestamp: fromRef.timestamp, + sequenceNumber: fromRef.sequenceNumber, + } + const toRefObject = { + timestamp: toRef.timestamp, + sequenceNumber: toRef.sequenceNumber, + } + sub.emit('gap', fromRefObject, toRefObject, 'publisherId', 'msgChainId') + sub.emit('gap', fromRefObject, { + timestamp: 10, + sequenceNumber: 0, + }, 'publisherId', 'msgChainId') + await wait() + expect(requests).toHaveLength(2) + const lastRequest = requests[requests.length - 1] + expect(lastRequest).toEqual(new ResendRangeRequest({ + streamId: sub.streamId, + streamPartition: sub.streamPartition, + requestId: lastRequest.requestId, + fromMsgRef: fromRef, + toMsgRef: toRef, + msgChainId: lastRequest.msgChainId, + publisherId: lastRequest.publisherId, + sessionToken, + })) }) }) describe('done', () => { - it('unsubscribes', (done) => { - const sub = mockSubscription('stream1', () => {}) + it('unsubscribes', async (done) => { + const sub = await mockSubscription('stream1', () => {}) - client.unsubscribe = (unsub) => { + client.subscriber.unsubscribe = async (unsub) => { expect(sub).toBe(unsub) done() } - sub.once('subscribed', async () => { - await wait() - sub.emit('done') - }) + await wait() + sub.emit('done') }) }) }) @@ -1267,17 +1138,15 @@ describe('StreamrClient', () => { describe('unsubscribe()', () => { // Before each, client is connected and subscribed let sub - beforeEach(async (done) => { + beforeEach(async () => { await client.connect() - sub = mockSubscription('stream1', () => { + sub = await mockSubscription('stream1', () => { errors.push(new Error('should not fire message handler')) }) - sub.once('subscribed', () => done()) }) it('sends an unsubscribe request', async () => { - client.unsubscribe(sub) - await wait() + await client.unsubscribe(sub) expect(requests).toHaveLength(2) const lastRequest = requests[requests.length - 1] expect(lastRequest).toEqual(new UnsubscribeRequest({ @@ -1289,39 +1158,49 @@ describe('StreamrClient', () => { }) it('does not send unsubscribe request if there are other subs remaining for the stream', async () => { - client.subscribe({ + await mockSubscription({ stream: sub.streamId, }, () => {}) - client.unsubscribe(sub) - await wait() + await client.unsubscribe(sub) expect(requests).toHaveLength(1) }) - it('sends unsubscribe request when the last subscription is unsubscribed', (done) => { - const sub2 = client.subscribe({ - stream: sub.streamId, - }, () => {}) + it('sends unsubscribe request when the last subscription is unsubscribed', async () => { + const sub2 = await mockSubscription(sub.streamId, () => {}) + + await client.unsubscribe(sub) + await client.unsubscribe(sub2) + const lastRequest = requests[requests.length - 1] + expect(lastRequest).toEqual(new UnsubscribeRequest({ + streamId: sub.streamId, + streamPartition: sub.streamPartition, + requestId: lastRequest.requestId, + sessionToken, + })) + }) - sub2.once('subscribed', async () => { - client.unsubscribe(sub) + it('sends only a single unsubscribe request when the last subscription is unsubscribed', async () => { + const sub2 = await mockSubscription(sub.streamId, () => {}) + requests = [] + await Promise.all([ + client.unsubscribe(sub), client.unsubscribe(sub2) - await wait() - const lastRequest = requests[requests.length - 1] - expect(lastRequest).toEqual(new UnsubscribeRequest({ - streamId: sub.streamId, - streamPartition: sub.streamPartition, - requestId: lastRequest.requestId, - sessionToken, - })) - done() - }) + ]) + expect(requests).toHaveLength(1) + const lastRequest = requests[requests.length - 1] + + expect(lastRequest).toEqual(new UnsubscribeRequest({ + streamId: sub.streamId, + streamPartition: sub.streamPartition, + requestId: lastRequest.requestId, + sessionToken, + })) }) it('does not send an unsubscribe request again if unsubscribe is called multiple times', async () => { - client.unsubscribe(sub) - client.unsubscribe(sub) - await wait() + await client.unsubscribe(sub) + await client.unsubscribe(sub) expect(requests).toHaveLength(2) const lastRequest = requests[requests.length - 1] expect(lastRequest).toEqual(new UnsubscribeRequest({ @@ -1336,31 +1215,31 @@ describe('StreamrClient', () => { const handler = jest.fn() sub.on('unsubscribed', handler) - client.unsubscribe(sub) - await wait() + await client.unsubscribe(sub) expect(sub.getState()).toEqual(Subscription.State.unsubscribed) - client.unsubscribe(sub) - await wait() + await client.unsubscribe(sub) expect(handler).toHaveBeenCalledTimes(1) }) it('throws if no Subscription is given', () => { - expect(() => { - client.unsubscribe() - }).toThrow() + expect(async () => { + await client.unsubscribe() + }).rejects.toThrow() }) it('throws if Subscription is of wrong type', () => { - expect(() => { - client.unsubscribe(sub.streamId) - }).toThrow() + expect(async () => { + await client.unsubscribe(sub.streamId) + }).rejects.toThrow() }) }) describe('publish', () => { function getPublishRequest(content, streamId, timestamp, seqNum, prevMsgRef, requestId) { - const messageId = new MessageID(streamId, 0, timestamp, seqNum, StubbedStreamrClient.hashedUsername, client.msgCreationUtil.msgChainId) + const { hashedUsername } = StubbedStreamrClient + const { msgChainId } = client.publisher.msgCreationUtil.msgChainer + const messageId = new MessageID(streamId, 0, timestamp, seqNum, hashedUsername, msgChainId) const streamMessage = new StreamMessage({ messageId, prevMsgRef, @@ -1445,7 +1324,7 @@ describe('StreamrClient', () => { const pubMsg = { value: uid('msg'), } - await expect(() => ( + await expect(async () => ( client.publish('stream1', pubMsg) )).rejects.toThrow(FailedToPublishError) }) @@ -1469,28 +1348,24 @@ describe('StreamrClient', () => { describe('disconnect()', () => { beforeEach(() => client.connect()) - it('calls connection.disconnect()', (done) => { - connection.disconnect = () => done() - client.disconnect() - }) - - it('resets subscriptions', async () => { - const sub = mockSubscription('stream1', () => {}) + it('calls connection.disconnect()', async () => { + const disconnect = jest.spyOn(connection, 'disconnect') await client.disconnect() - expect(client.getSubscriptions(sub.streamId)).toEqual([]) + expect(disconnect).toHaveBeenCalledTimes(1) }) }) describe('pause()', () => { beforeEach(() => client.connect()) - it('calls connection.disconnect()', (done) => { - connection.disconnect = done - client.pause() + it('calls connection.disconnect()', async () => { + const disconnect = jest.spyOn(connection, 'disconnect') + await client.pause() + expect(disconnect).toHaveBeenCalledTimes(1) }) it('does not reset subscriptions', async () => { - const sub = mockSubscription('stream1', () => {}) + const sub = await mockSubscription('stream1', () => {}) await client.pause() expect(client.getSubscriptions(sub.streamId)).toEqual([sub]) }) @@ -1511,7 +1386,7 @@ describe('StreamrClient', () => { expect(c.options.auth.apiKey).toBeTruthy() }) - it('sets private key with 0x prefix', (done) => { + it.skip('sets private key with 0x prefix', (done) => { connection = createConnectionMock() const c = new StubbedStreamrClient({ auth: { @@ -1525,7 +1400,7 @@ describe('StreamrClient', () => { c.once('connected', async () => { await wait() expect(requests[0]).toEqual(new SubscribeRequest({ - streamId: getKeyExchangeStreamId('0x650EBB201f635652b44E4afD1e0193615922381D'), + // streamId: getKeyExchangeStreamId('0x650EBB201f635652b44E4afD1e0193615922381D'), streamPartition: 0, sessionToken, requestId: requests[0].requestId, @@ -1539,80 +1414,6 @@ describe('StreamrClient', () => { const c = new StubbedStreamrClient({}, createConnectionMock()) expect(c.session.options.unauthenticated).toBeTruthy() }) - - it('sets start time of group key', () => { - const groupKey = crypto.randomBytes(32) - const c = new StubbedStreamrClient({ - subscriberGroupKeys: { - streamId: { - publisherId: groupKey - } - } - }, createConnectionMock()) - expect(c.options.subscriberGroupKeys.streamId.publisherId.groupKey).toBe(groupKey) - expect(c.options.subscriberGroupKeys.streamId.publisherId.start).toBeTruthy() - }) - - it('keeps start time passed in the constructor', () => { - const groupKey = crypto.randomBytes(32) - const c = new StubbedStreamrClient({ - subscriberGroupKeys: { - streamId: { - publisherId: { - groupKey, - start: 12 - } - } - } - }, createConnectionMock()) - expect(c.options.subscriberGroupKeys.streamId.publisherId.groupKey).toBe(groupKey) - expect(c.options.subscriberGroupKeys.streamId.publisherId.start).toBe(12) - }) - - it('updates the latest group key with a more recent key', () => { - const c = new StubbedStreamrClient({ - subscriberGroupKeys: { - streamId: { - publisherId: crypto.randomBytes(32) - } - } - }, createConnectionMock()) - c.subscribedStreamPartitions = { - streamId0: { - setSubscriptionsGroupKeys: sinon.stub() - } - } - const newGroupKey = { - groupKey: crypto.randomBytes(32), - start: Date.now() + 2000 - } - // eslint-disable-next-line no-underscore-dangle - c._setGroupKeys('streamId', 'publisherId', [newGroupKey]) - expect(c.options.subscriberGroupKeys.streamId.publisherId).toBe(newGroupKey) - }) - - it('does not update the latest group key with an older key', () => { - const groupKey = crypto.randomBytes(32) - const c = new StubbedStreamrClient({ - subscriberGroupKeys: { - streamId: { - publisherId: groupKey - } - } - }, createConnectionMock()) - c.subscribedStreamPartitions = { - streamId0: { - setSubscriptionsGroupKeys: sinon.stub() - } - } - const oldGroupKey = { - groupKey: crypto.randomBytes(32), - start: Date.now() - 2000 - } - // eslint-disable-next-line no-underscore-dangle - c._setGroupKeys('streamId', 'publisherId', [oldGroupKey]) - expect(c.options.subscriberGroupKeys.streamId.publisherId.groupKey).toBe(groupKey) - }) }) describe('StreamrClient.generateEthereumAccount()', () => { @@ -1623,4 +1424,3 @@ describe('StreamrClient', () => { }) }) }) - diff --git a/test/unit/SubscribedStreamPartition.test.js b/test/legacy/SubscribedStreamPartition.test.js similarity index 94% rename from test/unit/SubscribedStreamPartition.test.js rename to test/legacy/SubscribedStreamPartition.test.js index e483f55dc..ba91dbe80 100644 --- a/test/unit/SubscribedStreamPartition.test.js +++ b/test/legacy/SubscribedStreamPartition.test.js @@ -284,7 +284,10 @@ describe('SubscribedStreamPartition', () => { beforeEach(() => { ({ client } = setupClientAndStream()) subscribedStreamPartition = new SubscribedStreamPartition(client, 'streamId') - sub1 = new RealTimeSubscription('sub1Id', 0, () => {}) + sub1 = new RealTimeSubscription({ + streamId: 'sub1Id', + callback: () => {}, + }) }) it('should add and remove subscription correctly', () => { @@ -307,24 +310,5 @@ describe('SubscribedStreamPartition', () => { it('should return true', () => { expect(subscribedStreamPartition.emptySubscriptionsSet()).toBe(true) }) - - it('should call setGroupKeys() and checkQueue() for every subscription', async () => { - const sub2 = { - id: 'sub2Id', - setGroupKeys: sinon.stub(), - } - const sub3 = { - id: 'sub3Id', - setGroupKeys: sinon.stub(), - } - - subscribedStreamPartition.removeSubscription(sub1) - subscribedStreamPartition.addSubscription(sub2) - subscribedStreamPartition.addSubscription(sub3) - - await subscribedStreamPartition.setSubscriptionsGroupKeys('publisherId', ['group-key-1', 'group-key-2']) - expect(sub2.setGroupKeys.calledWith('publisherId', ['group-key-1', 'group-key-2'])).toBeTruthy() - expect(sub3.setGroupKeys.calledWith('publisherId', ['group-key-1', 'group-key-2'])).toBeTruthy() - }) }) }) diff --git a/test/unit/AggregatedError.test.ts b/test/unit/AggregatedError.test.ts new file mode 100644 index 000000000..5ca4ac5fc --- /dev/null +++ b/test/unit/AggregatedError.test.ts @@ -0,0 +1,151 @@ +import AggregatedError from '../../src/utils/AggregatedError' + +describe('AggregatedError', () => { + describe('new', () => { + it('works without args', () => { + const err = new AggregatedError() + expect(err.message).toBe('') + expect(err.stack).not.toBe('') + expect(err.errors).toEqual(new Set()) + }) + + it('can take subError', () => { + const subError = new Error('test') + const err = new AggregatedError([subError]) + expect(err.message).toContain(subError.message) + expect(err.stack).not.toBe('') + expect(err.errors).toEqual(new Set([subError])) + }) + + it('can take custom message', () => { + const subError = new Error('test') + const customMessage = 'customMessage' + const err = new AggregatedError([subError], customMessage) + expect(err.message).toContain(subError.message) + expect(err.message).toContain(customMessage) + expect(err.stack).not.toBe('') + expect(err.errors).toEqual(new Set([subError])) + }) + + it('works without Errors', () => { + const customMessage = 'customMessage' + const err = new AggregatedError([], customMessage) + expect(err.message).toContain(customMessage) + expect(err.stack).not.toBe('') + expect(err.errors).toEqual(new Set([])) + }) + }) + + describe('extend', () => { + it('can extend from another error', () => { + const subError1 = new Error('subError1') + const subError2 = new Error('subError2') + const err = new AggregatedError([subError1]).extend(subError2) + expect(err.message).toContain(subError1.message) + expect(err.message).toContain(subError2.message) + expect(err.stack).not.toBe('') + expect(err.errors).toEqual(new Set([subError1, subError2])) + }) + + it('can extend from another error and custom message', () => { + const subError1 = new Error('subError1') + const subError2 = new Error('subError2') + const customMessage = 'customMessage' + const err = new AggregatedError([subError1]).extend(subError2, customMessage) + expect(err.message).toContain(subError1.message) + expect(err.message).toContain(subError2.message) + expect(err.message).toContain(customMessage) + expect(err.stack).not.toBe('') + expect(err.errors).toEqual(new Set([subError1, subError2])) + }) + + it('can extend from another error with custom message and own custom message', () => { + const subError1 = new Error('subError1') + const subError2 = new Error('subError2') + const customMessage1 = 'customMessage1' + const customMessage2 = 'customMessage2' + const err = new AggregatedError([subError1], customMessage1).extend(subError2, customMessage2) + expect(err.message).toContain(subError1.message) + expect(err.message).toContain(subError2.message) + expect(err.message).toContain(customMessage1) + expect(err.message).toContain(customMessage2) + expect(err.stack).not.toBe('') + expect(err.errors).toEqual(new Set([subError1, subError2])) + }) + }) + + describe('from', () => { + it('does nothing with only oldErr', () => { + const subError = new Error('subError1') + const err = AggregatedError.from(subError) + expect(subError).toBe(err) + }) + + it('does nothing with only newErr', () => { + const subError = new Error('subError1') + const err = AggregatedError.from(undefined, subError) + expect(subError).toBe(err) + }) + + it('can rejig message', () => { + const subError = new Error('subError1') + const customMessage = 'customMessage' + const err = AggregatedError.from(undefined, subError, customMessage) + expect(err && err.message).toContain(customMessage) + expect(subError).toBe(err) + }) + + it('can extend from another Error with own custom message', () => { + const subError1 = new Error('subError1') + const subError2 = new Error('subError2') + const customMessage1 = 'customMessage2' + const err = AggregatedError.from(subError1, subError2, customMessage1) as AggregatedError + expect(err.message).toContain(subError1.message) + expect(err.message).toContain(subError2.message) + expect(err.message).toContain(customMessage1) + expect(err.stack).not.toBe('') + expect(err.errors).toEqual(new Set([subError1, subError2])) + expect(err).toBeInstanceOf(AggregatedError) + }) + + it('can extend from another AggregatedError with custom message and own custom message', () => { + const subError1 = new Error('subError1') + const subError2 = new Error('subError2') + const customMessage1 = 'customMessage1' + const customMessage2 = 'customMessage2' + const originalErr = new AggregatedError([subError1], customMessage1) + const err = AggregatedError.from(originalErr, subError2, customMessage2) as AggregatedError + expect(err.message).toContain(subError1.message) + expect(err.message).toContain(subError2.message) + expect(err.message).toContain(customMessage1) + expect(err.message).toContain(customMessage2) + expect(err.stack).not.toBe('') + expect(err.errors).toEqual(new Set([subError1, subError2])) + }) + }) + + describe('subclasses work', () => { + class MyError extends AggregatedError {} + it('does nothing with only oldErr', () => { + const subError = new Error('subError1') + const err = MyError.from(subError) + expect(subError).toBe(err) + }) + + it('can extend from another error with custom message and own custom message', () => { + const subError1 = new Error('subError1') + const subError2 = new Error('subError2') + const customMessage1 = 'customMessage1' + const customMessage2 = 'customMessage2' + const originalErr = new AggregatedError([subError1], customMessage1) + const err = MyError.from(originalErr, subError2, customMessage2) as AggregatedError + expect(err.message).toContain(subError1.message) + expect(err.message).toContain(subError2.message) + expect(err.message).toContain(customMessage1) + expect(err.message).toContain(customMessage2) + expect(err.stack).not.toBe('') + expect(err.errors).toEqual(new Set([subError1, subError2])) + expect(err).toBeInstanceOf(MyError) + }) + }) +}) diff --git a/test/unit/Config.test.ts b/test/unit/Config.test.ts new file mode 100644 index 000000000..1a43e613f --- /dev/null +++ b/test/unit/Config.test.ts @@ -0,0 +1,23 @@ +import { arrayify, BytesLike } from '@ethersproject/bytes' +import { StreamrClient } from '../../src/StreamrClient' + +const createClient = (privateKey: BytesLike) => { + return new StreamrClient({ + auth: { + privateKey + } + }) +} + +describe('Config', () => { + describe('private key', () => { + it('string', async () => { + const client = createClient('0x0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF') + expect(await client.getAddress()).toBe('0xFCAd0B19bB29D4674531d6f115237E16AfCE377c') + }) + it('byteslike', async () => { + const client = createClient(arrayify('0x0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF')) + expect(await client.getAddress()).toBe('0xFCAd0B19bB29D4674531d6f115237E16AfCE377c') + }) + }) +}) diff --git a/test/unit/Connection.test.js b/test/unit/Connection.test.js deleted file mode 100644 index b2e08d267..000000000 --- a/test/unit/Connection.test.js +++ /dev/null @@ -1,233 +0,0 @@ -import { ControlLayer, MessageLayer } from 'streamr-client-protocol' -import { wait } from 'streamr-test-utils' - -import Connection from '../../src/Connection' - -const { UnicastMessage, ControlMessage } = ControlLayer -const { StreamMessage, MessageIDStrict, MessageRef } = MessageLayer - -describe('Connection', () => { - let conn - beforeEach(() => { - conn = new Connection({ - url: 'foo', - }, { - on: jest.fn(), - close: jest.fn(), - }) - }) - - describe('initial state', () => { - it('should be correct', () => { - expect(conn.state).toEqual(Connection.State.DISCONNECTED) - }) - }) - - describe('connect()', () => { - it('returns a promise and resolves it when connected', async () => { - const result = conn.connect() - expect(result instanceof Promise).toBeTruthy() - conn.socket.onopen() - await result - }) - - it('adds listeners to socket', () => { - conn.connect() - expect(conn.socket.onopen != null).toBeTruthy() - expect(conn.socket.onclose != null).toBeTruthy() - expect(conn.socket.onmessage != null).toBeTruthy() - expect(conn.socket.onerror != null).toBeTruthy() - }) - - it('should report correct state when connecting', () => { - conn.connect() - expect(conn.state).toEqual(Connection.State.CONNECTING) - }) - - it('should report correct state flag when connected', () => { - conn.connect() - conn.socket.onopen() - expect(conn.state).toEqual(Connection.State.CONNECTED) - }) - - it('should reject the promise if already connected', async () => { - conn.connect() - conn.socket.onopen() - expect(conn.state).toEqual(Connection.State.CONNECTED) - - await expect(() => ( - conn.connect() - )).rejects.toThrow() - expect(conn.state).toEqual(Connection.State.CONNECTED) - }) - - it('should resolve the promise', async () => { - const task = conn.connect() - conn.socket.onopen() - conn.socket.onopen() - await task - }) - }) - - describe('disconnect()', () => { - beforeEach(() => { - conn.connect() - conn.socket.onopen() - expect(conn.state).toEqual(Connection.State.CONNECTED) - }) - - afterEach(() => { - conn.disconnect().catch(() => { - // ignore - }) - }) - - it('returns a promise and resolves it when disconnected', () => { - const result = conn.disconnect() - expect(result instanceof Promise).toBeTruthy() - conn.socket.onclose() - return result - }) - - it('should call socket.close()', () => { - conn.disconnect() - expect(conn.socket.close).toHaveBeenCalledTimes(1) - }) - - it('should report correct state when disconnecting', () => { - conn.disconnect() - expect(conn.state).toEqual(Connection.State.DISCONNECTING) - }) - - it('should report correct state flag when connected', () => { - conn.disconnect() - conn.socket.onclose() - expect(conn.state).toEqual(Connection.State.DISCONNECTED) - }) - - it('should reject the promise if already disconnected', async () => { - conn.disconnect() - conn.socket.onclose() - expect(conn.state).toEqual(Connection.State.DISCONNECTED) - - await expect(() => conn.disconnect()).rejects.toThrow() - expect(conn.state).toEqual(Connection.State.DISCONNECTED) - }) - - it('should resolve the promise', async () => { - const task = conn.disconnect() - conn.socket.onclose() - conn.socket.onclose() - await task - }) - }) - - describe('send()', () => { - beforeEach(() => { - conn.connect() - }) - - it('sends the serialized message over the socket', () => { - const request = { - serialize: jest.fn(() => 'foo') - } - conn.socket.send = jest.fn() - - conn.send(request) - expect(request.serialize).toHaveBeenCalledTimes(1) - expect(conn.socket.send).toHaveBeenCalledWith('foo', expect.any(Function)) - }) - - it('emits error event if socket.send throws', (done) => { - const request = { - serialize: jest.fn() - } - conn.socket.send = () => { - throw new Error('test') - } - - conn.once('error', (err) => { - expect(err.message).toEqual('test') - done() - }) - conn.send(request).catch((err) => { - // hm, this probably should *either* emit an error or reject - expect(err.message).toEqual('test') - }) - }) - }) - - describe('event handling on socket', () => { - beforeEach(() => { - conn.connect() - conn.socket.onopen() - }) - - describe('message', () => { - it('emits events named by messageTypeName and the ControlMessage as an argument', (done) => { - const timestamp = Date.now() - const content = { - hello: 'world', - } - conn.once(ControlMessage.TYPES.UnicastMessage, (message) => { - expect(message instanceof UnicastMessage).toBeTruthy() - expect(message.streamMessage.getTimestamp()).toEqual(timestamp) - expect(message.streamMessage.getParsedContent().hello).toEqual('world') - expect(message.requestId).toEqual('requestId') - done() - }) - - const message = new UnicastMessage({ - requestId: 'requestId', - streamMessage: new StreamMessage({ - messageId: new MessageIDStrict('streamId', 0, timestamp, 0, '', ''), - prevMsgRef: new MessageRef(timestamp - 100, 0), - content, - messageType: StreamMessage.MESSAGE_TYPES.MESSAGE, - encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, - signatureType: StreamMessage.SIGNATURE_TYPES.NONE, - }) - }) - - conn.socket.onmessage({ - data: message.serialize(), - }) - }) - - it('does not emit an error event when a message contains invalid json', (done) => { - const onError = jest.fn() - conn.once('error', onError) // shouldn't error because content itself not deserialized in connection - conn.once(ControlMessage.TYPES.UnicastMessage, () => { - expect(onError).not.toHaveBeenCalled() - done() - }) - const timestamp = Date.now() - - const message = new UnicastMessage({ - requestId: 'requestId', - streamMessage: new StreamMessage({ - messageId: new MessageIDStrict('streamId', 0, timestamp, 0, '', ''), - prevMsgRef: null, - content: '{', // bad json - messageType: StreamMessage.MESSAGE_TYPES.MESSAGE, - encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, - signatureType: StreamMessage.SIGNATURE_TYPES.NONE, - }) - }) - const data = message.serialize() - conn.socket.onmessage({ - data, - }) - }) - }) - - describe('close', () => { - it('tries to reconnect after 2 seconds', async () => { - conn.connect = jest.fn(async () => {}) - conn.socket.events.emit('close') - await wait(2100) - expect(conn.connect).toHaveBeenCalledTimes(1) - }) - }) - }) -}) diff --git a/test/unit/Connection.test.ts b/test/unit/Connection.test.ts new file mode 100644 index 000000000..dcaf21e08 --- /dev/null +++ b/test/unit/Connection.test.ts @@ -0,0 +1,1241 @@ +import { AddressInfo, Server } from 'ws' +import { wait } from 'streamr-test-utils' +import Debug from 'debug' + +import { describeRepeats } from '../utils' +import Connection from '../../src/Connection' +import { Defer } from '../../src/utils' +import { Todo } from '../../src/types' + +/* eslint-disable require-atomic-updates */ + +const debug = Debug('StreamrClient').extend('test') + +describeRepeats('Connection', () => { + let s: Connection + let onConnected: Todo + let onConnecting: Todo + let onDisconnecting: Todo + let onDisconnected: Todo + let onReconnecting: Todo + let onDone: Todo + let onError: Todo + let onMessage: Todo + let wss: Server + let port: number + let errors: Todo + + let expectErrors = 0 // check no errors by default + beforeAll((done) => { + wss = new Server({ + port: 0, + }).once('listening', () => { + port = (wss.address() as AddressInfo).port + done() + }) + + wss.on('connection', (ws) => { + ws.on('message', (msg) => ws.send(msg)) + }) + }) + + afterAll((done) => { + wss.close(done) + }) + + beforeEach(() => { + s = new Connection({ + url: `ws://localhost:${port}/`, + maxRetries: 2, + disconnectDelay: 1, + }) + + onConnected = jest.fn() + s.on('connected', onConnected) + onConnecting = jest.fn() + s.on('connecting', onConnecting) + onDisconnected = jest.fn() + s.on('disconnected', onDisconnected) + onDone = jest.fn() + s.on('done', onDone) + onDisconnecting = jest.fn() + s.on('disconnecting', onDisconnecting) + onReconnecting = jest.fn() + s.on('reconnecting', onReconnecting) + + errors = [] + const currentErrors = errors + onError = jest.fn((err) => { + currentErrors.push(err) + }) + + s.on('error', onError) + onMessage = jest.fn() + s.on('message', onMessage) + expectErrors = 0 + debug('starting test') + }) + + afterEach(async () => { + await wait(0) + // ensure no unexpected errors + try { + expect(errors).toHaveLength(expectErrors) + } catch (err) { + // print errors + debug('onError calls:', onError.mock.calls) + throw err + } + }) + + afterEach(async () => { + debug('disconnecting after test') + await s.disconnect() + const openSockets = Connection.getOpen() + if (openSockets !== 0) { + await Connection.closeOpen() + throw new Error(`sockets not closed: ${openSockets}`) + } + }) + + describe('basics', () => { + it('can connect & disconnect', async () => { + await s.connect() + expect(s.getState()).toBe('connected') + await s.disconnect() + expect(s.getState()).toBe('disconnected') + // check events + expect(onConnected).toHaveBeenCalledTimes(1) + expect(onDisconnected).toHaveBeenCalledTimes(1) + expect(onConnecting).toHaveBeenCalledTimes(1) + expect(onDisconnecting).toHaveBeenCalledTimes(1) + expect(onDone).toHaveBeenCalledTimes(1) + }) + + it('can connect after already connected', async () => { + await s.connect() + await s.connect() + expect(s.getState()).toBe('connected') + + expect(onConnected).toHaveBeenCalledTimes(1) + expect(onConnecting).toHaveBeenCalledTimes(1) + }) + + it('can connect twice in same tick', async () => { + await Promise.all([ + s.connect(), + s.connect(), + ]) + expect(s.getState()).toBe('connected') + expect(onConnected).toHaveBeenCalledTimes(1) + expect(onConnecting).toHaveBeenCalledTimes(1) + }) + + it('can connect and disconnect in same tick', async () => { + const connectTask = s.connect() + const disconnectTask = s.disconnect() + await expect(() => connectTask).rejects.toThrow() + await disconnectTask + expect(s.getState()).toBe('disconnected') + expect(onConnected).toHaveBeenCalledTimes(0) + expect(onConnecting).toHaveBeenCalledTimes(0) + expect(onDisconnected).toHaveBeenCalledTimes(0) + expect(onDisconnecting).toHaveBeenCalledTimes(0) + expect(onDone).toHaveBeenCalledTimes(0) + }) + + it('tracks open sockets and can close them', async () => { + expect(Connection.getOpen()).toEqual(0) + await s.connect() + expect(Connection.getOpen()).toEqual(1) + await s.disconnect() + expect(Connection.getOpen()).toEqual(0) + await s.connect() + expect(Connection.getOpen()).toEqual(1) + const s2 = new Connection({ + url: 'badurl', + maxRetries: 2, + disconnectDelay: 1, + }) + + await expect(async () => ( + s2.connect() + )).rejects.toThrow() + expect(Connection.getOpen()).toEqual(1) + + const s3 = new Connection({ + url: `ws://localhost:${port}/`, + disconnectDelay: 1, + }) + await s3.connect() + expect(Connection.getOpen()).toEqual(2) + await Connection.closeOpen() + expect(Connection.getOpen()).toEqual(0) + await wait(250) + expect(Connection.getOpen()).toEqual(0) + expect(s.getState()).toEqual('disconnected') + }) + + it('fires all events once if connected twice in same tick', async () => { + await Promise.all([ + s.connect(), + s.connect(), + ]) + expect(s.getState()).toBe('connected') + await Promise.all([ + s.disconnect(), + s.disconnect(), + ]) + expect(s.getState()).toBe('disconnected') + + expect(onConnected).toHaveBeenCalledTimes(1) + expect(onDisconnected).toHaveBeenCalledTimes(1) + expect(onDisconnecting).toHaveBeenCalledTimes(1) + expect(onConnecting).toHaveBeenCalledTimes(1) + }) + + it('fires all events minimally if connected twice in same tick then reconnected', async () => { + await Promise.all([ + s.connect(), + s.connect(), + ]) + s.socket.close() + await s.nextConnection() + + expect(s.getState()).toBe('connected') + + expect(onConnected).toHaveBeenCalledTimes(2) + expect(onDisconnected).toHaveBeenCalledTimes(1) + expect(onDisconnecting).toHaveBeenCalledTimes(1) + expect(onConnecting).toHaveBeenCalledTimes(2) + }) + + it('can connect again after disconnect', async () => { + await s.connect() + expect(s.getState()).toBe('connected') + const oldSocket = s.socket + await s.disconnect() + expect(s.getState()).toBe('disconnected') + await s.connect() + expect(s.getState()).toBe('connected') + // check events + expect(onConnected).toHaveBeenCalledTimes(2) + expect(onDisconnected).toHaveBeenCalledTimes(1) + expect(onDone).toHaveBeenCalledTimes(1) + // ensure new socket + expect(s.socket).not.toBe(oldSocket) + }) + + describe('connect/disconnect inside event handlers', () => { + it('can handle connect on connecting event', async () => { + const done = Defer() + s.once('connecting', done.wrap(async () => { + await s.connect() + expect(s.getState()).toBe('connected') + expect(onConnected).toHaveBeenCalledTimes(1) + expect(onConnecting).toHaveBeenCalledTimes(1) + })) + await s.connect() + expect(s.getState()).toBe('connected') + await done + }) + + it('can handle disconnect on connecting event', async () => { + const done = Defer() + s.once('connecting', done.wrap(async () => { + await s.disconnect() + expect(s.getState()).toBe('disconnected') + expect(onDone).toHaveBeenCalledTimes(1) + })) + + await expect(async () => { + await s.connect() + }).rejects.toThrow() + expect(s.getState()).toBe('disconnected') + await done + }) + + it('can handle disconnect on connected event', async () => { + const done = Defer() + s.once('connected', done.wrap(async () => { + await s.disconnect() + expect(s.getState()).toBe('disconnected') + })) + + await expect(async () => { + await s.connect() + }).rejects.toThrow() + expect(s.getState()).not.toBe('connected') + await done + expect(onDone).toHaveBeenCalledTimes(1) + }) + + it('can handle disconnect on connected event, repeated', async () => { + const done = Defer() + // connect -> disconnect in connected + // disconnect + s.once('connected', done.wrapError(async () => { + await expect(async () => { + await s.disconnect() + }).rejects.toThrow() + })) + + s.once('disconnected', done.wrapError(async () => { + s.once('connected', done.wrapError(async () => { + await s.disconnect() + })) + + await expect(async () => { + await s.connect() + }).rejects.toThrow() + done.resolve(undefined) + })) + + await expect(async () => { + await s.connect() + }).rejects.toThrow() + await done + await s.disconnect() + expect(s.getState()).toBe('disconnected') + expect(onDone).toHaveBeenCalledTimes(1) + }) + + it('can handle connect on disconnecting event', async () => { + const done = Defer() + s.once('disconnecting', done.wrap(async () => { + await s.connect() + expect(s.getState()).toBe('connected') + })) + + await s.connect() + await expect(async () => { + await s.disconnect() + }).rejects.toThrow('connected before disconnected') + expect(onDone).toHaveBeenCalledTimes(0) + expect(s.getState()).toBe('connected') + await done + await wait(250) + expect(s.getState()).toBe('connected') + expect(onDone).toHaveBeenCalledTimes(0) + expect(onConnected).toHaveBeenCalledTimes(1) + expect(onDisconnected).toHaveBeenCalledTimes(0) + expect(onDisconnecting).toHaveBeenCalledTimes(1) + }) + + it('delays disconnection', async () => { + await s.connect() + const DELAY = 150 + s.options.disconnectDelay = DELAY + const prevSocket = s.socket + const t = expect(async () => { + await s.disconnect() + }).rejects.toThrow('connected before disconnected') + await wait(DELAY / 2) + expect(onDisconnected).toHaveBeenCalledTimes(0) + await s.connect() + expect(s.getState()).toBe('connected') + await t + expect(s.getState()).toBe('connected') + expect(s.socket).toBe(prevSocket) + expect(onDone).toHaveBeenCalledTimes(0) + expect(s.getState()).toBe('connected') + expect(onDone).toHaveBeenCalledTimes(0) + expect(onConnected).toHaveBeenCalledTimes(2) + expect(onDisconnected).toHaveBeenCalledTimes(0) + expect(onDisconnecting).toHaveBeenCalledTimes(1) + }) + + it('can handle connect on disconnected event', async () => { + const done = Defer() + try { + await s.connect() + + s.once('disconnected', done.wrap(async () => { + await s.connect() + })) + + await expect(async () => { + await s.disconnect() + }).rejects.toThrow() + expect(s.getState()).toBe('connected') + } finally { + await done + expect(s.getState()).toBe('connected') + expect(onDone).toHaveBeenCalledTimes(0) + } + }) + }) + + it('rejects if no url', async () => { + s = new Connection({ + url: undefined, + maxRetries: 2, + disconnectDelay: 1, + }) + s.on('connected', onConnected) + s.on('error', onError) + await expect(async () => { + await s.connect() + }).rejects.toThrow('not defined') + expect(onConnected).toHaveBeenCalledTimes(0) + }) + + it('rejects if bad url', async () => { + s = new Connection({ + url: 'badurl', + maxRetries: 2, + disconnectDelay: 1, + }) + s.on('connected', onConnected) + s.on('error', onError) + s.on('done', onDone) + await expect(async () => { + await s.connect() + }).rejects.toThrow('badurl') + expect(onConnected).toHaveBeenCalledTimes(0) + expect(onDone).toHaveBeenCalledTimes(1) + }) + + it('rejects if cannot connect', async () => { + s = new Connection({ + url: 'wss://streamr.network/nope', + maxRetries: 2, + disconnectDelay: 1, + }) + s.on('connected', onConnected) + s.on('done', onDone) + await expect(async () => { + await s.connect() + }).rejects.toThrow('Unexpected server response') + expect(onConnected).toHaveBeenCalledTimes(0) + expect(onDone).toHaveBeenCalledTimes(1) + }) + + it('disconnect does not error if never connected', async () => { + expect(s.getState()).toBe('disconnected') + await s.disconnect() + expect(s.getState()).toBe('disconnected') + expect(onDisconnected).toHaveBeenCalledTimes(0) + }) + + it('disconnect does not error if already disconnected', async () => { + await s.connect() + await s.disconnect() + expect(s.getState()).toBe('disconnected') + await s.disconnect() + expect(s.getState()).toBe('disconnected') + expect(onDisconnected).toHaveBeenCalledTimes(1) + expect(onDone).toHaveBeenCalledTimes(1) + }) + + it('disconnect does not error if already closing', async () => { + await s.connect() + await Promise.all([ + s.disconnect(), + s.disconnect(), + ]) + expect(s.getState()).toBe('disconnected') + expect(onConnected).toHaveBeenCalledTimes(1) + expect(onDisconnected).toHaveBeenCalledTimes(1) + expect(onDone).toHaveBeenCalledTimes(1) + }) + + it('can handle disconnect before connect complete', async () => { + s.retryCount = 2 // adds some delay + await Promise.all([ + expect(async () => ( + s.connect() + )).rejects.toThrow(), + new Promise((resolve, reject) => { + s.once('connecting', () => { + // purposely unchained + // eslint-disable-next-line promise/catch-or-return + wait(0).then(() => ( + s.disconnect() + )).then(resolve, reject) + }) + }) + ]) + expect(s.getState()).toBe('disconnected') + expect(onConnected).toHaveBeenCalledTimes(0) + expect(onConnecting).toHaveBeenCalledTimes(1) + expect(onDisconnecting).toHaveBeenCalledTimes(1) + expect(onDisconnected).toHaveBeenCalledTimes(1) + expect(onDone).toHaveBeenCalledTimes(1) + }) + + it('can handle connect before disconnect complete', async () => { + await s.connect() + await Promise.all([ + new Promise((resolve, reject) => { + s.once('disconnecting', () => { + // purposely unchained + // eslint-disable-next-line promise/catch-or-return + Promise.resolve().then(() => ( + s.connect() + )).then(resolve, reject) + }) + }), + expect(async () => ( + s.disconnect() + )).rejects.toThrow(), + ]) + expect(s.getState()).toBe('connected') + expect(onConnected).toHaveBeenCalledTimes(1) + expect(onDisconnected).toHaveBeenCalledTimes(0) + expect(onDisconnecting).toHaveBeenCalledTimes(1) + expect(onConnecting).toHaveBeenCalledTimes(1) + expect(onDone).toHaveBeenCalledTimes(0) + }) + + it('emits error but does not disconnect if connect event handler fails', async () => { + expectErrors = 1 + const error = new Error('expected error') + const done = Defer() + s.once('connected', () => { + throw error // expected + }) + s.once('error', done.wrap(async (err) => { + expect(err).toBe(error) + await wait(0) + expect(s.getState()).toBe('connected') + })) + await s.connect() + expect(s.getState()).toBe('connected') + expect(onDone).toHaveBeenCalledTimes(0) + await done + }) + }) + + describe('isConnectionValid', () => { + it('works with explicit connect/disconnect', async () => { + expect(s.isConnectionValid()).not.toBeTruthy() + const onConnect = s.connect() + expect(s.isConnectionValid()).toBeTruthy() + await onConnect + expect(s.isConnectionValid()).toBeTruthy() + const onDisconnect = s.disconnect() + expect(s.isConnectionValid()).not.toBeTruthy() + await onDisconnect + expect(s.isConnectionValid()).not.toBeTruthy() + }) + + it('handles parallel calls', async () => { + s.enableAutoConnect() + await Promise.all([ + s.addHandle(1), + s.removeHandle(1), + ]) + expect(s.isConnectionValid()).not.toBeTruthy() + }) + + it('works with autoConnect', async () => { + s.enableAutoConnect() + expect(s.isConnectionValid()).not.toBeTruthy() + await s.addHandle(1) + expect(s.isConnectionValid()).toBeTruthy() + await s.removeHandle(1) + expect(s.isConnectionValid()).not.toBeTruthy() + }) + + it('works with autoDisconnect', async () => { + s.enableAutoConnect() + s.enableAutoDisconnect() + expect(s.isConnectionValid()).not.toBeTruthy() + await s.addHandle(1) + expect(s.isConnectionValid()).toBeTruthy() + await s.removeHandle(1) + expect(s.isConnectionValid()).not.toBeTruthy() + const onDisconnect = s.disconnect() + expect(s.isConnectionValid()).not.toBeTruthy() + await onDisconnect + expect(s.isConnectionValid()).not.toBeTruthy() + }) + }) + + describe('nextConnection', () => { + it('resolves on next connection', async () => { + let resolved = false + const next = s.nextConnection().then((v) => { + resolved = true + return v + }) + await s.connect() + await next + expect(resolved).toBe(true) + expect(s.getState()).toBe('connected') + }) + + it('resolves on next connection via autoConnect', async () => { + s.enableAutoConnect() + let resolved = false + const next = s.nextConnection().then((v) => { + resolved = true + return v + }) + await s.addHandle(1) + await next + expect(resolved).toBe(true) + expect(s.getState()).toBe('connected') + }) + + it('rejects on next error via autoConnect', async () => { + s.enableAutoConnect() + let errored = false + s.options.url = 'badurl' + const next = s.nextConnection().catch((err) => { + errored = true + throw err + }) + await expect(async () => { + await s.addHandle(1) + }).rejects.toThrow() + await expect(async () => { + await next + }).rejects.toThrow() + expect(errored).toBe(true) + expect(s.getState()).toBe('disconnected') + }) + + it('rejects on next error', async () => { + let errored = false + s.options.url = 'badurl' + const next = s.nextConnection().catch((err) => { + errored = true + throw err + }) + await expect(async () => { + await s.connect() + }).rejects.toThrow() + await expect(async () => { + await next + }).rejects.toThrow() + expect(errored).toBe(true) + expect(s.getState()).toBe('disconnected') + }) + + it('rejects if disconnected while connecting', async () => { + let errored = false + const next = s.nextConnection().catch((err) => { + errored = true + throw err + }) + await Promise.all([ + expect(async () => { + await s.connect() + }).rejects.toThrow(), + s.disconnect() + ]) + await expect(async () => { + await next + }).rejects.toThrow() + expect(s.getState()).toBe('disconnected') + expect(errored).toBe(true) + }) + }) + + describe('needsConnection', () => { + it('connects if autoConnect/autoDisconnect is on', async () => { + s.enableAutoConnect() + s.enableAutoDisconnect() + const t = s.addHandle(1) + await s.needsConnection() + await t + expect(s.getState()).toBe('connected') + }) + + it('errors if intentionally disconnected', async () => { + await s.disconnect() + await expect(() => ( + s.needsConnection() + )).rejects.toThrow('Needs connection') + expect(s.getState()).toBe('disconnected') + }) + + it('errors if autoConnect/autoDisconnect & no handles', async () => { + s.enableAutoConnect() + s.enableAutoDisconnect() + await expect(() => ( + s.needsConnection() + )).rejects.toThrow('Needs connection') + expect(s.getState()).toBe('disconnected') + }) + + it('ok if connected', async () => { + await s.connect() + await s.needsConnection() + expect(s.getState()).toBe('connected') + }) + + it('ok if connecting', async () => { + await s.disconnect() + const done = Defer() + s.on('connecting', done.wrap(async () => { + await s.needsConnection() + expect(s.getState()).toBe('connected') + })) + + await Promise.all([ + s.connect(), + done + ]) + + expect(s.getState()).toBe('connected') + }) + + it('ok if unintentionally disconnected', async () => { + await s.disconnect() + const done = Defer() + s.once('connected', done.wrap(async () => { + s.socket.close() + await s.needsConnection() + expect(s.getState()).toBe('connected') + })) + + await Promise.all([ + s.connect(), + done + ]) + + expect(s.getState()).toBe('connected') + }) + + it('ok if unintentionally disconnected + autoConnect/autoDisconnect is on', async () => { + await s.disconnect() + s.enableAutoConnect() + s.enableAutoDisconnect() + const done = Defer() + s.once('connected', done.wrap(async () => { + s.socket.close() + await s.needsConnection() + expect(s.getState()).toBe('connected') + })) + + await Promise.all([ + s.addHandle(1), + done + ]) + + expect(s.getState()).toBe('connected') + }) + }) + + describe('reconnecting', () => { + it('reconnects if unexpectedly disconnected', async () => { + await s.connect() + s.socket.close() + await s.nextConnection() + expect(s.getState()).toBe('connected') + }) + + it('reconnects if unexpectedly disconnected + needsConnection', async () => { + await s.connect() + s.socket.close() + await s.needsConnection() + expect(s.getState()).toBe('connected') + }) + + it('reconnects if unexpectedly disconnected on connected', async () => { + const connectTask = s.connect() + s.once('connected', async () => { + s.socket.close() + }) + await connectTask + expect(s.getState()).toBe('connected') + await s.needsConnection() + expect(s.getState()).toBe('connected') + }) + + it('reconnects if unexpectedly disconnected on connected and autoConnect/autoDisconnect is on', async () => { + s.enableAutoConnect() + s.enableAutoDisconnect() + s.once('connected', async () => { + s.socket.close() + }) + await s.addHandle(1) + await s.needsConnection() + expect(s.getState()).toBe('connected') + }) + + it('reconnects if unexpectedly disconnected and autoConnect is on', async () => { + await s.connect() + s.enableAutoConnect() + s.addHandle(1) + s.socket.close() + await s.nextConnection() + expect(s.getState()).toBe('connected') + s.removeHandle(1) + }) + + it('emits error if reconnect fails', async () => { + expectErrors = 1 + await s.connect() + s.options.url = 'badurl' + const done = Defer() + s.once('error', done.resolve) + s.socket.close() + const err = await done + expect(err).toBeTruthy() + expect(onConnected).toHaveBeenCalledTimes(1) + expect(s.getState()).toBe('disconnected') + await wait(0) + expect(onDone).toHaveBeenCalledTimes(1) + }) + + it('throws error if reconnect fails', async () => { + expectErrors = 1 + await s.connect() + s.options.url = 'badurl' + s.socket.close() + await expect(async () => ( + s.nextConnection() + )).rejects.toThrow('badurl') + expect(onConnected).toHaveBeenCalledTimes(1) + expect(s.getState()).toBe('disconnected') + await wait(0) + expect(onDone).toHaveBeenCalledTimes(1) + }) + + it('retries multiple times when disconnected', async () => { + s.options.maxRetries = 4 + /* eslint-disable no-underscore-dangle */ + await s.connect() + const goodUrl = s.options.url + let retryCount = 0 + s.options.url = 'badurl' + const done = Defer() + s.on('reconnecting', () => { + retryCount += 1 + // fail first 3 tries + // pass after + if (retryCount >= 3) { + s.options.url = goodUrl + } + }) + s.once('connected', () => { + done.resolve(undefined) + }) + s.socket.close() + await done + expect(s.getState()).toBe('connected') + expect(retryCount).toEqual(3) + /* eslint-enable no-underscore-dangle */ + }, 3000) + + it('fails if exceed max retries', async () => { + expectErrors = 1 + await s.connect() + const done = Defer() + s.options.maxRetries = 2 + s.options.url = 'badurl' + s.once('error', done.resolve) + s.socket.close() + const err = await done + expect(err).toBeTruthy() + // wait a moment for late errors + await wait(10) + expect(onDone).toHaveBeenCalledTimes(1) + await done + }) + + it('resets max retries on manual connect after failure', async () => { + expectErrors = 1 + await s.connect() + const goodUrl = s.options.url + s.options.maxRetries = 2 + s.options.url = 'badurl' + const done = Defer() + s.once('error', done.resolve) + s.socket.close() + const err = await done + expect(err).toBeTruthy() + s.options.url = goodUrl + await s.connect() + await wait(0) + expect(s.isReconnecting()).toBeFalsy() + expect(s.getState()).toBe('connected') + }) + + it('can try reconnect after error', async () => { + const goodUrl = s.options.url + s.options.url = 'badurl' + await expect(async () => ( + s.connect() + )).rejects.toThrow('badurl') + expect(onDone).toHaveBeenCalledTimes(1) + await s.disconnect() // shouldn't throw + expect(onDone).toHaveBeenCalledTimes(1) + expect(s.getState()).toBe('disconnected') + // ensure close + await expect(async () => ( + Promise.all([ + s.connect(), + s.disconnect(), + ]) + )).rejects.toThrow('disconnected before connected') + s.options.url = goodUrl + await s.connect() + expect(s.getState()).toBe('connected') + expect(onConnected).toHaveBeenCalledTimes(1) + await s.disconnect() + expect(onDone).toHaveBeenCalledTimes(2) + expect(s.getState()).toBe('disconnected') + }) + + it('stops reconnecting if disconnected while reconnecting', async () => { + await s.connect() + const goodUrl = s.options.url + s.options.url = 'badurl' + const done = Defer() + // once disconnected due to error, actually close + s.once('disconnected', done.resolve) + // trigger reconnecting cycle + s.socket.close() + await done + // i.e. would reconnect if not closing + s.options.url = goodUrl + await s.disconnect() + + // wait a moment + await wait(10) + // ensure is disconnected, not reconnecting + expect(s.getState()).toBe('disconnected') + expect(s.isReconnecting()).toBeFalsy() + expect(onDone).toHaveBeenCalledTimes(1) + }) + + it('stops reconnecting if disconnected while reconnecting, after some delay', async () => { + await s.connect() + const goodUrl = s.options.url + s.options.url = 'badurl' + const done = Defer() + // once disconnected due to error, actually close + s.once('disconnected', done.resolve) + // trigger reconnecting cycle + s.socket.close() + await done + // wait a moment + await wait(10) + // i.e. would reconnect if not closing + s.options.url = goodUrl + await s.disconnect() + await wait(20) + // ensure is disconnected, not reconnecting + expect(s.getState()).toBe('disconnected') + expect(s.isReconnecting()).toBeFalsy() + expect(onDone).toHaveBeenCalledTimes(1) + }) + }) + + describe('send', () => { + it('can send and receive messages', async () => { + await s.connect() + const done = Defer() + s.once('message', done.resolve) + + await s.send('test') + const { data }: any = await done + expect(data).toEqual('test') + }) + + it('fails if not autoconnecting or manually connected', async () => { + await expect(async () => { + await s.send('test') + }).rejects.toThrow('connection') + }) + + it('waits for connection if sending while connecting', async () => { + const done = Defer() + s.once('message', done.resolve) + + s.connect() // no await + await s.send('test') + const { data }: any = await done + expect(data).toEqual('test') + }) + + it('creates connection and waits if autoconnect true', async () => { + s.enableAutoConnect() + const done = Defer() + s.once('message', done.resolve) + // no connect + await s.send('test') + const { data }: any = await done + expect(data).toEqual('test') + }) + + it('waits for reconnecting if sending while reconnecting', async () => { + await s.connect() + const done = Defer() + s.once('message', done.resolve) + s.socket.close() // will trigger reconnect + await s.send('test') + const { data }: any = await done + expect(data).toEqual('test') + }) + + it('fails send if reconnect fails', async () => { + await s.connect() + // eslint-disable-next-line require-atomic-updates + s.options.url = 'badurl' + s.socket.close() + await expect(async () => { + await s.send('test') + }).rejects.toThrow('badurl') + }) + + it('fails send if intentionally disconnected', async () => { + await s.connect() + await s.disconnect() + await expect(async () => { + await s.send('test') + }).rejects.toThrow() + }) + + it('fails send if autoconnected but intentionally disconnected', async () => { + s.enableAutoConnect() + const received: Todo[] = [] + s.on('message', ({ data }: any = {}) => { + received.push(data) + }) + const nextMessage = Defer() + s.once('message', nextMessage.resolve) + + await s.send('test') // ok + await nextMessage + expect(received).toEqual(['test']) + await s.disconnect() // messages after this point should fail + await expect(async () => { + await s.send('test2') + }).rejects.toThrow('connection') + await wait(10) + expect(received).toEqual(['test']) + }) + + it('connects after autoconnect enabled after disconnect', async () => { + await s.connect() + await s.disconnect() + s.enableAutoConnect() + s.enableAutoDisconnect() + await s.addHandle(1) + await s.send('test') + expect(s.getState()).toBe('connected') + await s.removeHandle(1) + expect(s.getState()).toBe('disconnected') + }) + }) + + describe('autoDisconnect', () => { + beforeEach(() => { + s.enableAutoDisconnect() + s.enableAutoConnect() + }) + + it('auto-disconnects when all handles removed', async () => { + expect(s.getState()).toBe('disconnected') + await s.removeHandle(1) // noop + expect(s.getState()).toBe('disconnected') + await s.addHandle(1) + // must have had handle previously to disconnect + await s.removeHandle(2) + expect(s.getState()).toBe('connected') + await s.removeHandle(1) + expect(s.getState()).toBe('disconnected') + // can take multiple of the same handle (no error) + await s.addHandle(1) + expect(s.getState()).toBe('connected') + await s.addHandle(2) + expect(s.getState()).toBe('connected') + await s.removeHandle(2) + expect(s.getState()).toBe('connected') + // once both 1 & 2 are removed, should disconnect + await s.removeHandle(1) + expect(s.getState()).toBe('disconnected') + // can remove multiple of same handle (noop) + await s.removeHandle(1) + expect(s.getState()).toBe('disconnected') + expect(onDone).toHaveBeenCalledTimes(2) + // should not try reconnect + await wait(150) + expect(onDone).toHaveBeenCalledTimes(2) + expect(s.getState()).toBe('disconnected') + // auto disconnect should not affect auto-connect + expect(s.options.autoConnect).toBeTruthy() + await s.send('test') // ok + expect(s.getState()).toBe('disconnected') + }, 4000) + + it('auto-disconnects when all handles removed after enabling', async () => { + s.enableAutoDisconnect(false) + expect(s.getState()).toBe('disconnected') + await s.addHandle(1) + await s.send('test') + expect(s.getState()).toBe('connected') + await s.removeHandle(1) + expect(s.getState()).toBe('connected') + s.enableAutoDisconnect(true) + await s.addHandle(1) + expect(s.getState()).toBe('connected') + await s.removeHandle(1) + expect(s.getState()).toBe('disconnected') + }) + + it('handles concurrent call to removeHandle then connect', async () => { + await s.addHandle(1) + await Promise.all([ + s.removeHandle(1), + s.connect(), + ]) + + expect(s.getState()).toBe('connected') + // auto-disconnect disabled after connect + await s.addHandle(1) + await s.removeHandle(1) + expect(s.getState()).toBe('connected') + expect(s.options.autoConnect).not.toBeTruthy() + expect(s.options.autoDisconnect).not.toBeTruthy() + }) + + it('handles concurrent call to connect then removeHandle', async () => { + await s.connect() + + expect(s.getState()).toBe('connected') + await s.addHandle(1) + await Promise.all([ + s.connect(), + s.removeHandle(1), + ]) + expect(s.getState()).toBe('connected') + expect(s.options.autoConnect).not.toBeTruthy() + expect(s.options.autoDisconnect).not.toBeTruthy() + }) + + it('handles concurrent call to disconnect then removeHandle', async () => { + await s.connect() + + expect(s.getState()).toBe('connected') + await s.addHandle(1) + await Promise.all([ + s.disconnect(), + s.removeHandle(1), + ]) + expect(s.getState()).toBe('disconnected') + expect(s.options.autoConnect).not.toBeTruthy() + expect(s.options.autoDisconnect).not.toBeTruthy() + }) + + it('handles concurrent call to removeHandle then disconnect', async () => { + await s.connect() + + expect(s.getState()).toBe('connected') + await s.addHandle(1) + await Promise.all([ + s.removeHandle(1), + s.disconnect(), + ]) + expect(s.getState()).toBe('disconnected') + expect(s.options.autoConnect).not.toBeTruthy() + expect(s.options.autoDisconnect).not.toBeTruthy() + }) + + it('handles concurrent call to removeHandle then disconnect + connect', async () => { + await s.connect() + expect(s.getState()).toBe('connected') + await s.addHandle(1) + const tasks = Promise.all([ + expect(() => { + return s.disconnect() + }).rejects.toThrow(), + s.connect(), // this will cause disconnect call to throw + ]) + await s.removeHandle(1) + await tasks + expect(s.getState()).toBe('connected') + expect(s.options.autoConnect).not.toBeTruthy() + }) + + it('handles concurrent call to removeHandle', async () => { + await s.connect() + expect(s.getState()).toBe('connected') + await s.addHandle(1) + await Promise.all([ + s.removeHandle(1), + s.addHandle(1), + s.connect(), + s.removeHandle(1), + ]) + expect(s.getState()).toBe('connected') + expect(s.options.autoConnect).not.toBeTruthy() + }) + + it('late disconnect', async () => { + await s.addHandle(1) + await s.addHandle(2) + expect(s.getState()).toBe('connected') + await s.removeHandle(2) + expect(s.getState()).toBe('connected') + const t = s.removeHandle(1) + await wait(0) + await s.disconnect() // disconnect while auto-disconnecting + await t + expect(s.getState()).toBe('disconnected') + }) + + it('does nothing if autoDisconnect is false', async () => { + s.enableAutoConnect() + s.enableAutoDisconnect(false) + await s.addHandle(1) + expect(s.getState()).toBe('connected') + await s.addHandle(2) + expect(s.getState()).toBe('connected') + await s.removeHandle(2) + expect(s.getState()).toBe('connected') + await s.removeHandle(1) + expect(s.getState()).toBe('connected') + expect(s.options.autoConnect).toBeTruthy() + expect(s.options.autoDisconnect).not.toBeTruthy() + }) + }) + + describe('onTransition', () => { + it('runs functions', async () => { + const transitionFns = { + onConnected: jest.fn(), + onConnecting: jest.fn(), + onDisconnected: jest.fn(), + onDisconnecting: jest.fn(), + onDone: jest.fn(), + onError: jest.fn(), + } + + s.onTransition(transitionFns) + + await s.connect() + expect(transitionFns.onConnecting).toHaveBeenCalledTimes(1) + expect(transitionFns.onConnected).toHaveBeenCalledTimes(1) + s.socket.close() + await s.nextConnection() + expect(transitionFns.onDisconnecting).toHaveBeenCalledTimes(1) + expect(transitionFns.onDisconnected).toHaveBeenCalledTimes(1) + expect(transitionFns.onConnecting).toHaveBeenCalledTimes(2) + expect(transitionFns.onConnected).toHaveBeenCalledTimes(2) + expect(transitionFns.onDone).toHaveBeenCalledTimes(0) + await s.disconnect() + expect(transitionFns.onConnecting).toHaveBeenCalledTimes(2) + expect(transitionFns.onConnected).toHaveBeenCalledTimes(2) + expect(transitionFns.onDisconnecting).toHaveBeenCalledTimes(2) + expect(transitionFns.onDisconnected).toHaveBeenCalledTimes(2) + expect(transitionFns.onDone).toHaveBeenCalledTimes(1) + expect(transitionFns.onError).toHaveBeenCalledTimes(0) + + await s.connect() + // no more fired after disconnect done + expect(transitionFns.onConnecting).toHaveBeenCalledTimes(2) + expect(transitionFns.onConnected).toHaveBeenCalledTimes(2) + expect(transitionFns.onDisconnecting).toHaveBeenCalledTimes(2) + expect(transitionFns.onDisconnected).toHaveBeenCalledTimes(2) + expect(transitionFns.onDone).toHaveBeenCalledTimes(1) + expect(transitionFns.onError).toHaveBeenCalledTimes(0) + }) + }) +}) diff --git a/test/unit/EncryptionUtil.test.js b/test/unit/Encryption.test.js similarity index 71% rename from test/unit/EncryptionUtil.test.js rename to test/unit/Encryption.test.js index 743252893..5a52a1517 100644 --- a/test/unit/EncryptionUtil.test.js +++ b/test/unit/Encryption.test.js @@ -3,7 +3,7 @@ import crypto from 'crypto' import { ethers } from 'ethers' import { MessageLayer } from 'streamr-client-protocol' -import EncryptionUtil from '../../src/EncryptionUtil' +import EncryptionUtil, { GroupKey } from '../../src/stream/Encryption' const { StreamMessage, MessageID } = MessageLayer @@ -20,30 +20,28 @@ function TestEncryptionUtil({ isBrowser = false } = {}) { }) it('rsa decryption after encryption equals the initial plaintext', async () => { - const encryptionUtil = new EncryptionUtil() - await encryptionUtil.onReady() + const encryptionUtil = await EncryptionUtil.create() const plaintext = 'some random text' const ciphertext = EncryptionUtil.encryptWithPublicKey(Buffer.from(plaintext, 'utf8'), encryptionUtil.getPublicKey()) expect(encryptionUtil.decryptWithPrivateKey(ciphertext).toString('utf8')).toStrictEqual(plaintext) }) it('rsa decryption after encryption equals the initial plaintext (hex strings)', async () => { - const encryptionUtil = new EncryptionUtil() - await encryptionUtil.onReady() + const encryptionUtil = await EncryptionUtil.create() const plaintext = 'some random text' const ciphertext = EncryptionUtil.encryptWithPublicKey(Buffer.from(plaintext, 'utf8'), encryptionUtil.getPublicKey(), true) expect(encryptionUtil.decryptWithPrivateKey(ciphertext, true).toString('utf8')).toStrictEqual(plaintext) }) it('aes decryption after encryption equals the initial plaintext', () => { - const key = crypto.randomBytes(32) + const key = GroupKey.generate() const plaintext = 'some random text' const ciphertext = EncryptionUtil.encrypt(Buffer.from(plaintext, 'utf8'), key) expect(EncryptionUtil.decrypt(ciphertext, key).toString('utf8')).toStrictEqual(plaintext) }) it('aes encryption preserves size (plus iv)', () => { - const key = crypto.randomBytes(32) + const key = GroupKey.generate() const plaintext = 'some random text' const plaintextBuffer = Buffer.from(plaintext, 'utf8') const ciphertext = EncryptionUtil.encrypt(plaintextBuffer, key) @@ -52,7 +50,7 @@ function TestEncryptionUtil({ isBrowser = false } = {}) { }) it('multiple same encrypt() calls use different ivs and produce different ciphertexts', () => { - const key = crypto.randomBytes(32) + const key = GroupKey.generate() const plaintext = 'some random text' const ciphertext1 = EncryptionUtil.encrypt(Buffer.from(plaintext, 'utf8'), key) const ciphertext2 = EncryptionUtil.encrypt(Buffer.from(plaintext, 'utf8'), key) @@ -61,14 +59,14 @@ function TestEncryptionUtil({ isBrowser = false } = {}) { }) it('StreamMessage gets encrypted', () => { - const key = crypto.randomBytes(32) + const key = GroupKey.generate() const streamMessage = new StreamMessage({ messageId: new MessageID('streamId', 0, 1, 0, 'publisherId', 'msgChainId'), prevMesssageRef: null, content: { foo: 'bar', }, - messageType: StreamMessage.MESSAGE_TYPES.MESSAGE, + contentType: StreamMessage.CONTENT_TYPES.MESSAGE, encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, signatureType: StreamMessage.SIGNATURE_TYPES.NONE, signature: null, @@ -79,14 +77,14 @@ function TestEncryptionUtil({ isBrowser = false } = {}) { }) it('StreamMessage decryption after encryption equals the initial StreamMessage', () => { - const key = crypto.randomBytes(32) + const key = GroupKey.generate() const streamMessage = new StreamMessage({ messageId: new MessageID('streamId', 0, 1, 0, 'publisherId', 'msgChainId'), prevMesssageRef: null, content: { foo: 'bar', }, - messageType: StreamMessage.MESSAGE_TYPES.MESSAGE, + contentType: StreamMessage.CONTENT_TYPES.MESSAGE, encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, signatureType: StreamMessage.SIGNATURE_TYPES.NONE, signature: null, @@ -98,46 +96,6 @@ function TestEncryptionUtil({ isBrowser = false } = {}) { expect(streamMessage.encryptionType).toStrictEqual(StreamMessage.ENCRYPTION_TYPES.NONE) }) - it('StreamMessage gets encrypted with new key', () => { - const key = crypto.randomBytes(32) - const newKey = crypto.randomBytes(32) - const streamMessage = new StreamMessage({ - messageId: new MessageID('streamId', 0, 1, 0, 'publisherId', 'msgChainId'), - prevMesssageRef: null, - content: { - foo: 'bar', - }, - messageType: StreamMessage.MESSAGE_TYPES.MESSAGE, - encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, - signatureType: StreamMessage.SIGNATURE_TYPES.NONE, - signature: null, - }) - EncryptionUtil.encryptStreamMessageAndNewKey(newKey, streamMessage, key) - expect(streamMessage.getSerializedContent()).not.toStrictEqual('{"foo":"bar"}') - expect(streamMessage.encryptionType).toStrictEqual(StreamMessage.ENCRYPTION_TYPES.NEW_KEY_AND_AES) - }) - - it('StreamMessage decryption after encryption equals the initial StreamMessage (with new key)', () => { - const key = crypto.randomBytes(32) - const newKey = crypto.randomBytes(32) - const streamMessage = new StreamMessage({ - messageId: new MessageID('streamId', 0, 1, 0, 'publisherId', 'msgChainId'), - prevMesssageRef: null, - content: { - foo: 'bar', - }, - messageType: StreamMessage.MESSAGE_TYPES.MESSAGE, - encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, - signatureType: StreamMessage.SIGNATURE_TYPES.NONE, - signature: null, - }) - EncryptionUtil.encryptStreamMessageAndNewKey(newKey, streamMessage, key) - const newKeyReceived = EncryptionUtil.decryptStreamMessage(streamMessage, key) - expect(newKeyReceived).toStrictEqual(newKey) - expect(streamMessage.getSerializedContent()).toStrictEqual('{"foo":"bar"}') - expect(streamMessage.encryptionType).toStrictEqual(StreamMessage.ENCRYPTION_TYPES.NONE) - }) - it('throws if invalid public key passed in the constructor', () => { const keys = crypto.generateKeyPairSync('rsa', { modulusLength: 4096, @@ -207,12 +165,12 @@ function TestEncryptionUtil({ isBrowser = false } = {}) { it('validateGroupKey() throws if key is not a buffer', () => { expect(() => { - EncryptionUtil.validateGroupKey(ethers.utils.hexlify(crypto.randomBytes(32))) + EncryptionUtil.validateGroupKey(ethers.utils.hexlify(GroupKey.generate())) }).toThrow() }) it('validateGroupKey() does not throw', () => { - EncryptionUtil.validateGroupKey(crypto.randomBytes(32)) + EncryptionUtil.validateGroupKey(GroupKey.generate()) }) }) } diff --git a/test/unit/KeyExchangeUtil.test.js b/test/unit/KeyExchangeUtil.test.js deleted file mode 100644 index b9eca220c..000000000 --- a/test/unit/KeyExchangeUtil.test.js +++ /dev/null @@ -1,325 +0,0 @@ -import crypto from 'crypto' - -import sinon from 'sinon' -import { MessageLayer } from 'streamr-client-protocol' -import debugFactory from 'debug' - -import KeyExchangeUtil from '../../src/KeyExchangeUtil' -import EncryptionUtil from '../../src/EncryptionUtil' -import KeyStorageUtil from '../../src/KeyStorageUtil' -import InvalidGroupKeyResponseError from '../../src/errors/InvalidGroupKeyResponseError' -import InvalidGroupKeyRequestError from '../../src/errors/InvalidGroupKeyRequestError' -import { uid } from '../utils' - -const { StreamMessage, MessageIDStrict } = MessageLayer -const subscribers = ['0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa01'.toLowerCase(), 'subscriber2', 'subscriber3'] -const subscribersMap = {} -subscribers.forEach((p) => { - subscribersMap[p] = true -}) - -async function setupClient() { - const client = {} - client.debug = debugFactory('StreamrClient::test') - client.getStreamSubscribers = sinon.stub() - client.getStreamSubscribers.withArgs('streamId').resolves(subscribers) - client.isStreamSubscriber = sinon.stub() - client.isStreamSubscriber.withArgs('streamId', 'subscriber4').resolves(true) - client.isStreamSubscriber.withArgs('streamId', 'subscriber5').resolves(false) - client.keyStorageUtil = KeyStorageUtil.getKeyStorageUtil() - client.keyStorageUtil.addKey('streamId', crypto.randomBytes(32), 5) - client.keyStorageUtil.addKey('streamId', crypto.randomBytes(32), 12) - client.keyStorageUtil.addKey('streamId', crypto.randomBytes(32), 17) - client.keyStorageUtil.addKey('streamId', crypto.randomBytes(32), 25) - client.keyStorageUtil.addKey('streamId', crypto.randomBytes(32), 35) - client.subscribedStreamPartitions = { - streamId0: { // 'streamId' + 0 (stream partition) - setSubscriptionsGroupKey: sinon.stub(), - }, - } - client.encryptionUtil = new EncryptionUtil() - await client.encryptionUtil.onReady() - return client -} - -describe('KeyExchangeUtil', () => { - let client - let util - beforeEach(async () => { - client = await setupClient() - util = new KeyExchangeUtil(client) - }) - - describe('getSubscribers', () => { - it('should use endpoint to retrieve subscribers', async () => { - const retrievedSubscribers = await util.getSubscribers('streamId') - expect(client.getStreamSubscribers.calledOnce).toBeTruthy() - expect(subscribersMap).toStrictEqual(retrievedSubscribers) - expect(await util.subscribersPromise).toStrictEqual(subscribersMap) - }) - - it('should use stored subscribers and not the endpoint', async () => { - util.subscribersPromise = Promise.resolve(subscribersMap) - const retrievedSubscribers = await util.getSubscribers('streamId') - expect(client.getStreamSubscribers.notCalled).toBeTruthy() - expect(subscribersMap).toStrictEqual(retrievedSubscribers) - }) - - it('should call getStreamPublishers only once when multiple calls made simultaneously', async () => { - const p1 = util.getSubscribers('streamId') - const p2 = util.getSubscribers('streamId') - const [subscribers1, subscribers2] = await Promise.all([p1, p2]) - expect(client.getStreamSubscribers.calledOnce).toBeTruthy() - expect(subscribers1).toStrictEqual(subscribers2) - }) - - it('should use endpoint again after the list of locally stored publishers expires', async () => { - const clock = sinon.useFakeTimers() - await util.getSubscribers('streamId') - util.subscribersPromise = Promise.resolve(subscribersMap) - await util.getSubscribers('streamId') - clock.tick(KeyExchangeUtil.SUBSCRIBERS_EXPIRATION_TIME + 100) - await util.getSubscribers('streamId') - expect(client.getStreamSubscribers.calledTwice).toBeTruthy() - clock.restore() - }) - }) - - describe('handleGroupKeyRequest', () => { - it('should reject request for a stream for which the client does not have a group key', async (done) => { - const requestId = uid('requestId') - const streamMessage = new StreamMessage({ - messageId: new MessageIDStrict('clientKeyExchangeAddress', 0, Date.now(), 0, 'subscriber2', ''), - prevMsgRef: null, - content: { - streamId: 'wrong-streamId', - publicKey: 'rsa-public-key', - requestId, - }, - messageType: StreamMessage.MESSAGE_TYPES.GROUP_KEY_REQUEST, - encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, - signatureType: StreamMessage.SIGNATURE_TYPES.ETH, - signature: 'signature', - }) - - await util.handleGroupKeyRequest(streamMessage).catch((err) => { - expect(err).toBeInstanceOf(InvalidGroupKeyRequestError) - expect(err.message).toBe('Received group key request for stream \'wrong-streamId\' but no group key is set') - done() - }) - }) - - it('should send group key response (latest key)', async (done) => { - const requestId = uid('requestId') - const subscriberKeyPair = new EncryptionUtil() - await subscriberKeyPair.onReady() - const streamMessage = new StreamMessage({ - messageId: new MessageIDStrict('clientKeyExchangeAddress', 0, Date.now(), 0, 'subscriber2', ''), - prevMsgRef: null, - content: { - streamId: 'streamId', - publicKey: subscriberKeyPair.getPublicKey(), - requestId, - }, - messageType: StreamMessage.MESSAGE_TYPES.GROUP_KEY_REQUEST, - encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, - signatureType: StreamMessage.SIGNATURE_TYPES.ETH, - signature: 'signature', - }) - - client.msgCreationUtil = { - createGroupKeyResponse: ({ subscriberAddress, streamId, encryptedGroupKeys }) => { - expect(subscriberAddress).toBe('subscriber2') - expect(streamId).toBe('streamId') - expect(encryptedGroupKeys.length).toBe(1) - const keyObject = encryptedGroupKeys[0] - const expectedKeyObj = client.keyStorageUtil.getLatestKey('streamId') - expect(subscriberKeyPair.decryptWithPrivateKey(keyObject.groupKey, true)).toStrictEqual(expectedKeyObj.groupKey) - expect(keyObject.start).toStrictEqual(expectedKeyObj.start) - return Promise.resolve('fake response') - }, - } - client.publishStreamMessage = (response) => { - expect(response).toBe('fake response') - done() - } - - await util.handleGroupKeyRequest(streamMessage) - }) - - it('should send group key response (range of keys)', async (done) => { - const requestId = uid('requestId') - const subscriberKeyPair = new EncryptionUtil() - await subscriberKeyPair.onReady() - const streamMessage = new StreamMessage({ - messageId: new MessageIDStrict('clientKeyExchangeAddress', 0, Date.now(), 0, 'subscriber2', ''), - prevMsgRef: null, - content: { - streamId: 'streamId', - publicKey: subscriberKeyPair.getPublicKey(), - requestId, - range: { - start: 15, - end: 27 - } - }, - messageType: StreamMessage.MESSAGE_TYPES.GROUP_KEY_REQUEST, - encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, - signatureType: StreamMessage.SIGNATURE_TYPES.ETH, - signature: 'signature', - }) - - client.msgCreationUtil = { - createGroupKeyResponse: ({ subscriberAddress, streamId, encryptedGroupKeys }) => { - expect(subscriberAddress).toBe('subscriber2') - expect(streamId).toBe('streamId') - const decryptedKeys = [] - encryptedGroupKeys.forEach((keyObj) => { - const decryptedKey = subscriberKeyPair.decryptWithPrivateKey(keyObj.groupKey, true) - decryptedKeys.push({ - groupKey: decryptedKey, - start: keyObj.start - }) - }) - expect(decryptedKeys).toStrictEqual(client.keyStorageUtil.getKeysBetween('streamId', 15, 27)) - return Promise.resolve('fake response') - }, - } - - client.publishStreamMessage = (response) => { - expect(response).toBe('fake response') - done() - } - - await util.handleGroupKeyRequest(streamMessage) - }) - - it('should send group key response (latest key and no storage of past keys)', async (done) => { - const requestId = uid('requestId') - const subscriberKeyPair = new EncryptionUtil() - await subscriberKeyPair.onReady() - const streamMessage = new StreamMessage({ - messageId: new MessageIDStrict('clientKeyExchangeAddress', 0, Date.now(), 0, 'subscriber2', ''), - prevMsgRef: null, - content: { - requestId, - streamId: 'streamId', - publicKey: subscriberKeyPair.getPublicKey(), - }, - messageType: StreamMessage.MESSAGE_TYPES.GROUP_KEY_REQUEST, - encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, - signatureType: StreamMessage.SIGNATURE_TYPES.ETH, - signature: 'signature', - }) - client.msgCreationUtil = { - createGroupKeyResponse: ({ subscriberAddress, streamId, encryptedGroupKeys }) => { - expect(subscriberAddress).toBe('subscriber2') - expect(streamId).toBe('streamId') - expect(encryptedGroupKeys.length).toBe(1) - const keyObject = encryptedGroupKeys[0] - const expectedKeyObj = client.keyStorageUtil.getLatestKey('streamId') - expect(subscriberKeyPair.decryptWithPrivateKey(keyObject.groupKey, true)).toStrictEqual(expectedKeyObj.groupKey) - expect(keyObject.start).toStrictEqual(expectedKeyObj.start) - return Promise.resolve('fake response') - }, - } - client.publishStreamMessage = (response) => { - expect(response).toBe('fake response') - done() - } - util.handleGroupKeyRequest(streamMessage) - }) - }) - - describe('handleGroupKeyResponse', () => { - it('should reject response for a stream to which the client is not subscribed', async (done) => { - const requestId = uid('requestId') - const streamMessage = new StreamMessage({ - messageId: new MessageIDStrict('clientKeyExchangeAddress', 0, Date.now(), 0, 'publisherId', ''), - prevMsgRef: null, - content: { - streamId: 'wrong-streamId', - requestId, - keys: [{ - groupKey: 'encrypted-group-key', - start: 54256, - }], - }, - messageType: StreamMessage.MESSAGE_TYPES.GROUP_KEY_RESPONSE, - encryptionType: StreamMessage.ENCRYPTION_TYPES.RSA, - signatureType: StreamMessage.SIGNATURE_TYPES.ETH, - signature: 'signature', - }) - - try { - util.handleGroupKeyResponse(streamMessage) - } catch (err) { - expect(err).toBeInstanceOf(InvalidGroupKeyResponseError) - expect(err.message).toBe('Received group key response for a stream to which the client is not subscribed.') - done() - } - }) - - it('should reject response with invalid group key', async (done) => { - const requestId = uid('requestId') - const encryptedGroupKey = EncryptionUtil.encryptWithPublicKey(crypto.randomBytes(16), client.encryptionUtil.getPublicKey(), true) - const streamMessage = new StreamMessage({ - messageId: new MessageIDStrict('clientKeyExchangeAddress', 0, Date.now(), 0, 'publisherId', ''), - prevMsgRef: null, - content: { - streamId: 'streamId', - requestId, - keys: [{ - groupKey: encryptedGroupKey, - start: 54256, - }], - }, - messageType: StreamMessage.MESSAGE_TYPES.GROUP_KEY_RESPONSE, - encryptionType: StreamMessage.ENCRYPTION_TYPES.RSA, - signatureType: StreamMessage.SIGNATURE_TYPES.ETH, - signature: 'signature', - }) - try { - util.handleGroupKeyResponse(streamMessage) - } catch (err) { - expect(err).toBeInstanceOf(InvalidGroupKeyResponseError) - expect(err.message).toBe('Group key must have a size of 256 bits, not 128') - done() - } - }) - - it('should update client options and subscriptions with received group key', async (done) => { - const requestId = uid('requestId') - const groupKey = crypto.randomBytes(32) - const encryptedGroupKey = EncryptionUtil.encryptWithPublicKey(groupKey, client.encryptionUtil.getPublicKey(), true) - const streamMessage = new StreamMessage({ - messageId: new MessageIDStrict('clientKeyExchangeAddress', 0, Date.now(), 0, 'publisherId', ''), - prevMsgRef: null, - content: { - streamId: 'streamId', - requestId, - keys: [{ - groupKey: encryptedGroupKey, - start: 54256, - }], - }, - messageType: StreamMessage.MESSAGE_TYPES.GROUP_KEY_RESPONSE, - encryptionType: StreamMessage.ENCRYPTION_TYPES.RSA, - signatureType: StreamMessage.SIGNATURE_TYPES.ETH, - signature: 'signature', - }) - - // eslint-disable-next-line no-underscore-dangle - client._setGroupKeys = (streamId, publisherId, keys) => { - expect(streamId).toBe('streamId') - expect(publisherId).toBe('publisherId') - expect(keys).toStrictEqual([{ - groupKey, - start: 54256 - }]) - done() - } - await util.handleGroupKeyResponse(streamMessage) - }) - }) -}) diff --git a/test/unit/KeyHistoryStorageUtil.test.js b/test/unit/KeyHistoryStorageUtil.test.js deleted file mode 100644 index 3195e4b5f..000000000 --- a/test/unit/KeyHistoryStorageUtil.test.js +++ /dev/null @@ -1,122 +0,0 @@ -import crypto from 'crypto' - -import KeyStorageUtil from '../../src/KeyStorageUtil' - -describe('KeyHistoryStorageUtil', () => { - describe('hasKey()', () => { - it('returns true iff there is a GroupKeyHistory for the stream', () => { - const util = KeyStorageUtil.getKeyStorageUtil({ - streamId: { - groupKey: crypto.randomBytes(32), - start: Date.now() - } - }) - - expect(util.hasKey('streamId')).toBe(true) - expect(util.hasKey('wrong-streamId')).toBe(false) - }) - }) - - describe('addKey()', () => { - it('throws if adding an older key', () => { - const util = KeyStorageUtil.getKeyStorageUtil({ - streamId: { - groupKey: crypto.randomBytes(32), - start: Date.now() - } - }) - - expect(() => { - util.addKey('streamId', crypto.randomBytes(32), 0) - }).toThrow() - }) - }) - - describe('getLatestKey()', () => { - it('returns undefined if no key history', () => { - const util = KeyStorageUtil.getKeyStorageUtil() - expect(util.getLatestKey('streamId')).toBe(undefined) - }) - - it('returns key passed in constructor', () => { - const lastKey = crypto.randomBytes(32) - const util = KeyStorageUtil.getKeyStorageUtil({ - streamId: { - groupKey: lastKey, - start: 7 - } - }) - - expect(util.getLatestKey('streamId')).toStrictEqual({ - groupKey: lastKey, - start: 7, - }) - }) - - it('returns the last key', () => { - const util = KeyStorageUtil.getKeyStorageUtil() - util.addKey('streamId', crypto.randomBytes(32), 1) - util.addKey('streamId', crypto.randomBytes(32), 5) - const lastKey = crypto.randomBytes(32) - util.addKey('streamId', lastKey, 7) - - expect(util.getLatestKey('streamId')).toStrictEqual({ - groupKey: lastKey, - start: 7, - }) - }) - }) - - describe('getKeysBetween()', () => { - it('returns empty array for wrong streamId', () => { - const util = KeyStorageUtil.getKeyStorageUtil() - expect(util.getKeysBetween('wrong-streamId', 1, 2)).toStrictEqual([]) - }) - - it('returns empty array when end time is before start of first key', () => { - const util = KeyStorageUtil.getKeyStorageUtil() - util.addKey('streamId', crypto.randomBytes(32), 10) - expect(util.getKeysBetween('streamId', 1, 9)).toStrictEqual([]) - }) - - it('returns only the latest key when start time is after last key', () => { - const util = KeyStorageUtil.getKeyStorageUtil() - util.addKey('streamId', crypto.randomBytes(32), 5) - const lastKey = crypto.randomBytes(32) - util.addKey('streamId', lastKey, 10) - expect(util.getKeysBetween('streamId', 15, 120)).toStrictEqual([{ - groupKey: lastKey, - start: 10 - }]) - }) - - it('returns keys in interval start-end', () => { - const util = KeyStorageUtil.getKeyStorageUtil() - const key1 = crypto.randomBytes(32) - const key2 = crypto.randomBytes(32) - const key3 = crypto.randomBytes(32) - const key4 = crypto.randomBytes(32) - const key5 = crypto.randomBytes(32) - - util.addKey('streamId', key1, 10) - util.addKey('streamId', key2, 20) - util.addKey('streamId', key3, 30) - util.addKey('streamId', key4, 40) - util.addKey('streamId', key5, 50) - - const expectedKeys = [{ - groupKey: key2, - start: 20 - }, { - groupKey: key3, - start: 30 - }, { - groupKey: key4, - start: 40 - }] - - expect(util.getKeysBetween('streamId', 23, 47)).toStrictEqual(expectedKeys) - expect(util.getKeysBetween('streamId', 20, 40)).toStrictEqual(expectedKeys) - }) - }) -}) diff --git a/test/unit/LatestKeyStorageUtil.test.js b/test/unit/LatestKeyStorageUtil.test.js deleted file mode 100644 index 5eeeedd9e..000000000 --- a/test/unit/LatestKeyStorageUtil.test.js +++ /dev/null @@ -1,72 +0,0 @@ -import crypto from 'crypto' - -import KeyStorageUtil from '../../src/KeyStorageUtil' - -describe('LatestKeyStorageUtil', () => { - describe('hasKey()', () => { - it('returns true iff there is a GroupKeyHistory for the stream', () => { - const util = KeyStorageUtil.getKeyStorageUtil({ - streamId: { - groupKey: crypto.randomBytes(32), - start: Date.now() - } - }, false) - expect(util.hasKey('streamId')).toBe(true) - expect(util.hasKey('wrong-streamId')).toBe(false) - }) - }) - - describe('addKey()', () => { - it('throws if adding an older key', () => { - const util = KeyStorageUtil.getKeyStorageUtil({ - streamId: { - groupKey: crypto.randomBytes(32), - start: Date.now() - } - }, false) - expect(() => { - util.addKey('streamId', crypto.randomBytes(32), 0) - }).toThrow() - }) - }) - - describe('getLatestKey()', () => { - it('returns undefined if no key', () => { - const util = KeyStorageUtil.getKeyStorageUtil({}, false) - expect(util.getLatestKey('streamId')).toBe(undefined) - }) - - it('returns key passed in constructor', () => { - const lastKey = crypto.randomBytes(32) - const util = KeyStorageUtil.getKeyStorageUtil({ - streamId: { - groupKey: lastKey, - start: 7 - } - }, false) - expect(util.getLatestKey('streamId')).toStrictEqual({ - groupKey: lastKey, - start: 7, - }) - }) - - it('returns the last key', () => { - const util = KeyStorageUtil.getKeyStorageUtil({}, false) - util.addKey('streamId', crypto.randomBytes(32), 1) - util.addKey('streamId', crypto.randomBytes(32), 5) - const lastKey = crypto.randomBytes(32) - util.addKey('streamId', lastKey, 7) - expect(util.getLatestKey('streamId')).toStrictEqual({ - groupKey: lastKey, - start: 7, - }) - }) - }) - - describe('getKeysBetween()', () => { - it('throws since historical keys are not stored', () => { - const util = KeyStorageUtil.getKeyStorageUtil({}, false) - expect(() => util.getKeysBetween('wrong-streamId', 1, 2)).toThrow() - }) - }) -}) diff --git a/test/unit/MessageCreationUtil.test.js b/test/unit/MessageCreationUtil.test.js deleted file mode 100644 index 931a2789e..000000000 --- a/test/unit/MessageCreationUtil.test.js +++ /dev/null @@ -1,521 +0,0 @@ -import crypto from 'crypto' - -import sinon from 'sinon' -import { ethers } from 'ethers' -import { MessageLayer } from 'streamr-client-protocol' -import uniqueId from 'lodash.uniqueid' - -import MessageCreationUtil from '../../src/MessageCreationUtil' -import Stream from '../../src/rest/domain/Stream' -import KeyStorageUtil from '../../src/KeyStorageUtil' -import KeyExchangeUtil from '../../src/KeyExchangeUtil' -import InvalidGroupKeyRequestError from '../../src/errors/InvalidGroupKeyRequestError' - -const { StreamMessage, MessageID, MessageRef } = MessageLayer -const { getKeyExchangeStreamId } = KeyExchangeUtil - -describe('MessageCreationUtil', () => { - const hashedUsername = '0x16F78A7D6317F102BBD95FC9A4F3FF2E3249287690B8BDAD6B7810F82B34ACE3'.toLowerCase() - - describe('getPublisherId', () => { - it('uses address', async () => { - const wallet = ethers.Wallet.createRandom() - const client = { - options: { - auth: { - privateKey: wallet.privateKey, - }, - }, - getUserInfo: sinon.stub().resolves({ - username: 'username', - }), - } - const msgCreationUtil = new MessageCreationUtil(client.options.auth, undefined, client.getUserInfo) - const publisherId = await msgCreationUtil.getPublisherId() - expect(publisherId).toBe(wallet.address.toLowerCase()) - }) - - it('uses hash of username', async () => { - const client = { - options: { - auth: { - apiKey: 'apiKey', - }, - }, - getUserInfo: sinon.stub().resolves({ - username: 'username', - }), - } - const msgCreationUtil = new MessageCreationUtil(client.options.auth, undefined, client.getUserInfo) - const publisherId = await msgCreationUtil.getPublisherId() - expect(publisherId).toBe(hashedUsername) - }) - - it('uses hash of username', async () => { - const client = { - options: { - auth: { - username: 'username', - }, - }, - getUserInfo: sinon.stub().resolves({ - username: 'username', - }), - } - const msgCreationUtil = new MessageCreationUtil(client.options.auth, undefined, client.getUserInfo) - const publisherId = await msgCreationUtil.getPublisherId() - expect(publisherId).toBe(hashedUsername) - }) - - it('uses hash of username', async () => { - const client = { - options: { - auth: { - sessionToken: 'session-token', - }, - }, - getUserInfo: sinon.stub().resolves({ - username: 'username', - }), - } - const msgCreationUtil = new MessageCreationUtil(client.options.auth, undefined, client.getUserInfo) - const publisherId = await msgCreationUtil.getPublisherId() - expect(publisherId).toBe(hashedUsername) - }) - }) - - describe('partitioner', () => { - it('should throw if partition count is not defined', () => { - expect(() => { - new MessageCreationUtil().computeStreamPartition(undefined, 'foo') - }).toThrow() - }) - - it('should always return partition 0 for all keys if partition count is 1', () => { - for (let i = 0; i < 100; i++) { - expect(new MessageCreationUtil().computeStreamPartition(1, `foo${i}`)).toEqual(0) - } - }) - - it('should use md5 partitioner and produce same results as crypto.createHash(md5).update(string).digest()', () => { - const keys = [] - for (let i = 0; i < 100; i++) { - keys.push(`key-${i}`) - } - // Results must be the same as those produced by md5 - const correctResults = [6, 7, 4, 4, 9, 1, 8, 0, 6, 6, 7, 6, 7, 3, 2, 2, 0, 9, 4, 9, 9, 5, 5, - 1, 7, 3, 0, 6, 5, 6, 3, 6, 3, 5, 6, 2, 3, 6, 7, 2, 1, 3, 2, 7, 1, 1, 5, 1, 4, 0, 1, 9, 7, - 4, 2, 3, 2, 9, 7, 7, 4, 3, 5, 4, 5, 3, 9, 0, 4, 8, 1, 7, 4, 8, 1, 2, 9, 9, 5, 3, 5, 0, 9, - 4, 3, 9, 6, 7, 8, 6, 4, 6, 0, 1, 1, 5, 8, 3, 9, 7] - - expect(correctResults.length).toEqual(keys.length) - - for (let i = 0; i < keys.length; i++) { - const partition = new MessageCreationUtil().computeStreamPartition(10, keys[i]) - expect(correctResults[i]).toStrictEqual(partition) - } - }) - }) - - describe('createStreamMessage()', () => { - const pubMsg = { - foo: 'bar', - } - - const stream = new Stream(null, { - id: 'streamId', - partitions: 1, - }) - - let client - let msgCreationUtil - - beforeEach(() => { - client = { - options: { - auth: { - username: 'username', - }, - }, - signer: { - signStreamMessage: (streamMessage) => { - /* eslint-disable no-param-reassign */ - streamMessage.signatureType = StreamMessage.SIGNATURE_TYPES.ETH - streamMessage.signature = 'signature' - /* eslint-enable no-param-reassign */ - return Promise.resolve() - }, - }, - getUserInfo: () => Promise.resolve({ - username: 'username', - }), - getStream: sinon.stub().resolves(stream), - } - msgCreationUtil = new MessageCreationUtil(client.options.auth, client.signer, client.getUserInfo(), client.getStream) - }) - - afterAll(() => { - msgCreationUtil.stop() - }) - - function getStreamMessage(streamId, timestamp, sequenceNumber, prevMsgRef) { - return new StreamMessage({ - messageId: new MessageID(streamId, 0, timestamp, sequenceNumber, hashedUsername, msgCreationUtil.msgChainId), - prevMesssageRef: prevMsgRef, - content: pubMsg, - messageType: StreamMessage.MESSAGE_TYPES.MESSAGE, - encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, - signatureType: StreamMessage.SIGNATURE_TYPES.ETH, - signature: 'signature', - }) - } - - it('should create messages with increasing sequence numbers', async () => { - const ts = Date.now() - const promises = [] - let prevMsgRef = null - for (let i = 0; i < 10; i++) { - /* eslint-disable no-loop-func */ - prevMsgRef = new MessageRef(ts, i) - promises.push(async () => { - const streamMessage = await msgCreationUtil.createStreamMessage(stream, pubMsg, ts) - expect(streamMessage).toStrictEqual(getStreamMessage('streamId', ts, i, prevMsgRef)) - }) - /* eslint-enable no-loop-func */ - } - await Promise.all(promises) - }) - - it('should create messages with sequence number 0', async () => { - const ts = Date.now() - const promises = [] - let prevMsgRef = null - for (let i = 0; i < 10; i++) { - prevMsgRef = new MessageRef(ts + i, i) - /* eslint-disable no-loop-func */ - promises.push(async () => { - const streamMessage = await msgCreationUtil.createStreamMessage(stream, pubMsg, ts + i) - expect(streamMessage).toStrictEqual(getStreamMessage('streamId', ts + i, 0, prevMsgRef)) - }) - /* eslint-enable no-loop-func */ - } - await Promise.all(promises) - }) - - it('should publish messages with sequence number 0 (different streams)', async () => { - const ts = Date.now() - const stream2 = new Stream(null, { - id: 'streamId2', - partitions: 1, - }) - const stream3 = new Stream(null, { - id: 'streamId3', - partitions: 1, - }) - - const msg1 = await msgCreationUtil.createStreamMessage(stream, pubMsg, ts) - const msg2 = await msgCreationUtil.createStreamMessage(stream2, pubMsg, ts) - const msg3 = await msgCreationUtil.createStreamMessage(stream3, pubMsg, ts) - - expect(msg1).toEqual(getStreamMessage('streamId', ts, 0, null)) - expect(msg2).toEqual(getStreamMessage('streamId2', ts, 0, null)) - expect(msg3).toEqual(getStreamMessage('streamId3', ts, 0, null)) - }) - - it('should sign messages if signer is defined', async () => { - const msg1 = await msgCreationUtil.createStreamMessage(stream, pubMsg, Date.now()) - expect(msg1.signature).toBe('signature') - }) - - it('should create message from a stream id by fetching the stream', async () => { - const ts = Date.now() - const streamMessage = await msgCreationUtil.createStreamMessage(stream.id, pubMsg, ts) - expect(streamMessage).toEqual(getStreamMessage(stream.id, ts, 0, null)) - }) - }) - - describe('encryption', () => { - const pubMsg = { - foo: 'bar', - } - - const stream = new Stream(null, { - id: 'streamId', - partitions: 1, - }) - - let client - - beforeEach(() => { - client = { - options: { - auth: { - username: 'username', - }, - }, - signer: { - signStreamMessage: (streamMessage) => { - /* eslint-disable no-param-reassign */ - streamMessage.signatureType = StreamMessage.SIGNATURE_TYPES.ETH - streamMessage.signature = 'signature' - /* eslint-enable no-param-reassign */ - return Promise.resolve() - }, - }, - getUserInfo: () => Promise.resolve({ - username: 'username', - }), - getStream: sinon.stub().resolves(stream), - } - }) - - it('should create cleartext messages when no key is defined', async () => { - const msgCreationUtil = new MessageCreationUtil(client.options.auth, client.signer, client.getUserInfo(), client.getStream) - const msg = await msgCreationUtil.createStreamMessage(stream, pubMsg, Date.now()) - expect(msg.encryptionType).toBe(StreamMessage.ENCRYPTION_TYPES.NONE) - expect(msg.getParsedContent()).toEqual(pubMsg) - }) - - it('should create encrypted messages when key defined in constructor', async () => { - const key = crypto.randomBytes(32) - const keyStorageUtil = KeyStorageUtil.getKeyStorageUtil() - keyStorageUtil.addKey(stream.id, key) - - const msgCreationUtil = new MessageCreationUtil( - client.options.auth, client.signer, client.getUserInfo(), client.getStream, keyStorageUtil, - ) - const msg = await msgCreationUtil.createStreamMessage(stream, pubMsg, Date.now()) - expect(msg.encryptionType).toBe(StreamMessage.ENCRYPTION_TYPES.AES) - expect(msg.getSerializedContent().length).toBe(58) // 16*2 + 13*2 (hex string made of IV + msg of 13 chars) - }) - - it('should throw when using a key with a size smaller than 256 bits', (done) => { - const key = crypto.randomBytes(16) - const msgCreationUtil = new MessageCreationUtil(client.options.auth, client.signer, client.getUserInfo(), client.getStream) - msgCreationUtil.createStreamMessage(stream, pubMsg, Date.now(), null, key).catch((err) => { - expect(err.toString()).toBe('Error: Group key must have a size of 256 bits, not 128') - done() - }) - }) - - it('should create encrypted messages when key defined in createStreamMessage() and use the same key later', async () => { - const key = crypto.randomBytes(32) - const msgCreationUtil = new MessageCreationUtil(client.options.auth, client.signer, client.getUserInfo(), client.getStream) - const msg1 = await msgCreationUtil.createStreamMessage(stream, pubMsg, Date.now(), null, key) - expect(msg1.encryptionType).toBe(StreamMessage.ENCRYPTION_TYPES.AES) - expect(msg1.getSerializedContent().length).toBe(58) - const msg2 = await msgCreationUtil.createStreamMessage(stream, pubMsg, Date.now()) - expect(msg2.encryptionType).toBe(StreamMessage.ENCRYPTION_TYPES.AES) - expect(msg2.getSerializedContent().length).toBe(58) - // should use different IVs - expect(msg1.getSerializedContent().slice(0, 32)).not.toEqual(msg2.getSerializedContent().slice(0, 32)) - // should produce different ciphertexts even if same plaintexts and same key - expect(msg1.getSerializedContent().slice(32)).not.toEqual(msg2.getSerializedContent().slice(32)) - }) - - it('should update the key when redefined', async () => { - const key1 = crypto.randomBytes(32) - const key2 = crypto.randomBytes(32) - const msgCreationUtil = new MessageCreationUtil(client.options.auth, client.signer, client.getUserInfo(), client.getStream) - const msg1 = await msgCreationUtil.createStreamMessage(stream, pubMsg, Date.now(), null, key1) - expect(msg1.encryptionType).toBe(StreamMessage.ENCRYPTION_TYPES.AES) - expect(msg1.getSerializedContent().length).toBe(58) - const msg2 = await msgCreationUtil.createStreamMessage(stream, pubMsg, Date.now(), null, key2) - expect(msg2.encryptionType).toBe(StreamMessage.ENCRYPTION_TYPES.NEW_KEY_AND_AES) - expect(msg2.getSerializedContent().length).toBe(122)// 16*2 + 32*2 + 13*2 (IV + key of 32 bytes + msg of 13 chars) - }) - }) - - describe('createGroupKeyRequest', () => { - const stream = new Stream(null, { - id: 'streamId', - partitions: 1, - }) - - const auth = { - username: 'username', - } - - it('should not be able to create unsigned group key request', async (done) => { - const util = new MessageCreationUtil(auth, null, () => Promise.resolve({ - username: 'username', - }), sinon.stub().resolves(stream)) - - await util.createGroupKeyRequest({ - messagePublisherAddress: 'publisherId', - streamId: 'streamId', - publicKey: 'rsaPublicKey', - start: 1354155, - end: 2344155, - }).catch((err) => { - expect(err.message).toBe('Cannot create unsigned group key request. Must authenticate with "privateKey" or "provider"') - done() - }) - }) - - it('creates correct group key request', async () => { - const signer = { - signStreamMessage: (streamMessage) => { - /* eslint-disable no-param-reassign */ - streamMessage.signatureType = StreamMessage.SIGNATURE_TYPES.ETH - streamMessage.signature = 'signature' - /* eslint-enable no-param-reassign */ - return Promise.resolve() - }, - } - - const util = new MessageCreationUtil(auth, signer, () => Promise.resolve({ - username: 'username', - }), sinon.stub().resolves(stream)) - - const streamMessage = await util.createGroupKeyRequest({ - messagePublisherAddress: 'publisherId', - streamId: 'streamId', - publicKey: 'rsaPublicKey', - start: 1354155, - end: 2344155, - }) - - expect(streamMessage.getStreamId()).toBe(getKeyExchangeStreamId('publisherId')) // sending to publisher's keyexchange stream - const content = streamMessage.getParsedContent() - expect(streamMessage.messageType).toBe(StreamMessage.MESSAGE_TYPES.GROUP_KEY_REQUEST) - expect(streamMessage.encryptionType).toBe(StreamMessage.ENCRYPTION_TYPES.NONE) - expect(content.streamId).toBe('streamId') - expect(content.publicKey).toBe('rsaPublicKey') - expect(content.range.start).toBe(1354155) - expect(content.range.end).toBe(2344155) - expect(streamMessage.signature).toBeTruthy() - }) - }) - - describe('createGroupKeyResponse', () => { - const stream = new Stream(null, { - id: 'streamId', - partitions: 1, - }) - - const auth = { - username: 'username', - } - - it('should not be able to create unsigned group key response', async (done) => { - const util = new MessageCreationUtil(auth, null, () => Promise.resolve({ - username: 'username', - }), sinon.stub().resolves(stream)) - const requestId = uniqueId() - await util.createGroupKeyResponse({ - subscriberAddress: 'subscriberId', - streamId: 'streamId', - requestId, - encryptedGroupKeys: [{ - groupKey: 'group-key', - start: 34524, - }] - }).catch((err) => { - expect(err.message).toBe('Cannot create unsigned group key response. Must authenticate with "privateKey" or "provider"') - done() - }) - }) - - it('creates correct group key response', async () => { - const signer = { - signStreamMessage: (streamMessage) => { - /* eslint-disable no-param-reassign */ - streamMessage.signatureType = StreamMessage.SIGNATURE_TYPES.ETH - streamMessage.signature = 'signature' - /* eslint-enable no-param-reassign */ - return Promise.resolve() - }, - } - - const util = new MessageCreationUtil(auth, signer, () => Promise.resolve({ - username: 'username', - }), sinon.stub().resolves(stream)) - - const requestId = uniqueId() - const streamMessage = await util.createGroupKeyResponse({ - subscriberAddress: 'subscriberId', - streamId: 'streamId', - requestId, - encryptedGroupKeys: [{ - groupKey: 'encrypted-group-key', - start: 34524, - }] - }) - - expect(streamMessage.getStreamId()).toBe(getKeyExchangeStreamId('subscriberId')) // sending to subscriber's keyexchange stream - const content = streamMessage.getParsedContent() - expect(streamMessage.messageType).toBe(StreamMessage.MESSAGE_TYPES.GROUP_KEY_RESPONSE) - expect(streamMessage.encryptionType).toBe(StreamMessage.ENCRYPTION_TYPES.RSA) - expect(content.streamId).toBe('streamId') - expect(content.requestId).toBe(requestId) - expect(content.keys).toStrictEqual([{ - groupKey: 'encrypted-group-key', - start: 34524, - }]) - expect(streamMessage.signature).toBeTruthy() - }) - }) - - describe('createErrorMessage', () => { - const stream = new Stream(null, { - id: 'streamId', - partitions: 1, - }) - - const auth = { - username: 'username', - } - - it('should not be able to create unsigned error message', async (done) => { - const util = new MessageCreationUtil(auth, null, () => Promise.resolve({ - username: 'username', - }), sinon.stub().resolves(stream)) - - await util.createErrorMessage({ - keyExchangeStreamId: 'keyExchangeStreamId', - error: new Error(), - streamId: stream.id, - requestId: uniqueId('requestId'), - }).catch((err) => { - expect(err.message).toBe('Cannot create unsigned error message. Must authenticate with "privateKey" or "provider"') - done() - }) - }) - - it('creates correct group key response', async () => { - const signer = { - signStreamMessage: (streamMessage) => { - /* eslint-disable no-param-reassign */ - streamMessage.signatureType = StreamMessage.SIGNATURE_TYPES.ETH - streamMessage.signature = 'signature' - /* eslint-enable no-param-reassign */ - return Promise.resolve() - }, - } - - const util = new MessageCreationUtil(auth, signer, () => Promise.resolve({ - username: 'username', - }), sinon.stub().resolves(stream)) - - const requestId = uniqueId('requestId') - const streamMessage = await util.createErrorMessage({ - keyExchangeStreamId: 'keyExchangeStreamId', - error: new InvalidGroupKeyRequestError('invalid'), - streamId: stream.id, - requestId, - }) - - expect(streamMessage.getStreamId()).toBe('keyExchangeStreamId') // sending to subscriber's keyexchange stream - - const content = streamMessage.getParsedContent() - expect(streamMessage.messageType).toBe(StreamMessage.MESSAGE_TYPES.GROUP_KEY_ERROR_RESPONSE) - expect(streamMessage.encryptionType).toBe(StreamMessage.ENCRYPTION_TYPES.NONE) - expect(content.code).toBe('INVALID_GROUP_KEY_REQUEST') - expect(content.requestId).toBe(requestId) - expect(content.streamId).toBe(stream.id) - expect(content.message).toBe('invalid') - expect(streamMessage.signature).toBeTruthy() - }) - }) -}) diff --git a/test/unit/PushQueue.test.js b/test/unit/PushQueue.test.js new file mode 100644 index 000000000..9245649de --- /dev/null +++ b/test/unit/PushQueue.test.js @@ -0,0 +1,826 @@ +import { wait } from 'streamr-test-utils' +import AbortController from 'node-abort-controller' + +import PushQueue from '../../src/utils/PushQueue' + +const expected = [1, 2, 3, 4, 5, 6, 7, 8] +const WAIT = 20 +const MAX_ITEMS = 3 + +async function* generate(items = expected) { + await wait(WAIT * 0.1) + for await (const item of items) { + await wait(WAIT * 0.1) + yield item + await wait(WAIT * 0.1) + } + await wait(WAIT * 0.1) +} + +describe('PushQueue', () => { + it('supports pre-buffering, async push & return', async () => { + const q = new PushQueue() + expect(q.length).toBe(0) + q.push(expected[0]) + expect(q.length).toBe(1) + q.push(expected[1]) + expect(q.length).toBe(2) + + setTimeout(() => { + // buffer should have drained by now + expect(q.length).toBe(0) + q.push(expected[2]) + q.push(expected[3]) + setTimeout(() => { + q.return(5) // both items above should get through + q.push('nope') // this should not + }, 20) + }, 10) + + let i = 0 + for await (const msg of q) { + expect(msg).toBe(expected[i]) + i += 1 + } + + expect(i).toBe(4) + // buffer should have drained at end + expect(q.length).toBe(0) + }) + + it('supports passing initial values to constructor', async () => { + const q = new PushQueue(expected) + expect(q.length).toBe(expected.length) + + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + if (!q.length) { + break // this calls await q.return() + } + } + + expect(msgs).toEqual(expected) + + // buffer should have drained at end + expect(q.length).toBe(0) + + // these should have no effect + q.push('c') + expect(q.length).toBe(0) + await q.return() + expect(q.length).toBe(0) + }) + + describe('from', () => { + it('supports sync iterable', async () => { + const q = PushQueue.from(expected) + expect(q.length).toBe(expected.length) + + const msgs = [] + // will end when source ends + for await (const msg of q) { + msgs.push(msg) + } + + expect(msgs).toEqual(expected) + + // buffer should have drained at end + expect(q.length).toBe(0) + + // these should have no effect + q.push('c') + await q.return() + }) + + it('supports async iterable', async () => { + const q = PushQueue.from(generate()) + expect(q.length).toBe(0) // can't tell length upfront with async iterable + + const msgs = [] + // will end when source ends + for await (const msg of q) { + msgs.push(msg) + } + + expect(msgs).toEqual(expected) + + // buffer should have drained at end + expect(q.length).toBe(0) + + // these should have no effect + q.push('c') + expect(q.length).toBe(0) + }) + + it('errors if source errors', async () => { + expect.assertions(5) + const err = new Error('expected') + const q = PushQueue.from(async function* GenerateError() { + yield* generate() + throw err + }()) + expect(q.length).toBe(0) // can't tell length upfront with async iterable + + const msgs = [] + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + } + }).rejects.toThrow('expected') + + expect(msgs).toEqual(expected) + + // buffer should have drained at end + expect(q.length).toBe(0) + + // these should have no effect + q.push('c') + expect(q.length).toBe(0) + }) + + it('errors if source errors immediately', async () => { + expect.assertions(5) + const err = new Error('expected') + // eslint-disable-next-line require-yield + const q = PushQueue.from(async function* GenerateError() { + throw err + }()) + + expect(q.length).toBe(0) + + const msgs = [] + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + } + }).rejects.toThrow('expected') + + expect(msgs).toEqual([]) + + // buffer should have drained at end + expect(q.length).toBe(0) + + // these should have no effect + q.push('c') + expect(q.length).toBe(0) + }) + + it('errors if sync source errors immediately', async () => { + expect.assertions(5) + const err = new Error('expected') + // eslint-disable-next-line require-yield + const q = PushQueue.from(function* GenerateError() { + throw err + }()) + + expect(q.length).toBe(0) + + const msgs = [] + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + } + }).rejects.toThrow('expected') + + expect(msgs).toEqual([]) + + // buffer should have drained at end + expect(q.length).toBe(0) + + // these should have no effect + q.push('c') + expect(q.length).toBe(0) + }) + + it('can require manually ending with instance.from end: false', async () => { + expect.assertions(6) + const q = new PushQueue() + q.from(generate(), { + end: false, + }) + + const msgs = [] + const callEnd = jest.fn(() => { + let error + try { + expect(q.isWritable()).toEqual(true) + expect(q.isReadable()).toEqual(true) + } catch (err) { + error = err + } + q.end(error) + }) + // will NOT end when source ends + for await (const msg of q) { + msgs.push(msg) + if (msgs.length === expected.length) { + setTimeout(callEnd, 100) + } + } + + expect(callEnd).toHaveBeenCalledTimes(1) + expect(msgs).toEqual(expected) + expect(q.isWritable()).toEqual(false) + expect(q.isReadable()).toEqual(false) + }) + + it('can require manually ending with autoEnd: false', async () => { + expect.assertions(6) + const q = PushQueue.from(generate(), { + autoEnd: false, + }) + + const msgs = [] + const callEnd = jest.fn(() => { + let error + try { + expect(q.isWritable()).toEqual(true) + expect(q.isReadable()).toEqual(true) + } catch (err) { + error = err + } + q.end(error) + }) + // will NOT end when source ends + for await (const msg of q) { + msgs.push(msg) + if (msgs.length === expected.length) { + setTimeout(callEnd, 100) + } + } + + expect(callEnd).toHaveBeenCalledTimes(1) + expect(msgs).toEqual(expected) + expect(q.isWritable()).toEqual(false) + expect(q.isReadable()).toEqual(false) + }) + + it('can be aborted while waiting', async () => { + expect.assertions(3) + const startedWaiting = jest.fn() + const ac = new AbortController() + let q + const itr = (async function* Gen() { + yield* expected + yield await new Promise(() => { + setTimeout(() => { + ac.abort() + q.push('nope1') // should no-op + }) + startedWaiting() + }) // would wait forever + }()) + + q = PushQueue.from(itr, { + signal: ac.signal, + }) + + const msgs = [] + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + } + }).rejects.toThrow('abort') + + expect(msgs).toEqual(expected) + expect(startedWaiting).toHaveBeenCalledTimes(1) + }) + }) + + describe('end', () => { + it('can clean end after emptying buffer by pushing null', async () => { + const q = new PushQueue(expected) // wouldn't end on its own + expect(q.length).toBe(expected.length) + q.push(null) // won't end immediately + expect(q.length).toBe(expected.length) + + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + } + + expect(msgs).toEqual(expected) + + // buffer should have drained at end + expect(q.length).toBe(0) + + // these should have no effect + q.push('c') + expect(q.length).toBe(0) + }) + + it('does not buffer items after null', async () => { + const q = new PushQueue() // wouldn't end on its own + q.push(...expected, null, 'c') + expect(q.length).toBe(expected.length) + + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + } + + expect(msgs).toEqual(expected) + + // buffer should have drained at end + expect(q.length).toBe(0) + }) + + it('can clean end after emptying buffer with end', async () => { + const q = new PushQueue() // wouldn't end on its own + q.push(...expected) + + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + if (msgs.length === 1) { + q.end() // won't end immediately + } + } + + expect(msgs).toEqual(expected) + + // buffer should have drained at end + expect(q.length).toBe(0) + + // these should have no effect + q.push('c') + expect(q.length).toBe(0) + }) + + it('does not buffer more items after end', async () => { + const q = new PushQueue() // wouldn't end on its own + expected.forEach((v) => q.push(v)) + expect(q.length).toBe(expected.length) + q.end() + expect(q.length).toBe(expected.length) + q.push('c') // should have no effect + expect(q.length).toBe(expected.length) + + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + } + + expect(msgs).toEqual(expected) + + // buffer should have drained at end + expect(q.length).toBe(0) + }) + + it('can push final value then end after emptying buffer with end', async () => { + const q = new PushQueue() // wouldn't end on its own + q.push(...expected) + + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + if (msgs.length === MAX_ITEMS) { + q.end('c') // won't end immediately + } + } + + expect(msgs).toEqual([...expected, 'c']) + + // buffer should have drained at end + expect(q.length).toBe(0) + }) + + it('can end with error', async () => { + const q = new PushQueue() // wouldn't end on its own + q.push(...expected) + const err = new Error('expected error') + q.end(err) + + const msgs = [] + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + } + }).rejects.toThrow(err) + + expect(msgs).toEqual(expected) + + // buffer should have drained at end + expect(q.length).toBe(0) + }) + + it('ignores end after end', async () => { + const q = new PushQueue() // wouldn't end on its own + q.push(...expected) + q.end() + const err = new Error('expected error') + q.end(err) + + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + } + + expect(msgs).toEqual(expected) + + expect(q.length).toBe(0) + }) + + it('works with pending next', async () => { + const q = new PushQueue() + q.push(expected[0]) // preload first item + const msgsTask = Promise.all([ + q.next(), + q.next(), + ]).then((m) => m.map(({ value }) => value)) + q.push(...expected.slice(1)) // push rest after calls to next + q.end() // finish up + + const msgs = await msgsTask + for await (const msg of q) { + msgs.push(msg) // gets rest of messages + } + + expect(msgs).toEqual(expected) + + // buffer should have drained at end + expect(q.length).toBe(0) + + // buffer should have drained at end + expect(q.length).toBe(0) + }) + + it('works with end in loop', async () => { + const q = new PushQueue(expected) + const msgs = [] + for await (const msg of q) { + msgs.push(msg) // gets rest of messages + if (msgs.length === 2) { + q.end() + } + } + + expect(msgs).toEqual(expected) + + // buffer should have drained at end + expect(q.length).toBe(0) + + // buffer should have drained at end + expect(q.length).toBe(0) + }) + }) + + describe('onEnd', () => { + it('fires when returned', async () => { + const onEnd = jest.fn() + const q = new PushQueue(expected, { + onEnd, + }) + + expect(q.length).toBe(expected.length) + await q.return() + await wait(100) + expect(onEnd).toHaveBeenCalledTimes(1) + expect(q.length).toBe(0) + for await (const msg of q) { + throw new Error('should not get here ' + msg) + } + expect(onEnd).toHaveBeenCalledTimes(1) + }) + + it('fires when ended', async () => { + const onEnd = jest.fn() + const q = new PushQueue(expected, { + onEnd, + }) + q.end() + + expect(q.length).toBe(expected.length) + expect(onEnd).toHaveBeenCalledTimes(0) + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + } + expect(msgs).toEqual(expected) + expect(onEnd).toHaveBeenCalledTimes(1) + }) + + it('fires when thrown', async () => { + const onEnd = jest.fn() + const q = PushQueue.from(expected, { + onEnd, + }) + + const err = new Error('expected') + const msgs = [] + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) // gets rest of messages + if (msgs.length === 1) { + throw err + } + } + }).rejects.toThrow(err) + + expect(msgs).toEqual(expected.slice(0, 1)) + expect(onEnd).toHaveBeenCalledTimes(1) + }) + + it('fires when cancelled', async () => { + const onEnd = jest.fn() + const q = PushQueue.from(generate(), { + onEnd, + }) + + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + if (msgs.length === 1) { + await q.cancel() + } + } + expect(msgs).toEqual(expected.slice(0, 1)) + expect(onEnd).toHaveBeenCalledTimes(1) + }) + + it('fires only after all items consumed and source is closed', async () => { + const onEnd = jest.fn() + const q = PushQueue.from(expected, { + onEnd, + }) + + expect(q.length).toBe(expected.length) + expect(onEnd).toHaveBeenCalledTimes(0) + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + await wait(0) + expect(onEnd).toHaveBeenCalledTimes(0) + } + expect(msgs).toEqual(expected) + expect(onEnd).toHaveBeenCalledTimes(1) + }) + }) + + it('reduces length as items are consumed', async () => { + const q = new PushQueue(expected) + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + expect(q.length).toBe(expected.length - msgs.length) + if (q.length === 0) { + break + } + } + expect(msgs).toEqual(expected) + }) + + it('does not consume buffered items after return', async () => { + const q = new PushQueue(expected) + expect(q.length).toBe(expected.length) + await q.return() + expect(q.length).toBe(0) + for await (const msg of q) { + throw new Error('should not get here ' + msg) + } + }) + + it('handles break', async () => { + const q = new PushQueue(expected) + expect(q.length).toBe(expected.length) + const msgs = [] + for await (const msg of q) { + msgs.push(msg) // gets rest of messages + if (msgs.length === MAX_ITEMS) { + break + } + } + expect(msgs).toEqual(expected.slice(0, MAX_ITEMS)) + }) + + it('cannot iterate after iteration done', async () => { + const q = new PushQueue(expected) + q.end() + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + } + // can't iterate again after return + for await (const msg of q) { + throw new Error('should not get here ' + msg) + } + expect(msgs).toEqual(expected) + }) + + it('supports passing multiple values to push', async () => { + const q = new PushQueue() + q.push(...expected) + q.end() + const msgs = [] + for await (const msg of q) { + msgs.push(msg) + } + + expect(msgs).toEqual(expected) + + // buffer should have drained at end + expect(q.length).toBe(0) + }) + + it('supports multiple simultaneous calls to next', async () => { + const q = new PushQueue(expected) + const msgs = await Promise.all([ + q.next(), + q.next(), + ]).then((m) => m.map(({ value }) => value)) + await q.return() + + expect(msgs).toEqual(expected.slice(0, 2)) + + // buffer should have drained at end + expect(q.length).toBe(0) + }) + + it('handles throw during iteration', async () => { + const q = new PushQueue(expected) + const err = new Error('expected error') + const msgs = [] + + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + if (msgs.length === MAX_ITEMS) { + q.throw(err) // no await, no q.end + } + } + }).rejects.toThrow(err) + + expect(msgs).toEqual(expected.slice(0, MAX_ITEMS)) + expect(q.length).toBe(0) + }) + + it('handles throw after end', async () => { + const q = new PushQueue(expected) + q.end() + const err = new Error('expected error') + const msgs = [] + + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + if (msgs.length === MAX_ITEMS) { + q.throw(err) + } + } + }).rejects.toThrow(err) + + expect(msgs).toEqual(expected.slice(0, MAX_ITEMS)) + expect(q.length).toBe(0) + }) + + it('ignores pushed error after end', async () => { + const q = new PushQueue(expected) + q.end() + const err = new Error('expected error') + const msgs = [] + + for await (const msg of q) { + msgs.push(msg) + if (msgs.length === MAX_ITEMS) { + q.push(err) + } + } + + expect(msgs).toEqual(expected) + expect(q.length).toBe(0) + }) + + it('handles async throw', async () => { + const q = new PushQueue(expected) + const err = new Error('expected error') + const msgs = [] + setTimeout(() => { + q.throw(err) + q.push('c') // should no-op + }) + + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + } + }).rejects.toThrow(err) + + await wait(10) // wait for maybe push + // push('c') shouldn't have worked + expect(msgs).toEqual(expected) + expect(q.length).toBe(0) + }) + + it('handles throw early', async () => { + const q = new PushQueue() + q.push('a') // should no-op + const err = new Error('expected error') + q.throw(err) + q.push('c') // should no-op + + const msgs = [] + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + } + }).rejects.toThrow(err) + + await wait(10) // wait for maybe push + // push('c') shouldn't have worked + expect(q.length).toBe(0) + + expect(msgs).toEqual([]) + }) + + describe('abort', () => { + it('can be aborted', async () => { + const ac = new AbortController() + + const q = new PushQueue(expected, { + signal: ac.signal, + }) + + setTimeout(() => { + ac.abort() + q.push('nope1') // should no-op + }) + + const msgs = [] + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + } + }).rejects.toThrow('abort') + + expect(msgs).toEqual(expected) + }) + + it('handles aborting multiple buffers', async () => { + const ac = new AbortController() + + async function create(items = expected) { + const q = new PushQueue(items, { + signal: ac.signal, + }) + const msgs = [] + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + } + }).rejects.toThrow('abort') + await wait(10) // wait for maybe push + expect(q.length).toBe(0) + expect(msgs).toEqual(items) + } + + setTimeout(() => { + ac.abort() + }) + + await Promise.all([ + create(expected.slice(0, MAX_ITEMS)), + create(expected.slice(MAX_ITEMS)), + create([]), + ]) + }) + + it('can abort before iteration', async () => { + const ac = new AbortController() + + const q = new PushQueue(expected, { + signal: ac.signal, + }) + + q.push('nope1') // should no-op + const msgs = [] + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + if (msgs.length === MAX_ITEMS) { + ac.abort() + } + } + }).rejects.toThrow('abort') + expect(msgs).toEqual(expected.slice(0, MAX_ITEMS)) // only gives buffered items before abort + }) + + it('can abort before creating PushQueue', async () => { + const ac = new AbortController() + ac.abort() + + const q = new PushQueue(expected, { + signal: ac.signal, + }) + q.push('nope1') // should no-op + + const msgs = [] + await expect(async () => { + for await (const msg of q) { + msgs.push(msg) + } + }).rejects.toThrow('abort') + expect(msgs).toEqual([]) // still gives buffered items + }) + }) +}) diff --git a/test/unit/Scaffold.test.js b/test/unit/Scaffold.test.js new file mode 100644 index 000000000..24a78b243 --- /dev/null +++ b/test/unit/Scaffold.test.js @@ -0,0 +1,740 @@ +import Emitter from 'events' + +import { wait } from 'streamr-test-utils' + +import { Defer } from '../../src/utils' +import Scaffold from '../../src/utils/Scaffold' + +describe('Scaffold', () => { + let order + let up + let down + let emitter + let onDone + let onChange + // const log = debug.extend('Scaffold') + + beforeEach(() => { + if (emitter) { + emitter.removeAllListeners() + } + + order = [] + const currentOrder = order + emitter = new Emitter() + + emitter.on('next', (name, v = '') => { + const msg = `${name} ${v}`.trim() + // log(msg) + currentOrder.push(msg) + }) + + const currentEmitter = emitter + up = async (...args) => { + currentEmitter.emit('next', 'up start', ...args) + await wait(50) + currentEmitter.emit('next', 'up end', ...args) + } + + down = async (...args) => { + currentEmitter.emit('next', 'down start', ...args) + await wait(10) + currentEmitter.emit('next', 'down end', ...args) + } + + onDone = (isUp) => { + currentEmitter.emit('next', 'done', isUp ? 'up' : 'down') + } + + onChange = (isUp) => { + currentEmitter.emit('next', 'change', isUp ? 'up' : 'down') + } + }) + + it('calls up/down once', async () => { + let shouldUp = true + const next = Scaffold([ + async () => { + await up() + return () => down() + } + ], () => shouldUp, { + onDone, onChange + }) + + await Promise.all([ + next(), + next() + ]) + + await next() + + shouldUp = false + + await Promise.all([ + next(), + next() + ]) + + await next() + + expect(order).toEqual([ + 'change up', + 'up start', + 'up end', + 'done up', + 'change down', + 'down start', + 'down end', + 'done down' + ]) + }) + + it('calls down automatically if check is false after up complete', async () => { + let shouldUp = true + const next = Scaffold([ + async () => { + await up() + shouldUp = false + return () => down() + } + ], () => shouldUp, { + onDone, onChange + }) + + await next() + expect(order).toEqual([ + 'change up', + 'up start', + 'up end', + 'change down', + 'down start', + 'down end', + 'done down' + ]) + }) + + it('downs on error in up', async () => { + const err = new Error('expected') + const next = Scaffold([ + async () => { + await up('a') + return () => down('a') + }, + async () => { + await up('b') + throw err + }, + ], () => true, { + onDone, onChange + }) + + await expect(async () => { + await next() + }).rejects.toThrow(err) + + expect(order).toEqual([ + 'change up', + 'up start a', + 'up end a', + 'up start b', + 'up end b', + 'change down', + 'down start a', + 'down end a', + 'done down' + ]) + }) + + it('downs on error in check', async () => { + const err = new Error('expected') + let shouldThrow = false + const next = Scaffold([ + async () => { + await up('a') + return () => down('a') + }, + async () => { + await up('b') + shouldThrow = true + return () => down('b') + }, + ], () => { + if (shouldThrow) { + throw err + } + return true + }, { + onDone, onChange + }) + + await expect(async () => { + await next() + }).rejects.toThrow(err) + + expect(order).toEqual([ + 'change up', + 'up start a', + 'up end a', + 'up start b', + 'up end b', + 'change down', + 'down start b', // down should run + 'down end b', + 'down start a', + 'down end a', + 'done down' + ]) + }) + + it('continues to down if on error in down', async () => { + let shouldUp = true + + const err = new Error('expected') + const currentEmitter = emitter + currentEmitter.on('next', (event, name) => { + if (event === 'down start' && name === 'c') { + throw err // throw on down b + } + }) + + const next = Scaffold([ + async () => { + await up('a') + return () => down('a') + }, + async () => { + await up('b') + return async () => { + await down('b') + } + }, + async () => { + await up('c') + return async () => { + await down('c') // this should throw due to on('next' above + } + }, + ], () => shouldUp, { + onDone, onChange + }) + + await next() + shouldUp = false + await expect(async () => { + await next() + }).rejects.toThrow(err) + + expect(order).toEqual([ + 'change up', + 'up start a', + 'up end a', + 'up start b', + 'up end b', + 'up start c', + 'up end c', + 'done up', + 'change down', + 'down start c', // down should run (will error) + 'down start b', + 'down end b', + 'down start a', // down for other steps should continue + 'down end a', + 'done down', + ]) + }) + + it('continues to down if on error in last down', async () => { + let shouldUp = true + + const err = new Error('expected') + const currentEmitter = emitter + currentEmitter.on('next', (event, name) => { + if (event === 'down start' && name === 'a') { + throw err // throw on down b + } + }) + + const next = Scaffold([ + async () => { + await up('a') + return () => down('a') // this should throw due to on('next' above + }, + async () => { + await up('b') + return async () => { + await down('b') + } + }, + ], () => shouldUp, { + onDone, onChange + }) + + await next() + shouldUp = false + await expect(async () => { + await next() + }).rejects.toThrow(err) + + expect(order).toEqual([ + 'change up', + 'up start a', + 'up end a', + 'up start b', + 'up end b', + 'done up', + 'change down', + 'down start b', // down should run (will error) + 'down end b', + 'down start a', // down for other steps should continue + 'done down', + ]) + }) + + it('does not error if onError suppresses', async () => { + expect.assertions(2) + const shouldUp = true + + const err = new Error('expected') + const onErrorNoop = jest.fn() + const next = Scaffold([ + async () => { + await up('a') + return () => down('a') // this should throw due to on('next' above + }, + async () => { + await up('b') + return async () => { + await down('b') + } + }, + async () => { + throw err + } + ], () => shouldUp, { + onDone, + onChange, + onError: onErrorNoop, + }) + + await next() + + expect(order).toEqual([ + 'change up', + 'up start a', + 'up end a', + 'up start b', + 'up end b', + 'done up', + ]) + expect(onErrorNoop).toHaveBeenCalledWith(err) + }) + + it('does not error if onError rethrows', async () => { + expect.assertions(3) + const shouldUp = true + + const err = new Error('expected') + const onErrorRethrow = jest.fn((error) => { + throw error + }) + const next = Scaffold([ + async () => { + await up('a') + return () => down('a') // this should throw due to on('next' above + }, + async () => { + await up('b') + return async () => { + await down('b') + } + }, + async () => { + throw err + } + ], () => shouldUp, { + onDone, + onChange, + onError: onErrorRethrow, + }) + + await expect(async () => { + await next() + }).rejects.toThrow(err) + + expect(order).toEqual([ + 'change up', + 'up start a', + 'up end a', + 'up start b', + 'up end b', + 'change down', + 'down start b', + 'down end b', + 'down start a', + 'down end a', + 'done down', + ]) + expect(onErrorRethrow).toHaveBeenCalledWith(err) + }) + + it('does nothing if check fails', async () => { + const shouldUp = false + const next = Scaffold([ + async () => { + await up() + return () => down() + } + ], () => shouldUp, { + onDone, onChange + }) + + await next() + + expect(order).toEqual([]) + }) + + it('cancels up if check fails', async () => { + let shouldUp = true + const next = Scaffold([ + async () => { + await up() + shouldUp = false + return () => down() + } + ], () => shouldUp, { + onDone, onChange + }) + + await next() + + expect(order).toEqual([ + 'change up', + 'up start', + 'up end', + 'change down', + 'down start', + 'down end', + 'done down', + ]) + }) + + it('cancels up if onChange errors', async () => { + const err = new Error('expected') + const next = Scaffold([ + async () => { + await up() + return () => down() + } + ], () => true, { + onDone, + onChange: () => { + throw err + } + }) + + await expect(async () => next()).rejects.toThrow(err) + + expect(order).toEqual([]) + }) + + it('continues down if onChange errors', async () => { + let shouldUp = true + const err = new Error('expected') + const next = Scaffold([ + async () => { + await up() + return () => down() + } + ], () => shouldUp, { + onDone, + onChange: (goingUp) => { + onChange(goingUp) + if (!goingUp) { + throw err + } + } + }) + + await next() + + shouldUp = false + + await expect(async () => next()).rejects.toThrow(err) + + expect(order).toEqual([ + 'change up', + 'up start', + 'up end', + 'done up', + 'change down', + 'down start', + 'down end', + 'done down', + ]) + }) + + it('can change status in onChange', async () => { + let shouldUp = true + let once = false + const next = Scaffold([ + async () => { + await up() + return () => down() + } + ], () => shouldUp, { + onDone, + onChange: (goingUp) => { + onChange(goingUp) + if (!goingUp && !once) { + once = true + shouldUp = true + } + } + }) + + await next() + + shouldUp = false + + await next() + + expect(order).toEqual([ + 'change up', + 'up start', + 'up end', + 'done up', + 'change down', + 'change up', + ]) + }) + + it('calls one at a time when down called during up', async () => { + let shouldUp = true + + const next = Scaffold([ + async () => { + await up() + return () => down() + } + ], () => shouldUp, { + onDone, onChange + }) + const done = Defer() + emitter.on('next', async (name) => { + if (name === 'up start') { + shouldUp = false + done.resolve(next()) + } + }) + + await Promise.all([ + next(), + done, + ]) + + expect(order).toEqual([ + 'change up', + 'up start', + 'up end', + 'change down', + 'down start', + 'down end', + 'done down', + ]) + }) + + describe('plays undo stack at point of state change', () => { + let shouldUp + let next + const allUp = [ + 'change up', + 'up start a', + 'up end a', + 'up start b', + 'up end b', + 'up start c', + 'up end c', + 'done up', + ] + + const allDown = [ + 'change down', + 'down start c', + 'down end c', + 'down start b', + 'down end b', + 'down start a', + 'down end a', + 'done down', + ] + + beforeEach(() => { + shouldUp = false + + next = Scaffold([ + async () => { + await up('a') + return () => down('a') + }, + async () => { + await up('b') + return () => down('b') + }, + async () => { + await up('c') + return () => down('c') + }, + ], () => shouldUp, { + onDone, onChange + }) + }) + + it('plays all up steps in order, then down steps in order', async () => { + shouldUp = true + await next() + expect(order).toEqual(allUp) + shouldUp = false + + await next() + expect(order).toEqual([ + ...allUp, + ...allDown + ]) + }) + + it('can stop before first step', async () => { + shouldUp = true + const done = Defer() + emitter.on('next', async (name, v) => { + if (name === 'up start' && v === 'a') { + shouldUp = false + done.resolve() + } + }) + + await Promise.all([ + next(), + done, + ]) + + expect(order).toEqual([ + 'change up', + 'up start a', + 'up end a', + 'change down', + 'down start a', + 'down end a', + 'done down', + ]) + }) + + it('can stop before second step', async () => { + shouldUp = true + const done = Defer() + emitter.on('next', async (name, v) => { + if (name === 'up end' && v === 'b') { + shouldUp = false + done.resolve() + } + }) + + await Promise.all([ + next(), + done, + ]) + + expect(order).toEqual([ + 'change up', + 'up start a', + 'up end a', + 'up start b', + 'up end b', + 'change down', + 'down start b', + 'down end b', + 'down start a', + 'down end a', + 'done down', + ]) + }) + + it('can interrupt down while going down', async () => { + const done = Defer() + shouldUp = true + emitter.on('next', async (name, v) => { + if (name === 'down end' && v === 'b') { + shouldUp = true + done.resolve() + } + }) + await next() + shouldUp = false + await next() + await done + expect(order).toEqual([ + ...allUp, + 'change down', + 'down start c', + 'down end c', + 'down start b', + 'down end b', + 'change up', + 'up start b', + 'up end b', + 'up start c', + 'up end c', + 'done up', + ]) + }) + + it('can interrupt down while going down & during change', async () => { + const done1 = Defer() + const done2 = Defer() + const done3 = Defer() + shouldUp = true + let count = 0 + emitter.on('next', async (name, v) => { + if (name === 'down end' && v === 'b') { + count += 1 + shouldUp = true + done1.resolve() + } + + if (name === 'change' && v === 'up' && count === 1) { + count += 1 + shouldUp = false + done2.resolve() + } + + if (name === 'change' && v === 'down' && count === 2) { + count += 1 + shouldUp = true + done3.resolve() + } + }) + await next() + shouldUp = false + await next() + await done1 + await done2 + await done3 + expect(order).toEqual([ + ...allUp, + 'change down', + 'down start c', + 'down end c', + 'down start b', + 'down end b', + 'change up', + 'change down', + 'change up', + 'up start b', + 'up end b', + 'up start c', + 'up end c', + 'done up', + ]) + }) + }) +}) diff --git a/test/unit/Session.test.js b/test/unit/Session.test.js index 1d1884149..a31a7d40a 100644 --- a/test/unit/Session.test.js +++ b/test/unit/Session.test.js @@ -1,8 +1,9 @@ import sinon from 'sinon' -import StreamrClient from '../../src' -import config from '../integration/config' +import { StreamrClient } from '../../src/StreamrClient' +import { Defer } from '../../src/utils' import Session from '../../src/Session' +import config from '../integration/config' describe('Session', () => { let session @@ -10,9 +11,9 @@ describe('Session', () => { let clientSessionToken const createClient = (opts = {}) => new StreamrClient({ + ...config.clientOptions, autoConnect: false, autoDisconnect: false, - ...config.clientOptions, ...opts, }) @@ -55,27 +56,32 @@ describe('Session', () => { expect(sessionToken).toBe(undefined) }) - it('login function should throw if only session token provided', async (done) => { + it('login function should throw if only session token provided', async () => { clientSessionToken.onError = () => {} - await clientSessionToken.session.loginFunction().catch((err) => { - expect(err.toString()).toEqual( - 'Error: Need either "privateKey", "provider", "apiKey", "username"+"password" or "sessionToken" to login.' - ) - done() - }) + await expect(async () => ( + clientSessionToken.session.loginFunction() + )).rejects.toThrow( + 'Need either "privateKey", "ethereum", "apiKey", "username"+"password" or "sessionToken" to login.' + ) }) - it('login function should throw if no authentication', async (done) => { + it('login function should throw if no authentication', async () => { const clientNone = createClient({ auth: {}, }) clientNone.onError = () => {} await clientNone.session.loginFunction().catch((err) => { expect(err.toString()).toEqual( - 'Error: Need either "privateKey", "provider", "apiKey", "username"+"password" or "sessionToken" to login.' + 'Error: Need either "privateKey", "ethereum", "apiKey", "username"+"password" or "sessionToken" to login.' ) - done() }) + clientNone.onError = () => {} + + await expect(async () => ( + clientSessionToken.session.loginFunction() + )).rejects.toThrow( + 'Need either "privateKey", "ethereum", "apiKey", "username"+"password" or "sessionToken" to login.' + ) }) }) @@ -121,35 +127,31 @@ describe('Session', () => { beforeEach(() => { session = new Session() session.options.unauthenticated = false - msg = 'Error: Need either "privateKey", "provider", "apiKey" or "username"+"password" to login.' - session.loginFunction = sinon.stub().rejects(msg) + msg = 'Error: Need either "privateKey", "ethereum", "apiKey" or "username"+"password" to login.' + session.loginFunction = sinon.stub().rejects(new Error(msg)) clientSessionToken.onError = () => {} }) - it('should fail both requests with one call to loginFunction', async (done) => { + it('should fail simultaneous requests with one call to loginFunction', async () => { await Promise.all([ - session.getSessionToken().catch((err) => { - expect(err.toString()).toEqual(msg) - }), - session.getSessionToken().catch((err) => { - expect(err.toString()).toEqual(msg) - expect(session.loginFunction.calledOnce).toBeTruthy() - done() - }) + expect(async () => ( + session.getSessionToken() + )).rejects.toThrow(msg), + expect(async () => ( + session.getSessionToken() + )).rejects.toThrow(msg) ]) + expect(session.loginFunction.calledOnce).toBeTruthy() }) - it('should fail both requests with two calls to loginFunction', async (done) => { - const p1 = session.getSessionToken() - await p1.catch(async (err) => { - expect(err.toString()).toEqual(msg) - const p2 = session.getSessionToken() - await p2.catch((err2) => { - expect(err2.toString()).toEqual(msg) - expect(session.loginFunction.calledTwice).toBeTruthy() - done() - }) - }) + it('should fail both requests with two calls to loginFunction', async () => { + await expect(async () => ( + session.getSessionToken() + )).rejects.toThrow(msg) + await expect(async () => ( + session.getSessionToken() + )).rejects.toThrow(msg) + expect(session.loginFunction.calledTwice).toBeTruthy() }) }) }) @@ -170,38 +172,38 @@ describe('Session', () => { expect(clientSessionToken.logoutEndpoint.calledTwice).toBeTruthy() }) - it('should throw if already logging out', async (done) => { + it('should throw if already logging out', async () => { await session.getSessionToken() session.logout() clientSessionToken.onError = () => {} - await session.logout().catch((err) => { - expect(err.toString()).toBe('Error: Already logging out!') - done() - }) + await expect(async () => ( + session.logout() + )).rejects.toThrow('Already logging out!') }) - it('should throw if already logged out', async (done) => { + it('should throw if already logged out', async () => { await session.getSessionToken() + clientSessionToken.onError = () => {} await session.logout() - await session.logout().catch((err) => { - expect(err.toString()).toBe('Error: Already logged out!') - done() - }) + await expect(async () => ( + session.logout() + )).rejects.toThrow('Already logged out!') }) - it('can logout while logging in', async (done) => { - session.once('logging in', async () => { + it('can logout while logging in', async () => { + const done = Defer() + session.once('logging in', done.wrap(async () => { await session.logout() - done() - }) + })) await session.getSessionToken() + await done }) - it('can login while logging out', async (done) => { - session.once('logging out', async () => { + it('can login while logging out', async () => { + const done = Defer() + session.once('logging out', done.wrap(async () => { await session.getSessionToken() - done() - }) + })) await session.getSessionToken() await session.logout() }) diff --git a/test/unit/Signer.test.js b/test/unit/Signer.test.js index 32a56e258..0751cdb20 100644 --- a/test/unit/Signer.test.js +++ b/test/unit/Signer.test.js @@ -1,6 +1,7 @@ import { MessageLayer } from 'streamr-client-protocol' -import Signer from '../../src/Signer' +import Signer from '../../src/publish/Signer' +import { getAddressFromOptions } from '../../src/user' const { StreamMessage, MessageID, MessageRef } = MessageLayer /* @@ -10,48 +11,50 @@ we are testing the Signer which is internal, we use private keys with the '0x' p describe('Signer', () => { describe('construction', () => { it('should sign when constructed with private key', async () => { - const signer = new Signer({ + const signer = Signer({ privateKey: '0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709', }) - const signature = signer.signData('some-data') + const signature = await signer.signData('some-data') expect(signature).toBeTruthy() }) it('should throw when constructed with nothing', () => { expect(() => { // eslint-disable-next-line no-new - new Signer({}) + Signer({}, '') }).toThrow() }) - it('Should return undefined when "never" option is set', () => { - expect(Signer.createSigner({}, 'never')).toBe(undefined) + it('Should noop if "never" option is set', async () => { + const obj = {} + expect(await Signer({}, 'never')(obj)).toBe(obj) }) - it('Should return undefined when "auto" option is set with no private key or provider', () => { - expect(Signer.createSigner({}, 'auto')).toBe(undefined) + it('Should noop when "auto" option is set with no private key or provider', async () => { + const obj = {} + expect(await Signer({}, 'auto')(obj)).toBe(obj) }) it('Should return a Signer when "auto" option is set with private key', () => { - const signer = Signer.createSigner({ + const signer = Signer({ privateKey: '0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709', }, 'auto') - expect(signer instanceof Signer).toBeTruthy() + expect(signer).toBeInstanceOf(Function) }) it('Should return a Signer when "always" option is set with private key', () => { - const signer = Signer.createSigner({ + const signer = Signer({ privateKey: '0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709', }, 'always') - expect(signer instanceof Signer).toBeTruthy() + expect(signer).toBeInstanceOf(Function) }) it('Should throw when "always" option is set with no private key or provider', () => { - expect(() => Signer.createSigner({}, 'always')).toThrow() + expect(() => Signer({}, 'always')).toThrow() }) it('Should throw when unknown option is set', () => { - expect(() => Signer.createSigner({ + expect(() => Signer({ privateKey: '0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709', }, 'unknown')).toThrow() }) @@ -64,11 +67,12 @@ describe('Signer', () => { field: 'some-data', } const timestamp = 1529549961116 + const options = { + privateKey: '0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709', + } beforeEach(() => { - signer = new Signer({ - privateKey: '0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709', - }) + signer = Signer(options) }) it('should return correct signature', async () => { @@ -79,8 +83,9 @@ describe('Signer', () => { }) it('should sign StreamMessageV31 with null previous ref correctly', async () => { + const address = await getAddressFromOptions(options) const streamMessage = new StreamMessage({ - messageId: new MessageID(streamId, 0, timestamp, 0, await signer.getAddress(), 'chain-id'), + messageId: new MessageID(streamId, 0, timestamp, 0, address, 'chain-id'), prevMsgRef: null, content: data, encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, @@ -88,20 +93,21 @@ describe('Signer', () => { signature: null }) const payload = streamMessage.getStreamId() + streamMessage.getStreamPartition() + streamMessage.getTimestamp() - + streamMessage.messageId.sequenceNumber + (await signer.getAddress()).toLowerCase() + streamMessage.messageId.msgChainId + + streamMessage.messageId.sequenceNumber + address.toLowerCase() + streamMessage.messageId.msgChainId + streamMessage.getSerializedContent() const expectedSignature = await signer.signData(payload) - await signer.signStreamMessage(streamMessage) + await signer(streamMessage) expect(streamMessage.signature).toBe(expectedSignature) - expect(streamMessage.getPublisherId()).toBe(await signer.getAddress()) + expect(streamMessage.getPublisherId()).toBe(address) expect(streamMessage.signatureType).toBe(StreamMessage.SIGNATURE_TYPES.ETH) }) it('should sign StreamMessageV31 with non-null previous ref correctly', async () => { + const address = await getAddressFromOptions(options) const streamMessage = new StreamMessage({ version: 31, - messageId: new MessageID(streamId, 0, timestamp, 0, await signer.getAddress(), 'chain-id'), + messageId: new MessageID(streamId, 0, timestamp, 0, address, 'chain-id'), prevMsgRef: new MessageRef(timestamp - 10, 0), content: data, encryptionType: StreamMessage.ENCRYPTION_TYPES.NONE, @@ -110,15 +116,15 @@ describe('Signer', () => { }) const payload = [ streamMessage.getStreamId(), streamMessage.getStreamPartition(), streamMessage.getTimestamp(), - streamMessage.messageId.sequenceNumber, (await signer.getAddress()).toLowerCase(), streamMessage.messageId.msgChainId, + streamMessage.messageId.sequenceNumber, address.toLowerCase(), streamMessage.messageId.msgChainId, streamMessage.prevMsgRef.timestamp, streamMessage.prevMsgRef.sequenceNumber, streamMessage.getSerializedContent() ] const expectedSignature = await signer.signData(payload.join('')) expect(payload.join('')).toEqual(streamMessage.getPayloadToSign()) expect(expectedSignature).toEqual(await signer.signData(streamMessage.getPayloadToSign())) - await signer.signStreamMessage(streamMessage) + await signer(streamMessage) expect(streamMessage.signature).toBe(expectedSignature) - expect(streamMessage.getPublisherId()).toBe(await signer.getAddress()) + expect(streamMessage.getPublisherId()).toBe(address) expect(streamMessage.signatureType).toBe(StreamMessage.SIGNATURE_TYPES.ETH) }) }) diff --git a/test/unit/Stream.test.js b/test/unit/Stream.test.js index db22c2091..15f68dab6 100644 --- a/test/unit/Stream.test.js +++ b/test/unit/Stream.test.js @@ -1,6 +1,4 @@ -import sinon from 'sinon' - -import Stream from '../../src/rest/domain/Stream' +import { Stream } from '../../src/stream' describe('Stream', () => { let stream @@ -8,7 +6,7 @@ describe('Stream', () => { beforeEach(() => { clientMock = { - publish: sinon.stub(), + publish: jest.fn() } stream = new Stream(clientMock, { id: 'stream-id' @@ -25,7 +23,7 @@ describe('Stream', () => { stream.publish(msg, ts, pk) - sinon.assert.calledWith(clientMock.publish, stream.id, msg, ts, pk) + expect(clientMock.publish).toHaveBeenCalledWith(stream.id, msg, ts, pk) }) }) }) diff --git a/test/unit/StreamUtils.test.ts b/test/unit/StreamUtils.test.ts new file mode 100644 index 000000000..3cb5360aa --- /dev/null +++ b/test/unit/StreamUtils.test.ts @@ -0,0 +1,50 @@ +import { Stream } from '../../src/stream' +import { validateOptions } from '../../src/stream/utils' + +describe('Stream utils', () => { + + it('no definition', () => { + expect(() => validateOptions(undefined as any)).toThrow() + expect(() => validateOptions(null as any)).toThrow() + expect(() => validateOptions({})).toThrow() + }) + + it('string', () => { + expect(validateOptions('foo')).toMatchObject({ + streamId: 'foo', + streamPartition: 0, + key: 'foo::0' + }) + }) + + it('object', () => { + expect(validateOptions({ streamId: 'foo' })).toMatchObject({ + streamId: 'foo', + streamPartition: 0, + key: 'foo::0' + }) + expect(validateOptions({ streamId: 'foo', streamPartition: 123 })).toMatchObject({ + streamId: 'foo', + streamPartition: 123, + key: 'foo::123' + }) + expect(validateOptions({ id: 'foo', partition: 123 })).toMatchObject({ + streamId: 'foo', + streamPartition: 123, + key: 'foo::123' + }) + }) + + it('stream', () => { + const stream = new Stream(undefined as any, { + id: 'foo', + name: 'bar' + }) + expect(validateOptions({ stream })).toMatchObject({ + streamId: 'foo', + streamPartition: 0, + key: 'foo::0' + }) + }) + +}) diff --git a/test/unit/StubbedStreamrClient.js b/test/unit/StubbedStreamrClient.js index 3f2525c7e..d1086d26f 100644 --- a/test/unit/StubbedStreamrClient.js +++ b/test/unit/StubbedStreamrClient.js @@ -1,6 +1,5 @@ -import sinon from 'sinon' -import StreamrClient from '../../src/StreamrClient' -import Stream from '../../src/rest/domain/Stream' +import { StreamrClient } from '../../src/' +import { Stream } from '../../src/stream' export default class StubbedStreamrClient extends StreamrClient { getUserInfo() { @@ -9,10 +8,12 @@ export default class StubbedStreamrClient extends StreamrClient { }) } - getStream = sinon.stub().resolves(new Stream(null, { - id: 'streamId', - partitions: 1, - })) + async getStream () { + return new Stream(null, { + id: 'streamId', + partitions: 1, + }) + } } // publisherId is the hash of 'username' StubbedStreamrClient.hashedUsername = '0x16F78A7D6317F102BBD95FC9A4F3FF2E3249287690B8BDAD6B7810F82B34ACE3'.toLowerCase() diff --git a/test/unit/iterators.test.js b/test/unit/iterators.test.js new file mode 100644 index 000000000..268541443 --- /dev/null +++ b/test/unit/iterators.test.js @@ -0,0 +1,2168 @@ +import { wait } from 'streamr-test-utils' + +import { iteratorFinally, CancelableGenerator, pipeline } from '../../src/utils/iterators' +import { Defer } from '../../src/utils' +import PushQueue from '../../src/utils/PushQueue' + +const expected = [1, 2, 3, 4, 5, 6, 7, 8] +const WAIT = 20 + +async function* generate(items = expected) { + await wait(WAIT * 0.1) + for await (const item of items) { + await wait(WAIT * 0.1) + yield item + await wait(WAIT * 0.1) + } + await wait(WAIT * 0.1) +} + +const MAX_ITEMS = 3 + +function IteratorTest(name, fn) { + describe(`${name} IteratorTest`, () => { + it('runs to completion', async () => { + const received = [] + const itr = fn() + for await (const msg of itr) { + received.push(msg) + } + expect(received).toEqual(expected) + }) + + it('can return in finally', async () => { + const received = [] + const itr = (async function* Outer() { + const innerItr = fn()[Symbol.asyncIterator]() + try { + yield* innerItr + } finally { + await innerItr.return() // note itr.return would block + } + }()) + + for await (const msg of itr) { + received.push(msg) + if (received.length === MAX_ITEMS) { + break + } + } + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + }) + + it('can return mid-iteration', async () => { + const received = [] + for await (const msg of fn()) { + received.push(msg) + if (received.length === MAX_ITEMS) { + break + } + } + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + }) + + it('can throw mid-iteration', async () => { + const received = [] + const err = new Error('expected err') + await expect(async () => { + for await (const msg of fn()) { + received.push(msg) + if (received.length === MAX_ITEMS) { + throw err + } + } + }).rejects.toThrow(err) + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + }) + + it('throws parent mid-iteration', async () => { + const received = [] + const err = new Error('expected err') + async function* parentGen() { + for await (const msg of fn()) { + yield msg + if (received.length === MAX_ITEMS) { + throw err + } + } + } + await expect(async () => { + for await (const msg of parentGen()) { + received.push(msg) + } + }).rejects.toThrow(err) + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + }) + + it('can throw before iterating', async () => { + const received = [] + const itr = fn()[Symbol.asyncIterator]() + const err = new Error('expected err') + + await expect(async () => { + await itr.throw(err) + }).rejects.toThrow(err) + + // does not throw + for await (const msg of itr) { + received.push(msg) + } + expect(received).toEqual([]) + }) + + it('can return before iterating', async () => { + const itr = fn()[Symbol.asyncIterator]() + await itr.return() + const received = [] + for await (const msg of itr) { + received.push(msg) + } + expect(received).toEqual([]) + }) + + it('can queue next calls', async () => { + const itr = fn()[Symbol.asyncIterator]() + const tasks = expected.map(async () => itr.next()) + const received = await Promise.all(tasks) + expect(received.map(({ value }) => value)).toEqual(expected) + await itr.return() + }) + }) +} + +describe('Iterator Utils', () => { + describe('compare native generators', () => { + IteratorTest('baseline', () => generate()) + }) + + describe('iteratorFinally', () => { + let onFinally + let onFinallyAfter + + beforeEach(() => { + onFinallyAfter = jest.fn() + onFinally = jest.fn(async () => { + await wait(WAIT) + onFinallyAfter() + }) + }) + + afterEach(() => { + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + }) + + describe('iteratorFinally iteratorTests', () => { + IteratorTest('iteratorFinally', () => iteratorFinally(generate(), onFinally)) + }) + + it('runs fn when iterator.return() is called asynchronously', async () => { + const received = [] + const itr = iteratorFinally(generate(), onFinally) + const onTimeoutReached = jest.fn() + let receievedAtCallTime + for await (const msg of itr) { + received.push(msg) + if (received.length === MAX_ITEMS) { + // eslint-disable-next-line no-loop-func + setTimeout(() => { + onTimeoutReached() + receievedAtCallTime = received + itr.return() + }) + } + } + + expect(onTimeoutReached).toHaveBeenCalledTimes(1) + expect(received).toEqual(receievedAtCallTime) + }) + + it('runs fn when iterator returns + breaks during iteration', async () => { + const received = [] + const itr = iteratorFinally(generate(), onFinally) + for await (const msg of itr) { + received.push(msg) + if (received.length === MAX_ITEMS) { + itr.return() // no await + break + } + } + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + }) + + it('does not call inner iterators onFinally with error if outer errors', async () => { + // maybe not desirable, but captures existing behaviour. + // this matches native generator/iterator behaviour, at most outermost iteration errors + const received = [] + const err = new Error('expected err') + const itr = iteratorFinally(generate(), onFinally) + await expect(async () => { + for await (const msg of itr) { + received.push(msg) + if (received.length === MAX_ITEMS) { + throw err + } + } + }).rejects.toThrow(err) + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + expect(onFinally).not.toHaveBeenCalledWith(err) + }) + + it('runs fn when iterator returns + throws during iteration', async () => { + const received = [] + const err = new Error('expected err') + const itr = iteratorFinally(generate(), onFinally) + await expect(async () => { + for await (const msg of itr) { + received.push(msg) + if (received.length === MAX_ITEMS) { + itr.return() // no await + throw err + } + } + }).rejects.toThrow(err) + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + expect(onFinally).not.toHaveBeenCalledWith(err) // just outer onFinally will have err + }) + + it('runs fn when iterator returns before iteration', async () => { + const received = [] + const itr = iteratorFinally(generate(), onFinally) + await itr.return() + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + for await (const msg of itr) { + received.push(msg) + } + expect(received).toEqual([]) + }) + + it('runs fn when iterator returns before iteration', async () => { + const received = [] + const onStarted = jest.fn() + const itr = iteratorFinally((async function* Test() { + onStarted() + yield* generate() + }()), async () => { + await wait(WAIT * 5) + await onFinally() + }) + itr.return() // no await + for await (const msg of itr) { + received.push(msg) + } + expect(onStarted).toHaveBeenCalledTimes(0) + expect(received).toEqual([]) + }) + + it('runs finally once, waits for outstanding if returns before iteration', async () => { + const received = [] + const itr = iteratorFinally(generate(), onFinally) + + const t1 = itr.return() + const t2 = itr.return() + await Promise.race([t1, t2]) + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + await Promise.all([t1, t2]) + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + for await (const msg of itr) { + received.push(msg) + } + + expect(received).toEqual([]) + }) + + it('runs fn when iterator throws before iteration', async () => { + const received = [] + const err = new Error('expected err') + const itr = iteratorFinally(generate(), onFinally) + await expect(async () => itr.throw(err)).rejects.toThrow(err) + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + // doesn't throw, matches native iterators + for await (const msg of itr) { + received.push(msg) + } + expect(received).toEqual([]) + }) + + describe('nesting', () => { + let onFinallyInnerAfter + let onFinallyInner + + beforeEach(() => { + onFinallyInnerAfter = jest.fn() + const afterInner = onFinallyInnerAfter // capture so won't run afterInner of another test + onFinallyInner = jest.fn(async () => { + await wait(WAIT) + afterInner() + }) + }) + + afterEach(() => { + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + }) + + IteratorTest('iteratorFinally nested', () => { + const itrInner = iteratorFinally(generate(), onFinallyInner) + return iteratorFinally(itrInner, onFinally) + }) + + it('works nested', async () => { + const itrInner = iteratorFinally(generate(), onFinallyInner) + const itr = iteratorFinally(itrInner, onFinally) + + const received = [] + for await (const msg of itr) { + received.push(msg) + if (received.length === MAX_ITEMS) { + break + } + } + + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + }) + + it('calls iterator onFinally with error if outer errors', async () => { + const received = [] + const err = new Error('expected err') + const innerItr = iteratorFinally(generate(), onFinallyInner) + const itr = iteratorFinally((async function* Outer() { + for await (const msg of innerItr) { + yield msg + if (received.length === MAX_ITEMS) { + throw err + } + } + }()), onFinally) + + await expect(async () => { + for await (const msg of itr) { + received.push(msg) + } + }).rejects.toThrow(err) + + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + expect(onFinally).toHaveBeenCalledWith(err) + expect(onFinallyInner).not.toHaveBeenCalledWith(err) + }) + + it('calls iterator onFinally with error if inner errors', async () => { + const received = [] + const err = new Error('expected err') + const itrInner = iteratorFinally((async function* Outer() { + for await (const msg of generate()) { + yield msg + if (received.length === MAX_ITEMS) { + throw err + } + } + }()), onFinallyInner) + const itr = iteratorFinally(itrInner, onFinally) + + await expect(async () => { + for await (const msg of itr) { + received.push(msg) + } + }).rejects.toThrow(err) + + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + // both should see error + expect(onFinally).toHaveBeenCalledWith(err) + expect(onFinallyInner).toHaveBeenCalledWith(err) + }) + }) + + it('runs finally once, waits for outstanding', async () => { + const received = [] + const itr = iteratorFinally(generate(), onFinally) + + for await (const msg of itr) { + received.push(msg) + if (received.length === MAX_ITEMS) { + const t1 = itr.return() + const t2 = itr.return() + await Promise.race([t1, t2]) + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + await Promise.all([t1, t2]) + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + break + } + } + + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + }) + }) + + describe('CancelableGenerator', () => { + let onFinally + let onFinallyAfter + + beforeEach(() => { + onFinallyAfter = jest.fn() + onFinally = jest.fn(async () => { + await wait(WAIT) + onFinallyAfter() + }) + }) + + afterEach(() => { + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + }) + + IteratorTest('CancelableGenerator', () => { + const [, itr] = CancelableGenerator(generate(), onFinally) + return itr + }) + + it('can cancel during iteration', async () => { + const [cancel, itr] = CancelableGenerator(generate(), onFinally) + const received = [] + for await (const msg of itr) { + received.push(msg) + if (received.length === MAX_ITEMS) { + cancel() + } + } + + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + expect(itr.isCancelled()).toEqual(true) + }) + + it('can cancel before iteration', async () => { + const [cancel, itr] = CancelableGenerator(generate(), onFinally) + const received = [] + cancel() + expect(itr.isCancelled()).toEqual(true) + for await (const msg of itr) { + received.push(msg) + } + + expect(received).toEqual([]) + expect(itr.isCancelled()).toEqual(true) + }) + + it('can cancel with error before iteration', async () => { + const [cancel, itr] = CancelableGenerator(generate(), () => { + return onFinally() + }) + const received = [] + const err = new Error('expected') + cancel(err) + await expect(async () => { + for await (const msg of itr) { + received.push(msg) + } + }).rejects.toThrow(err) + + expect(received).toEqual([]) + }) + + it('cancels when iterator.cancel() is called asynchronously', async () => { + const received = [] + const [cancel, itr] = CancelableGenerator(generate(), onFinally, { + timeout: WAIT, + }) + let receievedAtCallTime + for await (const msg of itr) { + received.push(msg) + if (received.length === MAX_ITEMS) { + // eslint-disable-next-line no-loop-func + setTimeout(async () => { + receievedAtCallTime = received + await cancel() + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + }) + } + } + + expect(received).toEqual(receievedAtCallTime) + expect(itr.isCancelled()).toEqual(true) + }) + + it('prevents subsequent .next call', async () => { + const received = [] + const triggeredForever = jest.fn() + const [cancel, itr] = CancelableGenerator((async function* Gen() { + yield* expected + yield await new Promise(() => { + triggeredForever() // should not get here + }) + }()), onFinally) + + for await (const msg of itr) { + received.push(msg) + if (received.length === expected.length) { + await cancel() + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + } + } + + expect(triggeredForever).toHaveBeenCalledTimes(0) + expect(received).toEqual(expected) + expect(itr.isCancelled()).toEqual(true) + }) + + it('interrupts outstanding .next call', async () => { + const received = [] + const triggeredForever = jest.fn() + const [cancel, itr] = CancelableGenerator((async function* Gen() { + yield* expected + yield await new Promise(() => { + triggeredForever() + cancel() + }) // would wait forever + }()), onFinally) + + for await (const msg of itr) { + received.push(msg) + } + + expect(triggeredForever).toHaveBeenCalledTimes(1) + expect(received).toEqual(expected) + expect(itr.isCancelled()).toEqual(true) + }) + + it('interrupts outstanding .next call when called asynchronously', async () => { + const received = [] + const triggeredForever = jest.fn() + const [cancel, itr] = CancelableGenerator((async function* Gen() { + yield* expected + yield await new Promise(() => { + triggeredForever() + }) // would wait forever + }()), onFinally, { + timeout: WAIT, + }) + + for await (const msg of itr) { + received.push(msg) + if (received.length === expected.length) { + // eslint-disable-next-line no-loop-func + setTimeout(async () => { + await cancel() + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + }) + } + } + + expect(received).toEqual(expected) + expect(itr.isCancelled()).toEqual(true) + }) + + it('stops iterator', async () => { + const shouldRunFinally = jest.fn() + const [cancel, itr] = CancelableGenerator((async function* Gen() { + try { + yield 1 + await wait(WAIT) + yield 2 + await wait(WAIT) + yield 3 + } finally { + shouldRunFinally() + } + }()), onFinally, { + timeout: WAIT * 2 + }) + + const received = [] + for await (const msg of itr) { + received.push(msg) + if (received.length === 2) { + cancel() + expect(itr.isCancelled()).toEqual(true) + } + } + + expect(received).toEqual([1, 2]) + await wait(WAIT) + expect(onFinally).toHaveBeenCalledTimes(1) + expect(shouldRunFinally).toHaveBeenCalledTimes(1) + expect(itr.isCancelled()).toEqual(true) + }) + + it('interrupts outstanding .next call with error', async () => { + const received = [] + const [cancel, itr] = CancelableGenerator((async function* Gen() { + yield* expected + yield await new Promise(() => {}) // would wait forever + }()), onFinally, { + timeout: WAIT, + }) + + const err = new Error('expected') + + let receievedAtCallTime + await expect(async () => { + for await (const msg of itr) { + received.push(msg) + if (received.length === MAX_ITEMS) { + // eslint-disable-next-line no-loop-func + setTimeout(async () => { + receievedAtCallTime = received + await cancel(err) + + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + }) + } + } + }).rejects.toThrow(err) + + expect(received).toEqual(receievedAtCallTime) + expect(itr.isCancelled()).toEqual(true) + }) + + it('can handle queued next calls', async () => { + const triggeredForever = jest.fn() + const [cancel, itr] = CancelableGenerator((async function* Gen() { + yield* expected + setTimeout(async () => { + await cancel() + + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + }, WAIT * 2) + yield await new Promise(() => { + triggeredForever() + }) // would wait forever + }()), onFinally, { + timeout: WAIT, + }) + + const tasks = expected.map(async () => itr.next()) + tasks.push(itr.next()) // one more over the edge (should trigger forever promise) + const received = await Promise.all(tasks) + expect(received.map(({ value }) => value)).toEqual([...expected, undefined]) + expect(triggeredForever).toHaveBeenCalledTimes(1) + expect(itr.isCancelled()).toEqual(true) + }) + + it('can handle queued next calls resolving out of order', async () => { + const triggeredForever = jest.fn() + const [cancel, itr] = CancelableGenerator((async function* Gen() { + let i = 0 + for await (const v of expected) { + i += 1 + await wait((expected.length - i - 1) * 2 * WAIT) + yield v + } + + setTimeout(async () => { + await cancel() + + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + }, WAIT * 2) + + yield await new Promise(() => { + triggeredForever() + }) // would wait forever + }()), onFinally, { + timeout: WAIT, + }) + + const tasks = expected.map(async () => itr.next()) + tasks.push(itr.next()) // one more over the edge (should trigger forever promise) + const received = await Promise.all(tasks) + expect(received.map(({ value }) => value)).toEqual([...expected, undefined]) + expect(triggeredForever).toHaveBeenCalledTimes(1) + }) + + it('ignores err if cancelled', async () => { + const received = [] + const err = new Error('expected') + const d = Defer() + const [cancel, itr] = CancelableGenerator((async function* Gen() { + yield* expected + await wait(WAIT * 2) + d.resolve() + throw new Error('should not see this') + }()), onFinally) + + let receievedAtCallTime + await expect(async () => { + for await (const msg of itr) { + received.push(msg) + if (received.length === MAX_ITEMS) { + // eslint-disable-next-line no-loop-func + setTimeout(async () => { + receievedAtCallTime = received + await cancel(err) + + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + }) + } + } + }).rejects.toThrow(err) + + await d + await wait(WAIT * 2) + + expect(received).toEqual(receievedAtCallTime) + }) + + describe('nesting', () => { + let onFinallyInnerAfter + let onFinallyInner + + beforeEach(() => { + onFinallyInnerAfter = jest.fn() + const afterInner = onFinallyInnerAfter // capture so won't run afterInner of another test + onFinallyInner = jest.fn(async () => { + await wait(WAIT) + afterInner() + }) + }) + + afterEach(() => { + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + }) + + IteratorTest('CancelableGenerator nested', () => { + const [, itrInner] = CancelableGenerator(generate(), onFinallyInner) + const [, itrOuter] = CancelableGenerator(itrInner, onFinally) + return itrOuter + }) + + it('can cancel nested cancellable iterator in finally', async () => { + const waitInner = jest.fn() + const [cancelInner, itrInner] = CancelableGenerator((async function* Gen() { + yield* generate() + yield await new Promise(() => { + // should not get here + waitInner() + }) // would wait forever + }()), onFinallyInner, { + timeout: WAIT, + }) + + const waitOuter = jest.fn() + const [cancelOuter, itrOuter] = CancelableGenerator((async function* Gen() { + yield* itrInner + yield await new Promise(() => { + // should not get here + waitOuter() + }) // would wait forever + }()), async () => { + await cancelInner() + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + await onFinally() + }, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of itrOuter) { + received.push(msg) + if (received.length === expected.length) { + await cancelOuter() + } + } + + expect(received).toEqual(expected) + expect(waitOuter).toHaveBeenCalledTimes(0) + expect(waitInner).toHaveBeenCalledTimes(0) + }) + + it('can cancel nested cancellable iterator in finally, asynchronously', async () => { + const waitInner = jest.fn() + const [cancelInner, itrInner] = CancelableGenerator((async function* Gen() { + yield* generate() + yield await new Promise(() => { + // should not get here + waitInner() + }) // would wait forever + }()), onFinallyInner, { + timeout: WAIT, + }) + + const waitOuter = jest.fn() + const [cancelOuter, itrOuter] = CancelableGenerator((async function* Gen() { + yield* itrInner + yield await new Promise(() => { + // should not get here + waitOuter() + }) // would wait forever + }()), async () => { + await cancelInner() + await onFinally() + }, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of itrOuter) { + received.push(msg) + if (received.length === expected.length) { + setTimeout(() => { + cancelOuter() + }) + } + } + + expect(waitOuter).toHaveBeenCalledTimes(1) + expect(waitInner).toHaveBeenCalledTimes(1) + expect(received).toEqual(expected) + }) + }) + + it('can cancel in parallel and wait correctly for both', async () => { + const [cancel, itr] = CancelableGenerator(generate(), onFinally) + const ranTests = jest.fn() + + const received = [] + for await (const msg of itr) { + received.push(msg) + if (received.length === MAX_ITEMS) { + const t1 = cancel() + const t2 = cancel() + await Promise.race([t1, t2]) + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + await Promise.all([t1, t2]) + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + ranTests() + } + } + + expect(ranTests).toHaveBeenCalledTimes(1) + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + }) + }) + + describe('pipeline', () => { + let onFinally + let onFinallyAfter + + beforeEach(() => { + onFinallyAfter = jest.fn() + onFinally = jest.fn(async () => { + await wait(WAIT) + onFinallyAfter() + }) + }) + + afterEach(() => { + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + }) + + describe('baseline', () => { + IteratorTest('pipeline', () => { + return pipeline([ + generate(), + async function* Step1(s) { + for await (const msg of s) { + yield msg * 2 + } + }, + async function* Step2(s) { + for await (const msg of s) { + yield msg / 2 + } + } + ], onFinally) + }) + }) + + it('feeds items from one to next', async () => { + const receivedStep1 = [] + const receivedStep2 = [] + const afterStep1 = jest.fn() + const afterStep2 = jest.fn() + + const p = pipeline([ + generate(), + async function* Step1(s) { + try { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg * 2 + } + } finally { + afterStep1() + } + }, + async function* Step2(s) { + try { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg * 10 + } + } finally { + // ensure async finally works + await wait(WAIT) + afterStep2() + } + } + ], onFinally) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(received).toEqual(expected.map((v) => v * 20)) + expect(receivedStep2).toEqual(expected.map((v) => v * 2)) + expect(receivedStep1).toEqual(expected) + expect(afterStep1).toHaveBeenCalledTimes(1) + expect(afterStep2).toHaveBeenCalledTimes(1) + }) + + it('feeds items from one to next, stops all when start ends', async () => { + const receivedStep1 = [] + const receivedStep2 = [] + const afterStep1 = jest.fn() + const afterStep2 = jest.fn() + const p = pipeline([ + expected, + async function* Step1(s) { + try { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg * 2 + } + } finally { + afterStep1() + } + }, + async function* Step2(s) { + try { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg * 10 + } + } finally { + afterStep2() + } + } + ], onFinally) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(received).toEqual(expected.map((v) => v * 20)) + expect(receivedStep2).toEqual(expected.map((v) => v * 2)) + expect(receivedStep1).toEqual(expected) + expect(afterStep1).toHaveBeenCalledTimes(1) + expect(afterStep2).toHaveBeenCalledTimes(1) + }) + + it('feeds items from one to next, stops all when middle ends', async () => { + const receivedStep1 = [] + const receivedStep2 = [] + const afterStep1 = jest.fn() + const afterStep2 = jest.fn() + + const p = pipeline([ + generate(), + async function* Step1(s) { + try { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg * 2 + if (receivedStep1.length === MAX_ITEMS) { + break + } + } + } finally { + afterStep1() + } + }, + async function* Step2(s) { + try { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg * 10 + } + } finally { + afterStep2() + } + } + ], onFinally) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(received).toEqual(expected.slice(0, MAX_ITEMS).map((v) => v * 20)) + expect(receivedStep2).toEqual(expected.slice(0, MAX_ITEMS).map((v) => v * 2)) + expect(receivedStep1).toEqual(expected.slice(0, MAX_ITEMS)) + expect(afterStep1).toHaveBeenCalledTimes(1) + expect(afterStep2).toHaveBeenCalledTimes(1) + }) + + it('feeds items from one to next, stops all when middle throws', async () => { + const receivedStep1 = [] + const receivedStep2 = [] + const afterStep1 = jest.fn() + const afterStep2 = jest.fn() + const err = new Error('expected') + + const p = pipeline([ + generate(), + async function* Step1(s) { + try { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg * 2 + if (receivedStep1.length === MAX_ITEMS) { + throw err + } + } + } finally { + afterStep1() + } + }, + async function* Step2(s) { + try { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg * 10 + } + } finally { + afterStep2() + } + } + ], onFinally) + + const received = [] + await expect(async () => { + for await (const msg of p) { + received.push(msg) + } + }).rejects.toThrow(err) + + expect(received).toEqual(expected.slice(0, MAX_ITEMS).map((v) => v * 20)) + expect(receivedStep2).toEqual(expected.slice(0, MAX_ITEMS).map((v) => v * 2)) + expect(receivedStep1).toEqual(expected.slice(0, MAX_ITEMS)) + expect(afterStep1).toHaveBeenCalledTimes(1) + expect(afterStep2).toHaveBeenCalledTimes(1) + }) + + it('handles errors before', async () => { + const err = new Error('expected') + + const p = pipeline([ + generate(), + async function* Step1(s) { + yield* s + throw err + }, + async function* Step2(s) { + yield* s + yield await new Promise(() => {}) // would wait forever + } + ], onFinally) + + const received = [] + await expect(async () => { + for await (const msg of p) { + received.push(msg) + } + }).rejects.toThrow(err) + + expect(received).toEqual(expected) + }) + + it('handles errors after', async () => { + const err = new Error('expected') + + const p = pipeline([ + generate(), + async function* Step1(s) { + yield* s + }, + async function* Step2(s) { + yield* s + throw err + } + ], onFinally) + + const received = [] + await expect(async () => { + for await (const msg of p) { + received.push(msg) + } + }).rejects.toThrow(err) + + expect(received).toEqual(expected) + }) + + it('handles cancel with error after', async () => { + const err = new Error('expected') + const receivedStep2 = [] + const shouldNotGetHere = jest.fn() + + const p = pipeline([ + generate(), + async function* Step1(s) { + yield* s + }, + async function* Step2(s) { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg + if (receivedStep2.length === MAX_ITEMS) { + await p.cancel(err) + } + } + } + ], onFinally) + + const received = [] + await expect(async () => { + for await (const msg of p) { + received.push(msg) + } + }).rejects.toThrow(err) + + expect(shouldNotGetHere).toHaveBeenCalledTimes(0) + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + }) + + it('runs onFinally', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait(WAIT) + onFinallyInnerAfter() + }) + const p = pipeline([ + generate(), + async function* Step1(s) { + yield* s + }, + async function* finallyFn(s) { + yield* iteratorFinally(s, onFinallyInner) + } + ], onFinally) + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + expect(received).toEqual(expected) + }) + + it('runs onFinally even if not started', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait(WAIT) + onFinallyInnerAfter() + }) + const p = pipeline([ + generate(), + async function* Step1(s) { + yield* s + }, + async function* finallyFn(s) { + yield* iteratorFinally(s, onFinallyInner) + } + ], onFinally) + await p.return() + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(onFinallyInner).toHaveBeenCalledTimes(0) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(0) + expect(received).toEqual([]) + }) + + it('runs onFinally even if not started when cancelled', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait(WAIT) + onFinallyInnerAfter() + }) + const p = pipeline([ + generate(), + async function* Step1(s) { + yield* s + }, + async function* finallyFn(s) { + yield* iteratorFinally(s, onFinallyInner) + } + ], onFinally) + await p.cancel() + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(onFinallyInner).toHaveBeenCalledTimes(0) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(0) + expect(received).toEqual([]) + }) + + it('works with streams', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait(WAIT) + onFinallyInnerAfter() + }) + const onInputStreamClose = jest.fn() + const inputStream = PushQueue.from(generate(), { + onEnd: onInputStreamClose, + }) + const p = pipeline([ + inputStream, + async function* Step1(s) { + yield* s + }, + async function* finallyFn(s) { + yield* iteratorFinally(s, onFinallyInner) + } + ], onFinally) + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + expect(received).toEqual(expected) + expect(inputStream.isReadable()).toBe(false) + expect(onInputStreamClose).toHaveBeenCalledTimes(1) + }) + + it('can have delayed yields', async () => { + const receivedStep1 = [] + const receivedStep2 = [] + const onThroughStreamClose = jest.fn() + const throughStream = PushQueue.from(generate(), { + onEnd: onThroughStreamClose, + }) + + const p = pipeline([ + throughStream, + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + } + await wait(10) + for (const msg of receivedStep1) { + yield msg * 2 + } + }, + async function* Step2(s) { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg + } + }, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + expect(onFinally).toHaveBeenCalledTimes(0) + } + + expect(received).toEqual([...expected, ...expected.map((v) => v * 2)]) + expect(receivedStep1).toEqual(expected) + + // all streams were closed + expect(onThroughStreamClose).toHaveBeenCalledTimes(1) + }) + + it('does not end internal non-autoEnd streams automatically', async () => { + const receivedStep1 = [] + const receivedStep2 = [] + const receivedStep3 = [] + const onThroughStreamClose = jest.fn() + const afterLoop1 = jest.fn() + const throughStream = new PushQueue([], { + autoEnd: false, + onEnd: onThroughStreamClose, + }) + + const p = pipeline([ + generate(), + // eslint-disable-next-line require-yield + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + setTimeout(() => { + throughStream.push(msg) + }, 100) + } + afterLoop1() + }, + throughStream, + async function* Step2(s) { + for await (const msg of s) { + expect(afterLoop1).toHaveBeenCalledTimes(1) + receivedStep2.push(msg) + yield msg + if (receivedStep2.length === expected.length) { + // this should end pipeline + break + } + } + }, + async function* Step3(s) { + for await (const msg of s) { + receivedStep3.push(msg) + yield msg + // should close automatically + } + }, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + expect(onFinally).toHaveBeenCalledTimes(0) + } + expect(received).toEqual(expected) + expect(receivedStep1).toEqual(expected) + expect(receivedStep2).toEqual(expected) + expect(receivedStep3).toEqual(expected) + + // all streams were closed + expect(onThroughStreamClose).toHaveBeenCalledTimes(1) + expect(afterLoop1).toHaveBeenCalledTimes(1) + }) + + it('does not end internal streams automatically if going through non-autoEnd: false PushQueue', async () => { + const receivedStep1 = [] + const receivedStep2 = [] + const receivedStep3 = [] + const onThroughStreamClose = jest.fn() + const onThroughStream2Close = jest.fn() + const afterLoop1 = jest.fn() + const throughStream = new PushQueue([], { + autoEnd: false, + onEnd: onThroughStreamClose, + }) + const throughStream2 = new PushQueue([], { + autoEnd: true, + onEnd: onThroughStream2Close, + }) + + const p = pipeline([ + generate(), + // eslint-disable-next-line require-yield + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + setTimeout(() => { + throughStream.push(msg) + }, 100) + } + afterLoop1() + }, + throughStream, + async function* Step2(s) { + for await (const msg of s) { + expect(afterLoop1).toHaveBeenCalledTimes(1) + receivedStep2.push(msg) + yield msg + if (receivedStep2.length === expected.length) { + // end pipeline + break + } + } + }, + throughStream2, + async function* Step3(s) { + for await (const msg of s) { + receivedStep3.push(msg) + yield msg + // should close automatically + } + }, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + expect(onFinally).toHaveBeenCalledTimes(0) + } + expect(received).toEqual(expected) + expect(receivedStep1).toEqual(expected) + expect(receivedStep2).toEqual(expected) + expect(receivedStep3).toEqual(expected) + + // all streams were closed + expect(onThroughStreamClose).toHaveBeenCalledTimes(1) + expect(onThroughStream2Close).toHaveBeenCalledTimes(1) + }) + + it('works with nested pipelines', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait(WAIT) + onFinallyInnerAfter() + }) + + const receivedStep1 = [] + const receivedStep2 = [] + const onFirstStreamClose = jest.fn() + const onInputStreamClose = jest.fn() + + const inputStream = new PushQueue([], { + onEnd: onInputStreamClose, + }) + inputStream.id = 'inputStream' + const p1 = pipeline([ + inputStream, + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + } + }, + ], onFinallyInner) + + const firstStream = PushQueue.from(generate(), { + onEnd: onFirstStreamClose, + }) + firstStream.id = 'firststream' + const p = pipeline([ + firstStream, + p1, + async function* Step2(s) { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg + } + }, + ], onFinally) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + + expect(received).toEqual(expected) + expect(receivedStep1).toEqual(expected) + expect(receivedStep2).toEqual(expected) + + // all streams were closed + expect(onFirstStreamClose).toHaveBeenCalledTimes(1) + expect(onInputStreamClose).toHaveBeenCalledTimes(1) + }) + + it('works with nested pipeline in first position', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait(WAIT) + onFinallyInnerAfter() + }) + + const receivedStep1 = [] + const onFirstStreamClose = jest.fn() + + const firstStream = PushQueue.from(generate(), { + onEnd: onFirstStreamClose, + }) + firstStream.id = 'firststream' + const p1 = pipeline([ + firstStream + ], onFinallyInner) + + const p = pipeline([ + p1, + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + } + }, + ], onFinally) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + + expect(received).toEqual(expected) + expect(receivedStep1).toEqual(expected) + + // all streams were closed + expect(onFirstStreamClose).toHaveBeenCalledTimes(1) + }) + + it('works with nested pipelines that throw', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait(WAIT) + onFinallyInnerAfter() + }) + + const receivedStep1 = [] + const receivedStep2 = [] + + const err = new Error('expected err') + const p1 = pipeline([ + async function* Step2(s) { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg + if (receivedStep2.length === MAX_ITEMS) { + throw err + } + } + }, + ], onFinallyInner) + + const p = pipeline([ + generate(), + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + } + }, + p1 + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + await expect(async () => { + for await (const msg of p) { + received.push(msg) + } + }).rejects.toThrow(err) + + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + expect(receivedStep1).toEqual(received) + expect(receivedStep2).toEqual(received) + }) + + it('works with streams as pipeline steps', async () => { + const receivedStep1 = [] + const receivedStep2 = [] + const onThroughStreamClose = jest.fn() + const onThroughStream2Close = jest.fn() + + const throughStream = new PushQueue([], { + onEnd: onThroughStreamClose, + }) + const throughStream2 = new PushQueue([], { + onEnd: onThroughStream2Close, + }) + const p = pipeline([ + generate(), + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + } + }, + throughStream, + async function* Step2(s) { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg + } + }, + throughStream2, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(received).toEqual(expected) + expect(receivedStep1).toEqual(expected) + expect(receivedStep2).toEqual(expected) + // all streams were closed + expect(onThroughStreamClose).toHaveBeenCalledTimes(1) + expect(onThroughStream2Close).toHaveBeenCalledTimes(1) + }) + + it('works with streams as pipeline steps with early return', async () => { + const receivedStep1 = [] + const onThroughStreamClose = jest.fn() + const onThroughStream2Close = jest.fn() + + const throughStream = new PushQueue([], { + onEnd: onThroughStreamClose, + }) + const throughStream2 = new PushQueue([], { + onEnd: onThroughStream2Close, + }) + + const p = pipeline([ + generate(), + throughStream, + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + if (receivedStep1.length === MAX_ITEMS) { + break + } + } + }, + throughStream2, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + expect(receivedStep1).toEqual(expected.slice(0, MAX_ITEMS)) + + // all streams were closed + expect(onThroughStreamClose).toHaveBeenCalledTimes(1) + expect(onThroughStream2Close).toHaveBeenCalledTimes(1) + }) + + it('works with streams as pipeline steps with throw', async () => { + const receivedStep1 = [] + const onThroughStreamClose = jest.fn() + const throughStream = new PushQueue([], { + onEnd: onThroughStreamClose, + }) + + const err = new Error('expected err') + const p = pipeline([ + generate(), + throughStream, + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + if (receivedStep1.length === MAX_ITEMS) { + throw err + } + } + }, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + await expect(async () => { + for await (const msg of p) { + received.push(msg) + } + }).rejects.toThrow(err) + + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + expect(receivedStep1).toEqual(received) + + // all streams were closed + expect(onThroughStreamClose).toHaveBeenCalledTimes(1) + }) + + it('works with streams as pipeline steps after generator function', async () => { + const receivedStep1 = [] + const onThroughStreamClose = jest.fn() + const throughStream = new PushQueue([], { + onEnd: onThroughStreamClose, + }) + + const p = pipeline([ + async function* Step1() { + for await (const msg of generate()) { + receivedStep1.push(msg) + yield msg + } + }, + throughStream, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(received).toEqual(expected) + expect(receivedStep1).toEqual(received) + + // all streams were closed + expect(onThroughStreamClose).toHaveBeenCalledTimes(1) + }) + + it('works with streams as pipeline steps before generator function', async () => { + const receivedStep1 = [] + const onThroughStreamClose = jest.fn() + const throughStream = PushQueue.from(generate(), { + onEnd: onThroughStreamClose, + }) + + const p = pipeline([ + throughStream, + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + } + }, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(received).toEqual(expected) + expect(receivedStep1).toEqual(received) + + // all streams were closed + expect(onThroughStreamClose).toHaveBeenCalledTimes(1) + }) + + it('works with multiple streams as pipeline steps with throw', async () => { + const receivedStep1 = [] + const receivedStep2 = [] + const onThroughStreamClose = jest.fn() + const onThroughStream2Close = jest.fn() + + const throughStream = new PushQueue([], { + onEnd: onThroughStreamClose, + }) + throughStream.id = 'throughStream' + const throughStream2 = new PushQueue([], { + onEnd: onThroughStream2Close, + }) + throughStream2.id = 'throughStream2' + + const err = new Error('expected err') + let expectedStep1 + const p = pipeline([ + generate(), + throughStream, + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + } + }, + throughStream2, + async function* Step2(s) { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg + if (receivedStep2.length === MAX_ITEMS) { + expectedStep1 = receivedStep1.slice() + throw err + } + } + }, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + await expect(async () => { + for await (const msg of p) { + received.push(msg) + } + }).rejects.toThrow(err) + + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + expect(receivedStep1).toEqual(expectedStep1) + expect(receivedStep2).toEqual(received) + + // all streams were closed + expect(onThroughStream2Close).toHaveBeenCalledTimes(1) + expect(onThroughStreamClose).toHaveBeenCalledTimes(1) + }) + + it('passes outer pipeline to inner pipeline', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait(WAIT) + onFinallyInnerAfter() + }) + const receivedStep1 = [] + const receivedStep2 = [] + + const p1 = pipeline([ + async function* Step1(s) { // s should come from outer pipeline + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + } + }, + ], onFinallyInner, { + timeout: WAIT, + }) + + const p = pipeline([ + generate(), + p1, + async function* Step2(s) { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg + } + }, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + expect(received).toEqual(expected) + expect(receivedStep1).toEqual(expected) + expect(receivedStep2).toEqual(expected) + // all streams were closed + }) + + it('works with nested pipelines & streams', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait(WAIT) + onFinallyInnerAfter() + }) + const receivedStep1 = [] + const receivedStep2 = [] + const onFirstStreamClose = jest.fn() + const onInputStreamClose = jest.fn() + const inputStream = new PushQueue([], { + onEnd: onInputStreamClose, + }) + const p1 = pipeline([ + inputStream, + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + } + }, + ], onFinallyInner, { + timeout: WAIT, + }) + + const firstStream = PushQueue.from(generate(), { + onEnd: onFirstStreamClose, + }) + const p = pipeline([ + firstStream, + async function* Step2(s) { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg + } + }, + p1, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + expect(received).toEqual(expected) + expect(receivedStep1).toEqual(expected) + expect(receivedStep2).toEqual(expected) + // all streams were closed + expect(onFirstStreamClose).toHaveBeenCalledTimes(1) + expect(onInputStreamClose).toHaveBeenCalledTimes(1) + }) + + it('works with nested pipelines & streams closing before done', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait(WAIT) + onFinallyInnerAfter() + }) + const receivedStep1 = [] + const receivedStep2 = [] + const onFirstStreamClose = jest.fn() + const onInputStreamClose = jest.fn() + + const inputStream = new PushQueue([], { + onEnd: onInputStreamClose, + }) + const p1 = pipeline([ + inputStream, + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + if (receivedStep1.length === MAX_ITEMS) { + break + } + } + }, + ], onFinallyInner, { + timeout: WAIT, + }) + + const firstStream = PushQueue.from(generate(), { + onEnd: onFirstStreamClose, + }) + const p = pipeline([ + firstStream, + p1, + async function* Step2(s) { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg + } + }, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + expect(receivedStep1).toEqual(expected.slice(0, MAX_ITEMS)) + expect(receivedStep2).toEqual(expected.slice(0, MAX_ITEMS)) + // all streams were closed + expect(onFirstStreamClose).toHaveBeenCalledTimes(1) + expect(onInputStreamClose).toHaveBeenCalledTimes(1) + + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + }) + + it('works with nested pipelines & streams + cancel before done', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait(WAIT) + onFinallyInnerAfter() + }) + const receivedStep1 = [] + const receivedStep2 = [] + const onFirstStreamClose = jest.fn() + const onInputStreamClose = jest.fn() + + const inputStream = new PushQueue([], { + onEnd: onInputStreamClose, + }) + const p1 = pipeline([ + inputStream, + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + if (receivedStep1.length === MAX_ITEMS) { + await p1.cancel() + } + } + }, + ], onFinallyInner, { + timeout: WAIT, + }) + + const firstStream = PushQueue.from(generate(), { + onEnd: onFirstStreamClose, + }) + const p = pipeline([ + firstStream, + p1, + async function* Step2(s) { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg + } + }, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + expect(receivedStep1).toEqual(expected.slice(0, MAX_ITEMS)) + expect(receivedStep2).toEqual(expected.slice(0, MAX_ITEMS)) + // all streams were closed + expect(onFirstStreamClose).toHaveBeenCalledTimes(1) + expect(onInputStreamClose).toHaveBeenCalledTimes(1) + + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + }) + + it('works with nested pipelines & streams + cancel before done in second pipeline', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait() + onFinallyInnerAfter() + }) + const receivedStep1 = [] + const receivedStep2 = [] + const onFirstStreamClose = jest.fn() + const onInputStreamClose = jest.fn() + + const inputStream = new PushQueue([], { + onEnd: onInputStreamClose, + }) + + inputStream.id = 'inputStream' + let p + const p1 = pipeline([ + inputStream, + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + if (receivedStep1.length === MAX_ITEMS) { + await p.cancel() + expect(onFinally).toHaveBeenCalledTimes(1) + expect(onFinallyAfter).toHaveBeenCalledTimes(1) + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + } + } + }, + ], onFinallyInner, { + timeout: WAIT, + }) + + const firstStream = PushQueue.from(generate(), { + onEnd: onFirstStreamClose, + }) + firstStream.id = 'firstStream' + p = pipeline([ + firstStream, + p1, + async function* Step2(s) { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg + } + }, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(received).toEqual(expected.slice(0, MAX_ITEMS)) + expect(receivedStep1).toEqual(expected.slice(0, MAX_ITEMS)) + expect(receivedStep2).toEqual(expected.slice(0, MAX_ITEMS)) + // all streams were closed + expect(onFirstStreamClose).toHaveBeenCalledTimes(1) + expect(onInputStreamClose).toHaveBeenCalledTimes(1) + + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + }) + + it('works with nested pipelines at top level', async () => { + const onFinallyInnerAfter = jest.fn() + const onFinallyInner = jest.fn(async () => { + await wait(WAIT) + onFinallyInnerAfter() + }) + + const receivedStep1 = [] + const receivedStep2 = [] + const onFirstStreamClose = jest.fn() + const onInputStreamClose = jest.fn() + + const inputStream = new PushQueue([], { + onEnd: onInputStreamClose, + }) + const p1 = pipeline([ + inputStream, + async function* Step1(s) { + for await (const msg of s) { + receivedStep1.push(msg) + yield msg + } + }, + ], onFinallyInner, { + timeout: WAIT, + }) + + const firstStream = PushQueue.from(generate(), { + onEnd: onFirstStreamClose, + }) + const p = pipeline([ + firstStream, + async function* Step2(s) { + for await (const msg of s) { + receivedStep2.push(msg) + yield msg + } + }, + p1, + ], onFinally, { + timeout: WAIT, + }) + + const received = [] + for await (const msg of p) { + received.push(msg) + } + + expect(onFinallyInner).toHaveBeenCalledTimes(1) + expect(onFinallyInnerAfter).toHaveBeenCalledTimes(1) + expect(received).toEqual(expected) + expect(receivedStep1).toEqual(expected) + expect(receivedStep2).toEqual(expected) + // all streams were closed + expect(onFirstStreamClose).toHaveBeenCalledTimes(1) + expect(onInputStreamClose).toHaveBeenCalledTimes(1) + }) + }) +}) diff --git a/test/unit/pUtils.test.js b/test/unit/pUtils.test.js new file mode 100644 index 000000000..5a07bf4cb --- /dev/null +++ b/test/unit/pUtils.test.js @@ -0,0 +1,66 @@ +import { wait } from 'streamr-test-utils' + +import { pOrderedResolve, CacheAsyncFn } from '../../src/utils' + +describe('pOrderedResolve', () => { + it('Execute functions concurrently, resolving in order they were executed', async () => { + let count = 0 + let active = 0 + const orderedFn = pOrderedResolve(async (index) => { + try { + active += 1 + if (index === 1) { + await wait(50) // delay first call + } else { + expect(active).toBeGreaterThan(1) // ensure concurrent + await wait(1) + } + return index + } finally { + active -= 1 // eslint-disable-line require-atomic-updates + } + }) + + const results = [] + const fn = async () => { + count += 1 + const v = await orderedFn(count) + results.push(v) + return v + } + + await Promise.all([fn(), fn(), fn()]) + + expect(results).toEqual([1, 2, 3]) + + expect(active).toBe(0) + }) +}) + +describe('CacheAsyncFn', () => { + it('caches & be cleared', async () => { + const fn = jest.fn() + const cachedFn = CacheAsyncFn(fn) + await cachedFn() + expect(fn).toHaveBeenCalledTimes(1) + await cachedFn() + expect(fn).toHaveBeenCalledTimes(1) + await cachedFn(1) + expect(fn).toHaveBeenCalledTimes(2) + await cachedFn(1) + expect(fn).toHaveBeenCalledTimes(2) + await cachedFn(2) + expect(fn).toHaveBeenCalledTimes(3) + cachedFn.clear() + await cachedFn(1) + expect(fn).toHaveBeenCalledTimes(4) + await cachedFn(2) + expect(fn).toHaveBeenCalledTimes(5) + await cachedFn.clearMatching((v) => v === 1) + await cachedFn(1) + expect(fn).toHaveBeenCalledTimes(6) + await cachedFn.clearMatching((v) => v === 1) + await cachedFn(1) + expect(fn).toHaveBeenCalledTimes(7) + }) +}) diff --git a/test/unit/utils.test.js b/test/unit/utils.test.ts similarity index 71% rename from test/unit/utils.test.js rename to test/unit/utils.test.ts index 9f77db839..491ecd113 100644 --- a/test/unit/utils.test.js +++ b/test/unit/utils.test.ts @@ -1,16 +1,21 @@ import sinon from 'sinon' -import debugFactory from 'debug' +import Debug from 'debug' +import express, { Application } from 'express' import authFetch from '../../src/rest/authFetch' import { uuid, getEndpointUrl } from '../../src/utils' +import { Server } from 'http' -const debug = debugFactory('StreamrClient::test::utils') -const express = require('express') +const debug = Debug('StreamrClient::test::utils') + +interface TestResponse { + test: string +} describe('utils', () => { - let session - let expressApp - let server + let session: any + let expressApp: Application + let server: Server const baseUrl = 'http://127.0.0.1:30000' const testUrl = '/some-test-url' @@ -19,7 +24,7 @@ describe('utils', () => { session.options = {} expressApp = express() - function handle(req, res) { + function handle(req: any, res: any) { if (req.get('Authorization') !== 'Bearer session-token') { res.sendStatus(401) } else { @@ -29,10 +34,10 @@ describe('utils', () => { } } - expressApp.get(testUrl, (req, res) => handle(req, res)) + expressApp.get(testUrl, (req: any, res: any) => handle(req, res)) server = expressApp.listen(30000, () => { - debug('Mock server started on port 30000\n') // eslint-disable-line no-console + debug('Mock server started on port 30000\n') done() }) }) @@ -44,21 +49,23 @@ describe('utils', () => { describe('authFetch', () => { it('should return normally when valid session token is passed', async () => { session.getSessionToken = sinon.stub().resolves('session-token') - const res = await authFetch(baseUrl + testUrl, session) + const res = await authFetch(baseUrl + testUrl, session) expect(session.getSessionToken.calledOnce).toBeTruthy() expect(res.test).toBeTruthy() }) - it('should return 401 error when invalid session token is passed twice', (done) => { + it('should return 401 error when invalid session token is passed twice', async () => { session.getSessionToken = sinon.stub().resolves('invalid token') - return authFetch(baseUrl + testUrl, session).catch((err) => { + const onCaught = jest.fn() + await authFetch(baseUrl + testUrl, session).catch((err) => { + onCaught() expect(session.getSessionToken.calledTwice).toBeTruthy() - expect(err.toString()).toEqual( - `Error: Request to ${baseUrl + testUrl} returned with error code 401. Unauthorized` + expect(err.toString()).toMatch( + `${baseUrl + testUrl} returned with error code 401. Unauthorized` ) expect(err.body).toEqual('Unauthorized') - done() }) + expect(onCaught).toHaveBeenCalledTimes(1) }) it('should return normally when valid session token is passed after expired session token', async () => { @@ -66,7 +73,7 @@ describe('utils', () => { session.getSessionToken.onCall(0).resolves('expired-session-token') session.getSessionToken.onCall(1).resolves('session-token') - const res = await authFetch(baseUrl + testUrl, session) + const res = await authFetch(baseUrl + testUrl, session) expect(session.getSessionToken.calledTwice).toBeTruthy() expect(res.test).toBeTruthy() }) diff --git a/test/utils.js b/test/utils.js deleted file mode 100644 index 88ae9bee9..000000000 --- a/test/utils.js +++ /dev/null @@ -1,3 +0,0 @@ -const uniqueId = require('lodash.uniqueid') - -export const uid = (prefix) => uniqueId(`p${process.pid}${prefix ? '-' + prefix : ''}`) diff --git a/test/utils.ts b/test/utils.ts new file mode 100644 index 000000000..860c5fa9b --- /dev/null +++ b/test/utils.ts @@ -0,0 +1,263 @@ +import { inspect } from 'util' +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' + +const crypto = require('crypto') +const config = require('./integration/config') + +export const uid = (prefix?: string) => counterId(`p${process.pid}${prefix ? '-' + prefix : ''}`) + +export function fakePrivateKey() { + return crypto.randomBytes(32).toString('hex') +} + +const TEST_REPEATS = (process.env.TEST_REPEATS) ? parseInt(process.env.TEST_REPEATS, 10) : 1 + +export function describeRepeats(msg: any, fn: any, describeFn = describe) { + for (let k = 0; k < TEST_REPEATS; k++) { + // eslint-disable-next-line no-loop-func + describe(msg, () => { + describeFn(`test repeat ${k + 1} of ${TEST_REPEATS}`, fn) + }) + } +} + +describeRepeats.skip = (msg: any, fn: any) => { + describe.skip(`${msg} – test repeat ALL of ${TEST_REPEATS}`, fn) +} + +describeRepeats.only = (msg: any, fn: any) => { + describeRepeats(msg, fn, describe.only) +} + +export async function collect(iterator: any, fn: (item: any) => void = async () => {}) { + const received: any[] = [] + for await (const msg of iterator) { + received.push(msg.getParsedContent()) + await fn({ + msg, iterator, received, + }) + } + + return received +} + +export function addAfterFn() { + const afterFns: any[] = [] + afterEach(async () => { + const fns = afterFns.slice() + afterFns.length = 0 + // @ts-expect-error + AggregatedError.throwAllSettled(await Promise.allSettled(fns.map((fn) => fn()))) + }) + + return (fn: any) => { + afterFns.push(fn) + } +} + +export const Msg = (opts: any) => ({ + value: uid('msg'), + ...opts, +}) + +function defaultMessageMatchFn(msgTarget: any, msgGot: any) { + if (msgTarget.streamMessage.signature) { + // compare signatures by default + return msgTarget.streamMessage.signature === msgGot.signature + } + return JSON.stringify(msgGot.content) === JSON.stringify(msgTarget.streamMessage.getParsedContent()) +} + +export function getWaitForStorage(client: StreamrClient, defaultOpts = {}) { + /* eslint-disable no-await-in-loop */ + return async (publishRequest: any, opts = {}) => { + const { + // @ts-expect-error + streamId, streamPartition = 0, interval = 500, timeout = 5000, count = 100, messageMatchFn = defaultMessageMatchFn + } = validateOptions({ + ...defaultOpts, + ...opts, + }) + + if (!publishRequest && !publishRequest.streamMessage) { + throw new Error(`should check against publish request for comparison, got: ${inspect(publishRequest)}`) + } + + const start = Date.now() + let last: any + // eslint-disable-next-line no-constant-condition + let found = false + while (!found) { + const duration = Date.now() - start + if (duration > timeout) { + client.debug('waitForStorage timeout %o', { + timeout, + duration + }, { + publishRequest, + last: last!.map((l: any) => l.content), + }) + const err: any = new Error(`timed out after ${duration}ms waiting for message`) + err.publishRequest = publishRequest + throw err + } + + last = await client.getStreamLast({ + // @ts-expect-error + streamId, + streamPartition, + count, + }) + + for (const lastMsg of last) { + if (messageMatchFn(publishRequest, lastMsg)) { + found = true + return + } + } + + client.debug('message not found, retrying... %o', { + msg: publishRequest.streamMessage.getParsedContent(), + last: last.map(({ content }: any) => content) + }) + + await wait(interval) + } + } + /* eslint-enable no-await-in-loop */ +} + +export function getPublishTestMessages(client: StreamrClient, defaultOpts = {}) { + // second argument could also be streamId + if (typeof defaultOpts === 'string') { + // eslint-disable-next-line no-param-reassign + defaultOpts = { + streamId: defaultOpts, + } + } + + const publishTestMessagesRaw = async (n = 4, opts = {}) => { + const id = uid('test') + let msgCount = 0 + const { + streamId, + streamPartition = 0, + // @ts-expect-error + delay = 100, + // @ts-expect-error + timeout = 3500, + // @ts-expect-error + waitForLast = false, // wait for message to hit storage + // @ts-expect-error + waitForLastCount, + // @ts-expect-error + waitForLastTimeout, + // @ts-expect-error + beforeEach = (m: any) => m, + // @ts-expect-error + afterEach = () => {}, + // @ts-expect-error + timestamp, + // @ts-expect-error + partitionKey, + // @ts-expect-error + createMessage = () => { + msgCount += 1 + return { + test: id, + value: `${msgCount} of ${n}` + } + }, + } = validateOptions({ + ...defaultOpts, + ...opts, + }) + + let connectionDone = false + function checkDone() { + if (connectionDone) { + throw new Error('Connection done before finished publishing') + } + } + const onDone = () => { + connectionDone = true + } + try { + client.connection.once('done', onDone) + + const published = [] + /* eslint-disable no-await-in-loop, no-loop-func */ + for (let i = 0; i < n; i++) { + checkDone() + const message = createMessage() + await beforeEach(message) + checkDone() + const request = await pTimeout(client.publish( + { streamId, streamPartition }, + message, + typeof timestamp === 'function' ? timestamp() : timestamp, + partitionKey + ), timeout, `publish timeout ${streamId}: ${i} ${inspect(message)}`) + checkDone() + published.push([ + message, + request, + ]) + + await afterEach(message, request) + checkDone() + await wait(delay) // ensure timestamp increments for reliable resend response in test. + checkDone() + } + /* eslint-enable no-await-in-loop, no-loop-func */ + + checkDone() + + if (waitForLast) { + const msg = published[published.length - 1][1] + await getWaitForStorage(client)(msg, { + streamId, + streamPartition, + timeout: waitForLastTimeout, + count: waitForLastCount, + messageMatchFn(m: any, b: any) { + checkDone() + return m.streamMessage.signature === b.signature + } + }) + } + + return published + } finally { + client.connection.off('done', onDone) + } + } + + const publishTestMessages = async (...args: any[]) => { + const published = await publishTestMessagesRaw(...args) + return published.map(([msg]) => msg) + } + + publishTestMessages.raw = publishTestMessagesRaw + return publishTestMessages +} + +export const createMockAddress = () => '0x000000000000000000000000000' + Date.now() + +export const createClient = (providerSidechain?: providers.JsonRpcProvider) => { + const wallet = new Wallet(`0x100000000000000000000000000000000000000012300000001${Date.now()}`, providerSidechain) + return new StreamrClient({ + ...config.clientOptions, + auth: { + privateKey: wallet.privateKey + } + }) +} + +export const expectInvalidAddress = (operation: () => Promise) => { + return expect(() => operation()).rejects.toThrow('invalid address') +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..c9699f3c2 --- /dev/null +++ b/tsconfig.json @@ -0,0 +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" + ], + "strict": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "moduleResolution": "node" + }, + "globals": { + "ts-jest": {} + }, + "include": [ + "src/**/*", + "vendor/**/*", + "contracts/**/*" + ], + "exclude": ["node_modules", "dist"] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 000000000..06a4b2762 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,32 @@ +{ + "extends": "@tsconfig/node14/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "declaration": true, + "declarationDir": "dist/types", + "outDir": "dist", + "lib": [ + "ES5", + "ES2015", + "ES2016", + "ES2017", + "ES2018", + "ES2019", + "ES2020", + "ESNext", + "DOM" + ], + "strict": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "module": "commonjs" + }, + "globals": { + "ts-jest": {} + }, + "include": [ + "src/**/*", + "vendor/**/*", + "contracts/**/*" + ] +} diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 000000000..15f2d7de6 --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,5 @@ +{ + "extends": "./tsconfig.node.json", + "include": ["test/**/*"], + "exclude": ["node_modules", "dist", "test/legacy/*"] +} diff --git a/webpack.config.js b/webpack.config.js index d7677f911..c4952a461 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,113 +8,141 @@ const path = require('path') const webpack = require('webpack') const TerserPlugin = require('terser-webpack-plugin') const { merge } = require('webpack-merge') -const nodeExternals = require('webpack-node-externals') +const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer') +const GitRevisionPlugin = require('git-revision-webpack-plugin') const pkg = require('./package.json') -const isProduction = process.env.NODE_ENV === 'production' -const libraryName = pkg.name - -const commonConfig = { - mode: isProduction ? 'production' : 'development', - entry: path.join(__dirname, 'src', 'index.js'), - devtool: 'source-map', - output: { - path: path.join(__dirname, 'dist'), - library: { - root: 'StreamrClient', - amd: libraryName, - }, - umdNamedDefine: true, - }, - optimization: { - minimize: false - }, - module: { - rules: [ - { - test: /(\.jsx|\.js)$/, - exclude: /(node_modules|bower_components)/, - use: { - loader: 'babel-loader', - options: { - configFile: path.resolve(__dirname, '.babelrc'), - babelrc: false, - cacheDirectory: true, - } - } - - }, - { - test: /(\.jsx|\.js)$/, - loader: 'eslint-loader', - exclude: /(node_modules|streamr-client-protocol)/, // excluding streamr-client-protocol makes build work when 'npm link'ed - }, - ], - }, - resolve: { - modules: [path.resolve('./node_modules'), path.resolve('./src')], - extensions: ['.json', '.js'], - }, - plugins: [ - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), - }), - ] -} +const gitRevisionPlugin = new GitRevisionPlugin() -const serverConfig = merge({}, commonConfig, { - name: 'node-lib', - target: 'node', - externals: [nodeExternals()], - output: { - libraryTarget: 'commonjs2', - filename: libraryName + '.nodejs.js', - }, -}) +const libraryName = pkg.name -const clientConfig = merge({}, commonConfig, { - name: 'browser-lib', - target: 'web', - output: { - libraryTarget: 'umd2', - filename: libraryName + '.web.js', - }, - resolve: { - alias: { - http: path.resolve(__dirname, './src/shim/http-https.js'), - https: path.resolve(__dirname, './src/shim/http-https.js'), - ws: path.resolve(__dirname, './src/shim/ws.js'), - buffer: path.resolve(__dirname, 'node_modules', 'buffer'), - 'node-fetch': path.resolve(__dirname, './src/shim/node-fetch.js'), - 'node-webcrypto-ossl': path.resolve(__dirname, 'src/shim/crypto.js'), - } - } -}) +module.exports = (env, argv) => { + const isProduction = argv.mode === 'production' || process.env.NODE_ENV === 'production' -let clientMinifiedConfig = {} + const analyze = !!process.env.BUNDLE_ANALYSIS -if (isProduction) { - clientMinifiedConfig = merge({}, clientConfig, { + const commonConfig = { + mode: isProduction ? 'production' : 'development', + entry: path.join(__dirname, 'src', 'StreamrClient.ts'), + devtool: 'source-map', + output: { + umdNamedDefine: true, + }, optimization: { - minimize: true, - minimizer: [ - new TerserPlugin({ - cache: true, - parallel: true, - sourceMap: true, - terserOptions: { - output: { - comments: false, - }, - }, - }), + 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, + } + } + }, + { + test: /(\.jsx|\.js|\.ts)$/, + loader: 'eslint-loader', + exclude: /(node_modules|streamr-client-protocol|dist)/, // excluding streamr-client-protocol makes build work when 'npm link'ed + }, ], }, + resolve: { + modules: [path.resolve('./node_modules'), path.resolve('./vendor'), path.resolve('./src')], + extensions: ['.json', '.js', '.ts'], + }, + plugins: [ + gitRevisionPlugin, + new webpack.EnvironmentPlugin({ + NODE_ENV: process.env.NODE_ENV, + version: pkg.version, + GIT_VERSION: gitRevisionPlugin.version(), + GIT_COMMITHASH: gitRevisionPlugin.commithash(), + GIT_BRANCH: gitRevisionPlugin.branch(), + }) + ] + } + + const clientConfig = merge({}, commonConfig, { + name: 'browser-lib', + target: 'web', output: { - filename: libraryName + '.web.min.js', + 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: { + stream: 'readable-stream', + util: 'util', + http: path.resolve(__dirname, './src/shim/http-https.js'), + https: path.resolve(__dirname, './src/shim/http-https.js'), + ws: path.resolve(__dirname, './src/shim/ws.js'), + crypto: path.resolve(__dirname, 'node_modules', 'crypto-browserify'), + buffer: path.resolve(__dirname, 'node_modules', 'buffer'), + 'node-fetch': path.resolve(__dirname, './src/shim/node-fetch.js'), + 'node-webcrypto-ossl': path.resolve(__dirname, 'src/shim/crypto.js'), + 'streamr-client-protocol': path.resolve(__dirname, 'node_modules/streamr-client-protocol/dist/src'), + } + }, + plugins: [ + new webpack.ProvidePlugin({ + process: 'process/browser', + Buffer: ['buffer', 'Buffer'], + }), + ...(analyze ? [ + new BundleAnalyzerPlugin({ + analyzerMode: 'static', + openAnalyzer: false, + generateStatsFile: true, + }), + ] : []) + ] }) -} -module.exports = [serverConfig, clientConfig, clientMinifiedConfig] + let clientMinifiedConfig + + if (isProduction) { + clientMinifiedConfig = merge({}, clientConfig, { + name: 'browser-lib-min', + optimization: { + minimize: true, + minimizer: [ + new TerserPlugin({ + parallel: true, + terserOptions: { + ecma: 2018, + output: { + comments: false, + }, + }, + }), + ], + }, + output: { + filename: libraryName + '.web.min.js', + }, + }) + } + + return [clientConfig, clientMinifiedConfig].filter(Boolean) +}