difftreelog
Merge branch 'develop' into test/playground-migration
in: master
142 files changed
.github/workflows/canary.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/canary.yml
@@ -0,0 +1,12 @@
+on:
+ workflow_call:
+
+jobs:
+
+ market-e2e-test:
+ name: market e2e tests
+ uses: ./.github/workflows/market-test_v2.yml
+ secrets: inherit
+
+
+
.github/workflows/ci-develop.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/ci-develop.yml
@@ -0,0 +1,34 @@
+name: develop
+
+on:
+ pull_request:
+ branches: [ 'develop' ]
+ types: [ opened, reopened, synchronize, ready_for_review ]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.head_ref }}
+ cancel-in-progress: true
+
+jobs:
+
+ yarn-test-dev:
+ uses: ./.github/workflows/dev-build-tests_v2.yml
+
+ unit-test:
+ uses: ./.github/workflows/unit-test_v2.yml
+
+ canary:
+ if: ${{ contains( github.event.pull_request.labels.*.name, 'canary') }}
+ uses: ./.github/workflows/canary.yml
+ secrets: inherit # pass all secrets
+
+ xcm:
+ if: ${{ contains( github.event.pull_request.labels.*.name, 'xcm') }}
+ uses: ./.github/workflows/xcm.yml
+ secrets: inherit # pass all secrets
+
+ codestyle:
+ uses: ./.github/workflows/codestyle_v2.yml
+
+ yarn_eslint:
+ uses: ./.github/workflows/test_codestyle_v2.yml
.github/workflows/ci-master.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/ci-master.yml
@@ -0,0 +1,32 @@
+name: master
+
+on:
+ pull_request:
+ branches: [ 'master' ]
+ types: [ opened, reopened, synchronize, ready_for_review ]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.head_ref }}
+ cancel-in-progress: true
+
+jobs:
+
+ unit-test:
+ uses: ./.github/workflows/unit-test_v2.yml
+
+ node-only-update:
+ uses: ./.github/workflows/node-only-update_v2.yml
+
+ forkless:
+ uses: ./.github/workflows/forkless.yml
+
+ canary:
+ uses: ./.github/workflows/canary.yml
+ secrets: inherit # pass all secrets
+
+ xcm:
+ uses: ./.github/workflows/xcm.yml
+ secrets: inherit # pass all secrets
+
+ codestyle:
+ uses: ./.github/workflows/codestyle_v2.yml
\ No newline at end of file
.github/workflows/codestyle.ymldiffbeforeafterboth--- a/.github/workflows/codestyle.yml
+++ /dev/null
@@ -1,89 +0,0 @@
-name: cargo fmt
-
-on:
- pull_request:
- branches:
- - develop
- types:
- - opened
- - reopened
- - synchronize
- - ready_for_review
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref }}
- cancel-in-progress: true
-
-jobs:
- rustfmt:
- runs-on: self-hosted-ci
-
- steps:
- - name: Skip if pull request is in Draft
- # `if: github.event.pull_request.draft == true` should be kept here, at
- # the step level, rather than at the job level. The latter is not
- # recommended because when the PR is moved from "Draft" to "Ready to
- # review" the workflow will immediately be passing (since it was skipped),
- # even though it hasn't actually ran, since it takes a few seconds for
- # the workflow to start. This is also disclosed in:
- # https://github.community/t/dont-run-actions-on-draft-pull-requests/16817/17
- # That scenario would open an opportunity for the check to be bypassed:
- # 1. Get your PR approved
- # 2. Move it to Draft
- # 3. Push whatever commits you want
- # 4. Move it to "Ready for review"; now the workflow is passing (it was
- # skipped) and "Check reviews" is also passing (it won't be updated
- # until the workflow is finished)
- if: github.event.pull_request.draft == true
- run: exit 1
-
- - uses: actions/checkout@v3
- - name: Install latest nightly
- uses: actions-rs/toolchain@v1
- with:
- toolchain: nightly
- default: true
- target: wasm32-unknown-unknown
- components: rustfmt, clippy
- - name: Run cargo fmt
- run: cargo fmt -- --check # In that mode it returns only exit code.
- - name: Cargo fmt state
- if: success()
- run: echo "Nothing to do. Command 'cargo fmt -- --check' returned exit code 0."
-
-
- clippy:
- if: ${{ false }}
- runs-on: self-hosted-ci
-
- steps:
- - name: Skip if pull request is in Draft
- # `if: github.event.pull_request.draft == true` should be kept here, at
- # the step level, rather than at the job level. The latter is not
- # recommended because when the PR is moved from "Draft" to "Ready to
- # review" the workflow will immediately be passing (since it was skipped),
- # even though it hasn't actually ran, since it takes a few seconds for
- # the workflow to start. This is also disclosed in:
- # https://github.community/t/dont-run-actions-on-draft-pull-requests/16817/17
- # That scenario would open an opportunity for the check to be bypassed:
- # 1. Get your PR approved
- # 2. Move it to Draft
- # 3. Push whatever commits you want
- # 4. Move it to "Ready for review"; now the workflow is passing (it was
- # skipped) and "Check reviews" is also passing (it won't be updated
- # until the workflow is finished)
- if: github.event.pull_request.draft == true
- run: exit 1
-
- - uses: actions/checkout@v3
- - name: Install substrate dependencies
- run: sudo apt-get install libssl-dev pkg-config libclang-dev clang
- - name: Install latest nightly
- uses: actions-rs/toolchain@v1
- with:
- toolchain: nightly
- default: true
- target: wasm32-unknown-unknown
- components: rustfmt, clippy
- - name: Run cargo check
- run: cargo clippy -- -Dwarnings
.github/workflows/codestyle_v2.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/codestyle_v2.yml
@@ -0,0 +1,43 @@
+name: cargo fmt
+
+on:
+ workflow_call:
+
+jobs:
+ rustfmt:
+ runs-on: self-hosted-ci
+
+ steps:
+ - uses: actions/checkout@v3
+ - name: Install latest nightly
+ uses: actions-rs/toolchain@v1
+ with:
+ toolchain: nightly
+ default: true
+ target: wasm32-unknown-unknown
+ components: rustfmt, clippy
+ - name: Run cargo fmt
+ run: cargo fmt -- --check # In that mode it returns only exit code.
+ - name: Cargo fmt state
+ if: success()
+ run: echo "Nothing to do. Command 'cargo fmt -- --check' returned exit code 0."
+
+
+ clippy:
+ if: ${{ false }}
+ runs-on: self-hosted-ci
+
+ steps:
+
+ - uses: actions/checkout@v3
+ - name: Install substrate dependencies
+ run: sudo apt-get install libssl-dev pkg-config libclang-dev clang
+ - name: Install latest nightly
+ uses: actions-rs/toolchain@v1
+ with:
+ toolchain: nightly
+ default: true
+ target: wasm32-unknown-unknown
+ components: rustfmt, clippy
+ - name: Run cargo check
+ run: cargo clippy -- -Dwarnings
.github/workflows/dev-build-tests.ymldiffbeforeafterboth--- a/.github/workflows/dev-build-tests.yml
+++ /dev/null
@@ -1,125 +0,0 @@
-name: yarn test dev
-
-# Controls when the action will run.
-on:
- # Triggers the workflow on push or pull request events but only for the master branch
- pull_request:
- branches:
- - develop
- types:
- - opened
- - reopened
- - synchronize #commit(s) pushed to the pull request
- - ready_for_review
-
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-#Define Workflow variables
-env:
- REPO_URL: ${{ github.server_url }}/${{ github.repository }}
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref }}
- cancel-in-progress: true
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
-
- dev_build_int_tests:
- # The type of runner that the job will run on
- runs-on: [self-hosted-ci,medium]
- timeout-minutes: 1380
-
- name: ${{ matrix.network }}
-
- continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
-
- strategy:
- matrix:
- include:
- - network: "opal"
- features: "opal-runtime"
- - network: "quartz"
- features: "quartz-runtime"
- - network: "unique"
- features: "unique-runtime"
-
- steps:
- - name: Skip if pull request is in Draft
- # `if: github.event.pull_request.draft == true` should be kept here, at
- # the step level, rather than at the job level. The latter is not
- # recommended because when the PR is moved from "Draft" to "Ready to
- # review" the workflow will immediately be passing (since it was skipped),
- # even though it hasn't actually ran, since it takes a few seconds for
- # the workflow to start. This is also disclosed in:
- # https://github.community/t/dont-run-actions-on-draft-pull-requests/16817/17
- # That scenario would open an opportunity for the check to be bypassed:
- # 1. Get your PR approved
- # 2. Move it to Draft
- # 3. Push whatever commits you want
- # 4. Move it to "Ready for review"; now the workflow is passing (it was
- # skipped) and "Check reviews" is also passing (it won't be updated
- # until the workflow is finished)
- if: github.event.pull_request.draft == true
- run: exit 1
-
- - name: Clean Workspace
- uses: AutoModality/action-clean@v1.1.0
-
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v3
- with:
- ref: ${{ github.head_ref }} #Checking out head commit
-
- - name: Read .env file
- uses: xom9ikk/dotenv@v1.0.2
-
- - name: Generate ENV related extend file for docker-compose
- uses: cuchi/jinja2-action@v1.2.0
- with:
- template: .docker/docker-compose.tmp-dev.j2
- output_file: .docker/docker-compose.${{ matrix.network }}.yml
- variables: |
- RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
- FEATURE=${{ matrix.features }}
-
-
- - name: Show build configuration
- run: cat .docker/docker-compose.${{ matrix.network }}.yml
-
- - name: Build the stack
- run: docker-compose -f ".docker/docker-compose-dev.yaml" -f ".docker/docker-compose.${{ matrix.network }}.yml" up -d --build --remove-orphans
-
- - uses: actions/setup-node@v3
- with:
- node-version: 16
-
- - name: Run tests
- run: |
- cd tests
- yarn install
- yarn add mochawesome
- echo "Ready to start tests"
- node scripts/readyness.js
- NOW=$(date +%s) && yarn test --reporter mochawesome --reporter-options reportFilename=test-${NOW}
- env:
- RPC_URL: http://127.0.0.1:9933/
-
- - name: Test Report
- uses: phoenix-actions/test-reporting@v8
- id: test-report
- if: success() || failure() # run this step even if previous step failed
- with:
- name: int test results - ${{ matrix.network }} # Name of the check run which will be created
- path: tests/mochawesome-report/test-*.json # Path to test results
- reporter: mochawesome-json
- fail-on-error: 'false'
-
- - name: Read output variables
- run: |
- echo "url is ${{ steps.test-report.outputs.runHtmlUrl }}"
-
- - name: Stop running containers
- if: always() # run this step always
- run: docker-compose -f ".docker/docker-compose-dev.yaml" -f ".docker/docker-compose.${{ matrix.network }}.yml" down
.github/workflows/dev-build-tests_v2.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/dev-build-tests_v2.yml
@@ -0,0 +1,97 @@
+name: yarn test dev
+
+# Controls when the action will run.
+on:
+ # Triggers the workflow on push or pull request events but only for the master branch
+ workflow_call:
+
+
+#Define Workflow variables
+env:
+ REPO_URL: ${{ github.server_url }}/${{ github.repository }}
+
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+
+ dev_build_int_tests:
+ # The type of runner that the job will run on
+ runs-on: [self-hosted-ci,medium]
+ timeout-minutes: 1380
+
+ name: ${{ matrix.network }}
+
+ continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
+
+ strategy:
+ matrix:
+ include:
+ - network: "opal"
+ features: "opal-runtime"
+ - network: "quartz"
+ features: "quartz-runtime"
+ - network: "unique"
+ features: "unique-runtime"
+
+ steps:
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Generate ENV related extend file for docker-compose
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/docker-compose.tmp-dev.j2
+ output_file: .docker/docker-compose.${{ matrix.network }}.yml
+ variables: |
+ RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
+ FEATURE=${{ matrix.features }}
+
+
+ - name: Show build configuration
+ run: cat .docker/docker-compose.${{ matrix.network }}.yml
+
+ - name: Build the stack
+ run: docker-compose -f ".docker/docker-compose-dev.yaml" -f ".docker/docker-compose.${{ matrix.network }}.yml" up -d --build --remove-orphans
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 16
+
+ - name: Run tests
+ working-directory: tests
+ run: |
+ yarn install
+ yarn add mochawesome
+ echo "Ready to start tests"
+ node scripts/readyness.js
+ yarn polkadot-types
+ NOW=$(date +%s) && yarn test --reporter mochawesome --reporter-options reportFilename=test-${NOW}
+ env:
+ RPC_URL: http://127.0.0.1:9933/
+
+ - name: Test Report
+ uses: phoenix-actions/test-reporting@v8
+ id: test-report
+ if: success() || failure() # run this step even if previous step failed
+ with:
+ name: int test results - ${{ matrix.network }} # Name of the check run which will be created
+ path: tests/mochawesome-report/test-*.json # Path to test results
+ reporter: mochawesome-json
+ fail-on-error: 'false'
+
+ - name: Read output variables
+ run: |
+ echo "url is ${{ steps.test-report.outputs.runHtmlUrl }}"
+
+ - name: Stop running containers
+ if: always() # run this step always
+ run: docker-compose -f ".docker/docker-compose-dev.yaml" -f ".docker/docker-compose.${{ matrix.network }}.yml" down
.github/workflows/execution-matrix.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/execution-matrix.yml
@@ -0,0 +1,42 @@
+name: Reusable workflow
+
+on:
+ workflow_call:
+ # Map the workflow outputs to job outputs
+ outputs:
+ matrix:
+ description: "The first output string"
+ value: ${{ jobs.create-matrix.outputs.matrix_output }}
+
+jobs:
+
+ create-marix:
+
+ name: Prepare execution matrix
+
+ runs-on: self-hosted-ci
+ outputs:
+ matrix_output: ${{ steps.create_matrix.outputs.matrix }}
+
+ steps:
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Create Execution matrix
+ uses: CertainLach/create-matrix-action@v3
+ id: create_matrix
+ with:
+ matrix: |
+ network {opal}, runtime {opal}, features {opal-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}, replica_from_address {${{ env.OPAL_REPLICA_FROM }}}
+ network {quartz}, runtime {quartz}, features {quartz-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}, replica_from_address {${{ env.QUARTZ_REPLICA_FROM }}}
+ network {unique}, runtime {unique}, features {unique-runtime}, mainnet_branch {${{ env.UNIQUE_MAINNET_TAG }}}, replica_from_address {${{ env.UNIQUE_REPLICA_FROM }}}
+
.github/workflows/forkless-update-data.ymldiffbeforeafterboth--- a/.github/workflows/forkless-update-data.yml
+++ /dev/null
@@ -1,204 +0,0 @@
-name: upgrade replica
-
-# Controls when the action will run.
-on:
- # Triggers the workflow on push or pull request events but only for the master branch
- pull_request:
- branches:
- - master
- types:
- - opened
- - reopened
- - synchronize #commit(s) pushed to the pull request
- - ready_for_review
-
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-#Define Workflow variables
-env:
- REPO_URL: ${{ github.server_url }}/${{ github.repository }}
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref }}
- cancel-in-progress: true
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
-
- prepare-execution-marix:
-
- name: Prepare execution matrix
-
- runs-on: self-hosted-ci
- outputs:
- matrix: ${{ steps.create_matrix.outputs.matrix }}
-
- steps:
-
- - name: Clean Workspace
- uses: AutoModality/action-clean@v1.1.0
-
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v3
- with:
- ref: ${{ github.head_ref }} #Checking out head commit
-
- - name: Read .env file
- uses: xom9ikk/dotenv@v1.0.2
-
- - name: Create Execution matrix
- uses: CertainLach/create-matrix-action@v3
- id: create_matrix
- with:
- matrix: |
- network {opal}, runtime {opal}, features {opal-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}, replica_from_address {${{ env.OPAL_REPLICA_FROM }}}
- network {quartz}, runtime {quartz}, features {quartz-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}, replica_from_address {${{ env.QUARTZ_REPLICA_FROM }}}
- network {unique}, runtime {unique}, features {unique-runtime}, mainnet_branch {${{ env.UNIQUE_MAINNET_TAG }}}, replica_from_address {${{ env.UNIQUE_REPLICA_FROM }}}
-
-
-
- forkless-update-data:
- needs: prepare-execution-marix
- # The type of runner that the job will run on
- runs-on: [self-hosted-ci,large]
- timeout-minutes: 1380
-
-
-
- name: ${{ matrix.network }}
-
- continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
-
- strategy:
- matrix:
- include: ${{fromJson(needs.prepare-execution-marix.outputs.matrix)}}
-
-
- steps:
- - name: Skip if pull request is in Draft
- # `if: github.event.pull_request.draft == true` should be kept here, at
- # the step level, rather than at the job level. The latter is not
- # recommended because when the PR is moved from "Draft" to "Ready to
- # review" the workflow will immediately be passing (since it was skipped),
- # even though it hasn't actually ran, since it takes a few seconds for
- # the workflow to start. This is also disclosed in:
- # https://github.community/t/dont-run-actions-on-draft-pull-requests/16817/17
- # That scenario would open an opportunity for the check to be bypassed:
- # 1. Get your PR approved
- # 2. Move it to Draft
- # 3. Push whatever commits you want
- # 4. Move it to "Ready for review"; now the workflow is passing (it was
- # skipped) and "Check reviews" is also passing (it won't be updated
- # until the workflow is finished)
- if: github.event.pull_request.draft == true
- run: exit 1
-
- - name: Clean Workspace
- uses: AutoModality/action-clean@v1.1.0
-
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v3
- with:
- ref: ${{ github.head_ref }} #Checking out head commit
-
- - name: Read .env file
- uses: xom9ikk/dotenv@v1.0.2
-
- - name: Generate ENV related extend file for docker-compose
- uses: cuchi/jinja2-action@v1.2.0
- with:
- template: .docker/docker-compose.tmp-forkless-data.j2
- output_file: .docker/docker-compose.${{ matrix.network }}.yml
- variables: |
- REPO_URL=${{ github.server_url }}/${{ github.repository }}.git
- RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
- POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }}
- POLKADOT_MAINNET_BRANCH=${{ env.POLKADOT_MAINNET_BRANCH }}
- MAINNET_TAG=${{ matrix.mainnet_tag }}
- MAINNET_BRANCH=${{ matrix.mainnet_branch }}
- FEATURE=${{ matrix.features }}
- RUNTIME=${{ matrix.runtime }}
- BRANCH=${{ github.head_ref }}
- REPLICA_FROM=${{ matrix.replica_from_address }}
-
- - name: Show build configuration
- run: cat .docker/docker-compose.${{ matrix.network }}.yml
-
- - name: Generate launch-config-forkless-data.json
- uses: cuchi/jinja2-action@v1.2.0
- with:
- template: .docker/forkless-config/launch-config-forkless-data.j2
- output_file: .docker/launch-config-forkless-data.json
- variables: |
- FEATURE=${{ matrix.features }}
- RUNTIME=${{ matrix.runtime }}
-
- - name: Show launch-config-forkless configuration
- run: cat .docker/launch-config-forkless-data.json
-
-
- - name: Build the stack
- run: docker-compose -f ".docker/docker-compose-forkless.yml" -f ".docker/docker-compose.${{ matrix.network }}.yml" up -d --build --force-recreate --timeout 300
-
- - name: Check if docker logs consist logs related to Runtime Upgrade testing.
- if: success()
- run: |
- counter=160
- function check_container_status {
- docker inspect -f {{.State.Running}} node-parachain
- }
- function do_docker_logs {
- docker logs --details node-parachain 2>&1
- }
- function is_started {
- if [ "$(check_container_status)" == "true" ]; then
- echo "Container: node-parachain RUNNING";
- echo "Check Docker logs"
- DOCKER_LOGS=$(do_docker_logs)
- if [[ ${DOCKER_LOGS} = *"🛸 PARACHAINS' RUNTIME UPGRADE TESTING COMPLETE 🛸"* ]];then
- echo "🛸 PARACHAINS' RUNTIME UPGRADE TESTING COMPLETE 🛸"
- return 0
- elif [[ ${DOCKER_LOGS} = *"🚧 PARACHAINS' RUNTIME UPGRADE TESTING FAILED 🚧"* ]];then
- echo "🚧 PARACHAINS' RUNTIME UPGRADE TESTING FAILED 🚧"
- return 1
- else
- echo "Message not found in logs output, repeating..."
- return 1
- fi
- else
- echo "Container node-parachain not RUNNING"
- echo "Halting all future checks"
- exit 1
- fi
- exit 0
- }
- while ! is_started; do
- echo "Waiting for special message in log files "
- sleep 30s
- counter=$(( $counter - 1 ))
- echo "Counter: $counter"
- if [ "$counter" -gt "0" ]; then
- continue
- else
- break
- fi
- done
- echo "Halting script"
- exit 0
- shell: bash
-
- - name: Collect Docker Logs
- if: success() || failure()
- uses: jwalton/gh-docker-logs@v2.2.0
- with:
- dest: './forkless-parachain-upgrade-data-logs.${{ matrix.features }}'
- images: 'node-parachain'
-
- - name: Show Docker logs
- if: success() || failure()
- run: cat './forkless-parachain-upgrade-data-logs.${{ matrix.features }}/node-parachain.log'
-
- - name: Stop running containers
- if: always() # run this step always
- run: docker-compose -f ".docker/docker-compose-forkless.yml" -f ".docker/docker-compose.${{ matrix.network }}.yml" down
.github/workflows/forkless-update-data_v2.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/forkless-update-data_v2.yml
@@ -0,0 +1,165 @@
+# Controls when the action will run.
+on:
+ workflow_call:
+
+
+#Define Workflow variables
+env:
+ REPO_URL: ${{ github.server_url }}/${{ github.repository }}
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+
+ execution-marix:
+
+ name: execution matrix
+
+ runs-on: self-hosted-ci
+ outputs:
+ matrix: ${{ steps.create_matrix.outputs.matrix }}
+
+ steps:
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Create Execution matrix
+ uses: CertainLach/create-matrix-action@v3
+ id: create_matrix
+ with:
+ matrix: |
+ network {opal}, runtime {opal}, features {opal-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}, replica_from_address {${{ env.OPAL_REPLICA_FROM }}}
+ network {quartz}, runtime {quartz}, features {quartz-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}, replica_from_address {${{ env.QUARTZ_REPLICA_FROM }}}
+ network {unique}, runtime {unique}, features {unique-runtime}, mainnet_branch {${{ env.UNIQUE_MAINNET_TAG }}}, replica_from_address {${{ env.UNIQUE_REPLICA_FROM }}}
+
+ forkless-update-data:
+ needs: execution-marix
+ # The type of runner that the job will run on
+ runs-on: [self-hosted-ci,large]
+ timeout-minutes: 1380
+
+ name: ${{ matrix.network }}
+ strategy:
+ matrix:
+ include: ${{fromJson(needs.execution-marix.outputs.matrix)}}
+
+ continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
+
+
+ steps:
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Generate ENV related extend file for docker-compose
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/docker-compose.tmp-forkless-data.j2
+ output_file: .docker/docker-compose.${{ matrix.network }}.yml
+ variables: |
+ REPO_URL=${{ github.server_url }}/${{ github.repository }}.git
+ RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
+ POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }}
+ POLKADOT_MAINNET_BRANCH=${{ env.POLKADOT_MAINNET_BRANCH }}
+ MAINNET_TAG=${{ matrix.mainnet_tag }}
+ MAINNET_BRANCH=${{ matrix.mainnet_branch }}
+ FEATURE=${{ matrix.features }}
+ RUNTIME=${{ matrix.runtime }}
+ BRANCH=${{ github.head_ref }}
+ REPLICA_FROM=${{ matrix.replica_from_address }}
+
+ - name: Show build configuration
+ run: cat .docker/docker-compose.${{ matrix.network }}.yml
+
+ - name: Generate launch-config-forkless-data.json
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/forkless-config/launch-config-forkless-data.j2
+ output_file: .docker/launch-config-forkless-data.json
+ variables: |
+ FEATURE=${{ matrix.features }}
+ RUNTIME=${{ matrix.runtime }}
+
+ - name: Show launch-config-forkless configuration
+ run: cat .docker/launch-config-forkless-data.json
+
+
+ - name: Build the stack
+ run: docker-compose -f ".docker/docker-compose-forkless.yml" -f ".docker/docker-compose.${{ matrix.network }}.yml" up -d --build --force-recreate --timeout 300
+
+ - name: Check if docker logs consist logs related to Runtime Upgrade testing.
+ if: success()
+ run: |
+ counter=160
+ function check_container_status {
+ docker inspect -f {{.State.Running}} node-parachain
+ }
+ function do_docker_logs {
+ docker logs --details node-parachain 2>&1
+ }
+ function is_started {
+ if [ "$(check_container_status)" == "true" ]; then
+ echo "Container: node-parachain RUNNING";
+ echo "Check Docker logs"
+ DOCKER_LOGS=$(do_docker_logs)
+ if [[ ${DOCKER_LOGS} = *"🛸 PARACHAINS' RUNTIME UPGRADE TESTING COMPLETE 🛸"* ]];then
+ echo "🛸 PARACHAINS' RUNTIME UPGRADE TESTING COMPLETE 🛸"
+ return 0
+ elif [[ ${DOCKER_LOGS} = *"🚧 PARACHAINS' RUNTIME UPGRADE TESTING FAILED 🚧"* ]];then
+ echo "🚧 PARACHAINS' RUNTIME UPGRADE TESTING FAILED 🚧"
+ return 1
+ else
+ echo "Message not found in logs output, repeating..."
+ return 1
+ fi
+ else
+ echo "Container node-parachain not RUNNING"
+ echo "Halting all future checks"
+ exit 1
+ fi
+ exit 0
+ }
+ while ! is_started; do
+ echo "Waiting for special message in log files "
+ sleep 30s
+ counter=$(( $counter - 1 ))
+ echo "Counter: $counter"
+ if [ "$counter" -gt "0" ]; then
+ continue
+ else
+ break
+ fi
+ done
+ echo "Halting script"
+ exit 0
+ shell: bash
+
+ - name: Collect Docker Logs
+ if: success() || failure()
+ uses: jwalton/gh-docker-logs@v2.2.0
+ with:
+ dest: './forkless-parachain-upgrade-data-logs.${{ matrix.features }}'
+ images: 'node-parachain'
+
+ - name: Show Docker logs
+ if: success() || failure()
+ run: cat './forkless-parachain-upgrade-data-logs.${{ matrix.features }}/node-parachain.log'
+
+ - name: Stop running containers
+ if: always() # run this step always
+ run: docker-compose -f ".docker/docker-compose-forkless.yml" -f ".docker/docker-compose.${{ matrix.network }}.yml" down --volumes
.github/workflows/forkless-update-nodata.ymldiffbeforeafterboth--- a/.github/workflows/forkless-update-nodata.yml
+++ /dev/null
@@ -1,204 +0,0 @@
-name: upgrade nodata
-
-# Controls when the action will run.
-on:
- # Triggers the workflow on push or pull request events but only for the master branch
- pull_request:
- branches:
- - master
- types:
- - opened
- - reopened
- - synchronize #commit(s) pushed to the pull request
- - ready_for_review
-
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-#Define Workflow variables
-env:
- REPO_URL: ${{ github.server_url }}/${{ github.repository }}
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref }}
- cancel-in-progress: true
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
-
- prepare-execution-marix:
-
- name: Prepare execution matrix
-
- runs-on: self-hosted-ci
- outputs:
- matrix: ${{ steps.create_matrix.outputs.matrix }}
-
- steps:
-
- - name: Clean Workspace
- uses: AutoModality/action-clean@v1.1.0
-
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v3
- with:
- ref: ${{ github.head_ref }} #Checking out head commit
-
- - name: Read .env file
- uses: xom9ikk/dotenv@v1.0.2
-
- - name: Create Execution matrix
- uses: fabiocaccamo/create-matrix-action@v2
- id: create_matrix
- with:
- matrix: |
- network {opal}, runtime {opal}, features {opal-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}
- network {quartz}, runtime {quartz}, features {quartz-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}
- network {unique}, runtime {unique}, features {unique-runtime}, mainnet_branch {${{ env.UNIQUE_MAINNET_TAG }}}
-
-
-
- forkless-update-nodata:
- needs: prepare-execution-marix
- # The type of runner that the job will run on
- runs-on: [self-hosted-ci,large]
-
-
-
- timeout-minutes: 1380
-
- name: ${{ matrix.network }}
-
- continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
-
- strategy:
- matrix:
- include: ${{fromJson(needs.prepare-execution-marix.outputs.matrix)}}
-
-
- steps:
- - name: Skip if pull request is in Draft
- # `if: github.event.pull_request.draft == true` should be kept here, at
- # the step level, rather than at the job level. The latter is not
- # recommended because when the PR is moved from "Draft" to "Ready to
- # review" the workflow will immediately be passing (since it was skipped),
- # even though it hasn't actually ran, since it takes a few seconds for
- # the workflow to start. This is also disclosed in:
- # https://github.community/t/dont-run-actions-on-draft-pull-requests/16817/17
- # That scenario would open an opportunity for the check to be bypassed:
- # 1. Get your PR approved
- # 2. Move it to Draft
- # 3. Push whatever commits you want
- # 4. Move it to "Ready for review"; now the workflow is passing (it was
- # skipped) and "Check reviews" is also passing (it won't be updated
- # until the workflow is finished)
- if: github.event.pull_request.draft == true
- run: exit 1
-
- - name: Clean Workspace
- uses: AutoModality/action-clean@v1.1.0
-
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v3
- with:
- ref: ${{ github.head_ref }} #Checking out head commit
-
- - name: Read .env file
- uses: xom9ikk/dotenv@v1.0.2
-
- - name: Generate ENV related extend file for docker-compose
- uses: cuchi/jinja2-action@v1.2.0
- with:
- template: .docker/docker-compose.tmp-forkless-nodata.j2
- output_file: .docker/docker-compose.${{ matrix.network }}.yml
- variables: |
- REPO_URL=${{ github.server_url }}/${{ github.repository }}.git
- RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
- POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }}
- POLKADOT_MAINNET_BRANCH=${{ env.POLKADOT_MAINNET_BRANCH }}
- MAINNET_TAG=${{ matrix.mainnet_tag }}
- MAINNET_BRANCH=${{ matrix.mainnet_branch }}
- FEATURE=${{ matrix.features }}
- RUNTIME=${{ matrix.runtime }}
- BRANCH=${{ github.head_ref }}
-
- - name: Show build configuration
- run: cat .docker/docker-compose.${{ matrix.network }}.yml
-
- - name: Generate launch-config-forkless-nodata.json
- uses: cuchi/jinja2-action@v1.2.0
- with:
- template: .docker/forkless-config/launch-config-forkless-nodata.j2
- output_file: .docker/launch-config-forkless-nodata.json
- variables: |
- FEATURE=${{ matrix.features }}
- RUNTIME=${{ matrix.runtime }}
-
- - name: Show launch-config-forkless configuration
- run: cat .docker/launch-config-forkless-nodata.json
-
-
- - name: Build the stack
- run: docker-compose -f ".docker/docker-compose-forkless.yml" -f ".docker/docker-compose.${{ matrix.network }}.yml" up -d --build --force-recreate --timeout 300
-
- - name: Check if docker logs consist logs related to Runtime Upgrade testing.
- if: success()
- run: |
- counter=160
- function check_container_status {
- docker inspect -f {{.State.Running}} node-parachain
- }
- function do_docker_logs {
- docker logs --details node-parachain 2>&1
- }
- function is_started {
- if [ "$(check_container_status)" == "true" ]; then
- echo "Container: node-parachain RUNNING";
- echo "Check Docker logs"
- DOCKER_LOGS=$(do_docker_logs)
- if [[ ${DOCKER_LOGS} = *"🛸 PARACHAINS' RUNTIME UPGRADE TESTING COMPLETE 🛸"* ]];then
- echo "🛸 PARACHAINS' RUNTIME UPGRADE TESTING COMPLETE 🛸"
- return 0
- elif [[ ${DOCKER_LOGS} = *"🚧 PARACHAINS' RUNTIME UPGRADE TESTING FAILED 🚧"* ]];then
- echo "🚧 PARACHAINS' RUNTIME UPGRADE TESTING FAILED 🚧"
- return 1
- else
- echo "Message not found in logs output, repeating..."
- return 1
- fi
- else
- echo "Container node-parachain not RUNNING"
- echo "Halting all future checks"
- exit 1
- fi
- exit 0
- }
- while ! is_started; do
- echo "Waiting for special message in log files "
- sleep 30s
- counter=$(( $counter - 1 ))
- echo "Counter: $counter"
- if [ "$counter" -gt "0" ]; then
- continue
- else
- break
- fi
- done
- echo "Halting script"
- exit 0
- shell: bash
-
- - name: Collect Docker Logs
- if: success() || failure()
- uses: jwalton/gh-docker-logs@v2.2.0
- with:
- dest: './forkless-parachain-upgrade-nodata-logs.${{ matrix.features }}'
- images: 'node-parachain'
-
- - name: Show docker logs
- if: success() || failure()
- run: cat './forkless-parachain-upgrade-nodata-logs.${{ matrix.features }}/node-parachain.log'
-
- - name: Stop running containers
- if: always() # run this step always
- run: docker-compose -f ".docker/docker-compose-forkless.yml" -f ".docker/docker-compose.${{ matrix.network }}.yml" down
.github/workflows/forkless-update-nodata_v2.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/forkless-update-nodata_v2.yml
@@ -0,0 +1,167 @@
+
+
+# Controls when the action will run.
+on:
+ workflow_call:
+
+
+#Define Workflow variables
+env:
+ REPO_URL: ${{ github.server_url }}/${{ github.repository }}
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+ execution-marix:
+
+ name: Prepare execution matrix
+
+ runs-on: self-hosted-ci
+ outputs:
+ matrix: ${{ steps.create_matrix.outputs.matrix }}
+
+ steps:
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Create Execution matrix
+ uses: fabiocaccamo/create-matrix-action@v2
+ id: create_matrix
+ with:
+ matrix: |
+ network {opal}, runtime {opal}, features {opal-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}
+ network {quartz}, runtime {quartz}, features {quartz-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}
+ network {unique}, runtime {unique}, features {unique-runtime}, mainnet_branch {${{ env.UNIQUE_MAINNET_TAG }}}
+
+
+ forkless-update-nodata:
+ needs: execution-marix
+ # The type of runner that the job will run on
+ runs-on: [self-hosted-ci,large]
+
+ timeout-minutes: 1380
+
+ name: ${{ matrix.network }}
+
+ continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
+
+ strategy:
+ matrix:
+ include: ${{fromJson(needs.execution-marix.outputs.matrix)}}
+
+ steps:
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Generate ENV related extend file for docker-compose
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/docker-compose.tmp-forkless-nodata.j2
+ output_file: .docker/docker-compose.${{ matrix.network }}.yml
+ variables: |
+ REPO_URL=${{ github.server_url }}/${{ github.repository }}.git
+ RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
+ POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }}
+ POLKADOT_MAINNET_BRANCH=${{ env.POLKADOT_MAINNET_BRANCH }}
+ MAINNET_TAG=${{ matrix.mainnet_tag }}
+ MAINNET_BRANCH=${{ matrix.mainnet_branch }}
+ FEATURE=${{ matrix.features }}
+ RUNTIME=${{ matrix.runtime }}
+ BRANCH=${{ github.head_ref }}
+
+ - name: Show build configuration
+ run: cat .docker/docker-compose.${{ matrix.network }}.yml
+
+ - name: Generate launch-config-forkless-nodata.json
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/forkless-config/launch-config-forkless-nodata.j2
+ output_file: .docker/launch-config-forkless-nodata.json
+ variables: |
+ FEATURE=${{ matrix.features }}
+ RUNTIME=${{ matrix.runtime }}
+
+ - name: Show launch-config-forkless configuration
+ run: cat .docker/launch-config-forkless-nodata.json
+
+
+ - name: Build the stack
+ run: docker-compose -f ".docker/docker-compose-forkless.yml" -f ".docker/docker-compose.${{ matrix.network }}.yml" up -d --build --force-recreate --timeout 300
+
+ - name: Check if docker logs consist logs related to Runtime Upgrade testing.
+ if: success()
+ run: |
+ counter=160
+ function check_container_status {
+ docker inspect -f {{.State.Running}} node-parachain
+ }
+ function do_docker_logs {
+ docker logs --details node-parachain 2>&1
+ }
+ function is_started {
+ if [ "$(check_container_status)" == "true" ]; then
+ echo "Container: node-parachain RUNNING";
+ echo "Check Docker logs"
+ DOCKER_LOGS=$(do_docker_logs)
+ if [[ ${DOCKER_LOGS} = *"🛸 PARACHAINS' RUNTIME UPGRADE TESTING COMPLETE 🛸"* ]];then
+ echo "🛸 PARACHAINS' RUNTIME UPGRADE TESTING COMPLETE 🛸"
+ return 0
+ elif [[ ${DOCKER_LOGS} = *"🚧 PARACHAINS' RUNTIME UPGRADE TESTING FAILED 🚧"* ]];then
+ echo "🚧 PARACHAINS' RUNTIME UPGRADE TESTING FAILED 🚧"
+ return 1
+ else
+ echo "Message not found in logs output, repeating..."
+ return 1
+ fi
+ else
+ echo "Container node-parachain not RUNNING"
+ echo "Halting all future checks"
+ exit 1
+ fi
+ exit 0
+ }
+ while ! is_started; do
+ echo "Waiting for special message in log files "
+ sleep 30s
+ counter=$(( $counter - 1 ))
+ echo "Counter: $counter"
+ if [ "$counter" -gt "0" ]; then
+ continue
+ else
+ break
+ fi
+ done
+ echo "Halting script"
+ exit 0
+ shell: bash
+
+ - name: Collect Docker Logs
+ if: success() || failure()
+ uses: jwalton/gh-docker-logs@v2.2.0
+ with:
+ dest: './forkless-parachain-upgrade-nodata-logs.${{ matrix.features }}'
+ images: 'node-parachain'
+
+ - name: Show docker logs
+ if: success() || failure()
+ run: cat './forkless-parachain-upgrade-nodata-logs.${{ matrix.features }}/node-parachain.log'
+
+ - name: Stop running containers
+ if: always() # run this step always
+ run: docker-compose -f ".docker/docker-compose-forkless.yml" -f ".docker/docker-compose.${{ matrix.network }}.yml" down
.github/workflows/forkless.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/forkless.yml
@@ -0,0 +1,18 @@
+name: Nesting Forkless
+
+on:
+ workflow_call:
+
+jobs:
+
+ forkless-update-data:
+ name: with data
+ uses: ./.github/workflows/forkless-update-data_v2.yml
+
+ forkless-update-no-data:
+ name: no data
+ uses: ./.github/workflows/forkless-update-nodata_v2.yml
+
+ try-runtime:
+ name: try-runtime
+ uses: ./.github/workflows/try-runtime_v2.yml
.github/workflows/generate-execution-matrix.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/generate-execution-matrix.yml
@@ -0,0 +1,45 @@
+name: Prepare execution matrix
+
+on:
+ workflow_call:
+ # Map the workflow outputs to job outputs
+ outputs:
+ matrix_values:
+ description: "Matix output"
+ matrix: ${{ jobs.prepare-execution-matrix.outputs.matrix }}
+
+
+#concurrency:
+# group: ${{ github.workflow }}-${{ github.head_ref }}
+# cancel-in-progress: true
+
+
+jobs:
+ prepare-execution-matrix:
+ name: Generate output
+ runs-on: self-hosted-ci
+ # Map the job outputs to step outputs
+ outputs:
+ matrix: ${{ steps.create_matrix.outputs.matrix }}
+
+ steps:
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Create Execution matrix
+ uses: CertainLach/create-matrix-action@v3
+ id: create_matrix
+ with:
+ matrix: |
+ network {opal}, runtime {opal}, features {opal-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}, replica_from_address {${{ env.OPAL_REPLICA_FROM }}}
+ network {quartz}, runtime {quartz}, features {quartz-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}, replica_from_address {${{ env.QUARTZ_REPLICA_FROM }}}
+ network {unique}, runtime {unique}, features {unique-runtime}, mainnet_branch {${{ env.UNIQUE_MAINNET_TAG }}}, replica_from_address {${{ env.UNIQUE_REPLICA_FROM }}}
.github/workflows/market-test_v2.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/market-test_v2.yml
@@ -0,0 +1,192 @@
+name: market api tests
+
+# Controls when the action will run.
+on:
+ workflow_call:
+
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+
+ market_test:
+ # The type of runner that the job will run on
+ runs-on: [self-hosted-ci,large]
+ timeout-minutes: 1380
+
+ name: ${{ matrix.network }}
+
+ continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
+
+ strategy:
+ matrix:
+ include:
+ - network: "opal"
+ features: "opal-runtime"
+# - network: "quartz"
+# features: "quartz-runtime"
+# - network: "unique"
+# features: "unique-runtime"
+
+ steps:
+
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - name: Checkout master repo
+ uses: actions/checkout@master
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Checkout Market e2e tests
+ uses: actions/checkout@v3
+ with:
+ repository: 'UniqueNetwork/market-e2e-tests'
+ ssh-key: ${{ secrets.GH_PAT }}
+ path: 'qa-tests'
+ ref: 'ci_test_v2'
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Copy qa-tests/.env.example to qa-tests/.env
+ working-directory: qa-tests
+ run: cp .env.docker .env
+
+ - name: Generate ENV related extend file for docker-compose
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: qa-tests/.docker/docker-compose.tmp-market.j2
+ output_file: qa-tests/.docker/docker-compose.${{ matrix.network }}.yml
+ variables: |
+ REPO_URL=${{ github.server_url }}/${{ github.repository }}.git
+ RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
+ POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }}
+ FEATURE=${{ matrix.features }}
+ BRANCH=${{ github.head_ref }}
+
+
+ - name: Show build configuration
+ working-directory: qa-tests
+ run: cat .docker/docker-compose.${{ matrix.network }}.yml
+
+ - name: Start node-parachain
+ working-directory: qa-tests
+ run: docker-compose -f ".docker/docker-compose.market.yml" -f ".docker/docker-compose.${{ matrix.network }}.yml" up -d --build --remove-orphans --force-recreate node-parachain
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 16.17
+
+ - name: Setup TypeScript
+ working-directory: qa-tests
+ run: |
+ npm install -g ts-node
+ npm install
+
+ - name: Copy qa-tests/.env.docker to qa-tests/.env
+ working-directory: qa-tests
+ run: |
+ rm -rf .env
+ cp .env.docker .env
+
+ - name: Wait for chain up and running
+ working-directory: tests
+ run: |
+ yarn install
+ node scripts/readyness.js
+ echo "Ready to start tests"
+
+ - name: Show content of .env file and Generate accounts
+ working-directory: qa-tests
+ run: |
+ cat .env
+ ts-node ./src/scripts/create-market-accounts.ts
+
+ - name: Copy qa-tests/.env to qa-tests/.env.docker
+ working-directory: qa-tests
+ run: |
+ rm -rf .env.docker
+ cp .env .env.docker
+
+ - name: Get chain logs
+ if: always() # run this step always
+ run: |
+ docker exec node-parachain cat /polkadot-launch/9944.log
+ docker exec node-parachain cat /polkadot-launch/9945.log
+ docker exec node-parachain cat /polkadot-launch/alice.log
+ docker exec node-parachain cat /polkadot-launch/eve.log
+ docker exec node-parachain cat /polkadot-launch/dave.log
+ docker exec node-parachain cat /polkadot-launch/charlie.log
+
+ - name: Deploy contracts
+ run: |
+ cd qa-tests
+ ts-node ./src/scripts/deploy-contract.ts
+
+ - name: Timeout for debug
+ if: failure()
+ run: sleep 300s
+
+ - name: Import test data
+ working-directory: qa-tests
+ run: ts-node ./src/scripts/create-test-collections.ts
+
+ - name: Show content of qa-test .env
+ working-directory: qa-tests
+ run: cat .env
+
+ - name: Read qa -test .env file Before market start
+ uses: xom9ikk/dotenv@v1.0.2
+ with:
+ path: qa-tests/
+
+
+ - name: local-market:start
+ run: docker-compose -f "qa-tests/.docker/docker-compose.market.yml" -f "qa-tests/.docker/docker-compose.${{ matrix.network }}.yml" up -d --build
+
+ - name: Wait for market readyness
+ working-directory: qa-tests
+ run: src/scripts/wait-market-ready.sh
+ shell: bash
+
+ - name: Install dependecies
+ working-directory: qa-tests
+ run: |
+ npm ci
+ npm install -D @playwright/test
+ npx playwright install-deps
+ npx playwright install
+
+ - name: Show content of qa-test .env
+ working-directory: qa-tests
+ run: cat .env
+
+ - name: Test API interface
+ working-directory: qa-tests
+ run: |
+ npx playwright test --workers=8 --quiet .*.api.test.ts --reporter=github --config playwright.config.ts
+
+ - name: Timeout for debug
+ if: failure()
+ run: sleep 300s
+
+ - name: Stop running containers
+ if: always() # run this step always
+ run: docker-compose -f "qa-tests/.docker/docker-compose.market.yml" -f "qa-tests/.docker/docker-compose.${{ matrix.network }}.yml" down --volumes
+# run: docker-compose -f "qa-tests/.docker/docker-compose.market.yml" -f "qa-tests/.docker/docker-compose.${{ matrix.network }}.yml" down
+
+ - name: Remove builder cache
+ if: always() # run this step always
+ run: |
+ docker builder prune -f
+ docker system prune -f
+
+ - name: Clean Workspace
+ if: always()
+ uses: AutoModality/action-clean@v1.1.0
+
+
+
+
.github/workflows/node-only-update_v2.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/node-only-update_v2.yml
@@ -0,0 +1,271 @@
+name: nodes-only update
+
+# Controls when the action will run.
+on:
+ workflow_call:
+#Define Workflow variables
+env:
+ REPO_URL: ${{ github.server_url }}/${{ github.repository }}
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+
+ execution-marix:
+
+ name: execution matrix
+
+ runs-on: self-hosted-ci
+ outputs:
+ matrix: ${{ steps.create_matrix.outputs.matrix }}
+
+ steps:
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Create Execution matrix
+ uses: fabiocaccamo/create-matrix-action@v2
+ id: create_matrix
+ with:
+ matrix: |
+ network {opal}, runtime {opal}, features {opal-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}
+ network {quartz}, runtime {quartz}, features {quartz-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}
+ network {unique}, runtime {unique}, features {unique-runtime}, mainnet_branch {${{ env.UNIQUE_MAINNET_TAG }}}
+
+
+
+ forkless-update-nodata:
+ needs: execution-marix
+ # The type of runner that the job will run on
+ runs-on: [self-hosted-ci,large]
+
+
+
+ timeout-minutes: 1380
+
+ name: ${{ matrix.network }}
+
+ continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
+
+ strategy:
+ matrix:
+ include: ${{fromJson(needs.prepare-execution-marix.outputs.matrix)}}
+
+ steps:
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Generate ENV related extend file for docker-compose
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/docker-compose.tmp-node.j2
+ output_file: .docker/docker-compose.node.${{ matrix.network }}.yml
+ variables: |
+ REPO_URL=${{ github.server_url }}/${{ github.repository }}.git
+ RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
+ POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }}
+ POLKADOT_MAINNET_BRANCH=${{ env.POLKADOT_MAINNET_BRANCH }}
+ MAINNET_TAG=${{ matrix.mainnet_tag }}
+ MAINNET_BRANCH=${{ matrix.mainnet_branch }}
+ FEATURE=${{ matrix.features }}
+ RUNTIME=${{ matrix.runtime }}
+ BRANCH=${{ github.head_ref }}
+
+ - name: Show build configuration
+ run: cat .docker/docker-compose.node.${{ matrix.network }}.yml
+
+ - name: Generate launch-config-forkless-nodata.json
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/forkless-config/launch-config-forkless-nodata.j2
+ output_file: .docker/launch-config-forkless-nodata.json
+ variables: |
+ FEATURE=${{ matrix.features }}
+ RUNTIME=${{ matrix.runtime }}
+
+ - name: Show launch-config-forkless configuration
+ run: cat .docker/launch-config-forkless-nodata.json
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 16
+
+ - name: Build the stack
+ run: docker-compose -f ".docker/docker-compose-forkless.yml" -f ".docker/docker-compose.node.${{ matrix.network }}.yml" up -d --build --remove-orphans --force-recreate --timeout 300
+
+ # 🚀 POLKADOT LAUNCH COMPLETE 🚀
+ - name: Check if docker logs consist messages related to testing of Node Parachain Upgrade.
+ if: success()
+ run: |
+ counter=160
+ function check_container_status {
+ docker inspect -f {{.State.Running}} node-parachain
+ }
+ function do_docker_logs {
+ docker logs --details node-parachain 2>&1
+ }
+ function is_started {
+ if [ "$(check_container_status)" == "true" ]; then
+ echo "Container: node-parachain RUNNING";
+ echo "Check Docker logs"
+ DOCKER_LOGS=$(do_docker_logs)
+ if [[ ${DOCKER_LOGS} = *"POLKADOT LAUNCH COMPLETE"* ]];then
+ echo "🚀 POLKADOT LAUNCH COMPLETE 🚀"
+ return 0
+ else
+ echo "Message not found in logs output, repeating..."
+ return 1
+ fi
+ else
+ echo "Container node-parachain NOT RUNNING"
+ echo "Halting all future checks"
+ exit 1
+ fi
+ echo "something goes wrong"
+ exit 1
+ }
+ while ! is_started; do
+ echo "Waiting for special message in log files "
+ sleep 30s
+ counter=$(( $counter - 1 ))
+ echo "Counter: $counter"
+ if [ "$counter" -gt "0" ]; then
+ continue
+ else
+ break
+ fi
+ done
+ echo "Halting script"
+ exit 0
+ shell: bash
+
+ - name: Run tests before Node Parachain upgrade
+ working-directory: tests
+ run: |
+ yarn install
+ yarn add mochawesome
+ node scripts/readyness.js
+ echo "Ready to start tests"
+ yarn polkadot-types
+ NOW=$(date +%s) && yarn test --reporter mochawesome --reporter-options reportFilename=test-${NOW}
+ env:
+ RPC_URL: http://127.0.0.1:9933/
+
+ - name: Test Report Before Node upgrade
+ uses: phoenix-actions/test-reporting@v8
+ id: test-report-before
+ if: success() || failure() # run this step even if previous step failed
+ with:
+ name: Tests before node upgrade ${{ matrix.network }} # Name of the check run which will be created
+ path: tests/mochawesome-report/test-*.json # Path to test results
+ reporter: mochawesome-json
+ fail-on-error: 'false'
+
+ - name: Send SIGUSR1 to polkadotlaunch process
+ if: success() || failure()
+ run: |
+ #Get PID of polkadot-launch
+ PID=$(docker exec node-parachain pidof 'polkadot-launch')
+ echo "Polkadot-launch PID: $PID"
+ #Send SIGUSR1 signal to $PID
+ docker exec node-parachain kill -SIGUSR1 ${PID}
+
+ # 🌗 All parachain collators restarted with the new binaries.
+ - name: Check if docker logs consist messages related to testing of Node Parachain Upgrade.
+ if: success()
+ run: |
+ counter=160
+ function check_container_status {
+ docker inspect -f {{.State.Running}} node-parachain
+ }
+ function do_docker_logs {
+ docker logs --details node-parachain 2>&1
+ }
+ function is_started {
+ if [ "$(check_container_status)" == "true" ]; then
+ echo "Container: node-parachain RUNNING";
+ echo "Check Docker logs"
+ DOCKER_LOGS=$(do_docker_logs)
+ if [[ ${DOCKER_LOGS} = *"All parachain collators restarted with the new binaries."* ]];then
+ echo "🌗 All parachain collators restarted with the new binaries."
+ return 0
+ else
+ echo "Message not found in logs output, repeating..."
+ return 1
+ fi
+ else
+ echo "Container node-parachain NOT RUNNING"
+ echo "Halting all future checks"
+ exit 1
+ fi
+ echo "something goes wrong"
+ exit 1
+ }
+ while ! is_started; do
+ echo "Waiting for special message in log files "
+ sleep 30s
+ counter=$(( $counter - 1 ))
+ echo "Counter: $counter"
+ if [ "$counter" -gt "0" ]; then
+ continue
+ else
+ break
+ fi
+ done
+ echo "Halting script"
+ exit 0
+ shell: bash
+
+ - name: Run tests after Node Parachain upgrade
+ working-directory: tests
+ run: |
+ yarn install
+ yarn add mochawesome
+ node scripts/readyness.js
+ echo "Ready to start tests"
+ yarn polkadot-types
+ NOW=$(date +%s) && yarn test --reporter mochawesome --reporter-options reportFilename=test-${NOW}
+ env:
+ RPC_URL: http://127.0.0.1:9933/
+
+ - name: Test Report After Node upgrade
+ uses: phoenix-actions/test-reporting@v8
+ id: test-report-after
+ if: success() || failure() # run this step even if previous step failed
+ with:
+ name: Tests after node upgrade ${{ matrix.network }} # Name of the check run which will be created
+ path: tests/mochawesome-report/test-*.json # Path to test results
+ reporter: mochawesome-json
+ fail-on-error: 'false'
+
+
+ - name: Stop running containers
+ if: always() # run this step always
+ run: docker-compose -f ".docker/docker-compose-forkless.yml" -f ".docker/docker-compose.node.${{ matrix.network }}.yml" down --volumes
+
+ - name: Remove builder cache
+ if: always() # run this step always
+ run: |
+ docker builder prune -f
+ docker system prune -f
+
+ - name: Clean Workspace
+ if: always()
+ uses: AutoModality/action-clean@v1.1.0
.github/workflows/nodes-only-update.ymldiffbeforeafterboth--- a/.github/workflows/nodes-only-update.yml
+++ /dev/null
@@ -1,301 +0,0 @@
-name: nodes-only update
-
-# Controls when the action will run.
-on:
- # Triggers the workflow on push or pull request events but only for the master branch
- pull_request:
- branches:
- - master
- types:
- - opened
- - reopened
- - synchronize #commit(s) pushed to the pull request
- - ready_for_review
-
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-#Define Workflow variables
-env:
- REPO_URL: ${{ github.server_url }}/${{ github.repository }}
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref }}
- cancel-in-progress: true
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
-
- prepare-execution-marix:
-
- name: Prepare execution matrix
-
- runs-on: self-hosted-ci
- outputs:
- matrix: ${{ steps.create_matrix.outputs.matrix }}
-
- steps:
-
- - name: Clean Workspace
- uses: AutoModality/action-clean@v1.1.0
-
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v3
- with:
- ref: ${{ github.head_ref }} #Checking out head commit
-
- - name: Read .env file
- uses: xom9ikk/dotenv@v1.0.2
-
- - name: Create Execution matrix
- uses: fabiocaccamo/create-matrix-action@v2
- id: create_matrix
- with:
- matrix: |
- network {opal}, runtime {opal}, features {opal-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}
- network {quartz}, runtime {quartz}, features {quartz-runtime}, mainnet_branch {${{ env.QUARTZ_MAINNET_TAG }}}
- network {unique}, runtime {unique}, features {unique-runtime}, mainnet_branch {${{ env.UNIQUE_MAINNET_TAG }}}
-
-
-
- forkless-update-nodata:
- needs: prepare-execution-marix
- # The type of runner that the job will run on
- runs-on: [self-hosted-ci,large]
-
-
-
- timeout-minutes: 1380
-
- name: ${{ matrix.network }}
-
- continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
-
- strategy:
- matrix:
- include: ${{fromJson(needs.prepare-execution-marix.outputs.matrix)}}
-
-
- steps:
- - name: Skip if pull request is in Draft
- # `if: github.event.pull_request.draft == true` should be kept here, at
- # the step level, rather than at the job level. The latter is not
- # recommended because when the PR is moved from "Draft" to "Ready to
- # review" the workflow will immediately be passing (since it was skipped),
- # even though it hasn't actually ran, since it takes a few seconds for
- # the workflow to start. This is also disclosed in:
- # https://github.community/t/dont-run-actions-on-draft-pull-requests/16817/17
- # That scenario would open an opportunity for the check to be bypassed:
- # 1. Get your PR approved
- # 2. Move it to Draft
- # 3. Push whatever commits you want
- # 4. Move it to "Ready for review"; now the workflow is passing (it was
- # skipped) and "Check reviews" is also passing (it won't be updated
- # until the workflow is finished)
- if: github.event.pull_request.draft == true
- run: exit 1
-
- - name: Clean Workspace
- uses: AutoModality/action-clean@v1.1.0
-
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v3
- with:
- ref: ${{ github.head_ref }} #Checking out head commit
-
- - name: Read .env file
- uses: xom9ikk/dotenv@v1.0.2
-
- - name: Generate ENV related extend file for docker-compose
- uses: cuchi/jinja2-action@v1.2.0
- with:
- template: .docker/docker-compose.tmp-node.j2
- output_file: .docker/docker-compose.node.${{ matrix.network }}.yml
- variables: |
- REPO_URL=${{ github.server_url }}/${{ github.repository }}.git
- RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
- POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }}
- POLKADOT_MAINNET_BRANCH=${{ env.POLKADOT_MAINNET_BRANCH }}
- MAINNET_TAG=${{ matrix.mainnet_tag }}
- MAINNET_BRANCH=${{ matrix.mainnet_branch }}
- FEATURE=${{ matrix.features }}
- RUNTIME=${{ matrix.runtime }}
- BRANCH=${{ github.head_ref }}
-
- - name: Show build configuration
- run: cat .docker/docker-compose.node.${{ matrix.network }}.yml
-
- - name: Generate launch-config-forkless-nodata.json
- uses: cuchi/jinja2-action@v1.2.0
- with:
- template: .docker/forkless-config/launch-config-forkless-nodata.j2
- output_file: .docker/launch-config-forkless-nodata.json
- variables: |
- FEATURE=${{ matrix.features }}
- RUNTIME=${{ matrix.runtime }}
-
- - name: Show launch-config-forkless configuration
- run: cat .docker/launch-config-forkless-nodata.json
-
- - uses: actions/setup-node@v3
- with:
- node-version: 16
-
- - name: Build the stack
- run: docker-compose -f ".docker/docker-compose-forkless.yml" -f ".docker/docker-compose.node.${{ matrix.network }}.yml" up -d --build --remove-orphans --force-recreate --timeout 300
-
- # 🚀 POLKADOT LAUNCH COMPLETE 🚀
- - name: Check if docker logs consist messages related to testing of Node Parachain Upgrade.
- if: success()
- run: |
- counter=160
- function check_container_status {
- docker inspect -f {{.State.Running}} node-parachain
- }
- function do_docker_logs {
- docker logs --details node-parachain 2>&1
- }
- function is_started {
- if [ "$(check_container_status)" == "true" ]; then
- echo "Container: node-parachain RUNNING";
- echo "Check Docker logs"
- DOCKER_LOGS=$(do_docker_logs)
- if [[ ${DOCKER_LOGS} = *"POLKADOT LAUNCH COMPLETE"* ]];then
- echo "🚀 POLKADOT LAUNCH COMPLETE 🚀"
- return 0
- else
- echo "Message not found in logs output, repeating..."
- return 1
- fi
- else
- echo "Container node-parachain NOT RUNNING"
- echo "Halting all future checks"
- exit 1
- fi
- echo "something goes wrong"
- exit 1
- }
- while ! is_started; do
- echo "Waiting for special message in log files "
- sleep 30s
- counter=$(( $counter - 1 ))
- echo "Counter: $counter"
- if [ "$counter" -gt "0" ]; then
- continue
- else
- break
- fi
- done
- echo "Halting script"
- exit 0
- shell: bash
-
- - name: Run tests before Node Parachain upgrade
- working-directory: tests
- run: |
- yarn install
- yarn add mochawesome
- echo "Ready to start tests"
- NOW=$(date +%s) && yarn test --reporter mochawesome --reporter-options reportFilename=test-${NOW}
- env:
- RPC_URL: http://127.0.0.1:9933/
-
- - name: Test Report Before Node upgrade
- uses: phoenix-actions/test-reporting@v8
- id: test-report-before
- if: success() || failure() # run this step even if previous step failed
- with:
- name: Tests before node upgrade ${{ matrix.network }} # Name of the check run which will be created
- path: tests/mochawesome-report/test-*.json # Path to test results
- reporter: mochawesome-json
- fail-on-error: 'false'
-
- - name: Send SIGUSR1 to polkadotlaunch process
- if: success() || failure()
- run: |
- #Get PID of polkadot-launch
- PID=$(docker exec node-parachain pidof 'polkadot-launch')
- echo "Polkadot-launch PID: $PID"
- #Send SIGUSR1 signal to $PID
- docker exec node-parachain kill -SIGUSR1 ${PID}
-
- # 🌗 All parachain collators restarted with the new binaries.
- - name: Check if docker logs consist messages related to testing of Node Parachain Upgrade.
- if: success()
- run: |
- counter=160
- function check_container_status {
- docker inspect -f {{.State.Running}} node-parachain
- }
- function do_docker_logs {
- docker logs --details node-parachain 2>&1
- }
- function is_started {
- if [ "$(check_container_status)" == "true" ]; then
- echo "Container: node-parachain RUNNING";
- echo "Check Docker logs"
- DOCKER_LOGS=$(do_docker_logs)
- if [[ ${DOCKER_LOGS} = *"All parachain collators restarted with the new binaries."* ]];then
- echo "🌗 All parachain collators restarted with the new binaries."
- return 0
- else
- echo "Message not found in logs output, repeating..."
- return 1
- fi
- else
- echo "Container node-parachain NOT RUNNING"
- echo "Halting all future checks"
- exit 1
- fi
- echo "something goes wrong"
- exit 1
- }
- while ! is_started; do
- echo "Waiting for special message in log files "
- sleep 30s
- counter=$(( $counter - 1 ))
- echo "Counter: $counter"
- if [ "$counter" -gt "0" ]; then
- continue
- else
- break
- fi
- done
- echo "Halting script"
- exit 0
- shell: bash
-
- - name: Run tests after Node Parachain upgrade
- working-directory: tests
- run: |
- yarn install
- yarn add mochawesome
- echo "Ready to start tests"
- NOW=$(date +%s) && yarn test --reporter mochawesome --reporter-options reportFilename=test-${NOW}
- env:
- RPC_URL: http://127.0.0.1:9933/
-
- - name: Test Report After Node upgrade
- uses: phoenix-actions/test-reporting@v8
- id: test-report-after
- if: success() || failure() # run this step even if previous step failed
- with:
- name: Tests after node upgrade ${{ matrix.network }} # Name of the check run which will be created
- path: tests/mochawesome-report/test-*.json # Path to test results
- reporter: mochawesome-json
- fail-on-error: 'false'
-
-
- - name: Stop running containers
- if: always() # run this step always
- run: docker-compose -f ".docker/docker-compose-forkless.yml" -f ".docker/docker-compose.node.${{ matrix.network }}.yml" down --volumes
-
- - name: Remove builder cache
- if: always() # run this step always
- run: |
- docker builder prune -f
- docker system prune -f
-
- - name: Clean Workspace
- if: always()
- uses: AutoModality/action-clean@v1.1.0
.github/workflows/test_codestyle_v2.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/test_codestyle_v2.yml
@@ -0,0 +1,20 @@
+name: yarn eslint
+
+on:
+ workflow_call:
+
+jobs:
+ code_style:
+ runs-on: [ self-hosted-ci ]
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 16
+
+ - name: Install modules
+ run: cd tests && yarn
+ - name: Run ESLint
+ run: cd tests && yarn eslint --ext .ts,.js src/
.github/workflows/tests_codestyle.ymldiffbeforeafterboth--- a/.github/workflows/tests_codestyle.yml
+++ /dev/null
@@ -1,49 +0,0 @@
-name: yarn eslint
-
-on:
- pull_request:
- branches:
- - develop
- types:
- - opened
- - reopened
- - synchronize
- - ready_for_review
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref }}
- cancel-in-progress: true
-
-jobs:
- code_style:
- runs-on: self-hosted-ci
-
- steps:
- - name: Skip if pull request is in Draft
- # `if: github.event.pull_request.draft == true` should be kept here, at
- # the step level, rather than at the job level. The latter is not
- # recommended because when the PR is moved from "Draft" to "Ready to
- # review" the workflow will immediately be passing (since it was skipped),
- # even though it hasn't actually ran, since it takes a few seconds for
- # the workflow to start. This is also disclosed in:
- # https://github.community/t/dont-run-actions-on-draft-pull-requests/16817/17
- # That scenario would open an opportunity for the check to be bypassed:
- # 1. Get your PR approved
- # 2. Move it to Draft
- # 3. Push whatever commits you want
- # 4. Move it to "Ready for review"; now the workflow is passing (it was
- # skipped) and "Check reviews" is also passing (it won't be updated
- # until the workflow is finished)
- if: github.event.pull_request.draft == true
- run: exit 1
-
- - uses: actions/checkout@v3
-
- - uses: actions/setup-node@v3
- with:
- node-version: 16
-
- - name: Install modules
- run: cd tests && yarn
- - name: Run ESLint
- run: cd tests && yarn eslint --ext .ts,.js src/
.github/workflows/try-runtime.ymldiffbeforeafterboth--- a/.github/workflows/try-runtime.yml
+++ /dev/null
@@ -1,108 +0,0 @@
-name: try-runtime
-
-# Controls when the action will run.
-on:
- # Triggers the workflow on push or pull request events but only for the master branch
- pull_request:
- branches:
- - master
- types:
- - opened
- - reopened
- - synchronize #commit(s) pushed to the pull request
- - ready_for_review
-
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-#Define Workflow variables
-env:
- REPO_URL: ${{ github.server_url }}/${{ github.repository }}
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref }}
- cancel-in-progress: true
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
- try-runtime:
- # The type of runner that the job will run on
- runs-on: self-hosted-ci
-
- name: ${{ matrix.network }}
-
- continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
-
- strategy:
- matrix:
- include:
- - network: opal
- features: try-runtime,opal-runtime
- replica_from_address: wss://eu-ws-opal.unique.network:443
- - network: quartz
- features: try-runtime,quartz-runtime
- replica_from_address: wss://eu-ws-quartz.unique.network:443
- - network: unique
- features: try-runtime,unique-runtime
- replica_from_address: wss://eu-ws.unique.network:443
-
- steps:
- - name: Skip if pull request is in Draft
- # `if: github.event.pull_request.draft == true` should be kept here, at
- # the step level, rather than at the job level. The latter is not
- # recommended because when the PR is moved from "Draft" to "Ready to
- # review" the workflow will immediately be passing (since it was skipped),
- # even though it hasn't actually ran, since it takes a few seconds for
- # the workflow to start. This is also disclosed in:
- # https://github.community/t/dont-run-actions-on-draft-pull-requests/16817/17
- # That scenario would open an opportunity for the check to be bypassed:
- # 1. Get your PR approved
- # 2. Move it to Draft
- # 3. Push whatever commits you want
- # 4. Move it to "Ready for review"; now the workflow is passing (it was
- # skipped) and "Check reviews" is also passing (it won't be updated
- # until the workflow is finished)
- if: github.event.pull_request.draft == true
- run: exit 1
-
-
- - name: Clean Workspace
- uses: AutoModality/action-clean@v1.1.0
-
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v3
- with:
- ref: ${{ github.head_ref }} #Checking out head commit
-
- - name: Read .env file
- uses: xom9ikk/dotenv@v1.0.2
-
- - name: Generate ENV related extend file for docker-compose
- uses: cuchi/jinja2-action@v1.2.0
- with:
- template: .docker/docker-compose.try-runtime.j2
- output_file: .docker/docker-compose.try-runtime.${{ matrix.network }}.yml
- variables: |
- RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
- FEATURE=${{ matrix.features }}
- REPLICA_FROM=${{ matrix.replica_from_address }}
-
- - name: Show build configuration
- run: cat .docker/docker-compose.try-runtime.${{ matrix.network }}.yml
-
- - name: Build the stack
- run: docker-compose -f ".docker/docker-compose-try-runtime.yml" -f ".docker/docker-compose.try-runtime.${{ matrix.network }}.yml" up --build --force-recreate --timeout 300 --remove-orphans --exit-code-from try-runtime
-
- - name: Collect Docker Logs
- if: success() || failure()
- uses: jwalton/gh-docker-logs@v2.2.0
- with:
- dest: './try-runtime-logs.${{ matrix.network }}'
- images: 'try-runtime'
-
- - name: Show docker logs
- run: cat './try-runtime-logs.${{ matrix.network }}/try-runtime.log'
-
- - name: Stop running containers
- if: always() # run this step always
- run: docker-compose -f ".docker/docker-compose-try-runtime.yml" -f ".docker/docker-compose.try-runtime.${{ matrix.network }}.yml" down
.github/workflows/try-runtime_v2.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/try-runtime_v2.yml
@@ -0,0 +1,69 @@
+on:
+ workflow_call:
+
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+ try-runtime:
+ # The type of runner that the job will run on
+ runs-on: self-hosted-ci
+
+ name: ${{ matrix.network }}
+
+ continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
+
+ strategy:
+ matrix:
+ include:
+ - network: opal
+ features: opal-runtime
+ replica_from_address: wss://eu-ws-opal.unique.network:443
+ - network: quartz
+ features: quartz-runtime
+ replica_from_address: wss://eu-ws-quartz.unique.network:443
+ - network: unique
+ features: unique-runtime
+ replica_from_address: wss://eu-ws.unique.network:443
+
+ steps:
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Generate ENV related extend file for docker-compose
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/docker-compose.try-runtime.j2
+ output_file: .docker/docker-compose.try-runtime.${{ matrix.network }}.yml
+ variables: |
+ RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
+ FEATURE=${{ matrix.features }}
+ REPLICA_FROM=${{ matrix.replica_from_address }}
+
+ - name: Show build configuration
+ run: cat .docker/docker-compose.try-runtime.${{ matrix.network }}.yml
+
+ - name: Build the stack
+ run: docker-compose -f ".docker/docker-compose-try-runtime.yml" -f ".docker/docker-compose.try-runtime.${{ matrix.network }}.yml" up --build --force-recreate --timeout 300 --remove-orphans --exit-code-from try-runtime
+
+ - name: Collect Docker Logs
+ if: success() || failure()
+ uses: jwalton/gh-docker-logs@v2.2.0
+ with:
+ dest: './try-runtime-logs.${{ matrix.network }}'
+ images: 'try-runtime'
+
+ - name: Show docker logs
+ run: cat './try-runtime-logs.${{ matrix.network }}/try-runtime.log'
+
+ - name: Stop running containers
+ if: always() # run this step always
+ run: docker-compose -f ".docker/docker-compose-try-runtime.yml" -f ".docker/docker-compose.try-runtime.${{ matrix.network }}.yml" down
.github/workflows/unit-test.ymldiffbeforeafterboth--- a/.github/workflows/unit-test.yml
+++ /dev/null
@@ -1,84 +0,0 @@
-name: unit tests
-
-# Controls when the action will run.
-on:
- # Triggers the workflow on push or pull request events but only for the master branch
- pull_request:
- branches:
- - develop
- - master
- types:
- - opened
- - reopened
- - synchronize #commit(s) pushed to the pull request
- - ready_for_review
-
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref }}
- cancel-in-progress: true
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
-
- unit_tests:
- # The type of runner that the job will run on
- runs-on: [self-hosted-ci,medium]
- timeout-minutes: 1380
-
- name: ${{ github.base_ref }}
-
- continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
-
-
- steps:
- - name: Skip if pull request is in Draft
- # `if: github.event.pull_request.draft == true` should be kept here, at
- # the step level, rather than at the job level. The latter is not
- # recommended because when the PR is moved from "Draft" to "Ready to
- # review" the workflow will immediately be passing (since it was skipped),
- # even though it hasn't actually ran, since it takes a few seconds for
- # the workflow to start. This is also disclosed in:
- # https://github.community/t/dont-run-actions-on-draft-pull-requests/16817/17
- # That scenario would open an opportunity for the check to be bypassed:
- # 1. Get your PR approved
- # 2. Move it to Draft
- # 3. Push whatever commits you want
- # 4. Move it to "Ready for review"; now the workflow is passing (it was
- # skipped) and "Check reviews" is also passing (it won't be updated
- # until the workflow is finished)
- if: github.event.pull_request.draft == true
- run: exit 1
-
- - name: Clean Workspace
- uses: AutoModality/action-clean@v1.1.0
-
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v3
- with:
- ref: ${{ github.head_ref }} #Checking out head commit
-
- - name: Read .env file
- uses: xom9ikk/dotenv@v1.0.2
-
- - name: Generate ENV related extend file for docker-compose
- uses: cuchi/jinja2-action@v1.2.0
- with:
- template: .docker/docker-compose.tmp-unit.j2
- output_file: .docker/docker-compose.unit.yml
- variables: |
- RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
- FEATURE=${{ matrix.features }}
-
-
- - name: Show build configuration
- run: cat .docker/docker-compose.unit.yml
-
- - name: Build the stack
- run: docker-compose -f ".docker/docker-compose-dev.yaml" -f ".docker/docker-compose.unit.yml" up --build --force-recreate --timeout 300 --remove-orphans --exit-code-from node-dev
-
- - name: Stop running containers
- if: always() # run this step always
- run: docker-compose -f ".docker/docker-compose-dev.yaml" -f ".docker/docker-compose.unit.yml" down
.github/workflows/unit-test_v2.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/unit-test_v2.yml
@@ -0,0 +1,51 @@
+name: unit tests
+
+# Controls when the action will run.
+on:
+ # Triggers the workflow on push or pull request events but only for the master branch
+ workflow_call:
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+
+ unit_tests:
+ # The type of runner that the job will run on
+ runs-on: [self-hosted-ci,medium]
+ timeout-minutes: 1380
+
+ name: ${{ github.base_ref }}
+
+ continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
+
+
+ steps:
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Generate ENV related extend file for docker-compose
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/docker-compose.tmp-unit.j2
+ output_file: .docker/docker-compose.unit.yml
+ variables: |
+ RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
+
+
+ - name: Show build configuration
+ run: cat .docker/docker-compose.unit.yml
+
+ - name: Build the stack
+ run: docker-compose -f ".docker/docker-compose-dev.yaml" -f ".docker/docker-compose.unit.yml" up --build --force-recreate --timeout 300 --remove-orphans --exit-code-from node-dev
+
+ - name: Stop running containers
+ if: always() # run this step always
+ run: docker-compose -f ".docker/docker-compose-dev.yaml" -f ".docker/docker-compose.unit.yml" down
.github/workflows/xcm-testnet-build.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/xcm-testnet-build.yml
@@ -0,0 +1,151 @@
+name: xcm-testnet-build
+
+# Controls when the action will run.
+on:
+ workflow_call:
+
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+#Define Workflow variables
+env:
+ REPO_URL: ${{ github.server_url }}/${{ github.repository }}
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+
+ prepare-execution-marix:
+
+ name: Prepare execution matrix
+
+ runs-on: [XL]
+ outputs:
+ matrix: ${{ steps.create_matrix.outputs.matrix }}
+
+ steps:
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Create Execution matrix
+ uses: fabiocaccamo/create-matrix-action@v2
+ id: create_matrix
+ with:
+ matrix: |
+ network {opal}, runtime {opal}, features {opal-runtime}, acala_version {${{ env.ACALA_BUILD_BRANCH }}}, moonbeam_version {${{ env.MOONBEAM_BUILD_BRANCH }}}, cumulus_version {${{ env.WESTMINT_BUILD_BRANCH }}}
+ network {quartz}, runtime {quartz}, features {quartz-runtime}, acala_version {${{ env.KARURA_BUILD_BRANCH }}}, moonbeam_version {${{ env.MOONRIVER_BUILD_BRANCH }}}, cumulus_version {${{ env.STATEMINE_BUILD_BRANCH }}}
+ network {unique}, runtime {unique}, features {unique-runtime}, acala_version {${{ env.ACALA_BUILD_BRANCH }}}, moonbeam_version {${{ env.MOONBEAM_BUILD_BRANCH }}}, cumulus_version {${{ env.STATEMINT_BUILD_BRANCH }}}
+
+ xcm-build:
+
+ needs: prepare-execution-marix
+ # The type of runner that the job will run on
+ runs-on: [XL]
+
+ timeout-minutes: 600
+
+ name: ${{ matrix.network }}
+
+ continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
+
+ strategy:
+ matrix:
+ include: ${{fromJson(needs.prepare-execution-marix.outputs.matrix)}}
+
+ steps:
+ - name: Skip if pull request is in Draft
+ if: github.event.pull_request.draft == true
+ run: exit 1
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Generate ENV related extend Dockerfile file
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/Dockerfile-xcm.j2
+ output_file: .docker/Dockerfile-xcm.${{ matrix.network }}.yml
+ variables: |
+ RUST_TOOLCHAIN=${{ env.RUST_TOOLCHAIN }}
+ NETWORK=${{ matrix.network }}
+ POLKADOT_BUILD_BRANCH=${{ env.POLKADOT_BUILD_BRANCH }}
+ POLKADOT_LAUNCH_BRANCH=${{ env.POLKADOT_LAUNCH_BRANCH }}
+ FEATURE=${{ matrix.features }}
+ RUNTIME=${{ matrix.runtime }}
+ BRANCH=${{ github.head_ref }}
+ ACALA_BUILD_BRANCH=${{ matrix.acala_version }}
+ MOONBEAM_BUILD_BRANCH=${{ matrix.moonbeam_version }}
+ CUMULUS_BUILD_BRANCH=${{ matrix.cumulus_version }}
+
+ - name: Show build Dockerfile
+ run: cat .docker/Dockerfile-xcm.${{ matrix.network }}.yml
+
+ - name: Show launch-config-xcm-${{ matrix.network }} configuration
+ run: cat .docker/xcm-config/launch-config-xcm-${{ matrix.network }}.json
+
+ - name: Run find-and-replace to remove slashes from branch name
+ uses: mad9000/actions-find-and-replace-string@2
+ id: branchname
+ with:
+ source: ${{ github.head_ref }}
+ find: '/'
+ replace: '-'
+
+ - name: Log in to Docker Hub
+ uses: docker/login-action@v2.0.0
+ with:
+ username: ${{ secrets.CORE_DOCKERHUB_USERNAME }}
+ password: ${{ secrets.CORE_DOCKERHUB_TOKEN }}
+
+ - name: Pull acala docker image
+ run: docker pull uniquenetwork/builder-acala:${{ matrix.acala_version }}
+
+ - name: Pull moonbeam docker image
+ run: docker pull uniquenetwork/builder-moonbeam:${{ matrix.moonbeam_version }}
+
+ - name: Pull cumulus docker image
+ run: docker pull uniquenetwork/builder-cumulus:${{ matrix.cumulus_version }}
+
+ - name: Pull polkadot docker image
+ run: docker pull uniquenetwork/builder-polkadot:${{ env.POLKADOT_BUILD_BRANCH }}
+
+ - name: Pull chainql docker image
+ run: docker pull uniquenetwork/builder-chainql:latest
+
+ - name: Build the stack
+ run: cd .docker/ && docker build --no-cache --file ./Dockerfile-xcm.${{ matrix.network }}.yml --tag uniquenetwork/xcm-${{ matrix.network }}-testnet-local:nightly-${{ steps.branchname.outputs.value }}-${{ github.sha }} --tag uniquenetwork/xcm-${{ matrix.network }}-testnet-local:latest .
+
+ - name: Push docker image version
+ run: docker push uniquenetwork/xcm-${{ matrix.network }}-testnet-local:nightly-${{ steps.branchname.outputs.value }}-${{ github.sha }}
+
+ - name: Push docker image latest
+ run: docker push uniquenetwork/xcm-${{ matrix.network }}-testnet-local:latest
+
+ - name: Clean Workspace
+ if: always()
+ uses: AutoModality/action-clean@v1.1.0
+
+ - name: Remove builder cache
+ if: always() # run this step always
+ run: |
+ docker builder prune -f
+ docker system prune -f
+
+
+
.github/workflows/xcm-tests_v2.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/xcm-tests_v2.yml
@@ -0,0 +1,175 @@
+name: xcm-tests
+
+# Controls when the action will run.
+on:
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_call:
+
+#Define Workflow variables
+env:
+ REPO_URL: ${{ github.server_url }}/${{ github.repository }}
+
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+
+ prepare-execution-marix:
+
+ name: Prepare execution matrix
+
+# needs: [xcm-testnet-build]
+
+ runs-on: XL
+ outputs:
+ matrix: ${{ steps.create_matrix.outputs.matrix }}
+
+ steps:
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Create Execution matrix
+ uses: fabiocaccamo/create-matrix-action@v2
+ id: create_matrix
+ with:
+ matrix: |
+ network {opal}, runtime {opal}, features {opal-runtime}, runtest {testXcmOpal}
+ network {quartz}, runtime {quartz}, features {quartz-runtime}, runtest {testXcmQuartz}
+ network {unique}, runtime {unique}, features {unique-runtime}, runtest {testXcmUnique}
+
+ xcm-tests:
+ needs: prepare-execution-marix
+ # The type of runner that the job will run on
+ runs-on: [XL]
+
+ timeout-minutes: 600
+
+ name: ${{ matrix.network }}
+
+ continue-on-error: true #Do not stop testing of matrix runs failed. As it decided during PR review - it required 50/50& Let's check it with false.
+
+ strategy:
+ matrix:
+ include: ${{fromJson(needs.prepare-execution-marix.outputs.matrix)}}
+
+
+ steps:
+ - name: Skip if pull request is in Draft
+ if: github.event.pull_request.draft == true
+ run: exit 1
+
+ - name: Clean Workspace
+ uses: AutoModality/action-clean@v1.1.0
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+ with:
+ ref: ${{ github.head_ref }} #Checking out head commit
+
+ - name: Read .env file
+ uses: xom9ikk/dotenv@v1.0.2
+
+ - name: Generate ENV related extend file for docker-compose
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/docker-compose.tmp-xcm-tests.j2
+ output_file: .docker/docker-compose.xcm-tests.${{ matrix.network }}.yml
+ variables: |
+ NETWORK=${{ matrix.network }}
+
+ - name: Show build configuration
+ run: cat .docker/docker-compose.xcm-tests.${{ matrix.network }}.yml
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 16
+
+ - name: Build the stack
+ run: docker-compose -f ".docker/docker-compose.xcm-tests.${{ matrix.network }}.yml" up -d --remove-orphans --force-recreate --timeout 300
+
+ # 🚀 POLKADOT LAUNCH COMPLETE 🚀
+ - name: Check if docker logs consist messages related to testing of xcm tests
+ if: success()
+ run: |
+ counter=160
+ function check_container_status {
+ docker inspect -f {{.State.Running}} xcm-${{ matrix.network }}-testnet-local
+ }
+ function do_docker_logs {
+ docker logs --details xcm-${{ matrix.network }}-testnet-local 2>&1
+ }
+ function is_started {
+ if [ "$(check_container_status)" == "true" ]; then
+ echo "Container: xcm-${{ matrix.network }}-testnet-local RUNNING";
+ echo "Check Docker logs"
+ DOCKER_LOGS=$(do_docker_logs)
+ if [[ ${DOCKER_LOGS} = *"POLKADOT LAUNCH COMPLETE"* ]];then
+ echo "🚀 POLKADOT LAUNCH COMPLETE 🚀"
+ return 0
+ else
+ echo "Message not found in logs output, repeating..."
+ return 1
+ fi
+ else
+ echo "Container xcm-${{ matrix.network }}-testnet-local NOT RUNNING"
+ echo "Halting all future checks"
+ exit 1
+ fi
+ echo "something goes wrong"
+ exit 1
+ }
+ while ! is_started; do
+ echo "Waiting for special message in log files "
+ sleep 30s
+ counter=$(( $counter - 1 ))
+ echo "Counter: $counter"
+ if [ "$counter" -gt "0" ]; then
+ continue
+ else
+ break
+ fi
+ done
+ echo "Halting script"
+ exit 0
+ shell: bash
+
+ - name: Run XCM tests
+ working-directory: tests
+ run: |
+ yarn install
+ yarn add mochawesome
+ node scripts/readyness.js
+ echo "Ready to start tests"
+ NOW=$(date +%s) && yarn ${{ matrix.runtest }} --reporter mochawesome --reporter-options reportFilename=test-${NOW}
+
+ - name: XCM Test Report
+ uses: phoenix-actions/test-reporting@v8
+ id: test-report
+ if: success() || failure() # run this step even if previous step failed
+ with:
+ name: XCM Tests ${{ matrix.network }} # Name of the check run which will be created
+ path: tests/mochawesome-report/test-*.json # Path to test results
+ reporter: mochawesome-json
+ fail-on-error: 'false'
+
+ - name: Stop running containers
+ if: always() # run this step always
+ run: docker-compose -f ".docker/docker-compose.xcm-tests.${{ matrix.network }}.yml" down
+
+ - name: Clean Workspace
+ if: always()
+ uses: AutoModality/action-clean@v1.1.0
+
+ - name: Remove builder cache
+ if: always() # run this step always
+ run: |
+ docker system prune -a -f
+
.github/workflows/xcm.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/xcm.yml
@@ -0,0 +1,19 @@
+name: Nesting XCM
+
+on:
+ workflow_call:
+
+
+jobs:
+
+ xcm-testnet-build:
+ name: testnet build
+ uses: ./.github/workflows/xcm-testnet-build.yml
+ secrets: inherit
+
+ xcm-tests:
+ name: tests
+ needs: [ xcm-testnet-build ]
+ uses: ./.github/workflows/xcm-tests_v2.yml
+
+
.maintain/scripts/generate_sol.shdiffbeforeafterboth--- a/.maintain/scripts/generate_sol.sh
+++ b/.maintain/scripts/generate_sol.sh
@@ -1,11 +1,14 @@
#!/bin/sh
set -eu
+PRETTIER_CONFIG="$(pwd)""/.prettierrc"
+
tmp=$(mktemp)
cargo test --package $PACKAGE -- $NAME --exact --nocapture --ignored | tee $tmp
raw=$(mktemp --suffix .sol)
sed -n '/=== SNIP START ===/, /=== SNIP END ===/{ /=== SNIP START ===/! { /=== SNIP END ===/! p } }' $tmp > $raw
+
formatted=$(mktemp)
-prettier --use-tabs $raw > $formatted
+prettier --config $PRETTIER_CONFIG $raw > $formatted
mv $formatted $OUTPUT
.prettierignorediffbeforeafterboth--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1 @@
+!**/*.sol
.prettierrcdiffbeforeafterboth--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,16 @@
+{
+ "useTabs": true,
+ "tabWidth": 2,
+ "singleQuote": true,
+ "trailingComma": "all",
+ "overrides": [
+ {
+ "files": "*.sol",
+ "options": {
+ "singleQuote": false,
+ "printWidth": 120,
+ "explicitTypes": "always"
+ }
+ }
+ ]
+}
\ No newline at end of file
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2324,7 +2324,7 @@
[[package]]
name = "fc-consensus"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"async-trait",
"fc-db",
@@ -2343,7 +2343,7 @@
[[package]]
name = "fc-db"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"fp-storage",
"kvdb-rocksdb",
@@ -2359,7 +2359,7 @@
[[package]]
name = "fc-mapping-sync"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"fc-db",
"fp-consensus",
@@ -2376,7 +2376,7 @@
[[package]]
name = "fc-rpc"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"ethereum",
"ethereum-types",
@@ -2416,7 +2416,7 @@
[[package]]
name = "fc-rpc-core"
version = "1.1.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"ethereum",
"ethereum-types",
@@ -2557,7 +2557,7 @@
[[package]]
name = "fp-consensus"
version = "2.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"ethereum",
"parity-scale-codec 3.1.5",
@@ -2569,7 +2569,7 @@
[[package]]
name = "fp-evm"
version = "3.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"evm",
"frame-support",
@@ -2583,7 +2583,7 @@
[[package]]
name = "fp-evm-mapping"
version = "0.1.0"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"frame-support",
"sp-core",
@@ -2592,7 +2592,7 @@
[[package]]
name = "fp-rpc"
version = "3.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"ethereum",
"ethereum-types",
@@ -2609,7 +2609,7 @@
[[package]]
name = "fp-self-contained"
version = "1.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"ethereum",
"frame-support",
@@ -2625,7 +2625,7 @@
[[package]]
name = "fp-storage"
version = "2.0.0"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"parity-scale-codec 3.1.5",
]
@@ -5445,7 +5445,7 @@
[[package]]
name = "pallet-base-fee"
version = "1.0.0"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"fp-evm",
"frame-support",
@@ -5660,7 +5660,7 @@
[[package]]
name = "pallet-ethereum"
version = "4.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"ethereum",
"ethereum-types",
@@ -5689,7 +5689,7 @@
[[package]]
name = "pallet-evm"
version = "6.0.0-dev"
-source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27#69945f20e8dc06ab9e0dd636848a8db6a408c71c"
+source = "git+https://github.com/uniquenetwork/frontier?branch=unique-polkadot-v0.9.27-fee-limit#0ae36821312f4a26e7f96225f1b2cb16216cddf5"
dependencies = [
"evm",
"fp-evm",
@@ -5733,7 +5733,7 @@
[[package]]
name = "pallet-evm-contract-helpers"
-version = "0.2.0"
+version = "0.3.0"
dependencies = [
"ethereum",
"evm-coder",
@@ -5744,6 +5744,7 @@
"pallet-common",
"pallet-evm",
"pallet-evm-coder-substrate",
+ "pallet-evm-transaction-payment",
"parity-scale-codec 3.1.5",
"scale-info",
"sp-core",
@@ -12316,7 +12317,7 @@
[[package]]
name = "unique-rpc"
-version = "0.1.1"
+version = "0.1.2"
dependencies = [
"app-promotion-rpc",
"fc-db",
client/rpc/Cargo.tomldiffbeforeafterboth--- a/client/rpc/Cargo.toml
+++ b/client/rpc/Cargo.toml
@@ -19,4 +19,4 @@
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-rpc = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
client/rpc/src/lib.rsdiffbeforeafterboth--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -577,8 +577,8 @@
BlockNumber: Decode + Member + AtLeast32BitUnsigned,
AccountId: Decode,
C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
+ CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,
C::Api: AppPromotionRuntimeApi<Block, BlockNumber, CrossAccountId, AccountId>,
- CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,
{
pass_method!(total_staked(staker: Option<CrossAccountId>) -> String => |v| v.to_string(), app_promotion_api);
pass_method!(total_staked_per_block(staker: CrossAccountId) -> Vec<(BlockNumber, String)> =>
doc/sponsoring-flow.drawio.svgdiffbeforeafterboth--- /dev/null
+++ b/doc/sponsoring-flow.drawio.svg
@@ -0,0 +1,305 @@
+<svg host="65bd71144e" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="560" height="156" viewBox="-0.5 -0.5 560 156" content="<mxfile><diagram id="gc-t5MPR75mNDmyf0fnB" name="Page-1">7VvZbuM2FP0aA50HB9rtPMaO2xRIgAE8TdOngJYomY0kqhTtyP36khJpLZQTOd40SYFBIF6uuueew0vKMzCnUfYbAcnyAXswHBialw3M24Fh2LbG/nLDpjCYplkYAoK8wqSXhjn6Fwqj6BeskAfTWkOKcUhRUje6OI6hS2s2QAh+rTfzcVifNQEBVAxzF4Sq9U/k0WVhHRuj0n4HUbCUM+vOdVGzAO5LQPAqFvPFOIZFTQTkMOId0yXw8GtlPnM2MKcEY1o8RdkUhtyr0mNFv1931G6XTGBMu3S4R9ibPt/f+wv94ccczKfuUzYUo6xBuBKumD0+cEeDMEzFuulGuonCjE01WdIoZAadPaaU4Bc4xSEmzJK/vTnxURg2TCBEQcyKLlssZPbJGhKK2Cw3oiJCnsenmbwuEYXzBLh8zlcWbcyWOxjy99BYSX1x+RZsTJg1PcxiFuIIUrJhTUStYwlQZLzK8muJviNMywrwEksg4i3Yjlw6nj0I3++Bg6ngMDCckDvbQ2v2GPDHWUYJilPkprKSzVWp/8R4GXW8LOPCeDmKr6HHFEUUMaFLHOAYhLPS2vBK2eYe40TA8zekdCPkEaworoO305EpXhEXvrFcS2gqIAGkb7Szi3b8Xd6EhcAQULSuq2ebk/OuN4SATaVBglFM08rI37mhRNswG2jrWgOwYsQSvu3SPo7o9SUQZUCSzZPonxf+4oUrWxZvs2rl7eY9Sh0tEsYniQQVarsd6u0QxUJFrwZpj4C61UV3/0iZBH4xxd2mZnKHHKmKa51TcQ3zaxDU7khQ3uq4DD0IHrsLkearBaMDoPDLsakpc9qF8xfdvgibMkSfKs8VLrFSSSVekEw6PwPHHRmoW73IlsxGtmTajXPgfu1Pk12Nu8jDjC4hgavoq6vDxU+j+vizq0M1KAaG6QE49l0lgliN447hwj9IT/SuObc+6oWgWKP9BOWd9qcRFF3N3BMQhpA+w3U0MG/4PyEjC1ILZeefFb9ym/g4psM0D0bWVBslWY6yrJay84OAOAUuRTh+ZLrhIbq5A+5LT9WIv5Qg2Og44mR2EKfrs4rTZU7qn1WcRl3FqVfHDbnsloQiaWV7iGI4lPHJ+a7zFJxlwcUerrWogSIFcgbetqukKIMIlXKX3OFcrJ5pqTCqcBWdpjj2UVDUztbRPMFxikm6RMkdiJk2ELVLJYkq1quYk8+fWdna++KlG+dUL+syqdVHlai+nZxTmCQCP0vWNGruk9dvZ01K+9GeWda+7c+RlUnQ1KxsP72bEMTDv0XmeqlUx8+6mh+8zHGLcOnnFC7zIp+8TiNcvu8bbqtwec7CsZ3DhMvoKFyG06uUSq5b5W5a8BDFQZ2v+eXMB9Ogaa4HlcPVd7CJYJ6n/Dx3Pyc4bVl2jfeWZqu811p43/xudjze64rz+8z7cxLd6Uh0s1c8t9SbE5pdYX73qv7ih6/5HixgWIenO4kIZEIAFvl4HCCRRrHB7cnAvu1CojfDUqHW9kdiYtKB2BJ3Um6oXRnGtcDoo5+zJV3rHbDvp/A0363/342PTFKZOPWFpbsvOCr7IiMuy6iv+K/1Om6cvSW0jOijENq0ZN8DCT1s7quno7SM1F2IH3bftCuHa79j2n3B9EXzMmtcP4+1fcBvzctOdx5Tt/FW1EDE/ZNjNyU4TW9cl/mK/u4NDDax9sudzj8t8sdH6Nbbr8bbco72t6LdFHDw4hzqWv3e0VC9Kdp1t9SzG0WjcTC3HDUQrPMezNWf3rwXCI0YmObbRx4N3w5HdLtp79rm+46oqSK6/UJ/IKKsWP7gv9g4yv9PYc7+Aw==</diagram></mxfile>">
+ <defs>
+ <filter id="dropShadow">
+ <feGaussianBlur in="SourceAlpha" stdDeviation="1.7" result="blur"/>
+ <feOffset in="blur" dx="3" dy="3" result="offsetBlur"/>
+ <feFlood flood-color="#3D4574" flood-opacity="0.4" result="offsetColor"/>
+ <feComposite in="offsetColor" in2="offsetBlur" operator="in" result="offsetBlur"/>
+ <feBlend in="SourceGraphic" in2="offsetBlur"/>
+ </filter>
+ </defs>
+ <g filter="url(#dropShadow)">
+ <rect x="430" y="4" width="60" height="20" fill="none" stroke="none" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 14px; margin-left: 431px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
+ EVM calls
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="460" y="18" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
+ EVM calls
+ </text>
+ </switch>
+ </g>
+ <rect x="410" y="84" width="60" height="20" fill="none" stroke="none" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 94px; margin-left: 411px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
+ <div>
+ Extrinsics
+ </div>
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="440" y="98" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
+ Extrinsics
+ </text>
+ </switch>
+ </g>
+ <path d="M 20 54 L 20 74 L 33.63 74" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/>
+ <path d="M 38.88 74 L 31.88 77.5 L 33.63 74 L 31.88 70.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/>
+ <path d="M 20 34 L 20 14 L 33.63 14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/>
+ <path d="M 38.88 14 L 31.88 17.5 L 33.63 14 L 31.88 10.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/>
+ <rect x="0" y="34" width="40" height="20" fill="none" stroke="none" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 44px; margin-left: 1px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
+ <div>
+ User
+ </div>
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="20" y="48" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
+ User
+ </text>
+ </switch>
+ </g>
+ <path d="M 100 74 L 120 74 L 115 74 L 128.63 74" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/>
+ <path d="M 133.88 74 L 126.88 77.5 L 128.63 74 L 126.88 70.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/>
+ <rect x="40" y="64" width="60" height="20" fill="none" stroke="none" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 74px; margin-left: 41px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
+ <div>
+ Substrate
+ </div>
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="70" y="78" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
+ Substrate
+ </text>
+ </switch>
+ </g>
+ <path d="M 100 14 L 120 14 L 133.63 14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/>
+ <path d="M 138.88 14 L 131.88 17.5 L 133.63 14 L 131.88 10.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/>
+ <rect x="40" y="4" width="60" height="20" fill="none" stroke="none" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 14px; margin-left: 41px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
+ <div>
+ Ethereum
+ </div>
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="70" y="18" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
+ Ethereum
+ </text>
+ </switch>
+ </g>
+ <path d="M 230 14 L 260 14 L 283.63 14" fill="none" stroke="#6c8ebf" stroke-miterlimit="10" pointer-events="stroke"/>
+ <path d="M 288.88 14 L 281.88 17.5 L 283.63 14 L 281.88 10.5 Z" fill="#6c8ebf" stroke="#6c8ebf" stroke-miterlimit="10" pointer-events="all"/>
+ <rect x="140" y="4" width="90" height="20" fill="none" stroke="none" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 14px; margin-left: 141px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 7px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
+ pallet_evm::
+ <br style="font-size: 7px"/>
+ TransactionValidityHack
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="185" y="16" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="7px" text-anchor="middle">
+ pallet_evm::...
+ </text>
+ </switch>
+ </g>
+ <path d="M 410 14 L 423.63 14" fill="none" stroke="#6c8ebf" stroke-miterlimit="10" pointer-events="stroke"/>
+ <path d="M 428.88 14 L 421.88 17.5 L 423.63 14 L 421.88 10.5 Z" fill="#6c8ebf" stroke="#6c8ebf" stroke-miterlimit="10" pointer-events="all"/>
+ <rect x="290" y="4" width="120" height="20" fill="none" stroke="none" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 14px; margin-left: 291px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
+ <p style="line-height: 100% ; font-size: 7px">
+ <font style="font-size: 7px">
+ pallet_charge_evm_transaction::
+ <br/>
+ Config::EvmSponsorshipHandler
+ <br/>
+ </font>
+ </p>
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="350" y="18" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
+ pallet_charge_evm_tr...
+ </text>
+ </switch>
+ </g>
+ <path d="M 520 54 L 540 54 L 540 34 L 260 34 L 260 14 L 283.63 14" fill="none" stroke="#6c8ebf" stroke-miterlimit="10" pointer-events="stroke"/>
+ <path d="M 288.88 14 L 281.88 17.5 L 283.63 14 L 281.88 10.5 Z" fill="#6c8ebf" stroke="#6c8ebf" stroke-miterlimit="10" pointer-events="all"/>
+ <rect x="410" y="44" width="110" height="20" fill="none" stroke="none" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 54px; margin-left: 411px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 7px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
+ pallet_charge_evm_transaction::
+ <br/>
+ BridgeSponsorshipHandler
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="465" y="56" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="7px" text-anchor="middle">
+ pallet_charge_evm_transaction::...
+ </text>
+ </switch>
+ </g>
+ <path d="M 235 74 L 255 74 L 250 74 L 263.63 74" fill="none" stroke="#d6b656" stroke-miterlimit="10" pointer-events="stroke"/>
+ <path d="M 268.88 74 L 261.88 77.5 L 263.63 74 L 261.88 70.5 Z" fill="#d6b656" stroke="#d6b656" stroke-miterlimit="10" pointer-events="all"/>
+ <rect x="135" y="69" width="100" height="10" fill="none" stroke="none" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 74px; margin-left: 136px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 7px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
+ pallet_sponsoring::
+ <div style="font-size: 7px">
+ ChargeTransactionPayment
+ </div>
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="185" y="76" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="7px" text-anchor="middle">
+ pallet_sponsoring::...
+ </text>
+ </switch>
+ </g>
+ <path d="M 370 74 L 390 74 L 390 94 L 403.63 94" fill="none" stroke="#d6b656" stroke-miterlimit="10" pointer-events="stroke"/>
+ <path d="M 408.88 94 L 401.88 97.5 L 403.63 94 L 401.88 90.5 Z" fill="#d6b656" stroke="#d6b656" stroke-miterlimit="10" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 81px; margin-left: 390px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 7px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">
+ tx.others
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="390" y="83" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="7px" text-anchor="middle">
+ tx.others
+ </text>
+ </switch>
+ </g>
+ <path d="M 370 74 L 390 74 L 390 54 L 403.63 54" fill="none" stroke="#d6b656" stroke-miterlimit="10" pointer-events="stroke"/>
+ <path d="M 408.88 54 L 401.88 57.5 L 403.63 54 L 401.88 50.5 Z" fill="#d6b656" stroke="#d6b656" stroke-miterlimit="10" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 64px; margin-left: 390px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 7px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">
+ <div>
+ tx.evm.call
+ </div>
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="390" y="66" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="7px" text-anchor="middle">
+ tx.evm.call
+ </text>
+ </switch>
+ </g>
+ <rect x="270" y="64" width="100" height="20" fill="none" stroke="none" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 74px; margin-left: 271px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 7px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
+ <div style="font-size: 7px">
+ pallet_sponsoring::
+ <br/>
+ Config::SponsorshipHandler
+ </div>
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="320" y="76" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="7px" text-anchor="middle">
+ pallet_sponsoring::...
+ </text>
+ </switch>
+ </g>
+ <rect x="10" y="124" width="410" height="20" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 408px; height: 1px; padding-top: 134px; margin-left: 11px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
+ SponsorshipHandler<CrossAccountId, (H160, Vec<u8>), CallContext>
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="215" y="138" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
+ SponsorshipHandler<CrossAccountId, (H160, Vec<u8>), CallContext>
+ </text>
+ </switch>
+ </g>
+ <rect x="10" y="94" width="250" height="20" fill="#fff2cc" stroke="#d6b656" pointer-events="all"/>
+ <g transform="translate(-0.5 -0.5)">
+ <switch>
+ <foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;">
+ <div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 104px; margin-left: 11px;">
+ <div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;">
+ <div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">
+ SponsorshipHandler<AccountId, Call, ()>
+ </div>
+ </div>
+ </div>
+ </foreignObject>
+ <text x="135" y="108" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">
+ SponsorshipHandler<AccountId, Call, ()>
+ </text>
+ </switch>
+ </g>
+ </g>
+ <switch>
+ <g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/>
+ <a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank">
+ <text text-anchor="middle" font-size="10px" x="50%" y="100%">
+ Viewer does not support full SVG 1.1
+ </text>
+ </a>
+ </switch>
+</svg>
doc/sponsoring.mddiffbeforeafterboth--- /dev/null
+++ b/doc/sponsoring.md
@@ -0,0 +1,13 @@
+# Sponsoring
+
+
+
+## Implementation
+
+If you need to add sponsoring for pallet call, you should implement `SponsorshipHandler<AccountId, Call, ()>`, see `UniqueSponsorshipHandler` for example.
+
+If you need to add sponsoring for EVM contract call, you should implement `SponsorshipHandler<CrossAccountId, (H160, Vec<u8>), CallContext>`, see `UniqueEthSponsorshipHandler` for example.
+
+## EVM bridging
+
+In case if Ethereum call is being called using substrate `evm.call` extrinsic, `BridgeSponsorshipHandler` is used to convert between two different `SponsorshipHandler` types
node/cli/CHANGELOG.mddiffbeforeafterboth--- a/node/cli/CHANGELOG.md
+++ b/node/cli/CHANGELOG.md
@@ -1,4 +1,10 @@
<!-- bureaucrate goes here -->
+
+## [v0.9.27] 2022-09-08
+
+### Added
+- Support RPC for `AppPromotion` pallet.
+
## [v0.9.27] 2022-08-16
### Other changes
node/cli/Cargo.tomldiffbeforeafterboth--- a/node/cli/Cargo.toml
+++ b/node/cli/Cargo.toml
@@ -309,13 +309,13 @@
jsonrpsee = { version = "0.14.0", features = ["server", "macros"] }
tokio = { version = "1.19.2", features = ["time"] }
-fc-rpc-core = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fc-consensus = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fc-mapping-sync = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fc-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fc-db = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+fc-rpc-core = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fc-consensus = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fc-mapping-sync = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fc-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fc-db = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-rpc = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
unique-rpc = { default-features = false, path = "../rpc" }
app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}
node/rpc/CHANGELOG.mddiffbeforeafterboth--- a/node/rpc/CHANGELOG.md
+++ b/node/rpc/CHANGELOG.md
@@ -1,4 +1,9 @@
<!-- bureaucrate goes here -->
+## [v0.1.2] 2022-09-08
+
+### Added
+- Support RPC for `AppPromotion` pallet.
+
## [v0.1.1] 2022-08-16
### Other changes
node/rpc/Cargo.tomldiffbeforeafterboth--- a/node/rpc/Cargo.toml
+++ b/node/rpc/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "unique-rpc"
-version = "0.1.1"
+version = "0.1.2"
authors = ['Unique Network <support@uniquenetwork.io>']
license = 'GPLv3'
edition = "2021"
@@ -40,13 +40,13 @@
substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
tokio = { version = "1.19.2", features = ["macros", "sync"] }
-pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fc-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-storage = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fc-rpc-core = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fc-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-storage = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fc-rpc-core = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
pallet-common = { default-features = false, path = "../../pallets/common" }
up-common = { path = "../../primitives/common" }
pallets/app-promotion/Cargo.tomldiffbeforeafterboth--- a/pallets/app-promotion/Cargo.toml
+++ b/pallets/app-promotion/Cargo.toml
@@ -52,7 +52,7 @@
pallet-balances ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
pallet-timestamp ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
pallet-randomness-collective-flip ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-pallet-evm ={ default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm ={ default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
sp-std ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
pallets/app-promotion/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/app-promotion/src/benchmarking.rs
+++ b/pallets/app-promotion/src/benchmarking.rs
@@ -112,6 +112,7 @@
let share = Perbill::from_rational(1u32, 20);
let _ = <T as Config>::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::<T>::max_value());
(0..10).map(|_| {
+ // used to change block number
<frame_system::Pallet<T>>::finalize();
PromototionPallet::<T>::stake(RawOrigin::Signed(caller.clone()).into(), share * <T as Config>::Currency::total_balance(&caller))
}).collect::<Result<Vec<_>, _>>()?;
pallets/app-promotion/src/lib.rsdiffbeforeafterboth--- a/pallets/app-promotion/src/lib.rs
+++ b/pallets/app-promotion/src/lib.rs
@@ -14,13 +14,34 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-//! # App promotion
+//! # App Promotion pallet
+//!
+//! The pallet implements the mechanics of staking and sponsoring collections/contracts.
//!
-//! The app promotion pallet is designed to ... .
+//! - [`Config`]
+//! - [`Pallet`]
+//! - [`Error`]
+//! - [`Event`]
+//!
+//! ## Overview
+//! The App Promotion pallet allows fund holders to stake at a certain daily rate of return.
+//! The mechanics implemented in the pallet allow it to act as a sponsor for collections / contracts,
+//! the list of which is set by the pallet administrator.
+//!
//!
//! ## Interface
+//! The pallet provides interfaces for funds, collection/contract operations (see [types] module).
+
//!
//! ### Dispatchable Functions
+//! - [`set_admin_address`][`Pallet::set_admin_address`] - sets an address as the the admin.
+//! - [`stake`][`Pallet::stake`] - stakes the amount of native tokens.
+//! - [`unstake`][`Pallet::unstake`] - unstakes all stakes.
+//! - [`sponsor_collection`][`Pallet::sponsor_collection`] - sets the pallet to be the sponsor for the collection.
+//! - [`stop_sponsoring_collection`][`Pallet::stop_sponsoring_collection`] - removes the pallet as the sponsor for the collection.
+//! - [`sponsor_contract`][`Pallet::sponsor_contract`] - sets the pallet to be the sponsor for the contract.
+//! - [`stop_sponsoring_contract`][`Pallet::stop_sponsoring_contract`] - removes the pallet as the sponsor for the contract.
+//! - [`payout_stakers`][`Pallet::payout_stakers`] - recalculates interest for the specified number of stakers.
//!
// #![recursion_limit = "1024"]
@@ -95,10 +116,10 @@
/// Type for interacting with conrtacts
type ContractHandler: ContractHandler<AccountId = Self::CrossAccountId, ContractId = H160>;
- /// ID for treasury
+ /// `AccountId` for treasury
type TreasuryAccountId: Get<Self::AccountId>;
- /// The app's pallet id, used for deriving its sovereign account ID.
+ /// The app's pallet id, used for deriving its sovereign account address.
#[pallet::constant]
type PalletId: Get<PalletId>;
@@ -138,7 +159,7 @@
/// Staking recalculation was performed
///
/// # Arguments
- /// * AccountId: ID of the staker.
+ /// * AccountId: account of the staker.
/// * Balance : recalculation base
/// * Balance : total income
StakingRecalculation(
@@ -153,21 +174,21 @@
/// Staking was performed
///
/// # Arguments
- /// * AccountId: ID of the staker
+ /// * AccountId: account of the staker
/// * Balance : staking amount
Stake(T::AccountId, BalanceOf<T>),
/// Unstaking was performed
///
/// # Arguments
- /// * AccountId: ID of the staker
+ /// * AccountId: account of the staker
/// * Balance : unstaking amount
Unstake(T::AccountId, BalanceOf<T>),
/// The admin was set
///
/// # Arguments
- /// * AccountId: ID of the admin
+ /// * AccountId: account address of the admin
SetAdmin(T::AccountId),
}
@@ -187,13 +208,20 @@
IncorrectLockedBalanceOperation,
}
+ /// Stores the total staked amount.
#[pallet::storage]
pub type TotalStaked<T: Config> = StorageValue<Value = BalanceOf<T>, QueryKind = ValueQuery>;
+ /// Stores the `admin` account. Some extrinsics can only be executed if they were signed by `admin`.
#[pallet::storage]
pub type Admin<T: Config> = StorageValue<Value = T::AccountId, QueryKind = OptionQuery>;
- /// Amount of tokens staked by account in the blocknumber.
+ /// Stores the amount of tokens staked by account in the blocknumber.
+ ///
+ /// * **Key1** - Staker account.
+ /// * **Key2** - Relay block number when the stake was made.
+ /// * **(Balance, BlockNumber)** - Balance of the stake.
+ /// The number of the relay block in which we must perform the interest recalculation
#[pallet::storage]
pub type Staked<T: Config> = StorageNMap<
Key = (
@@ -203,11 +231,19 @@
Value = (BalanceOf<T>, T::BlockNumber),
QueryKind = ValueQuery,
>;
- /// Amount of stakes for an Account
+
+ /// Stores amount of stakes for an `Account`.
+ ///
+ /// * **Key** - Staker account.
+ /// * **Value** - Amount of stakes.
#[pallet::storage]
pub type StakesPerAccount<T: Config> =
StorageMap<_, Blake2_128Concat, T::AccountId, u8, ValueQuery>;
+ /// Stores amount of stakes for an `Account`.
+ ///
+ /// * **Key** - Staker account.
+ /// * **Value** - Amount of stakes.
#[pallet::storage]
pub type PendingUnstake<T: Config> = StorageMap<
_,
@@ -252,6 +288,15 @@
T::BlockNumber: From<u32> + Into<u32>,
<<T as Config>::Currency as Currency<T::AccountId>>::Balance: Sum + From<u128>,
{
+ /// Sets an address as the the admin.
+ ///
+ /// # Permissions
+ ///
+ /// * Sudo
+ ///
+ /// # Arguments
+ ///
+ /// * `admin`: account of the new admin.
#[pallet::weight(T::WeightInfo::set_admin_address())]
pub fn set_admin_address(origin: OriginFor<T>, admin: T::CrossAccountId) -> DispatchResult {
ensure_root(origin)?;
@@ -263,6 +308,13 @@
Ok(())
}
+ /// Stakes the amount of native tokens.
+ /// Sets `amount` to the locked state.
+ /// The maximum number of stakes for a staker is 10.
+ ///
+ /// # Arguments
+ ///
+ /// * `amount`: in native tokens.
#[pallet::weight(T::WeightInfo::stake())]
pub fn stake(staker: OriginFor<T>, amount: BalanceOf<T>) -> DispatchResult {
let staker_id = ensure_signed(staker)?;
@@ -280,6 +332,7 @@
let balance =
<<T as Config>::Currency as Currency<T::AccountId>>::free_balance(&staker_id);
+ // checks that we can lock `amount` on the `staker` account.
<<T as Config>::Currency as Currency<T::AccountId>>::ensure_can_withdraw(
&staker_id,
amount,
@@ -293,6 +346,8 @@
let block_number = T::RelayBlockNumberProvider::current_block_number();
+ // Calculation of the number of recalculation periods,
+ // after how much the first interest calculation should be performed for the stake
let recalculate_after_interval: T::BlockNumber =
if block_number % T::RecalculationInterval::get() == 0u32.into() {
1u32.into()
@@ -300,6 +355,8 @@
2u32.into()
};
+ // Сalculation of the number of the relay block
+ // in which it is necessary to accrue remuneration for the stake.
let recalc_block = (block_number / T::RecalculationInterval::get()
+ recalculate_after_interval)
* T::RecalculationInterval::get();
@@ -327,12 +384,20 @@
Ok(())
}
+ /// Unstakes all stakes.
+ /// Moves the sum of all stakes to the `reserved` state.
+ /// After the end of `PendingInterval` this sum becomes completely
+ /// free for further use.
#[pallet::weight(T::WeightInfo::unstake())]
pub fn unstake(staker: OriginFor<T>) -> DispatchResultWithPostInfo {
let staker_id = ensure_signed(staker)?;
+
+ // calculate block number where the sum would be free
let block = <frame_system::Pallet<T>>::block_number() + T::PendingInterval::get();
+
let mut pendings = <PendingUnstake<T>>::get(block);
+ // checks that we can do unreserve stakes in the block
ensure!(!pendings.is_full(), Error::<T>::PendingForBlockOverflow);
let mut total_stakes = 0u64;
@@ -371,6 +436,15 @@
Ok(None.into())
}
+ /// Sets the pallet to be the sponsor for the collection.
+ ///
+ /// # Permissions
+ ///
+ /// * Pallet admin
+ ///
+ /// # Arguments
+ ///
+ /// * `collection_id`: ID of the collection that will be sponsored by `pallet_id`
#[pallet::weight(T::WeightInfo::sponsor_collection())]
pub fn sponsor_collection(
admin: OriginFor<T>,
@@ -384,6 +458,18 @@
T::CollectionHandler::set_sponsor(Self::account_id(), collection_id)
}
+
+ /// Removes the pallet as the sponsor for the collection.
+ /// Returns [`NoPermission`][`Error::NoPermission`]
+ /// if the pallet wasn't the sponsor.
+ ///
+ /// # Permissions
+ ///
+ /// * Pallet admin
+ ///
+ /// # Arguments
+ ///
+ /// * `collection_id`: ID of the collection that is sponsored by `pallet_id`
#[pallet::weight(T::WeightInfo::stop_sponsoring_collection())]
pub fn stop_sponsoring_collection(
admin: OriginFor<T>,
@@ -404,6 +490,15 @@
T::CollectionHandler::remove_collection_sponsor(collection_id)
}
+ /// Sets the pallet to be the sponsor for the contract.
+ ///
+ /// # Permissions
+ ///
+ /// * Pallet admin
+ ///
+ /// # Arguments
+ ///
+ /// * `contract_id`: the contract address that will be sponsored by `pallet_id`
#[pallet::weight(T::WeightInfo::sponsor_contract())]
pub fn sponsor_contract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {
let admin_id = ensure_signed(admin)?;
@@ -419,6 +514,17 @@
)
}
+ /// Removes the pallet as the sponsor for the contract.
+ /// Returns [`NoPermission`][`Error::NoPermission`]
+ /// if the pallet wasn't the sponsor.
+ ///
+ /// # Permissions
+ ///
+ /// * Pallet admin
+ ///
+ /// # Arguments
+ ///
+ /// * `contract_id`: the contract address that is sponsored by `pallet_id`
#[pallet::weight(T::WeightInfo::stop_sponsoring_contract())]
pub fn stop_sponsoring_contract(admin: OriginFor<T>, contract_id: H160) -> DispatchResult {
let admin_id = ensure_signed(admin)?;
@@ -437,6 +543,18 @@
T::ContractHandler::remove_contract_sponsor(contract_id)
}
+ /// Recalculates interest for the specified number of stakers.
+ /// If all stakers are not recalculated, the next call of the extrinsic
+ /// will continue the recalculation, from those stakers for whom this
+ /// was not perform in last call.
+ ///
+ /// # Permissions
+ ///
+ /// * Pallet admin
+ ///
+ /// # Arguments
+ ///
+ /// * `stakers_number`: the number of stakers for which recalculation will be performed
#[pallet::weight(T::WeightInfo::payout_stakers(stakers_number.unwrap_or(20) as u32))]
pub fn payout_stakers(admin: OriginFor<T>, stakers_number: Option<u8>) -> DispatchResult {
let admin_id = ensure_signed(admin)?;
@@ -446,63 +564,19 @@
Error::<T>::NoPermission
);
+ // calculate the number of the current recalculation block,
+ // this is necessary in order to understand which stakers we should calculate interest
let current_recalc_block =
Self::get_current_recalc_block(T::RelayBlockNumberProvider::current_block_number());
+
+ // calculate the number of the next recalculation block,
+ // this value is set for the stakers to whom the recalculation will be performed
let next_recalc_block = current_recalc_block + T::RecalculationInterval::get();
let mut storage_iterator = Self::get_next_calculated_key()
.map_or(Staked::<T>::iter(), |key| Staked::<T>::iter_from(key));
NextCalculatedRecord::<T>::set(None);
-
- // {
- // let mut stakers_number = stakers_number.unwrap_or(20);
- // let mut last_id = admin_id;
- // let mut income_acc = BalanceOf::<T>::default();
- // let mut amount_acc = BalanceOf::<T>::default();
-
- // while let Some((
- // (current_id, staked_block),
- // (amount, next_recalc_block_for_stake),
- // )) = storage_iterator.next()
- // {
- // if last_id != current_id {
- // if income_acc != BalanceOf::<T>::default() {
- // <T::Currency as Currency<T::AccountId>>::transfer(
- // &T::TreasuryAccountId::get(),
- // &last_id,
- // income_acc,
- // ExistenceRequirement::KeepAlive,
- // )
- // .and_then(|_| Self::add_lock_balance(&last_id, income_acc))?;
-
- // Self::deposit_event(Event::StakingRecalculation(
- // last_id, amount, income_acc,
- // ));
- // }
-
- // if stakers_number == 0 {
- // NextCalculatedRecord::<T>::set(Some((current_id, staked_block)));
- // break;
- // }
- // stakers_number -= 1;
- // income_acc = BalanceOf::<T>::default();
- // last_id = current_id;
- // };
- // if current_recalc_block >= next_recalc_block_for_stake {
- // Self::recalculate_and_insert_stake(
- // &last_id,
- // staked_block,
- // next_recalc_block,
- // amount,
- // ((current_recalc_block - next_recalc_block_for_stake)
- // / T::RecalculationInterval::get())
- // .into() + 1,
- // &mut income_acc,
- // );
- // }
- // }
- // }
{
let mut stakers_number = stakers_number.unwrap_or(20);
@@ -510,6 +584,8 @@
let income_acc = RefCell::new(BalanceOf::<T>::default());
let amount_acc = RefCell::new(BalanceOf::<T>::default());
+ // this closure is used to perform some of the actions if we break the loop because we reached the number of stakers for recalculation,
+ // but there were unrecalculated records in the storage.
let flush_stake = || -> DispatchResult {
if let Some(last_id) = &*last_id.borrow() {
if !income_acc.borrow().is_zero() {
@@ -578,10 +654,18 @@
}
impl<T: Config> Pallet<T> {
+ /// The account address of the app promotion pot.
+ ///
+ /// This actually does computation. If you need to keep using it, then make sure you cache the
+ /// value and only call this once.
pub fn account_id() -> T::AccountId {
T::PalletId::get().into_account_truncating()
}
+ /// Unlocks the balance that was locked by the pallet.
+ ///
+ /// - `staker`: staker account.
+ /// - `amount`: amount of unlocked funds.
fn unlock_balance(staker: &T::AccountId, amount: BalanceOf<T>) -> DispatchResult {
let locked_balance = Self::get_locked_balance(staker)
.map(|l| l.amount)
@@ -598,6 +682,10 @@
Ok(())
}
+ /// Adds the balance to locked by the pallet.
+ ///
+ /// - `staker`: staker account.
+ /// - `amount`: amount of added locked funds.
fn add_lock_balance(staker: &T::AccountId, amount: BalanceOf<T>) -> DispatchResult {
Self::get_locked_balance(staker)
.map_or(<BalanceOf<T>>::default(), |l| l.amount)
@@ -606,6 +694,10 @@
.ok_or(ArithmeticError::Overflow.into())
}
+ /// Sets the new state of a balance locked by the pallet.
+ ///
+ /// - `staker`: staker account.
+ /// - `amount`: amount of locked funds.
fn set_lock_unchecked(staker: &T::AccountId, amount: BalanceOf<T>) {
if amount.is_zero() {
<T::Currency as LockableCurrency<T::AccountId>>::remove_lock(LOCK_IDENTIFIER, &staker);
@@ -619,6 +711,9 @@
}
}
+ /// Returns the balance locked by the pallet for the staker.
+ ///
+ /// - `staker`: staker account.
pub fn get_locked_balance(
staker: impl EncodeLike<T::AccountId>,
) -> Option<BalanceLock<BalanceOf<T>>> {
@@ -627,6 +722,9 @@
.find(|l| l.id == LOCK_IDENTIFIER)
}
+ /// Returns the total staked balance for the staker.
+ ///
+ /// - `staker`: staker account.
pub fn total_staked_by_id(staker: impl EncodeLike<T::AccountId>) -> Option<BalanceOf<T>> {
let staked = Staked::<T>::iter_prefix((staker,))
.into_iter()
@@ -640,6 +738,10 @@
}
}
+ /// Returns all relay block numbers when stake was made,
+ /// the amount of the stake.
+ ///
+ /// - `staker`: staker account.
pub fn total_staked_by_id_per_block(
staker: impl EncodeLike<T::AccountId>,
) -> Option<Vec<(T::BlockNumber, BalanceOf<T>)>> {
@@ -655,6 +757,9 @@
}
}
+ /// Returns the total staked balance for the staker.
+ /// If `staker` is `None`, returns the total amount staked.
+ /// - `staker`: staker account.
pub fn cross_id_total_staked(staker: Option<T::CrossAccountId>) -> Option<BalanceOf<T>> {
staker.map_or(Some(<TotalStaked<T>>::get()), |s| {
Self::total_staked_by_id(s.as_sub())
@@ -667,6 +772,10 @@
// .unwrap_or_default()
// }
+ /// Returns all relay block numbers when stake was made,
+ /// the amount of the stake.
+ ///
+ /// - `staker`: staker account.
pub fn cross_id_total_staked_per_block(
staker: T::CrossAccountId,
) -> Vec<(T::BlockNumber, BalanceOf<T>)> {
@@ -703,10 +812,6 @@
fn get_current_recalc_block(current_relay_block: T::BlockNumber) -> T::BlockNumber {
(current_relay_block / T::RecalculationInterval::get()) * T::RecalculationInterval::get()
}
-
- // fn get_next_recalc_block(current_relay_block: T::BlockNumber) -> T::BlockNumber {
- // Self::get_current_recalc_block(current_relay_block) + T::RecalculationInterval::get()
- // }
fn get_next_calculated_key() -> Option<Vec<u8>> {
Self::get_next_calculated_record().map(|key| Staked::<T>::hashed_key_for(key))
@@ -717,6 +822,11 @@
where
<<T as Config>::Currency as Currency<T::AccountId>>::Balance: Sum,
{
+ /// Returns the amount reserved by the pending.
+ /// If `staker` is `None`, returns the total pending.
+ ///
+ /// -`staker`: staker account.
+ ///
/// Since user funds are not transferred anywhere by staking, overflow protection is provided
/// at the level of the associated type `Balance` of `Currency` trait. In order to overflow,
/// the staker must have more funds on his account than the maximum set for `Balance` type.
@@ -740,6 +850,10 @@
)
}
+ /// Returns all parachain block numbers when unreserve is expected,
+ /// the amount of the unreserved funds.
+ ///
+ /// - `staker`: staker account.
pub fn cross_id_pending_unstake_per_block(
staker: T::CrossAccountId,
) -> Vec<(T::BlockNumber, BalanceOf<T>)> {
pallets/app-promotion/src/types.rsdiffbeforeafterboth--- a/pallets/app-promotion/src/types.rs
+++ b/pallets/app-promotion/src/types.rs
@@ -9,7 +9,10 @@
use sp_std::borrow::ToOwned;
use pallet_evm_contract_helpers::{Pallet as EvmHelpersPallet, Config as EvmHelpersConfig};
+/// This trait was defined because `LockableCurrency`
+/// has no way to know the state of the lock for an account.
pub trait ExtendedLockableCurrency<AccountId: Parameter>: LockableCurrency<AccountId> {
+ /// Returns lock balance for an account. Allows to determine the cause of the lock.
fn locks<KArg>(who: KArg) -> WeakBoundedVec<BalanceLock<Self::Balance>, Self::MaxLocks>
where
KArg: EncodeLike<AccountId>;
@@ -25,18 +28,28 @@
Self::locks(who)
}
}
-
+/// Trait for interacting with collections.
pub trait CollectionHandler {
type CollectionId;
type AccountId;
+ /// Sets sponsor for a collection.
+ ///
+ /// - `sponsor_id`: the account of the sponsor-to-be.
+ /// - `collection_id`: ID of the modified collection.
fn set_sponsor(
sponsor_id: Self::AccountId,
collection_id: Self::CollectionId,
) -> DispatchResult;
+ /// Removes sponsor for a collection.
+ ///
+ /// - `collection_id`: ID of the modified collection.
fn remove_collection_sponsor(collection_id: Self::CollectionId) -> DispatchResult;
+ /// Retuns the current sponsor for a collection if one is set.
+ ///
+ /// - `collection_id`: ID of the collection.
fn sponsor(collection_id: Self::CollectionId)
-> Result<Option<Self::AccountId>, DispatchError>;
}
@@ -66,18 +79,28 @@
.map(|acc| acc.to_owned()))
}
}
-
+/// Trait for interacting with contracts.
pub trait ContractHandler {
type ContractId;
type AccountId;
+ /// Sets sponsor for a contract.
+ ///
+ /// - `sponsor_id`: the account of the sponsor-to-be.
+ /// - `contract_address`: the address of the modified contract.
fn set_sponsor(
sponsor_id: Self::AccountId,
contract_address: Self::ContractId,
) -> DispatchResult;
+ /// Removes sponsor for a contract.
+ ///
+ /// - `contract_address`: the address of the modified contract.
fn remove_contract_sponsor(contract_address: Self::ContractId) -> DispatchResult;
+ /// Retuns the current sponsor for a contract if one is set.
+ ///
+ /// - `contract_address`: the contract address.
fn sponsor(
contract_address: Self::ContractId,
) -> Result<Option<Self::AccountId>, DispatchError>;
pallets/common/Cargo.tomldiffbeforeafterboth--- a/pallets/common/Cargo.toml
+++ b/pallets/common/Cargo.toml
@@ -17,12 +17,12 @@
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
ethereum = { version = "0.12.0", default-features = false }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
serde = { version = "1.0.130", default-features = false }
scale-info = { version = "2.0.1", default-features = false, features = [
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -20,6 +20,7 @@
solidity_interface, solidity, ToLog,
types::*,
execution::{Result, Error},
+ weight,
};
pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};
use pallet_evm_coder_substrate::dispatch_to_evm;
@@ -31,8 +32,12 @@
use alloc::format;
use crate::{
- Pallet, CollectionHandle, Config, CollectionProperties,
- eth::{convert_cross_account_to_uint256, convert_uint256_to_cross_account},
+ Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,
+ eth::{
+ convert_cross_account_to_uint256, convert_uint256_to_cross_account,
+ convert_cross_account_to_tuple,
+ },
+ weights::WeightInfo,
};
/// Events for ethereum collection helper.
@@ -69,6 +74,7 @@
///
/// @param key Property key.
/// @param value Propery value.
+ #[weight(<SelfWeightOf<T>>::set_collection_properties(1))]
fn set_collection_property(
&mut self,
caller: caller,
@@ -88,7 +94,10 @@
/// Delete collection property.
///
/// @param key Property key.
+ #[weight(<SelfWeightOf<T>>::delete_collection_properties(1))]
fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {
+ self.consume_store_reads_and_writes(1, 1)?;
+
let caller = T::CrossAccountId::from_eth(caller);
let key = <Vec<u8>>::from(key)
.try_into()
@@ -120,6 +129,8 @@
///
/// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {
+ self.consume_store_reads_and_writes(1, 1)?;
+
check_is_owner_or_admin(caller, self)?;
let sponsor = T::CrossAccountId::from_eth(sponsor);
@@ -138,6 +149,8 @@
caller: caller,
sponsor: uint256,
) -> Result<void> {
+ self.consume_store_reads_and_writes(1, 1)?;
+
check_is_owner_or_admin(caller, self)?;
let sponsor = convert_uint256_to_cross_account::<T>(sponsor);
@@ -146,7 +159,7 @@
save(self)
}
- // /// Whether there is a pending sponsor.
+ /// Whether there is a pending sponsor.
fn has_collection_pending_sponsor(&self) -> Result<bool> {
Ok(matches!(
self.collection.sponsorship,
@@ -158,6 +171,8 @@
///
/// @dev After setting the sponsor for the collection, it must be confirmed with this function.
fn confirm_collection_sponsorship(&mut self, caller: caller) -> Result<void> {
+ self.consume_store_writes(1)?;
+
let caller = T::CrossAccountId::from_eth(caller);
if !self
.confirm_sponsorship(caller.as_sub())
@@ -170,6 +185,7 @@
/// Remove collection sponsor.
fn remove_collection_sponsor(&mut self, caller: caller) -> Result<void> {
+ self.consume_store_reads_and_writes(1, 1)?;
check_is_owner_or_admin(caller, self)?;
self.remove_sponsor().map_err(dispatch_to_evm::<T>)?;
save(self)
@@ -206,6 +222,8 @@
/// @param value Value of the limit.
#[solidity(rename_selector = "setCollectionLimit")]
fn set_int_limit(&mut self, caller: caller, limit: string, value: uint32) -> Result<void> {
+ self.consume_store_reads_and_writes(1, 1)?;
+
check_is_owner_or_admin(caller, self)?;
let mut limits = self.limits.clone();
@@ -249,6 +267,8 @@
/// @param value Value of the limit.
#[solidity(rename_selector = "setCollectionLimit")]
fn set_bool_limit(&mut self, caller: caller, limit: string, value: bool) -> Result<void> {
+ self.consume_store_reads_and_writes(1, 1)?;
+
check_is_owner_or_admin(caller, self)?;
let mut limits = self.limits.clone();
@@ -275,7 +295,7 @@
}
/// Get contract address.
- fn contract_address(&self, _caller: caller) -> Result<address> {
+ fn contract_address(&self) -> Result<address> {
Ok(crate::eth::collection_id_to_address(self.id))
}
@@ -286,6 +306,8 @@
caller: caller,
new_admin: uint256,
) -> Result<void> {
+ self.consume_store_writes(2)?;
+
let caller = T::CrossAccountId::from_eth(caller);
let new_admin = convert_uint256_to_cross_account::<T>(new_admin);
<Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;
@@ -299,6 +321,8 @@
caller: caller,
admin: uint256,
) -> Result<void> {
+ self.consume_store_writes(2)?;
+
let caller = T::CrossAccountId::from_eth(caller);
let admin = convert_uint256_to_cross_account::<T>(admin);
<Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;
@@ -308,6 +332,8 @@
/// Add collection admin.
/// @param newAdmin Address of the added administrator.
fn add_collection_admin(&mut self, caller: caller, new_admin: address) -> Result<void> {
+ self.consume_store_writes(2)?;
+
let caller = T::CrossAccountId::from_eth(caller);
let new_admin = T::CrossAccountId::from_eth(new_admin);
<Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;
@@ -318,6 +344,8 @@
///
/// @param admin Address of the removed administrator.
fn remove_collection_admin(&mut self, caller: caller, admin: address) -> Result<void> {
+ self.consume_store_writes(2)?;
+
let caller = T::CrossAccountId::from_eth(caller);
let admin = T::CrossAccountId::from_eth(admin);
<Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;
@@ -329,6 +357,8 @@
/// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
#[solidity(rename_selector = "setCollectionNesting")]
fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {
+ self.consume_store_reads_and_writes(1, 1)?;
+
check_is_owner_or_admin(caller, self)?;
let mut permissions = self.collection.permissions.clone();
@@ -358,6 +388,8 @@
enable: bool,
collections: Vec<address>,
) -> Result<void> {
+ self.consume_store_reads_and_writes(1, 1)?;
+
if collections.is_empty() {
return Err("no addresses provided".into());
}
@@ -401,6 +433,8 @@
/// 0 for Normal
/// 1 for AllowList
fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {
+ self.consume_store_reads_and_writes(1, 1)?;
+
check_is_owner_or_admin(caller, self)?;
let permissions = CollectionPermissions {
access: Some(match mode {
@@ -420,30 +454,78 @@
save(self)
}
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ fn allowed(&self, user: address) -> Result<bool> {
+ Ok(Pallet::<T>::allowed(
+ self.id,
+ T::CrossAccountId::from_eth(user),
+ ))
+ }
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
fn add_to_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {
+ self.consume_store_writes(1)?;
+
let caller = T::CrossAccountId::from_eth(caller);
let user = T::CrossAccountId::from_eth(user);
<Pallet<T>>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;
Ok(())
}
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ fn add_to_collection_allow_list_substrate(
+ &mut self,
+ caller: caller,
+ user: uint256,
+ ) -> Result<void> {
+ self.consume_store_writes(1)?;
+
+ let caller = T::CrossAccountId::from_eth(caller);
+ let user = convert_uint256_to_cross_account::<T>(user);
+ Pallet::<T>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;
+ Ok(())
+ }
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
fn remove_from_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {
+ self.consume_store_writes(1)?;
+
let caller = T::CrossAccountId::from_eth(caller);
let user = T::CrossAccountId::from_eth(user);
<Pallet<T>>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;
Ok(())
}
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ fn remove_from_collection_allow_list_substrate(
+ &mut self,
+ caller: caller,
+ user: uint256,
+ ) -> Result<void> {
+ self.consume_store_writes(1)?;
+
+ let caller = T::CrossAccountId::from_eth(caller);
+ let user = convert_uint256_to_cross_account::<T>(user);
+ Pallet::<T>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;
+ Ok(())
+ }
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {
+ self.consume_store_reads_and_writes(1, 1)?;
+
check_is_owner_or_admin(caller, self)?;
let permissions = CollectionPermissions {
mint_mode: Some(mode),
@@ -481,7 +563,7 @@
/// Returns collection type
///
/// @return `Fungible` or `NFT` or `ReFungible`
- fn unique_collection_type(&mut self) -> Result<string> {
+ fn unique_collection_type(&self) -> Result<string> {
let mode = match self.collection.mode {
CollectionMode::Fungible(_) => "Fungible",
CollectionMode::NFT => "NFT",
@@ -490,11 +572,23 @@
Ok(mode.into())
}
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ fn collection_owner(&self) -> Result<(address, uint256)> {
+ Ok(convert_cross_account_to_tuple::<T>(
+ &T::CrossAccountId::from_sub(self.owner.clone()),
+ ))
+ }
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
/// @param newOwner new owner account
fn set_owner(&mut self, caller: caller, new_owner: address) -> Result<void> {
+ self.consume_store_writes(1)?;
+
let caller = T::CrossAccountId::from_eth(caller);
let new_owner = T::CrossAccountId::from_eth(new_owner);
self.set_owner_internal(caller, new_owner)
@@ -506,13 +600,25 @@
/// @dev Owner can be changed only by current owner
/// @param newOwner new owner substrate account
fn set_owner_substrate(&mut self, caller: caller, new_owner: uint256) -> Result<void> {
+ self.consume_store_writes(1)?;
+
let caller = T::CrossAccountId::from_eth(caller);
let new_owner = convert_uint256_to_cross_account::<T>(new_owner);
self.set_owner_internal(caller, new_owner)
.map_err(dispatch_to_evm::<T>)
}
+
+ // TODO: need implement AbiWriter for &Vec<T>
+ // fn collection_admins(&self) -> Result<Vec<(address, uint256)>> {
+ // let result = pallet_common::IsAdmin::<T>::iter_prefix((self.id,))
+ // .map(|(admin, _)| pallet_common::eth::convert_cross_account_to_tuple::<T>(&admin))
+ // .collect();
+ // Ok(result)
+ // }
}
+/// ### Note
+/// Do not forget to add: `self.consume_store_reads(1)?;`
fn check_is_owner_or_admin<T: Config>(
caller: caller,
collection: &CollectionHandle<T>,
@@ -524,9 +630,9 @@
Ok(caller)
}
+/// ### Note
+/// Do not forget to add: `self.consume_store_writes(1)?;`
fn save<T: Config>(collection: &CollectionHandle<T>) -> Result<void> {
- // TODO possibly delete for the lack of transaction
- collection.consume_store_writes(1)?;
collection
.check_is_internal()
.map_err(dispatch_to_evm::<T>)?;
pallets/common/src/eth.rsdiffbeforeafterboth--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -16,7 +16,7 @@
//! The module contains a number of functions for converting and checking ethereum identifiers.
-use evm_coder::types::uint256;
+use evm_coder::types::{uint256, address};
pub use pallet_evm::account::{Config, CrossAccountId};
use sp_core::H160;
use up_data_structs::CollectionId;
@@ -69,3 +69,19 @@
let account_id = T::AccountId::from(new_admin_arr);
T::CrossAccountId::from_sub(account_id)
}
+
+/// Convert `CrossAccountId` to `(address, uint256)`.
+pub fn convert_cross_account_to_tuple<T: Config>(
+ cross_account_id: &T::CrossAccountId,
+) -> (address, uint256)
+where
+ T::AccountId: AsRef<[u8; 32]>,
+{
+ if cross_account_id.is_canonical_substrate() {
+ let sub = convert_cross_account_to_uint256::<T>(cross_account_id);
+ (Default::default(), sub)
+ } else {
+ let eth = *cross_account_id.as_eth();
+ (eth, Default::default())
+ }
+}
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -112,7 +112,6 @@
RmrkBoundedTheme,
RmrkNftChild,
CollectionPermissions,
- SchemaVersion,
};
pub use pallet::*;
@@ -202,6 +201,21 @@
))
}
+ /// Consume gas for reading and writing.
+ pub fn consume_store_reads_and_writes(
+ &self,
+ reads: u64,
+ writes: u64,
+ ) -> evm_coder::execution::Result<()> {
+ let weight = <T as frame_system::Config>::DbWeight::get();
+ let reads = weight.read.saturating_mul(reads);
+ let writes = weight.read.saturating_mul(writes);
+ self.recorder
+ .consume_gas(T::GasWeightMapping::weight_to_gas(
+ reads.saturating_add(writes),
+ ))
+ }
+
/// Save collection to storage.
pub fn save(&self) -> DispatchResult {
<CollectionById<T>>::insert(self.id, &self.collection);
@@ -310,6 +324,8 @@
}
/// Changes collection owner to another account
+ /// #### Store read/writes
+ /// 1 writes
fn set_owner_internal(
&mut self,
caller: T::CrossAccountId,
@@ -1292,6 +1308,8 @@
}
/// Toggle `user` participation in the `collection`'s allow list.
+ /// #### Store read/writes
+ /// 1 writes
pub fn toggle_allowlist(
collection: &CollectionHandle<T>,
sender: &T::CrossAccountId,
@@ -1312,6 +1330,8 @@
}
/// Toggle `user` participation in the `collection`'s admin list.
+ /// #### Store read/writes
+ /// 2 writes
pub fn toggle_admin(
collection: &CollectionHandle<T>,
sender: &T::CrossAccountId,
pallets/configuration/Cargo.tomldiffbeforeafterboth--- a/pallets/configuration/Cargo.toml
+++ b/pallets/configuration/Cargo.toml
@@ -16,7 +16,7 @@
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
smallvec = "1.6.1"
[features]
pallets/evm-coder-substrate/Cargo.tomldiffbeforeafterboth--- a/pallets/evm-coder-substrate/Cargo.toml
+++ b/pallets/evm-coder-substrate/Cargo.toml
@@ -12,8 +12,8 @@
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
ethereum = { version = "0.12.0", default-features = false }
evm-coder = { default-features = false, path = "../../crates/evm-coder" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
pallets/evm-contract-helpers/CHANGELOG.mddiffbeforeafterboth--- a/pallets/evm-contract-helpers/CHANGELOG.md
+++ b/pallets/evm-contract-helpers/CHANGELOG.md
@@ -2,29 +2,35 @@
All notable changes to this project will be documented in this file.
+## [v0.3.0] 2022-09-05
+
+### Added
+
+- Methods `force_set_sponsor` , `force_remove_sponsor` to be able to administer sponsorships with other pallets. Added to implement `AppPromotion` pallet logic.
+
## [v0.2.0] - 2022-08-19
### Added
- - Set arbitrary evm address as contract sponsor.
- - Ability to remove current sponsor.
+- Set arbitrary evm address as contract sponsor.
+- Ability to remove current sponsor.
### Removed
- - Remove methods
- + sponsoring_enabled
- + toggle_sponsoring
- ### Changed
+- Remove methods
+ - sponsoring_enabled
+ - toggle_sponsoring
- - Change `toggle_sponsoring` to `self_sponsored_enable`.
+### Changed
+- Change `toggle_sponsoring` to `self_sponsored_enable`.
## [v0.1.2] 2022-08-16
### Other changes
-- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
+- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
-- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
+- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
-- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
\ No newline at end of file
+- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
pallets/evm-contract-helpers/Cargo.tomldiffbeforeafterboth--- a/pallets/evm-contract-helpers/Cargo.toml
+++ b/pallets/evm-contract-helpers/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "pallet-evm-contract-helpers"
-version = "0.2.0"
+version = "0.3.0"
license = "GPLv3"
edition = "2021"
@@ -19,14 +19,15 @@
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
# Unique
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
# Locals
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
pallet-common = { default-features = false, path = '../../pallets/common' }
pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
+pallet-evm-transaction-payment = { default-features = false, path = '../../pallets/evm-transaction-payment' }
up-data-structs = { default-features = false, path = '../../primitives/data-structs', features = [
'serde1',
] }
pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -20,16 +20,17 @@
use evm_coder::{
abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*, ToLog,
};
-use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm};
use pallet_evm::{
ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure, PrecompileHandle,
account::CrossAccountId,
};
-use sp_core::H160;
+use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm};
+use pallet_evm_transaction_payment::CallContext;
+use sp_core::{H160, U256};
use up_data_structs::SponsorshipState;
use crate::{
- AllowlistEnabled, Config, Owner, Pallet, SponsorBasket, SponsoringRateLimit, SponsoringModeT,
- Sponsoring,
+ AllowlistEnabled, Config, Owner, Pallet, SponsorBasket, SponsoringFeeLimit,
+ SponsoringRateLimit, SponsoringModeT, Sponsoring,
};
use frame_support::traits::Get;
use up_sponsorship::SponsorshipHandler;
@@ -171,14 +172,9 @@
fn get_sponsor(&self, contract_address: address) -> Result<(address, uint256)> {
let sponsor =
Pallet::<T>::get_sponsor(contract_address).ok_or("Contract has no sponsor")?;
- let result: (address, uint256) = if sponsor.is_canonical_substrate() {
- let sponsor = pallet_common::eth::convert_cross_account_to_uint256::<T>(&sponsor);
- (Default::default(), sponsor)
- } else {
- let sponsor = *sponsor.as_eth();
- (sponsor, Default::default())
- };
- Ok(result)
+ Ok(pallet_common::eth::convert_cross_account_to_tuple::<T>(
+ &sponsor,
+ ))
}
/// Check tat contract has confirmed sponsor.
@@ -222,9 +218,11 @@
}
/// Get current contract sponsoring rate limit
- /// @param contractAddress Contract to get sponsoring mode of
+ /// @param contractAddress Contract to get sponsoring rate limit of
/// @return uint32 Amount of blocks between two sponsored transactions
fn get_sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {
+ self.recorder().consume_sload()?;
+
Ok(<SponsoringRateLimit<T>>::get(contract_address)
.try_into()
.map_err(|_| "rate limit > u32::MAX")?)
@@ -250,6 +248,37 @@
Ok(())
}
+ /// Set contract sponsoring fee limit
+ /// @dev Sponsoring fee limit - is maximum fee that could be spent by
+ /// single transaction
+ /// @param contractAddress Contract to change sponsoring fee limit of
+ /// @param feeLimit Fee limit
+ /// @dev Only contract owner can change this setting
+ fn set_sponsoring_fee_limit(
+ &mut self,
+ caller: caller,
+ contract_address: address,
+ fee_limit: uint256,
+ ) -> Result<void> {
+ self.recorder().consume_sload()?;
+ self.recorder().consume_sstore()?;
+
+ <Pallet<T>>::ensure_owner(contract_address, caller).map_err(dispatch_to_evm::<T>)?;
+ <Pallet<T>>::set_sponsoring_fee_limit(contract_address, fee_limit.into())
+ .map_err(dispatch_to_evm::<T>)?;
+ Ok(())
+ }
+
+ /// Get current contract sponsoring fee limit
+ /// @param contractAddress Contract to get sponsoring fee limit of
+ /// @return uint256 Maximum amount of fee that could be spent by single
+ /// transaction
+ fn get_sponsoring_fee_limit(&self, contract_address: address) -> Result<uint256> {
+ self.recorder().consume_sload()?;
+
+ Ok(get_sponsoring_fee_limit::<T>(contract_address))
+ }
+
/// Is specified user present in contract allow list
/// @dev Contract owner always implicitly included
/// @param contractAddress Contract to check allowlist of
@@ -363,23 +392,26 @@
/// Bridge to pallet-sponsoring
pub struct HelpersContractSponsoring<T: Config>(PhantomData<*const T>);
-impl<T: Config> SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)>
+impl<T: Config> SponsorshipHandler<T::CrossAccountId, CallContext>
for HelpersContractSponsoring<T>
{
- fn get_sponsor(who: &T::CrossAccountId, call: &(H160, Vec<u8>)) -> Option<T::CrossAccountId> {
- let (contract_address, _) = call;
- let mode = <Pallet<T>>::sponsoring_mode(*contract_address);
+ fn get_sponsor(
+ who: &T::CrossAccountId,
+ call_context: &CallContext,
+ ) -> Option<T::CrossAccountId> {
+ let contract_address = call_context.contract_address;
+ let mode = <Pallet<T>>::sponsoring_mode(contract_address);
if mode == SponsoringModeT::Disabled {
return None;
}
- let sponsor = match <Pallet<T>>::get_sponsor(*contract_address) {
+ let sponsor = match <Pallet<T>>::get_sponsor(contract_address) {
Some(sponsor) => sponsor,
None => return None,
};
if mode == SponsoringModeT::Allowlisted
- && !<Pallet<T>>::allowed(*contract_address, *who.as_eth())
+ && !<Pallet<T>>::allowed(contract_address, *who.as_eth())
{
return None;
}
@@ -394,11 +426,24 @@
}
}
+ let sponsored_fee_limit = get_sponsoring_fee_limit::<T>(contract_address);
+
+ if call_context.max_fee > sponsored_fee_limit {
+ return None;
+ }
+
<SponsorBasket<T>>::insert(contract_address, who.as_eth(), block_number);
Some(sponsor)
}
}
+fn get_sponsoring_fee_limit<T: Config>(contract_address: address) -> uint256 {
+ <SponsoringFeeLimit<T>>::get(contract_address)
+ .get(&0xffffffff)
+ .cloned()
+ .unwrap_or(U256::MAX)
+}
+
generate_stubgen!(contract_helpers_impl, ContractHelpersCall<()>, true);
generate_stubgen!(contract_helpers_iface, ContractHelpersCall<()>, false);
pallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/lib.rs
+++ b/pallets/evm-contract-helpers/src/lib.rs
@@ -22,15 +22,19 @@
pub use pallet::*;
pub use eth::*;
use scale_info::TypeInfo;
+use frame_support::storage::bounded_btree_map::BoundedBTreeMap;
pub mod eth;
+/// Maximum number of methods per contract that could have fee limit
+pub const MAX_FEE_LIMITED_METHODS: u32 = 5;
+
#[frame_support::pallet]
pub mod pallet {
pub use super::*;
use crate::eth::ContractHelpersEvents;
use frame_support::pallet_prelude::*;
use pallet_evm_coder_substrate::DispatchResult;
- use sp_core::H160;
+ use sp_core::{H160, U256};
use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
use up_data_structs::SponsorshipState;
use evm_coder::ToLog;
@@ -57,6 +61,9 @@
/// No pending sponsor for contract.
NoPendingSponsor,
+
+ /// Number of methods that sponsored limit is defined for exceeds maximum.
+ TooManyMethodsHaveSponsoredLimit,
}
#[pallet::pallet]
@@ -118,6 +125,14 @@
/// * **Key2** - sponsored user address.
/// * **Value** - last sponsored block number.
#[pallet::storage]
+ pub(super) type SponsoringFeeLimit<T: Config> = StorageMap<
+ Hasher = Twox128,
+ Key = H160,
+ Value = BoundedBTreeMap<u32, U256, ConstU32<MAX_FEE_LIMITED_METHODS>>,
+ QueryKind = ValueQuery,
+ >;
+
+ #[pallet::storage]
pub(super) type SponsorBasket<T: Config> = StorageDoubleMap<
Hasher1 = Twox128,
Key1 = H160,
@@ -216,9 +231,10 @@
Ok(())
}
- /// TO-DO
- ///
+ /// Force set `sponsor` for `contract`.
///
+ /// Differs from `set_sponsor` in that confirmation
+ /// from the sponsor is not required.
pub fn force_set_sponsor(
contract_address: H160,
sponsor: &T::CrossAccountId,
@@ -269,9 +285,10 @@
Self::force_remove_sponsor(contract_address)
}
- /// TO-DO
- ///
+ /// Force remove `sponsor` for `contract`.
///
+ /// Differs from `remove_sponsor` in that
+ /// it doesn't require consent from the `owner` of the contract.
pub fn force_remove_sponsor(contract_address: H160) -> DispatchResult {
Sponsoring::<T>::remove(contract_address);
@@ -353,6 +370,16 @@
<SponsoringRateLimit<T>>::insert(contract, rate_limit);
}
+ /// Set maximum for gas limit of transaction
+ pub fn set_sponsoring_fee_limit(contract: H160, fee_limit: U256) -> DispatchResult {
+ <SponsoringFeeLimit<T>>::try_mutate(contract, |limits_map| {
+ limits_map
+ .try_insert(0xffffffff, fee_limit)
+ .map_err(|_| <Error<T>>::TooManyMethodsHaveSponsoredLimit)
+ })?;
+ Ok(())
+ }
+
/// Is user added to allowlist, or he is owner of specified contract
pub fn allowed(contract: H160, user: H160) -> bool {
<Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user
pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
+++ b/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
@@ -32,7 +32,7 @@
}
/// @title Magic contract, which allows users to reconfigure other contracts
-/// @dev the ERC-165 identifier for this interface is 0xd77fab70
+/// @dev the ERC-165 identifier for this interface is 0x172cb4fb
contract ContractHelpers is Dummy, ERC165, ContractHelpersEvents {
/// Get user, which deployed specified contract
/// @dev May return zero address in case if contract is deployed
@@ -171,7 +171,7 @@
}
/// Get current contract sponsoring rate limit
- /// @param contractAddress Contract to get sponsoring mode of
+ /// @param contractAddress Contract to get sponsoring rate limit of
/// @return uint32 Amount of blocks between two sponsored transactions
/// @dev EVM selector for this function is: 0x610cfabd,
/// or in textual repr: getSponsoringRateLimit(address)
@@ -203,6 +203,40 @@
dummy = 0;
}
+ /// Set contract sponsoring fee limit
+ /// @dev Sponsoring fee limit - is maximum fee that could be spent by
+ /// single transaction
+ /// @param contractAddress Contract to change sponsoring fee limit of
+ /// @param feeLimit Fee limit
+ /// @dev Only contract owner can change this setting
+ /// @dev EVM selector for this function is: 0x03aed665,
+ /// or in textual repr: setSponsoringFeeLimit(address,uint256)
+ function setSponsoringFeeLimit(address contractAddress, uint256 feeLimit)
+ public
+ {
+ require(false, stub_error);
+ contractAddress;
+ feeLimit;
+ dummy = 0;
+ }
+
+ /// Get current contract sponsoring fee limit
+ /// @param contractAddress Contract to get sponsoring fee limit of
+ /// @return uint256 Maximum amount of fee that could be spent by single
+ /// transaction
+ /// @dev EVM selector for this function is: 0xc3fdc9ee,
+ /// or in textual repr: getSponsoringFeeLimit(address)
+ function getSponsoringFeeLimit(address contractAddress)
+ public
+ view
+ returns (uint256)
+ {
+ require(false, stub_error);
+ contractAddress;
+ dummy;
+ return 0;
+ }
+
/// Is specified user present in contract allow list
/// @dev Contract owner always implicitly included
/// @param contractAddress Contract to check allowlist of
pallets/evm-migration/Cargo.tomldiffbeforeafterboth--- a/pallets/evm-migration/Cargo.toml
+++ b/pallets/evm-migration/Cargo.toml
@@ -15,8 +15,8 @@
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
[dependencies.codec]
default-features = false
pallets/evm-transaction-payment/Cargo.tomldiffbeforeafterboth--- a/pallets/evm-transaction-payment/Cargo.toml
+++ b/pallets/evm-transaction-payment/Cargo.toml
@@ -14,11 +14,11 @@
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
[dependencies.codec]
default-features = false
pallets/evm-transaction-payment/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-transaction-payment/src/lib.rs
+++ b/pallets/evm-transaction-payment/src/lib.rs
@@ -22,8 +22,8 @@
use fp_evm::WithdrawReason;
use frame_support::traits::IsSubType;
pub use pallet::*;
-use pallet_evm::{EnsureAddressOrigin, account::CrossAccountId};
-use sp_core::H160;
+use pallet_evm::{account::CrossAccountId, EnsureAddressOrigin};
+use sp_core::{H160, U256};
use sp_runtime::{TransactionOutcome, DispatchError};
use up_sponsorship::SponsorshipHandler;
@@ -33,10 +33,20 @@
use sp_std::vec::Vec;
+ /// Contains call data
+ pub struct CallContext {
+ /// Contract address
+ pub contract_address: H160,
+ /// Transaction data
+ pub input: Vec<u8>,
+ /// Max fee for transaction - gasLimit * gasPrice
+ pub max_fee: U256,
+ }
+
#[pallet::config]
pub trait Config: frame_system::Config + pallet_evm::account::Config {
/// Loosly-coupled handlers for evm call sponsoring
- type EvmSponsorshipHandler: SponsorshipHandler<Self::CrossAccountId, (H160, Vec<u8>)>;
+ type EvmSponsorshipHandler: SponsorshipHandler<Self::CrossAccountId, CallContext>;
}
#[pallet::pallet]
@@ -47,11 +57,20 @@
/// Implements [`fp_evm::TransactionValidityHack`], which provides sponsor address to pallet-evm
pub struct TransactionValidityHack<T: Config>(PhantomData<*const T>);
impl<T: Config> fp_evm::TransactionValidityHack<T::CrossAccountId> for TransactionValidityHack<T> {
- fn who_pays_fee(origin: H160, reason: &WithdrawReason) -> Option<T::CrossAccountId> {
+ fn who_pays_fee(
+ origin: H160,
+ max_fee: U256,
+ reason: &WithdrawReason,
+ ) -> Option<T::CrossAccountId> {
match reason {
WithdrawReason::Call { target, input } => {
let origin_sub = T::CrossAccountId::from_eth(origin);
- T::EvmSponsorshipHandler::get_sponsor(&origin_sub, &(*target, input.clone()))
+ let call_context = CallContext {
+ contract_address: *target,
+ input: input.clone(),
+ max_fee,
+ };
+ T::EvmSponsorshipHandler::get_sponsor(&origin_sub, &call_context)
}
_ => None,
}
@@ -71,6 +90,8 @@
source,
target,
input,
+ gas_limit,
+ max_fee_per_gas,
..
} => {
let _ = T::CallOrigin::ensure_address_origin(
@@ -79,11 +100,17 @@
)
.ok()?;
let who = T::CrossAccountId::from_sub(who.clone());
+ let max_fee = max_fee_per_gas.saturating_mul((*gas_limit).into());
+ let call_context = CallContext {
+ contract_address: *target,
+ input: input.clone(),
+ max_fee,
+ };
// Effects from EvmSponsorshipHandler are applied by pallet_evm::runner
// TODO: Should we implement simulation mode (test, but do not apply effects) in `up-sponsorship`?
let sponsor = frame_support::storage::with_transaction(|| {
TransactionOutcome::Rollback(Ok::<_, DispatchError>(
- T::EvmSponsorshipHandler::get_sponsor(&who, &(*target, input.clone())),
+ T::EvmSponsorshipHandler::get_sponsor(&who, &call_context),
))
})
// FIXME: it may fail with DispatchError in case of depth limit
pallets/fungible/Cargo.tomldiffbeforeafterboth--- a/pallets/fungible/Cargo.toml
+++ b/pallets/fungible/Cargo.toml
@@ -23,7 +23,7 @@
pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' }
ethereum = { version = "0.12.0", default-features = false }
frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
scale-info = { version = "2.0.1", default-features = false, features = [
"derive",
] }
pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -22,7 +22,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
contract Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -255,6 +255,18 @@
dummy = 0;
}
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ /// @dev EVM selector for this function is: 0xd63a8e11,
+ /// or in textual repr: allowed(address)
+ function allowed(address user) public view returns (bool) {
+ require(false, stub_error);
+ user;
+ dummy;
+ return false;
+ }
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
@@ -266,6 +278,17 @@
dummy = 0;
}
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xd06ad267,
+ /// or in textual repr: addToCollectionAllowListSubstrate(uint256)
+ function addToCollectionAllowListSubstrate(uint256 user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
@@ -277,6 +300,17 @@
dummy = 0;
}
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xa31913ed,
+ /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+ function removeFromCollectionAllowListSubstrate(uint256 user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
@@ -325,6 +359,18 @@
return "";
}
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0xdf727d3b,
+ /// or in textual repr: collectionOwner()
+ function collectionOwner() public view returns (Tuple6 memory) {
+ require(false, stub_error);
+ dummy;
+ return Tuple6(0x0000000000000000000000000000000000000000, 0);
+ }
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
pallets/nonfungible/Cargo.tomldiffbeforeafterboth--- a/pallets/nonfungible/Cargo.toml
+++ b/pallets/nonfungible/Cargo.toml
@@ -16,7 +16,7 @@
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
pallet-common = { default-features = false, path = '../common' }
pallet-structure = { default-features = false, path = '../structure' }
up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -99,7 +99,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
contract Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -332,6 +332,18 @@
dummy = 0;
}
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ /// @dev EVM selector for this function is: 0xd63a8e11,
+ /// or in textual repr: allowed(address)
+ function allowed(address user) public view returns (bool) {
+ require(false, stub_error);
+ user;
+ dummy;
+ return false;
+ }
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
@@ -343,6 +355,17 @@
dummy = 0;
}
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xd06ad267,
+ /// or in textual repr: addToCollectionAllowListSubstrate(uint256)
+ function addToCollectionAllowListSubstrate(uint256 user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
@@ -354,6 +377,17 @@
dummy = 0;
}
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xa31913ed,
+ /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+ function removeFromCollectionAllowListSubstrate(uint256 user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
@@ -402,6 +436,18 @@
return "";
}
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0xdf727d3b,
+ /// or in textual repr: collectionOwner()
+ function collectionOwner() public view returns (Tuple17 memory) {
+ require(false, stub_error);
+ dummy;
+ return Tuple17(0x0000000000000000000000000000000000000000, 0);
+ }
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
pallets/proxy-rmrk-core/Cargo.tomldiffbeforeafterboth--- a/pallets/proxy-rmrk-core/Cargo.toml
+++ b/pallets/proxy-rmrk-core/Cargo.toml
@@ -20,7 +20,7 @@
pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" }
pallet-structure = { default-features = false, path = "../../pallets/structure" }
up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
rmrk-traits = { default-features = false, path = "../../primitives/rmrk-traits" }
scale-info = { version = "2.0.1", default-features = false, features = [
pallets/proxy-rmrk-equip/Cargo.tomldiffbeforeafterboth--- a/pallets/proxy-rmrk-equip/Cargo.toml
+++ b/pallets/proxy-rmrk-equip/Cargo.toml
@@ -19,7 +19,7 @@
pallet-common = { default-features = false, path = '../common' }
pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" }
up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
rmrk-traits = { default-features = false, path = "../../primitives/rmrk-traits" }
scale-info = { version = "2.0.1", default-features = false, features = [
pallets/refungible/Cargo.tomldiffbeforeafterboth--- a/pallets/refungible/Cargo.toml
+++ b/pallets/refungible/Cargo.toml
@@ -16,7 +16,7 @@
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
pallet-common = { default-features = false, path = '../common' }
pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -99,7 +99,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
contract Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -332,6 +332,18 @@
dummy = 0;
}
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ /// @dev EVM selector for this function is: 0xd63a8e11,
+ /// or in textual repr: allowed(address)
+ function allowed(address user) public view returns (bool) {
+ require(false, stub_error);
+ user;
+ dummy;
+ return false;
+ }
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
@@ -343,6 +355,17 @@
dummy = 0;
}
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xd06ad267,
+ /// or in textual repr: addToCollectionAllowListSubstrate(uint256)
+ function addToCollectionAllowListSubstrate(uint256 user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
@@ -354,6 +377,17 @@
dummy = 0;
}
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xa31913ed,
+ /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+ function removeFromCollectionAllowListSubstrate(uint256 user) public {
+ require(false, stub_error);
+ user;
+ dummy = 0;
+ }
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
@@ -402,6 +436,18 @@
return "";
}
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0xdf727d3b,
+ /// or in textual repr: collectionOwner()
+ function collectionOwner() public view returns (Tuple17 memory) {
+ require(false, stub_error);
+ dummy;
+ return Tuple17(0x0000000000000000000000000000000000000000, 0);
+ }
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
pallets/structure/Cargo.tomldiffbeforeafterboth--- a/pallets/structure/Cargo.toml
+++ b/pallets/structure/Cargo.toml
@@ -16,7 +16,7 @@
"derive",
] }
up-data-structs = { path = "../../primitives/data-structs", default-features = false }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
[features]
default = ["std"]
pallets/unique/CHANGELOG.mddiffbeforeafterboth--- a/pallets/unique/CHANGELOG.md
+++ b/pallets/unique/CHANGELOG.md
@@ -4,7 +4,12 @@
<!-- bureaucrate goes here -->
-## [v0.1.4] 2022-09-5
+## [v0.2.0] 2022-09-13
+
+### Changes
+- Change **collectionHelper** method `createRefungibleCollection` to `createRFTCollection`,
+
+## [v0.1.4] 2022-09-05
### Added
pallets/unique/Cargo.tomldiffbeforeafterboth--- a/pallets/unique/Cargo.toml
+++ b/pallets/unique/Cargo.toml
@@ -9,7 +9,7 @@
license = 'GPLv3'
name = 'pallet-unique'
repository = 'https://github.com/UniqueNetwork/unique-chain'
-version = "0.1.4"
+version = "0.2.0"
[package.metadata.docs.rs]
targets = ['x86_64-unknown-linux-gnu']
@@ -98,7 +98,7 @@
scale-info = { version = "2.0.1", default-features = false, features = [
"derive",
] }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
pallet-common = { default-features = false, path = "../common" }
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
pallets/unique/src/eth/mod.rsdiffbeforeafterboth--- a/pallets/unique/src/eth/mod.rs
+++ b/pallets/unique/src/eth/mod.rs
@@ -21,25 +21,23 @@
use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*};
use frame_support::traits::Get;
use pallet_common::{
- CollectionById, CollectionHandle,
+ CollectionById,
dispatch::CollectionDispatch,
erc::{
CollectionHelpersEvents,
static_property::{key, value as property_value},
},
- Pallet as PalletCommon,
};
use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};
-use pallet_evm_coder_substrate::dispatch_to_evm;
use up_data_structs::{
CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,
- CollectionMode, PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue,
+ CollectionMode, PropertyValue,
};
use crate::{Config, SelfWeightOf, weights::WeightInfo};
-use sp_std::{vec, vec::Vec};
+use sp_std::vec::Vec;
use alloc::format;
/// See [`CollectionHelpersCall`]
@@ -245,6 +243,7 @@
}
#[weight(<SelfWeightOf<T>>::create_collection())]
+ #[solidity(rename_selector = "createRFTCollection")]
fn create_refungible_collection(
&mut self,
caller: caller,
pallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/unique/src/eth/stubs/CollectionHelpers.soldiffbeforeafterboth--- a/pallets/unique/src/eth/stubs/CollectionHelpers.sol
+++ b/pallets/unique/src/eth/stubs/CollectionHelpers.sol
@@ -10,11 +10,7 @@
}
contract ERC165 is Dummy {
- function supportsInterface(bytes4 interfaceID)
- external
- view
- returns (bool)
- {
+ function supportsInterface(bytes4 interfaceID) external view returns (bool) {
require(false, stub_error);
interfaceID;
return true;
@@ -23,14 +19,11 @@
/// @dev inlined interface
contract CollectionHelpersEvents {
- event CollectionCreated(
- address indexed owner,
- address indexed collectionId
- );
+ event CollectionCreated(address indexed owner, address indexed collectionId);
}
/// @title Contract, which allows users to operate with collections
-/// @dev the ERC-165 identifier for this interface is 0x675f3074
+/// @dev the ERC-165 identifier for this interface is 0x88ee8ef1
contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {
/// Create an NFT collection
/// @param name Name of the collection
@@ -69,9 +62,9 @@
return 0x0000000000000000000000000000000000000000;
}
- /// @dev EVM selector for this function is: 0x44a68ad5,
- /// or in textual repr: createRefungibleCollection(string,string,string)
- function createRefungibleCollection(
+ /// @dev EVM selector for this function is: 0xab173450,
+ /// or in textual repr: createRFTCollection(string,string,string)
+ function createRFTCollection(
string memory name,
string memory description,
string memory tokenPrefix
@@ -106,11 +99,7 @@
/// @return bool Does the collection exist?
/// @dev EVM selector for this function is: 0xc3de1494,
/// or in textual repr: isCollectionExist(address)
- function isCollectionExist(address collectionAddress)
- public
- view
- returns (bool)
- {
+ function isCollectionExist(address collectionAddress) public view returns (bool) {
require(false, stub_error);
collectionAddress;
dummy;
pallets/unique/src/lib.rsdiffbeforeafterboth--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -1105,6 +1105,15 @@
}
impl<T: Config> Pallet<T> {
+ /// Force set `sponsor` for `collection`.
+ ///
+ /// Differs from [`set_collection_sponsor`][`Pallet::set_collection_sponsor`] in that confirmation
+ /// from the `sponsor` is not required.
+ ///
+ /// # Arguments
+ ///
+ /// * `sponsor`: ID of the account of the sponsor-to-be.
+ /// * `collection_id`: ID of the modified collection.
pub fn force_set_sponsor(sponsor: T::AccountId, collection_id: CollectionId) -> DispatchResult {
let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
target_collection.check_is_internal()?;
@@ -1125,6 +1134,14 @@
target_collection.save()
}
+ /// Force remove `sponsor` for `collection`.
+ ///
+ /// Differs from `remove_sponsor` in that
+ /// it doesn't require consent from the `owner` of the collection.
+ ///
+ /// # Arguments
+ ///
+ /// * `collection_id`: ID of the modified collection.
pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult {
let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
target_collection.check_is_internal()?;
primitives/app_promotion_rpc/Cargo.tomldiffbeforeafterboth--- a/primitives/app_promotion_rpc/Cargo.toml
+++ b/primitives/app_promotion_rpc/Cargo.toml
@@ -14,7 +14,7 @@
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
[features]
default = ["std"]
primitives/common/CHANGELOG.mddiffbeforeafterboth--- a/primitives/common/CHANGELOG.md
+++ b/primitives/common/CHANGELOG.md
@@ -1,4 +1,9 @@
<!-- bureaucrate goes here -->
+## [v0.9.27] 2022-09-08
+
+### Added
+- Relay block constants. In particular, it is necessary to add the `AppPromotion` pallet at runtime.
+
## [v0.9.25] 2022-08-16
### Other changes
primitives/common/Cargo.tomldiffbeforeafterboth--- a/primitives/common/Cargo.toml
+++ b/primitives/common/Cargo.toml
@@ -48,9 +48,9 @@
[dependencies.fp-rpc]
default-features = false
git = "https://github.com/uniquenetwork/frontier"
-branch = "unique-polkadot-v0.9.27"
+branch = "unique-polkadot-v0.9.27-fee-limit"
[dependencies.pallet-evm]
default-features = false
git = "https://github.com/uniquenetwork/frontier"
-branch = "unique-polkadot-v0.9.27"
+branch = "unique-polkadot-v0.9.27-fee-limit"
primitives/data-structs/Cargo.tomldiffbeforeafterboth--- a/primitives/data-structs/Cargo.toml
+++ b/primitives/data-structs/Cargo.toml
@@ -25,7 +25,7 @@
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
derivative = { version = "2.2.0", features = ["use_core"] }
struct-versioning = { path = "../../crates/struct-versioning" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
rmrk-traits = { default-features = false, path = "../rmrk-traits" }
[features]
primitives/rpc/Cargo.tomldiffbeforeafterboth--- a/primitives/rpc/Cargo.toml
+++ b/primitives/rpc/Cargo.toml
@@ -14,7 +14,7 @@
sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
[features]
default = ["std"]
runtime/common/config/sponsoring.rsdiffbeforeafterboth--- a/runtime/common/config/sponsoring.rs
+++ b/runtime/common/config/sponsoring.rs
@@ -14,15 +14,17 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-use frame_support::parameter_types;
use crate::{
runtime_common::{sponsoring::UniqueSponsorshipHandler},
Runtime,
};
-use up_common::{types::BlockNumber, constants::*};
+use frame_support::parameter_types;
+use sp_core::U256;
+use up_common::{constants::*, types::BlockNumber};
parameter_types! {
pub const DefaultSponsoringRateLimit: BlockNumber = 1 * DAYS;
+ pub const DefaultSponsoringFeeLimit: U256 = U256::MAX;
}
type SponsorshipHandler = (
runtime/common/ethereum/sponsoring.rsdiffbeforeafterboth--- a/runtime/common/ethereum/sponsoring.rs
+++ b/runtime/common/ethereum/sponsoring.rs
@@ -16,27 +16,30 @@
//! Implements EVM sponsoring logic via TransactionValidityHack
+use core::{convert::TryInto, marker::PhantomData};
use evm_coder::{Call, abi::AbiReader};
use pallet_common::{CollectionHandle, eth::map_eth_to_id};
-use sp_core::H160;
+use pallet_evm::account::CrossAccountId;
+use pallet_evm_transaction_payment::CallContext;
+use pallet_nonfungible::{
+ Config as NonfungibleConfig,
+ erc::{
+ UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call,
+ TokenPropertiesCall,
+ },
+};
+use pallet_fungible::{
+ Config as FungibleConfig,
+ erc::{UniqueFungibleCall, ERC20Call},
+};
+use pallet_refungible::Config as RefungibleConfig;
+use pallet_unique::Config as UniqueConfig;
use sp_std::prelude::*;
+use up_data_structs::{CollectionMode, CreateItemData, CreateNftData, TokenId};
use up_sponsorship::SponsorshipHandler;
-use core::marker::PhantomData;
-use core::convert::TryInto;
-use pallet_evm::account::CrossAccountId;
-use up_data_structs::{TokenId, CreateItemData, CreateNftData, CollectionMode};
-use pallet_unique::Config as UniqueConfig;
use crate::{Runtime, runtime_common::sponsoring::*};
-use pallet_nonfungible::erc::{
- UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call, TokenPropertiesCall,
-};
-use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};
-use pallet_fungible::Config as FungibleConfig;
-use pallet_nonfungible::Config as NonfungibleConfig;
-use pallet_refungible::Config as RefungibleConfig;
-
pub type EvmSponsorshipHandler = (
UniqueEthSponsorshipHandler<Runtime>,
pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,
@@ -44,13 +47,16 @@
pub struct UniqueEthSponsorshipHandler<T: UniqueConfig>(PhantomData<*const T>);
impl<T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig>
- SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)> for UniqueEthSponsorshipHandler<T>
+ SponsorshipHandler<T::CrossAccountId, CallContext> for UniqueEthSponsorshipHandler<T>
{
- fn get_sponsor(who: &T::CrossAccountId, call: &(H160, Vec<u8>)) -> Option<T::CrossAccountId> {
- let collection_id = map_eth_to_id(&call.0)?;
+ fn get_sponsor(
+ who: &T::CrossAccountId,
+ call_context: &CallContext,
+ ) -> Option<T::CrossAccountId> {
+ let collection_id = map_eth_to_id(&call_context.contract_address)?;
let collection = <CollectionHandle<T>>::new(collection_id)?;
let sponsor = collection.sponsorship.sponsor()?.clone();
- let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;
+ let (method_id, mut reader) = AbiReader::new_call(&call_context.input).ok()?;
Some(T::CrossAccountId::from_sub(match &collection.mode {
CollectionMode::NFT => {
let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;
runtime/opal/CHANGELOG.mddiffbeforeafterboth--- a/runtime/opal/CHANGELOG.md
+++ b/runtime/opal/CHANGELOG.md
@@ -3,16 +3,23 @@
All notable changes to this project will be documented in this file.
<!-- bureaucrate goes here -->
+
+## [v0.9.27] 2022-09-08
+
+### Added
+
+- `AppPromotion` pallet to runtime.
+
## [v0.9.27] 2022-08-16
### Bugfixes
-- Add missing config keys 74f532ac28dce15c15e7d576c074a58eba658c08
+- Add missing config keys 74f532ac28dce15c15e7d576c074a58eba658c08
### Other changes
-- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
+- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
-- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
+- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
-- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
+- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
runtime/opal/Cargo.tomldiffbeforeafterboth--- a/runtime/opal/Cargo.toml
+++ b/runtime/opal/Cargo.toml
@@ -417,7 +417,7 @@
up-rpc = { path = "../../primitives/rpc", default-features = false }
app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}
rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
pallet-inflation = { path = '../../pallets/inflation', default-features = false }
pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
up-data-structs = { path = '../../primitives/data-structs', default-features = false }
@@ -436,13 +436,13 @@
pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }
pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }
pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
-up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' }
+up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
################################################################################
# Build Dependencies
runtime/quartz/CHANGELOG.mddiffbeforeafterboth--- a/runtime/quartz/CHANGELOG.md
+++ b/runtime/quartz/CHANGELOG.md
@@ -3,17 +3,23 @@
All notable changes to this project will be documented in this file.
<!-- bureaucrate goes here -->
+
+## [v0.9.27] 2022-09-08
+
+### Added
+
+- `AppPromotion` pallet to runtime.
+
## [v0.9.27] 2022-08-16
### Bugfixes
-- Add missing config keys 74f532ac28dce15c15e7d576c074a58eba658c08
+- Add missing config keys 74f532ac28dce15c15e7d576c074a58eba658c08
### Other changes
-- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
+- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
-- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
+- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
-- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
-
+- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
runtime/quartz/Cargo.tomldiffbeforeafterboth--- a/runtime/quartz/Cargo.toml
+++ b/runtime/quartz/Cargo.toml
@@ -418,7 +418,7 @@
pallet-unique = { path = '../../pallets/unique', default-features = false }
up-rpc = { path = "../../primitives/rpc", default-features = false }
app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false}
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
pallet-inflation = { path = '../../pallets/inflation', default-features = false }
pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
up-data-structs = { path = '../../primitives/data-structs', default-features = false }
@@ -437,13 +437,13 @@
pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }
pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }
pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
-up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' }
+up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
################################################################################
# Build Dependencies
runtime/tests/Cargo.tomldiffbeforeafterboth--- a/runtime/tests/Cargo.toml
+++ b/runtime/tests/Cargo.toml
@@ -16,7 +16,7 @@
sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
@@ -25,8 +25,8 @@
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
pallet-common = { path = '../../pallets/common' }
pallet-structure = { path = '../../pallets/structure' }
@@ -43,4 +43,4 @@
scale-info = "*"
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
-up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' }
+up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
runtime/unique/CHANGELOG.mddiffbeforeafterboth--- a/runtime/unique/CHANGELOG.md
+++ b/runtime/unique/CHANGELOG.md
@@ -3,16 +3,23 @@
All notable changes to this project will be documented in this file.
<!-- bureaucrate goes here -->
+
+## [v0.9.27] 2022-09-08
+
+### Added
+
+- `AppPromotion` pallet to runtime.
+
## [v0.9.27] 2022-08-16
### Bugfixes
-- Add missing config keys 74f532ac28dce15c15e7d576c074a58eba658c08
+- Add missing config keys 74f532ac28dce15c15e7d576c074a58eba658c08
### Other changes
-- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
+- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
-- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
+- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
-- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
+- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
runtime/unique/Cargo.tomldiffbeforeafterboth--- a/runtime/unique/Cargo.toml
+++ b/runtime/unique/Cargo.toml
@@ -430,14 +430,14 @@
pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }
pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }
pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" }
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
+fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27-fee-limit" }
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
-up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.27' }
+up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.27" }
################################################################################
# Build Dependencies
tests/package.jsondiffbeforeafterboth--- a/tests/package.json
+++ b/tests/package.json
@@ -73,6 +73,7 @@
"testRemoveFromContractAllowList": "mocha --timeout 9999999 -r ts-node/register ./**/removeFromContractAllowList.test.ts",
"testSetContractSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setContractSponsoringRateLimit.test.ts",
"testSetOffchainSchema": "mocha --timeout 9999999 -r ts-node/register ./**/setOffchainSchema.test.ts",
+ "testNextSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/nextSponsoring.test.ts",
"testOverflow": "mocha --timeout 9999999 -r ts-node/register ./**/overflow.test.ts",
"testInflation": "mocha --timeout 9999999 -r ts-node/register ./**/inflation.test.ts",
"testScheduler": "mocha --timeout 9999999 -r ts-node/register ./**/scheduler.test.ts",
@@ -99,7 +100,7 @@
"dependencies": {
"@polkadot/api": "9.2.2",
"@polkadot/api-contract": "9.2.2",
- "@polkadot/util-crypto": "10.1.1",
+ "@polkadot/util-crypto": "10.1.7",
"bignumber.js": "^9.0.2",
"chai-as-promised": "^7.1.1",
"chai-like": "^1.1.1",
tests/scripts/readyness.jsdiffbeforeafterboth--- a/tests/scripts/readyness.js
+++ b/tests/scripts/readyness.js
@@ -6,9 +6,9 @@
await api.isReadyOrError;
const head = (await api.rpc.chain.getHeader()).number.toNumber();
+ await api.disconnect();
if(head < 1) throw Error('No block #1');
- await api.disconnect();
}
const sleep = time => {
tests/src/addCollectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/addCollectionAdmin.test.ts
+++ b/tests/src/addCollectionAdmin.test.ts
@@ -15,121 +15,111 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
import {IKeyringPair} from '@polkadot/types/types';
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import {usingPlaygrounds} from './util/playgrounds';
+import {itSub, usingPlaygrounds, expect} from './util/playgrounds';
-chai.use(chaiAsPromised);
-const expect = chai.expect;
+describe('Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
+ let donor: IKeyringPair;
-let donor: IKeyringPair;
-
-before(async () => {
- await usingPlaygrounds(async (_, privateKeyWrapper) => {
- donor = privateKeyWrapper('//Alice');
+ before(async () => {
+ await usingPlaygrounds(async (_, privateKeyWrapper) => {
+ donor = privateKeyWrapper('//Alice');
+ });
});
-});
-describe('Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
- it('Add collection admin.', async () => {
- await usingPlaygrounds(async (helper) => {
- const [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor);
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
+ itSub('Add collection admin.', async ({helper}) => {
+ const [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor);
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
- const collection = await helper.collection.getData(collectionId);
- expect(collection!.normalizedOwner!).to.be.equal(alice.address);
+ const collection = await helper.collection.getData(collectionId);
+ expect(collection!.normalizedOwner!).to.be.equal(helper.address.normalizeSubstrate(alice.address));
- await helper.nft.addAdmin(alice, collectionId, {Substrate: bob.address});
+ await helper.nft.addAdmin(alice, collectionId, {Substrate: bob.address});
- const adminListAfterAddAdmin = await helper.collection.getAdmins(collectionId);
- expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: bob.address});
- });
+ const adminListAfterAddAdmin = await helper.collection.getAdmins(collectionId);
+ expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: bob.address});
});
});
describe('Negative Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
- it("Not owner can't add collection admin.", async () => {
- await usingPlaygrounds(async (helper) => {
- const [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
+ let donor: IKeyringPair;
+
+ before(async () => {
+ await usingPlaygrounds(async (_, privateKeyWrapper) => {
+ donor = privateKeyWrapper('//Alice');
+ });
+ });
- const collection = await helper.collection.getData(collectionId);
- expect(collection?.normalizedOwner).to.be.equal(alice.address);
+ itSub("Not owner can't add collection admin.", async ({helper}) => {
+ const [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
- const changeAdminTxBob = async () => helper.collection.addAdmin(bob, collectionId, {Substrate: bob.address});
- const changeAdminTxCharlie = async () => helper.collection.addAdmin(bob, collectionId, {Substrate: charlie.address});
- await expect(changeAdminTxCharlie()).to.be.rejected;
- await expect(changeAdminTxBob()).to.be.rejected;
+ const collection = await helper.collection.getData(collectionId);
+ expect(collection?.normalizedOwner).to.be.equal(helper.address.normalizeSubstrate(alice.address));
+
+ const changeAdminTxBob = async () => helper.collection.addAdmin(bob, collectionId, {Substrate: bob.address});
+ const changeAdminTxCharlie = async () => helper.collection.addAdmin(bob, collectionId, {Substrate: charlie.address});
+ await expect(changeAdminTxCharlie()).to.be.rejectedWith(/common\.NoPermission/);
+ await expect(changeAdminTxBob()).to.be.rejectedWith(/common\.NoPermission/);
- const adminListAfterAddAdmin = await helper.collection.getAdmins(collectionId);
- expect(adminListAfterAddAdmin).to.be.not.deep.contains({Substrate: charlie.address});
- expect(adminListAfterAddAdmin).to.be.not.deep.contains({Substrate: bob.address});
- });
+ const adminListAfterAddAdmin = await helper.collection.getAdmins(collectionId);
+ expect(adminListAfterAddAdmin).to.be.not.deep.contains({Substrate: charlie.address});
+ expect(adminListAfterAddAdmin).to.be.not.deep.contains({Substrate: bob.address});
});
- it("Admin can't add collection admin.", async () => {
- await usingPlaygrounds(async (helper) => {
- const [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
- const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
+ itSub("Admin can't add collection admin.", async ({helper}) => {
+ const [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
+ const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
- await collection.addAdmin(alice, {Substrate: bob.address});
+ await collection.addAdmin(alice, {Substrate: bob.address});
- const adminListAfterAddAdmin = await collection.getAdmins();
- expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: bob.address});
+ const adminListAfterAddAdmin = await collection.getAdmins();
+ expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: bob.address});
- const changeAdminTxCharlie = async () => collection.addAdmin(bob, {Substrate: charlie.address});
- await expect(changeAdminTxCharlie()).to.be.rejected;
+ const changeAdminTxCharlie = async () => collection.addAdmin(bob, {Substrate: charlie.address});
+ await expect(changeAdminTxCharlie()).to.be.rejectedWith(/common\.NoPermission/);
- const adminListAfterAddNewAdmin = await collection.getAdmins();
- expect(adminListAfterAddNewAdmin).to.be.deep.contains({Substrate: bob.address});
- expect(adminListAfterAddNewAdmin).to.be.not.deep.contains({Substrate: charlie.address});
- });
+ const adminListAfterAddNewAdmin = await collection.getAdmins();
+ expect(adminListAfterAddNewAdmin).to.be.deep.contains({Substrate: bob.address});
+ expect(adminListAfterAddNewAdmin).to.be.not.deep.contains({Substrate: charlie.address});
});
- it("Can't add collection admin of not existing collection.", async () => {
- await usingPlaygrounds(async (helper) => {
- const [alice, bob] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
- // tslint:disable-next-line: no-bitwise
- const collectionId = (1 << 32) - 1;
+ itSub("Can't add collection admin of not existing collection.", async ({helper}) => {
+ const [alice, bob] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
+ const collectionId = (1 << 32) - 1;
- const addAdminTx = async () => helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});
- await expect(addAdminTx()).to.be.rejected;
+ const addAdminTx = async () => helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});
+ await expect(addAdminTx()).to.be.rejectedWith(/common\.CollectionNotFound/);
- // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
- await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
- });
+ // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
+ await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
});
- it("Can't add an admin to a destroyed collection.", async () => {
- await usingPlaygrounds(async (helper) => {
- const [alice, bob] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
- const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
+ itSub("Can't add an admin to a destroyed collection.", async ({helper}) => {
+ const [alice, bob] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
+ const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
- await collection.burn(alice);
- const addAdminTx = async () => collection.addAdmin(alice, {Substrate: bob.address});
- await expect(addAdminTx()).to.be.rejected;
+ await collection.burn(alice);
+ const addAdminTx = async () => collection.addAdmin(alice, {Substrate: bob.address});
+ await expect(addAdminTx()).to.be.rejectedWith(/common\.CollectionNotFound/);
- // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
- await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
- });
+ // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
+ await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
});
- it('Add an admin to a collection that has reached the maximum number of admins limit', async () => {
- await usingPlaygrounds(async (helper) => {
- const [alice, ...accounts] = await helper.arrange.createAccounts([10n, 0n, 0n, 0n, 0n, 0n, 0n, 0n], donor);
- const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
+ itSub('Add an admin to a collection that has reached the maximum number of admins limit', async ({helper}) => {
+ const [alice, ...accounts] = await helper.arrange.createAccounts([10n, 0n, 0n, 0n, 0n, 0n, 0n, 0n], donor);
+ const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
- const chainAdminLimit = (helper.api!.consts.common.collectionAdminsLimit as any).toNumber();
- expect(chainAdminLimit).to.be.equal(5);
+ const chainAdminLimit = (helper.api!.consts.common.collectionAdminsLimit as any).toNumber();
+ expect(chainAdminLimit).to.be.equal(5);
- for (let i = 0; i < chainAdminLimit; i++) {
- await collection.addAdmin(alice, {Substrate: accounts[i].address});
- const adminListAfterAddAdmin = await collection.getAdmins();
- expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: accounts[i].address});
- }
+ for (let i = 0; i < chainAdminLimit; i++) {
+ await collection.addAdmin(alice, {Substrate: accounts[i].address});
+ const adminListAfterAddAdmin = await collection.getAdmins();
+ expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: accounts[i].address});
+ }
- const addExtraAdminTx = async () => collection.addAdmin(alice, {Substrate: accounts[chainAdminLimit].address});
- await expect(addExtraAdminTx()).to.be.rejected;
- });
+ const addExtraAdminTx = async () => collection.addAdmin(alice, {Substrate: accounts[chainAdminLimit].address});
+ await expect(addExtraAdminTx()).to.be.rejectedWith(/common\.CollectionAdminCountExceeded/);
});
});
tests/src/approve.test.tsdiffbeforeafterboth--- a/tests/src/approve.test.ts
+++ b/tests/src/approve.test.ts
@@ -15,26 +15,8 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
import {IKeyringPair} from '@polkadot/types/types';
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import {
- approveExpectFail,
- approveExpectSuccess,
- createCollectionExpectSuccess,
- createItemExpectSuccess,
-} from './util/helpers';
-import {usingPlaygrounds} from './util/playgrounds';
-
-let donor: IKeyringPair;
-
-before(async () => {
- await usingPlaygrounds(async (_, privateKey) => {
- donor = privateKey('//Alice');
- });
-});
+import {expect, itSub, Pallets, usingPlaygrounds} from './util/playgrounds';
-chai.use(chaiAsPromised);
-const expect = chai.expect;
describe('Integration Test approve(spender, collection_id, item_id, amount):', () => {
let alice: IKeyringPair;
@@ -42,89 +24,76 @@
let charlie: IKeyringPair;
before(async () => {
- await usingPlaygrounds(async (helper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
[alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
});
});
- it('[nft] Execute the extrinsic and check approvedList', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
- await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
- expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;
- });
+ itSub('[nft] Execute the extrinsic and check approvedList', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
+ await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
+ expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;
});
- it('[fungible] Execute the extrinsic and check approvedList', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
- await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);
- const tokenId = await helper.ft.getLastTokenId(collectionId);
- await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
- const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- expect(amount).to.be.equal(BigInt(1));
- });
+ itSub('[fungible] Execute the extrinsic and check approvedList', async ({helper}) => {
+ const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+ await helper.ft.mintTokens(alice, collectionId, 10n, {Substrate: alice.address});
+ const tokenId = await helper.ft.getLastTokenId(collectionId);
+ await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
+ const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ expect(amount).to.be.equal(BigInt(1));
});
- it('[refungible] Execute the extrinsic and check approvedList', async function() {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
- await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
- const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- expect(amount).to.be.equal(BigInt(1));
- });
+ itSub.ifWithPallets('[refungible] Execute the extrinsic and check approvedList', [Pallets.ReFungible], async ({helper}) => {
+ const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
+ await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
+ const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ expect(amount).to.be.equal(BigInt(1));
});
- it('[nft] Remove approval by using 0 amount', async () => {
- await usingPlaygrounds(async (helper) => {
- const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const collectionId = collection.collectionId;
- const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
- await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
- expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;
- await helper.signTransaction(alice, helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0));
- expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;
- });
+ itSub('[nft] Remove approval by using 0 amount', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const collectionId = collection.collectionId;
+ const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
+ await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
+ expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;
+ await helper.signTransaction(alice, helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0));
+ expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;
});
- it('[fungible] Remove approval by using 0 amount', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
- await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);
- const tokenId = await helper.ft.getLastTokenId(collectionId);
- await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
- const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- expect(amountBefore).to.be.equal(BigInt(1));
+ itSub('[fungible] Remove approval by using 0 amount', async ({helper}) => {
+ const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+ await helper.ft.mintTokens(alice, collectionId, 10n, {Substrate: alice.address});
+ const tokenId = await helper.ft.getLastTokenId(collectionId);
+ await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
+ const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ expect(amountBefore).to.be.equal(BigInt(1));
- await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
- const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- expect(amountAfter).to.be.equal(BigInt(0));
- });
+ await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
+ const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ expect(amountAfter).to.be.equal(BigInt(0));
});
- it('[refungible] Remove approval by using 0 amount', async function() {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
- await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
- const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- expect(amountBefore).to.be.equal(BigInt(1));
+ itSub.ifWithPallets('[refungible] Remove approval by using 0 amount', [Pallets.ReFungible], async ({helper}) => {
+ const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
+ await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
+ const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ expect(amountBefore).to.be.equal(BigInt(1));
- await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
- const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- expect(amountAfter).to.be.equal(BigInt(0));
- });
+ await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
+ const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ expect(amountAfter).to.be.equal(BigInt(0));
});
- it('can`t be called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
- const approveTokenTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});
- await expect(approveTokenTx()).to.be.rejected;
- });
+ itSub('can`t be called by collection owner on non-owned item when OwnerCanTransfer == false', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
+ const approveTokenTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});
+ await expect(approveTokenTx()).to.be.rejected;
});
});
@@ -134,39 +103,34 @@
let charlie: IKeyringPair;
before(async () => {
- await usingPlaygrounds(async (helper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
[alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
});
});
- it('NFT', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
- await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
- expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.true;
- });
+ itSub('NFT', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
+ await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
+ expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.true;
});
- it('Fungible up to an approved amount', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
- await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);
- const tokenId = await helper.ft.getLastTokenId(collectionId);
- await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
- const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});
- expect(amount).to.be.equal(BigInt(1));
- });
+ itSub('Fungible up to an approved amount', async ({helper}) => {
+ const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+ await helper.ft.mintTokens(alice, collectionId, 10n, bob.address);
+ const tokenId = await helper.ft.getLastTokenId(collectionId);
+ await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
+ const amount = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});
+ expect(amount).to.be.equal(BigInt(1));
});
- it('ReFungible up to an approved amount', async function() {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});
- await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address}, 100n);
- const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});
- expect(amount).to.be.equal(BigInt(100n));
- });
+ itSub.ifWithPallets('ReFungible up to an approved amount', [Pallets.ReFungible], async ({helper}) => {
+ const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});
+ await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address}, 100n);
+ const amount = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: charlie.address}, {Substrate: bob.address});
+ expect(amount).to.be.equal(BigInt(100n));
});
});
@@ -176,45 +140,40 @@
let charlie: IKeyringPair;
before(async () => {
- await usingPlaygrounds(async (helper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
[alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
});
});
- it('NFT', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
- await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
- await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- const owner = await helper.nft.getTokenOwner(collectionId, tokenId);
- expect(owner.Substrate).to.be.equal(alice.address);
- });
+ itSub('NFT', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
+ await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
+ await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ const owner = await helper.nft.getTokenOwner(collectionId, tokenId);
+ expect(owner.Substrate).to.be.equal(alice.address);
});
- it('Fungible up to an approved amount', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
- await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);
- const tokenId = await helper.ft.getLastTokenId(collectionId);
- await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
- const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
- await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);
- const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
- expect(after - before).to.be.equal(BigInt(1));
- });
+ itSub('Fungible up to an approved amount', async ({helper}) => {
+ const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+ await helper.ft.mintTokens(alice, collectionId, 10n, bob.address);
+ const tokenId = await helper.ft.getLastTokenId(collectionId);
+ await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
+ const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
+ await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);
+ const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
+ expect(after - before).to.be.equal(BigInt(1));
});
- it('ReFungible up to an approved amount', async function() {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});
- await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
- const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
- await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);
- const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
- expect(after - before).to.be.equal(BigInt(1));
- });
+ itSub.ifWithPallets('ReFungible up to an approved amount', [Pallets.ReFungible], async ({helper}) => {
+ const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});
+ await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
+ const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
+ await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);
+ const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
+ expect(after - before).to.be.equal(BigInt(1));
});
});
@@ -224,52 +183,47 @@
let charlie: IKeyringPair;
before(async () => {
- await usingPlaygrounds(async (helper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
[alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
});
});
- it('NFT', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
- await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
- await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- const owner = await helper.nft.getTokenOwner(collectionId, tokenId);
- expect(owner.Substrate).to.be.equal(alice.address);
- const transferTokenFromTx = async () => helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- await expect(transferTokenFromTx()).to.be.rejected;
- });
+ itSub('NFT', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
+ await helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
+ await helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ const owner = await helper.nft.getTokenOwner(collectionId, tokenId);
+ expect(owner.Substrate).to.be.equal(alice.address);
+ const transferTokenFromTx = async () => helper.nft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ await expect(transferTokenFromTx()).to.be.rejected;
});
- it('Fungible up to an approved amount', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
- await helper.ft.mintTokens(alice, collectionId, bob.address, 10n);
- const tokenId = await helper.ft.getLastTokenId(collectionId);
- await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
- const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
- await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);
- const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
- expect(after - before).to.be.equal(BigInt(1));
+ itSub('Fungible up to an approved amount', async ({helper}) => {
+ const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+ await helper.ft.mintTokens(alice, collectionId, 10n, bob.address);
+ const tokenId = await helper.ft.getLastTokenId(collectionId);
+ await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
+ const before = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
+ await helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);
+ const after = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
+ expect(after - before).to.be.equal(BigInt(1));
- const transferTokenFromTx = async () => helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);
- await expect(transferTokenFromTx()).to.be.rejected;
- });
+ const transferTokenFromTx = async () => helper.ft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 1n);
+ await expect(transferTokenFromTx()).to.be.rejected;
});
- it('ReFungible up to an approved amount', async function() {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});
- await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address}, 100n);
- const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
- await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);
- const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
- expect(after - before).to.be.equal(BigInt(100));
- const transferTokenFromTx = async () => helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);
- await expect(transferTokenFromTx()).to.be.rejected;
- });
+ itSub.ifWithPallets('ReFungible up to an approved amount', [Pallets.ReFungible], async ({helper}) => {
+ const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: bob.address, pieces: 100n});
+ await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address}, 100n);
+ const before = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
+ await helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);
+ const after = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
+ expect(after - before).to.be.equal(BigInt(100));
+ const transferTokenFromTx = async () => helper.rft.transferTokenFrom(charlie, collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address}, 100n);
+ await expect(transferTokenFromTx()).to.be.rejected;
});
});
@@ -280,28 +234,27 @@
let dave: IKeyringPair;
before(async () => {
- await usingPlaygrounds(async (helper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
[alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);
});
});
- it('If a user B is approved to transfer 10 Fungible tokens from user A, they can transfer 2 tokens to user C, which will result in decreasing approval from 10 to 8. Then user B can transfer 8 tokens to user D.', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
- await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);
- const tokenId = await helper.ft.getLastTokenId(collectionId);
- await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);
+ itSub('If a user B is approved to transfer 10 Fungible tokens from user A, they can transfer 2 tokens to user C, which will result in decreasing approval from 10 to 8. Then user B can transfer 8 tokens to user D.', async ({helper}) => {
+ const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+ await helper.ft.mintTokens(alice, collectionId, 10n, alice.address);
+ const tokenId = await helper.ft.getLastTokenId(collectionId);
+ await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);
- const charlieBefore = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});
- await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: charlie.address}, 2n);
- const charlieAfter = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});
- expect(charlieAfter - charlieBefore).to.be.equal(BigInt(2));
+ const charlieBefore = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});
+ await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: charlie.address}, 2n);
+ const charlieAfter = await helper.ft.getBalance(collectionId, {Substrate: charlie.address});
+ expect(charlieAfter - charlieBefore).to.be.equal(BigInt(2));
- const daveBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});
- await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: dave.address}, 8n);
- const daveAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});
- expect(daveAfter - daveBefore).to.be.equal(BigInt(8));
- });
+ const daveBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});
+ await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: alice.address}, {Substrate: dave.address}, 8n);
+ const daveAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});
+ expect(daveAfter - daveBefore).to.be.equal(BigInt(8));
});
});
@@ -311,57 +264,52 @@
let charlie: IKeyringPair;
before(async () => {
- await usingPlaygrounds(async (helper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
[alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
});
});
- it('NFT', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
- await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
- expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;
- await helper.signTransaction(alice, helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0));
- expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;
- const transferTokenFromTx = async () => helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: bob.address});
- await expect(transferTokenFromTx()).to.be.rejected;
- });
+ itSub('NFT', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
+ await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
+ expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;
+ await helper.signTransaction(alice, helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0));
+ expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;
+ const transferTokenFromTx = async () => helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: bob.address});
+ await expect(transferTokenFromTx()).to.be.rejected;
});
- it('Fungible', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
- await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);
- const tokenId = await helper.ft.getLastTokenId(collectionId);
- await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
- const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- expect(amountBefore).to.be.equal(BigInt(1));
+ itSub('Fungible', async ({helper}) => {
+ const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+ await helper.ft.mintTokens(alice, collectionId, 10n, alice.address);
+ const tokenId = await helper.ft.getLastTokenId(collectionId);
+ await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
+ const amountBefore = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ expect(amountBefore).to.be.equal(BigInt(1));
- await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
- const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- expect(amountAfter).to.be.equal(BigInt(0));
+ await helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
+ const amountAfter = await helper.ft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ expect(amountAfter).to.be.equal(BigInt(0));
- const transferTokenFromTx = async () => helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 1n);
- await expect(transferTokenFromTx()).to.be.rejected;
- });
+ const transferTokenFromTx = async () => helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 1n);
+ await expect(transferTokenFromTx()).to.be.rejected;
});
- it('ReFungible', async function() {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
- await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
- const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- expect(amountBefore).to.be.equal(BigInt(1));
+ itSub.ifWithPallets('ReFungible', [Pallets.ReFungible], async ({helper}) => {
+ const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
+ await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});
+ const amountBefore = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ expect(amountBefore).to.be.equal(BigInt(1));
- await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
- const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
- expect(amountAfter).to.be.equal(BigInt(0));
+ await helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 0n);
+ const amountAfter = await helper.rft.getTokenApprovedPieces(collectionId, tokenId, {Substrate: bob.address}, {Substrate: alice.address});
+ expect(amountAfter).to.be.equal(BigInt(0));
- const transferTokenFromTx = async () => helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 100n);
- await expect(transferTokenFromTx()).to.be.rejected;
- });
+ const transferTokenFromTx = async () => helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: charlie.address}, 100n);
+ await expect(transferTokenFromTx()).to.be.rejected;
});
});
@@ -371,38 +319,33 @@
let charlie: IKeyringPair;
before(async () => {
- await usingPlaygrounds(async (helper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
[alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
});
});
- it('1 for NFT', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
- const approveTx = async () => helper.signTransaction(bob, helper.api?.tx.unique.approve({Substrate: charlie.address}, collectionId, tokenId, 2));
- await expect(approveTx()).to.be.rejected;
- expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.false;
- });
+ itSub('1 for NFT', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
+ const approveTx = async () => helper.signTransaction(bob, helper.api?.tx.unique.approve({Substrate: charlie.address}, collectionId, tokenId, 2));
+ await expect(approveTx()).to.be.rejected;
+ expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.false;
});
- it('Fungible', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
- await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);
- const tokenId = await helper.ft.getLastTokenId(collectionId);
- const approveTx = async () => helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 11n);
- await expect(approveTx()).to.be.rejected;
- });
+ itSub('Fungible', async ({helper}) => {
+ const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+ await helper.ft.mintTokens(alice, collectionId, 10n, alice.address);
+ const tokenId = await helper.ft.getLastTokenId(collectionId);
+ const approveTx = async () => helper.ft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 11n);
+ await expect(approveTx()).to.be.rejected;
});
- it('ReFungible', async function() {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
- const approveTx = async () => helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 101n);
- await expect(approveTx()).to.be.rejected;
- });
+ itSub.ifWithPallets('ReFungible', [Pallets.ReFungible], async ({helper}) => {
+ const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
+ const approveTx = async () => helper.rft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address}, 101n);
+ await expect(approveTx()).to.be.rejected;
});
});
@@ -413,67 +356,62 @@
let dave: IKeyringPair;
before(async () => {
- await usingPlaygrounds(async (helper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
[alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);
});
});
- it('NFT', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});
- const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: charlie.address});
+ itSub('NFT', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});
+ const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: charlie.address});
- await helper.nft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address});
- const owner1 = await helper.nft.getTokenOwner(collectionId, tokenId);
- expect(owner1.Substrate).to.be.equal(dave.address);
+ await helper.nft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address});
+ const owner1 = await helper.nft.getTokenOwner(collectionId, tokenId);
+ expect(owner1.Substrate).to.be.equal(dave.address);
- await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});
- await helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address});
- const owner2 = await helper.nft.getTokenOwner(collectionId, tokenId);
- expect(owner2.Substrate).to.be.equal(alice.address);
- });
+ await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});
+ await helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address});
+ const owner2 = await helper.nft.getTokenOwner(collectionId, tokenId);
+ expect(owner2.Substrate).to.be.equal(alice.address);
});
- it('Fungible up to an approved amount', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
- await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});
- await helper.ft.mintTokens(alice, collectionId, charlie.address, 10n);
- const tokenId = await helper.ft.getLastTokenId(collectionId);
+ itSub('Fungible up to an approved amount', async ({helper}) => {
+ const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);
+ await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});
+ await helper.ft.mintTokens(alice, collectionId, 10n, charlie.address);
+ const tokenId = await helper.ft.getLastTokenId(collectionId);
- const daveBalanceBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});
- await helper.ft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address}, 1n);
- const daveBalanceAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});
- expect(daveBalanceAfter - daveBalanceBefore).to.be.equal(BigInt(1));
+ const daveBalanceBefore = await helper.ft.getBalance(collectionId, {Substrate: dave.address});
+ await helper.ft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address}, 1n);
+ const daveBalanceAfter = await helper.ft.getBalance(collectionId, {Substrate: dave.address});
+ expect(daveBalanceAfter - daveBalanceBefore).to.be.equal(BigInt(1));
- await helper.collection.addAdmin(alice ,collectionId, {Substrate: bob.address});
+ await helper.collection.addAdmin(alice ,collectionId, {Substrate: bob.address});
- const aliceBalanceBefore = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
- await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address}, 1n);
- const aliceBalanceAfter = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
- expect(aliceBalanceAfter - aliceBalanceBefore).to.be.equal(BigInt(1));
- });
+ const aliceBalanceBefore = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
+ await helper.ft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address}, 1n);
+ const aliceBalanceAfter = await helper.ft.getBalance(collectionId, {Substrate: alice.address});
+ expect(aliceBalanceAfter - aliceBalanceBefore).to.be.equal(BigInt(1));
});
- it('ReFungible up to an approved amount', async function() {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});
- const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: charlie.address, pieces: 100n});
+ itSub.ifWithPallets('ReFungible up to an approved amount', [Pallets.ReFungible], async ({helper}) => {
+ const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: true});
+ const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: charlie.address, pieces: 100n});
- const daveBefore = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: dave.address});
- await helper.rft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address}, 1n);
- const daveAfter = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: dave.address});
- expect(daveAfter - daveBefore).to.be.equal(BigInt(1));
+ const daveBefore = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: dave.address});
+ await helper.rft.transferTokenFrom(alice, collectionId, tokenId, {Substrate: charlie.address}, {Substrate: dave.address}, 1n);
+ const daveAfter = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: dave.address});
+ expect(daveAfter - daveBefore).to.be.equal(BigInt(1));
- await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});
+ await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});
- const aliceBefore = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
- await helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address}, 1n);
- const aliceAfter = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
- expect(aliceAfter - aliceBefore).to.be.equal(BigInt(1));
- });
+ const aliceBefore = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
+ await helper.rft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: dave.address}, {Substrate: alice.address}, 1n);
+ const aliceAfter = await helper.rft.getTokenBalance(collectionId, tokenId, {Substrate: alice.address});
+ expect(aliceAfter - aliceBefore).to.be.equal(BigInt(1));
});
});
@@ -484,45 +422,48 @@
let dave: IKeyringPair;
before(async () => {
- await usingPlaygrounds(async (helper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
[alice, bob, charlie, dave] = await helper.arrange.createAccounts([100n, 100n, 100n, 100n], donor);
});
});
- it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. Fungible', async () => {
- const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});
- await createItemExpectSuccess(alice, collectionId, 'Fungible', alice.address);
- await approveExpectSuccess(collectionId, 0, alice, bob.address, 1);
- await approveExpectSuccess(collectionId, 0, alice, charlie.address, 1);
+ itSub.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. Fungible', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {});
+ await collection.mint(alice, 10n);
+ await collection.approveTokens(alice, {Substrate: bob.address}, 1n);
+ await collection.approveTokens(alice, {Substrate: charlie.address}, 1n);
// const allowances1 = await getAllowance(collectionId, 0, Alice.address, Bob.address);
// const allowances2 = await getAllowance(collectionId, 0, Alice.address, Charlie.address);
// expect(allowances1 + allowances2).to.be.eq(BigInt(2));
});
- it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. ReFungible', async () => {
- const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
- const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', alice.address);
- await approveExpectSuccess(collectionId, itemId, alice, bob.address, 1);
- await approveExpectSuccess(collectionId, itemId, alice, charlie.address, 1);
+ itSub.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. ReFungible', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {});
+ const token = await collection.mintToken(alice, 10n);
+ await token.approve(alice, {Substrate: bob.address}, 1n);
+ await token.approve(alice, {Substrate: charlie.address}, 1n);
// const allowances1 = await getAllowance(collectionId, itemId, Alice.address, Bob.address);
// const allowances2 = await getAllowance(collectionId, itemId, Alice.address, Charlie.address);
// expect(allowances1 + allowances2).to.be.eq(BigInt(2));
});
// Canceled by changing approve logic
- it.skip('Cannot approve for more than total user`s amount (owned: 10, approval 1: 5 - should succeed, approval 2: 6 - should fail). Fungible', async () => {
- const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});
- await createItemExpectSuccess(alice, collectionId, 'Fungible', dave.address);
- await approveExpectSuccess(collectionId, 0, dave, bob.address, 5);
- await approveExpectFail(collectionId, 0, dave, charlie, 6);
+ itSub.skip('Cannot approve for more than total user\'s amount (owned: 10, approval 1: 5 - should succeed, approval 2: 6 - should fail). Fungible', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {});
+ await collection.mint(alice, 10n, {Substrate: dave.address});
+ await collection.approveTokens(dave, {Substrate: bob.address}, 5n);
+ await expect(collection.approveTokens(dave, {Substrate: charlie.address}, 6n))
+ .to.be.rejectedWith('this test would fail (since it is skipped), replace this expecting message with what would have been received');
});
// Canceled by changing approve logic
- it.skip('Cannot approve for more than total users amount (owned: 100, approval 1: 50 - should succeed, approval 2: 51 - should fail). ReFungible', async () => {
- const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
- const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', dave.address);
- await approveExpectSuccess(collectionId, itemId, dave, bob.address, 50);
- await approveExpectFail(collectionId, itemId, dave, charlie, 51);
+ itSub.skip('Cannot approve for more than total user\'s amount (owned: 100, approval 1: 50 - should succeed, approval 2: 51 - should fail). ReFungible', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {});
+ const token = await collection.mintToken(alice, 100n, {Substrate: dave.address});
+ await token.approve(dave, {Substrate: bob.address}, 50n);
+ await expect(token.approve(dave, {Substrate: charlie.address}, 51n))
+ .to.be.rejectedWith('this test would fail (since it is skipped), replace this expecting message with what would have been received');
});
});
@@ -532,19 +473,18 @@
let charlie: IKeyringPair;
before(async () => {
- await usingPlaygrounds(async (helper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
[alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
});
});
- it('can be called by collection admin on non-owned item', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
- await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});
- const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
- await expect(approveTx()).to.be.rejected;
- });
+ itSub('can be called by collection admin on non-owned item', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
+ await helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address});
+ const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: charlie.address});
+ await expect(approveTx()).to.be.rejected;
});
});
@@ -554,139 +494,112 @@
let charlie: IKeyringPair;
before(async () => {
- await usingPlaygrounds(async (helper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
[alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);
});
});
- it('[nft] Approve for a collection that does not exist', async () => {
- await usingPlaygrounds(async (helper) => {
- const collectionId = 1 << 32 - 1;
- const approveTx = async () => helper.nft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});
- await expect(approveTx()).to.be.rejected;
- });
+ itSub('[nft] Approve for a collection that does not exist', async ({helper}) => {
+ const collectionId = 1 << 32 - 1;
+ const approveTx = async () => helper.nft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});
+ await expect(approveTx()).to.be.rejected;
});
- it('[fungible] Approve for a collection that does not exist', async () => {
- await usingPlaygrounds(async (helper) => {
- const collectionId = 1 << 32 - 1;
- const approveTx = async () => helper.ft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});
- await expect(approveTx()).to.be.rejected;
- });
+ itSub('[fungible] Approve for a collection that does not exist', async ({helper}) => {
+ const collectionId = 1 << 32 - 1;
+ const approveTx = async () => helper.ft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});
+ await expect(approveTx()).to.be.rejected;
});
- it('[refungible] Approve for a collection that does not exist', async function() {
- await usingPlaygrounds(async (helper) => {
- const collectionId = 1 << 32 - 1;
- const approveTx = async () => helper.rft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});
- await expect(approveTx()).to.be.rejected;
- });
+ itSub.ifWithPallets('[refungible] Approve for a collection that does not exist', [Pallets.ReFungible], async ({helper}) => {
+ const collectionId = 1 << 32 - 1;
+ const approveTx = async () => helper.rft.approveToken(bob, collectionId, 1, {Substrate: charlie.address});
+ await expect(approveTx()).to.be.rejected;
});
- it('[nft] Approve for a collection that was destroyed', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- await helper.nft.burn(alice, collectionId);
- const approveTx = async () => helper.nft.approveToken(alice, collectionId, 1, {Substrate: bob.address});
- await expect(approveTx()).to.be.rejected;
- });
+ itSub('[nft] Approve for a collection that was destroyed', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ await helper.nft.burn(alice, collectionId);
+ const approveTx = async () => helper.nft.approveToken(alice, collectionId, 1, {Substrate: bob.address});
+ await expect(approveTx()).to.be.rejected;
});
- it('[fungible] Approve for a collection that was destroyed', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- await helper.ft.burn(alice, collectionId);
- const approveTx = async () => helper.ft.approveToken(alice, collectionId, 1, {Substrate: bob.address});
- await expect(approveTx()).to.be.rejected;
- });
+ itSub('[fungible] Approve for a collection that was destroyed', async ({helper}) => {
+ const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ await helper.ft.burn(alice, collectionId);
+ const approveTx = async () => helper.ft.approveToken(alice, collectionId, 1, {Substrate: bob.address});
+ await expect(approveTx()).to.be.rejected;
});
- it('[refungible] Approve for a collection that was destroyed', async function() {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- await helper.rft.burn(alice, collectionId);
- const approveTx = async () => helper.rft.approveToken(alice, collectionId, 1, {Substrate: bob.address});
- await expect(approveTx()).to.be.rejected;
- });
+ itSub.ifWithPallets('[refungible] Approve for a collection that was destroyed', [Pallets.ReFungible], async ({helper}) => {
+ const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ await helper.rft.burn(alice, collectionId);
+ const approveTx = async () => helper.rft.approveToken(alice, collectionId, 1, {Substrate: bob.address});
+ await expect(approveTx()).to.be.rejected;
});
-
- it('[nft] Approve transfer of a token that does not exist', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const approveTx = async () => helper.nft.approveToken(alice, collectionId, 2, {Substrate: bob.address});
- await expect(approveTx()).to.be.rejected;
- });
+
+ itSub('[nft] Approve transfer of a token that does not exist', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const approveTx = async () => helper.nft.approveToken(alice, collectionId, 2, {Substrate: bob.address});
+ await expect(approveTx()).to.be.rejected;
});
- it('[refungible] Approve transfer of a token that does not exist', async function() {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const approveTx = async () => helper.rft.approveToken(alice, collectionId, 2, {Substrate: bob.address});
- await expect(approveTx()).to.be.rejected;
- });
+ itSub.ifWithPallets('[refungible] Approve transfer of a token that does not exist', [Pallets.ReFungible], async ({helper}) => {
+ const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const approveTx = async () => helper.rft.approveToken(alice, collectionId, 2, {Substrate: bob.address});
+ await expect(approveTx()).to.be.rejected;
});
- it('[nft] Approve using the address that does not own the approved token', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
- const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});
- await expect(approveTx()).to.be.rejected;
- });
+ itSub('[nft] Approve using the address that does not own the approved token', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});
+ const approveTx = async () => helper.nft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});
+ await expect(approveTx()).to.be.rejected;
});
- it('[fungible] Approve using the address that does not own the approved token', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);
- const tokenId = await helper.ft.getLastTokenId(collectionId);
- const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});
- await expect(approveTx()).to.be.rejected;
- });
+ itSub('[fungible] Approve using the address that does not own the approved token', async ({helper}) => {
+ const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ await helper.ft.mintTokens(alice, collectionId, 10n, alice.address);
+ const tokenId = await helper.ft.getLastTokenId(collectionId);
+ const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});
+ await expect(approveTx()).to.be.rejected;
});
- it('[refungible] Approve using the address that does not own the approved token', async function() {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
- const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});
- await expect(approveTx()).to.be.rejected;
- });
+ itSub.ifWithPallets('[refungible] Approve using the address that does not own the approved token', [Pallets.ReFungible], async ({helper}) => {
+ const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
+ const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address});
+ await expect(approveTx()).to.be.rejected;
});
- it('should fail if approved more ReFungibles than owned', async function() {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
- await helper.rft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 100n);
- await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 100n);
+ itSub.ifWithPallets('should fail if approved more ReFungibles than owned', [Pallets.ReFungible], async ({helper}) => {
+ const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.rft.mintToken(alice, {collectionId: collectionId, owner: alice.address, pieces: 100n});
+ await helper.rft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 100n);
+ await helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 100n);
- const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 101n);
- await expect(approveTx()).to.be.rejected;
- });
+ const approveTx = async () => helper.rft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 101n);
+ await expect(approveTx()).to.be.rejected;
});
- it('should fail if approved more Fungibles than owned', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- await helper.ft.mintTokens(alice, collectionId, alice.address, 10n);
- const tokenId = await helper.ft.getLastTokenId(collectionId);
+ itSub('should fail if approved more Fungibles than owned', async ({helper}) => {
+ const {collectionId} = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ await helper.ft.mintTokens(alice, collectionId, 10n, alice.address);
+ const tokenId = await helper.ft.getLastTokenId(collectionId);
- await helper.ft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);
- await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 10n);
- const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 11n);
- await expect(approveTx()).to.be.rejected;
- });
+ await helper.ft.transferToken(alice, collectionId, tokenId, {Substrate: bob.address}, 10n);
+ await helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 10n);
+ const approveTx = async () => helper.ft.approveToken(bob, collectionId, tokenId, {Substrate: alice.address}, 11n);
+ await expect(approveTx()).to.be.rejected;
});
- it('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {
- await usingPlaygrounds(async (helper) => {
- const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
- const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
- await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: false});
+ itSub('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', async ({helper}) => {
+ const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});
+ const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});
+ await helper.collection.setLimits(alice, collectionId, {ownerCanTransfer: false});
- const approveTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});
- await expect(approveTx()).to.be.rejected;
- });
+ const approveTx = async () => helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: charlie.address});
+ await expect(approveTx()).to.be.rejected;
});
});
tests/src/eth/allowlist.test.tsdiffbeforeafterboth--- a/tests/src/eth/allowlist.test.ts
+++ b/tests/src/eth/allowlist.test.ts
@@ -14,10 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+import {IKeyringPair} from '@polkadot/types/types';
import {expect} from 'chai';
-import {contractHelpers, createEthAccountWithBalance, deployFlipper, itWeb3} from './util/helpers';
+import {isAllowlisted, normalizeAccountId} from '../util/helpers';
+import {
+ contractHelpers,
+ createEthAccount,
+ createEthAccountWithBalance,
+ deployFlipper,
+ evmCollection,
+ evmCollectionHelpers,
+ getCollectionAddressFromResult,
+ itWeb3,
+} from './util/helpers';
+import {itEth, usingEthPlaygrounds} from './util/playgrounds';
-describe('EVM allowlist', () => {
+describe('EVM contract allowlist', () => {
itWeb3('Contract allowlist can be toggled', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, owner);
@@ -58,3 +70,79 @@
expect(await flipper.methods.getValue().call()).to.be.false;
});
});
+
+describe('EVM collection allowlist', () => {
+ let donor: IKeyringPair;
+
+ before(async function() {
+ await usingEthPlaygrounds(async (_helper, privateKey) => {
+ donor = privateKey('//Alice');
+ });
+ });
+
+ itEth('Collection allowlist can be added and removed by [eth] address', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const user = helper.eth.createAccount();
+
+ const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
+ await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;
+
+ await collectionEvm.methods.removeFromCollectionAllowList(user).send({from: owner});
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
+ });
+
+ itEth('Collection allowlist can be added and removed by [sub] address', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const user = donor;
+
+ const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
+ await collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).send({from: owner});
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;
+
+ await collectionEvm.methods.removeFromCollectionAllowListSubstrate(user.addressRaw).send({from: owner});
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
+ });
+
+ itEth('Collection allowlist can not be add and remove [eth] address by not owner', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const notOwner = await helper.eth.createAccountWithBalance(donor);
+ const user = helper.eth.createAccount();
+
+ const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
+ await expect(collectionEvm.methods.addToCollectionAllowList(user).call({from: notOwner})).to.be.rejectedWith('NoPermission');
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
+ await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});
+
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;
+ await expect(collectionEvm.methods.removeFromCollectionAllowList(user).call({from: notOwner})).to.be.rejectedWith('NoPermission');
+ expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;
+ });
+
+ itEth('Collection allowlist can not be add and remove [sub] address by not owner', async ({helper}) => {
+ const owner = await helper.eth.createAccountWithBalance(donor);
+ const notOwner = await helper.eth.createAccountWithBalance(donor);
+ const user = donor;
+
+ const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
+ await expect(collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).call({from: notOwner})).to.be.rejectedWith('NoPermission');
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
+ await collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).send({from: owner});
+
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;
+ await expect(collectionEvm.methods.removeFromCollectionAllowListSubstrate(user.addressRaw).call({from: notOwner})).to.be.rejectedWith('NoPermission');
+ expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;
+ });
+});
tests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth--- a/tests/src/eth/api/CollectionHelpers.sol
+++ b/tests/src/eth/api/CollectionHelpers.sol
@@ -14,14 +14,11 @@
/// @dev inlined interface
interface CollectionHelpersEvents {
- event CollectionCreated(
- address indexed owner,
- address indexed collectionId
- );
+ event CollectionCreated(address indexed owner, address indexed collectionId);
}
/// @title Contract, which allows users to operate with collections
-/// @dev the ERC-165 identifier for this interface is 0x675f3074
+/// @dev the ERC-165 identifier for this interface is 0x88ee8ef1
interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {
/// Create an NFT collection
/// @param name Name of the collection
@@ -45,9 +42,9 @@
string memory baseUri
) external returns (address);
- /// @dev EVM selector for this function is: 0x44a68ad5,
- /// or in textual repr: createRefungibleCollection(string,string,string)
- function createRefungibleCollection(
+ /// @dev EVM selector for this function is: 0xab173450,
+ /// or in textual repr: createRFTCollection(string,string,string)
+ function createRFTCollection(
string memory name,
string memory description,
string memory tokenPrefix
@@ -67,8 +64,5 @@
/// @return bool Does the collection exist?
/// @dev EVM selector for this function is: 0xc3de1494,
/// or in textual repr: isCollectionExist(address)
- function isCollectionExist(address collectionAddress)
- external
- view
- returns (bool);
+ function isCollectionExist(address collectionAddress) external view returns (bool);
}
tests/src/eth/api/ContractHelpers.soldiffbeforeafterboth--- a/tests/src/eth/api/ContractHelpers.sol
+++ b/tests/src/eth/api/ContractHelpers.sol
@@ -23,7 +23,7 @@
}
/// @title Magic contract, which allows users to reconfigure other contracts
-/// @dev the ERC-165 identifier for this interface is 0xd77fab70
+/// @dev the ERC-165 identifier for this interface is 0x172cb4fb
interface ContractHelpers is Dummy, ERC165, ContractHelpersEvents {
/// Get user, which deployed specified contract
/// @dev May return zero address in case if contract is deployed
@@ -111,7 +111,7 @@
function setSponsoringMode(address contractAddress, uint8 mode) external;
/// Get current contract sponsoring rate limit
- /// @param contractAddress Contract to get sponsoring mode of
+ /// @param contractAddress Contract to get sponsoring rate limit of
/// @return uint32 Amount of blocks between two sponsored transactions
/// @dev EVM selector for this function is: 0x610cfabd,
/// or in textual repr: getSponsoringRateLimit(address)
@@ -131,6 +131,28 @@
function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)
external;
+ /// Set contract sponsoring fee limit
+ /// @dev Sponsoring fee limit - is maximum fee that could be spent by
+ /// single transaction
+ /// @param contractAddress Contract to change sponsoring fee limit of
+ /// @param feeLimit Fee limit
+ /// @dev Only contract owner can change this setting
+ /// @dev EVM selector for this function is: 0x03aed665,
+ /// or in textual repr: setSponsoringFeeLimit(address,uint256)
+ function setSponsoringFeeLimit(address contractAddress, uint256 feeLimit)
+ external;
+
+ /// Get current contract sponsoring fee limit
+ /// @param contractAddress Contract to get sponsoring fee limit of
+ /// @return uint256 Maximum amount of fee that could be spent by single
+ /// transaction
+ /// @dev EVM selector for this function is: 0xc3fdc9ee,
+ /// or in textual repr: getSponsoringFeeLimit(address)
+ function getSponsoringFeeLimit(address contractAddress)
+ external
+ view
+ returns (uint256);
+
/// Is specified user present in contract allow list
/// @dev Contract owner always implicitly included
/// @param contractAddress Contract to check allowlist of
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -13,7 +13,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
interface Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -164,6 +164,13 @@
/// or in textual repr: setCollectionAccess(uint8)
function setCollectionAccess(uint8 mode) external;
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ /// @dev EVM selector for this function is: 0xd63a8e11,
+ /// or in textual repr: allowed(address)
+ function allowed(address user) external view returns (bool);
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
@@ -171,6 +178,13 @@
/// or in textual repr: addToCollectionAllowList(address)
function addToCollectionAllowList(address user) external;
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xd06ad267,
+ /// or in textual repr: addToCollectionAllowListSubstrate(uint256)
+ function addToCollectionAllowListSubstrate(uint256 user) external;
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
@@ -178,6 +192,13 @@
/// or in textual repr: removeFromCollectionAllowList(address)
function removeFromCollectionAllowList(address user) external;
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xa31913ed,
+ /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+ function removeFromCollectionAllowListSubstrate(uint256 user) external;
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
@@ -208,6 +229,14 @@
/// or in textual repr: uniqueCollectionType()
function uniqueCollectionType() external returns (string memory);
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0xdf727d3b,
+ /// or in textual repr: collectionOwner()
+ function collectionOwner() external view returns (Tuple6 memory);
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -65,7 +65,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
interface Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -216,6 +216,13 @@
/// or in textual repr: setCollectionAccess(uint8)
function setCollectionAccess(uint8 mode) external;
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ /// @dev EVM selector for this function is: 0xd63a8e11,
+ /// or in textual repr: allowed(address)
+ function allowed(address user) external view returns (bool);
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
@@ -223,6 +230,13 @@
/// or in textual repr: addToCollectionAllowList(address)
function addToCollectionAllowList(address user) external;
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xd06ad267,
+ /// or in textual repr: addToCollectionAllowListSubstrate(uint256)
+ function addToCollectionAllowListSubstrate(uint256 user) external;
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
@@ -230,6 +244,13 @@
/// or in textual repr: removeFromCollectionAllowList(address)
function removeFromCollectionAllowList(address user) external;
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xa31913ed,
+ /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+ function removeFromCollectionAllowListSubstrate(uint256 user) external;
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
@@ -260,6 +281,14 @@
/// or in textual repr: uniqueCollectionType()
function uniqueCollectionType() external returns (string memory);
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0xdf727d3b,
+ /// or in textual repr: collectionOwner()
+ function collectionOwner() external view returns (Tuple17 memory);
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -65,7 +65,7 @@
}
/// @title A contract that allows you to work with collections.
-/// @dev the ERC-165 identifier for this interface is 0xe54be640
+/// @dev the ERC-165 identifier for this interface is 0x9f70d4e0
interface Collection is Dummy, ERC165 {
/// Set collection property.
///
@@ -216,6 +216,13 @@
/// or in textual repr: setCollectionAccess(uint8)
function setCollectionAccess(uint8 mode) external;
+ /// Checks that user allowed to operate with collection.
+ ///
+ /// @param user User address to check.
+ /// @dev EVM selector for this function is: 0xd63a8e11,
+ /// or in textual repr: allowed(address)
+ function allowed(address user) external view returns (bool);
+
/// Add the user to the allowed list.
///
/// @param user Address of a trusted user.
@@ -223,6 +230,13 @@
/// or in textual repr: addToCollectionAllowList(address)
function addToCollectionAllowList(address user) external;
+ /// Add substrate user to allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xd06ad267,
+ /// or in textual repr: addToCollectionAllowListSubstrate(uint256)
+ function addToCollectionAllowListSubstrate(uint256 user) external;
+
/// Remove the user from the allowed list.
///
/// @param user Address of a removed user.
@@ -230,6 +244,13 @@
/// or in textual repr: removeFromCollectionAllowList(address)
function removeFromCollectionAllowList(address user) external;
+ /// Remove substrate user from allowed list.
+ ///
+ /// @param user User substrate address.
+ /// @dev EVM selector for this function is: 0xa31913ed,
+ /// or in textual repr: removeFromCollectionAllowListSubstrate(uint256)
+ function removeFromCollectionAllowListSubstrate(uint256 user) external;
+
/// Switch permission for minting.
///
/// @param mode Enable if "true".
@@ -260,6 +281,14 @@
/// or in textual repr: uniqueCollectionType()
function uniqueCollectionType() external returns (string memory);
+ /// Get collection owner.
+ ///
+ /// @return Tuble with sponsor address and his substrate mirror.
+ /// If address is canonical then substrate mirror is zero and vice versa.
+ /// @dev EVM selector for this function is: 0xdf727d3b,
+ /// or in textual repr: collectionOwner()
+ function collectionOwner() external view returns (Tuple17 memory);
+
/// Changes collection owner to another account
///
/// @dev Owner can be changed only by current owner
tests/src/eth/collectionHelpersAbi.jsondiffbeforeafterboth--- a/tests/src/eth/collectionHelpersAbi.json
+++ b/tests/src/eth/collectionHelpersAbi.json
@@ -59,7 +59,7 @@
{ "internalType": "string", "name": "description", "type": "string" },
{ "internalType": "string", "name": "tokenPrefix", "type": "string" }
],
- "name": "createRefungibleCollection",
+ "name": "createRFTCollection",
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
"stateMutability": "nonpayable",
"type": "function"
tests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth--- a/tests/src/eth/contractSponsoring.test.ts
+++ b/tests/src/eth/contractSponsoring.test.ts
@@ -14,8 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+import * as solc from 'solc';
import {expect} from 'chai';
-import { expectSubstrateEventsAtBlock } from '../util/helpers';
+import {expectSubstrateEventsAtBlock} from '../util/helpers';
+import Web3 from 'web3';
+
import {
contractHelpers,
createEthAccountWithBalance,
@@ -26,7 +29,11 @@
createEthAccount,
ethBalanceViaSub,
normalizeEvents,
+ CompiledContract,
+ GAS_ARGS,
+ subToEth,
} from './util/helpers';
+import {submitTransactionAsync} from '../substrate/substrate-api';
describe('Sponsoring EVM contracts', () => {
itWeb3('Self sponsored can be set by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {
@@ -478,3 +485,167 @@
expect(await helpers.methods.getSponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');
});
});
+
+describe('Sponsoring Fee Limit', () => {
+
+ let testContract: CompiledContract;
+
+ function compileTestContract() {
+ if (!testContract) {
+ const input = {
+ language: 'Solidity',
+ sources: {
+ ['TestContract.sol']: {
+ content:
+ `
+ // SPDX-License-Identifier: MIT
+ pragma solidity ^0.8.0;
+
+ contract TestContract {
+ event Result(bool);
+
+ function test(uint32 cycles) public {
+ uint256 counter = 0;
+ while(true) {
+ counter ++;
+ if (counter > cycles){
+ break;
+ }
+ }
+ emit Result(true);
+ }
+ }
+ `,
+ },
+ },
+ settings: {
+ outputSelection: {
+ '*': {
+ '*': ['*'],
+ },
+ },
+ },
+ };
+ const json = JSON.parse(solc.compile(JSON.stringify(input)));
+ const out = json.contracts['TestContract.sol']['TestContract'];
+
+ testContract = {
+ abi: out.abi,
+ object: '0x' + out.evm.bytecode.object,
+ };
+ }
+ return testContract;
+ }
+
+ async function deployTestContract(web3: Web3, owner: string) {
+ const compiled = compileTestContract();
+ const testContract = new web3.eth.Contract(compiled.abi, undefined, {
+ data: compiled.object,
+ from: owner,
+ ...GAS_ARGS,
+ });
+ return await testContract.deploy({data: compiled.object}).send({from: owner});
+ }
+
+ itWeb3('Default fee limit', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const flipper = await deployFlipper(web3, owner);
+ const helpers = contractHelpers(web3, owner);
+ expect(await helpers.methods.getSponsoringFeeLimit(flipper.options.address).call()).to.be.equals('115792089237316195423570985008687907853269984665640564039457584007913129639935');
+ });
+
+ itWeb3('Set fee limit', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const flipper = await deployFlipper(web3, owner);
+ const helpers = contractHelpers(web3, owner);
+ await helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send();
+ expect(await helpers.methods.getSponsoringFeeLimit(flipper.options.address).call()).to.be.equals('100');
+ });
+
+ itWeb3('Negative test - set fee limit by non-owner', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const stranger = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const flipper = await deployFlipper(web3, owner);
+ const helpers = contractHelpers(web3, owner);
+ await expect(helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send({from: stranger})).to.be.rejected;
+ });
+
+ itWeb3('Negative test - check that eth transactions exceeding fee limit are not executed', async ({api, web3, privateKeyWrapper}) => {
+ const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const user = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const testContract = await deployTestContract(web3, owner);
+ const helpers = contractHelpers(web3, owner);
+
+ await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});
+ await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});
+
+ await helpers.methods.setSponsor(testContract.options.address, sponsor).send();
+ await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});
+
+ const gasPrice = BigInt(await web3.eth.getGasPrice());
+
+ await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();
+
+ const originalUserBalance = await web3.eth.getBalance(user);
+ await testContract.methods.test(100).send({from: user, gas: 2_000_000});
+ expect(await web3.eth.getBalance(user)).to.be.equal(originalUserBalance);
+
+ await testContract.methods.test(100).send({from: user, gas: 2_100_000});
+ expect(await web3.eth.getBalance(user)).to.not.be.equal(originalUserBalance);
+ });
+
+ itWeb3('Negative test - check that evm.call transactions exceeding fee limit are not executed', async ({api, web3, privateKeyWrapper}) => {
+ const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const testContract = await deployTestContract(web3, owner);
+ const helpers = contractHelpers(web3, owner);
+
+ await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});
+ await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});
+
+ await helpers.methods.setSponsor(testContract.options.address, sponsor).send();
+ await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});
+
+ const gasPrice = BigInt(await web3.eth.getGasPrice());
+
+ await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();
+
+ const alice = privateKeyWrapper('//Alice');
+ const originalAliceBalance = (await api.query.system.account(alice.address)).data.free.toBigInt();
+
+ await submitTransactionAsync(
+ alice,
+ api.tx.evm.call(
+ subToEth(alice.address),
+ testContract.options.address,
+ testContract.methods.test(100).encodeABI(),
+ Uint8Array.from([]),
+ 2_000_000n,
+ gasPrice,
+ null,
+ null,
+ [],
+ ),
+ );
+ expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.be.equal(originalAliceBalance);
+
+ await submitTransactionAsync(
+ alice,
+ api.tx.evm.call(
+ subToEth(alice.address),
+ testContract.options.address,
+ testContract.methods.test(100).encodeABI(),
+ Uint8Array.from([]),
+ 2_100_000n,
+ gasPrice,
+ null,
+ null,
+ [],
+ ),
+ );
+ expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.not.be.equal(originalAliceBalance);
+ });
+});
tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createRFTCollection.test.ts
+++ b/tests/src/eth/createRFTCollection.test.ts
@@ -41,7 +41,7 @@
const collectionCountBefore = await getCreatedCollectionCount(api);
const result = await collectionHelper.methods
- .createRefungibleCollection(collectionName, description, tokenPrefix)
+ .createRFTCollection(collectionName, description, tokenPrefix)
.send();
const collectionCountAfter = await getCreatedCollectionCount(api);
@@ -65,7 +65,7 @@
.call()).to.be.false;
await collectionHelpers.methods
- .createRefungibleCollection('A', 'A', 'A')
+ .createRFTCollection('A', 'A', 'A')
.send();
expect(await collectionHelpers.methods
@@ -76,7 +76,7 @@
itWeb3('Set sponsorship', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionHelpers = evmCollectionHelpers(web3, owner);
- let result = await collectionHelpers.methods.createRefungibleCollection('Sponsor collection', '1', '1').send();
+ let result = await collectionHelpers.methods.createRFTCollection('Sponsor collection', '1', '1').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionEvm = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
@@ -96,7 +96,7 @@
itWeb3('Set limits', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionHelpers = evmCollectionHelpers(web3, owner);
- const result = await collectionHelpers.methods.createRefungibleCollection('Const collection', '5', '5').send();
+ const result = await collectionHelpers.methods.createRFTCollection('Const collection', '5', '5').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const limits = {
accountTokenOwnershipLimit: 1000,
@@ -141,7 +141,7 @@
.isCollectionExist(collectionAddressForNonexistentCollection).call())
.to.be.false;
- const result = await collectionHelpers.methods.createRefungibleCollection('Collection address exist', '7', '7').send();
+ const result = await collectionHelpers.methods.createRFTCollection('Collection address exist', '7', '7').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
expect(await collectionHelpers.methods
.isCollectionExist(collectionIdAddress).call())
@@ -164,7 +164,7 @@
const tokenPrefix = 'A';
await expect(helper.methods
- .createRefungibleCollection(collectionName, description, tokenPrefix)
+ .createRFTCollection(collectionName, description, tokenPrefix)
.call()).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGHT);
}
@@ -174,7 +174,7 @@
const description = 'A'.repeat(MAX_DESCRIPTION_LENGHT + 1);
const tokenPrefix = 'A';
await expect(helper.methods
- .createRefungibleCollection(collectionName, description, tokenPrefix)
+ .createRFTCollection(collectionName, description, tokenPrefix)
.call()).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGHT);
}
{
@@ -183,7 +183,7 @@
const description = 'A';
const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGHT + 1);
await expect(helper.methods
- .createRefungibleCollection(collectionName, description, tokenPrefix)
+ .createRFTCollection(collectionName, description, tokenPrefix)
.call()).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGHT);
}
});
@@ -196,7 +196,7 @@
const tokenPrefix = 'A';
await expect(helper.methods
- .createRefungibleCollection(collectionName, description, tokenPrefix)
+ .createRFTCollection(collectionName, description, tokenPrefix)
.call()).to.be.rejectedWith('NotSufficientFounds');
});
@@ -204,7 +204,7 @@
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const notOwner = createEthAccount(web3);
const collectionHelpers = evmCollectionHelpers(web3, owner);
- const result = await collectionHelpers.methods.createRefungibleCollection('A', 'A', 'A').send();
+ const result = await collectionHelpers.methods.createRFTCollection('A', 'A', 'A').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
const contractEvmFromNotOwner = evmCollection(web3, notOwner, collectionIdAddress, {type: 'ReFungible'});
const EXPECTED_ERROR = 'NoPermission';
@@ -229,7 +229,7 @@
itWeb3('(!negative test!) Set limits', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionHelpers = evmCollectionHelpers(web3, owner);
- const result = await collectionHelpers.methods.createRefungibleCollection('Schema collection', 'A', 'A').send();
+ const result = await collectionHelpers.methods.createRFTCollection('Schema collection', 'A', 'A').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
const collectionEvm = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
await expect(collectionEvm.methods
tests/src/eth/fractionalizer/Fractionalizer.soldiffbeforeafterboth--- a/tests/src/eth/fractionalizer/Fractionalizer.sol
+++ b/tests/src/eth/fractionalizer/Fractionalizer.sol
@@ -10,179 +10,158 @@
/// stores allowlist of NFT tokens available for fractionalization, has methods
/// for fractionalization and defractionalization of NFT tokens.
contract Fractionalizer {
- struct Token {
- address _collection;
- uint256 _tokenId;
- }
- address rftCollection;
- mapping(address => bool) nftCollectionAllowList;
- mapping(address => mapping(uint256 => uint256)) public nft2rftMapping;
- mapping(address => Token) public rft2nftMapping;
- bytes32 refungibleCollectionType = keccak256(bytes("ReFungible"));
+ struct Token {
+ address _collection;
+ uint256 _tokenId;
+ }
+ address rftCollection;
+ mapping(address => bool) nftCollectionAllowList;
+ mapping(address => mapping(uint256 => uint256)) public nft2rftMapping;
+ mapping(address => Token) public rft2nftMapping;
+ bytes32 refungibleCollectionType = keccak256(bytes("ReFungible"));
- receive() external payable onlyOwner {}
+ receive() external payable onlyOwner {}
- /// @dev Method modifier to only allow contract owner to call it.
- modifier onlyOwner() {
- address contracthelpersAddress = 0x842899ECF380553E8a4de75bF534cdf6fBF64049;
- ContractHelpers contractHelpers = ContractHelpers(contracthelpersAddress);
- address contractOwner = contractHelpers.contractOwner(address(this));
- require(msg.sender == contractOwner, "Only owner can");
- _;
- }
+ /// @dev Method modifier to only allow contract owner to call it.
+ modifier onlyOwner() {
+ address contracthelpersAddress = 0x842899ECF380553E8a4de75bF534cdf6fBF64049;
+ ContractHelpers contractHelpers = ContractHelpers(contracthelpersAddress);
+ address contractOwner = contractHelpers.contractOwner(address(this));
+ require(msg.sender == contractOwner, "Only owner can");
+ _;
+ }
- /// @dev This emits when RFT collection setting is changed.
- event RFTCollectionSet(address _collection);
+ /// @dev This emits when RFT collection setting is changed.
+ event RFTCollectionSet(address _collection);
- /// @dev This emits when NFT collection is allowed or disallowed.
- event AllowListSet(address _collection, bool _status);
+ /// @dev This emits when NFT collection is allowed or disallowed.
+ event AllowListSet(address _collection, bool _status);
- /// @dev This emits when NFT token is fractionalized by contract.
- event Fractionalized(address _collection, uint256 _tokenId, address _rftToken, uint128 _amount);
+ /// @dev This emits when NFT token is fractionalized by contract.
+ event Fractionalized(address _collection, uint256 _tokenId, address _rftToken, uint128 _amount);
- /// @dev This emits when NFT token is defractionalized by contract.
- event Defractionalized(address _rftToken, address _nftCollection, uint256 _nftTokenId);
+ /// @dev This emits when NFT token is defractionalized by contract.
+ event Defractionalized(address _rftToken, address _nftCollection, uint256 _nftTokenId);
- /// Set RFT collection that contract will work with. RFT tokens for fractionalized NFT tokens
- /// would be created in this collection.
- /// @dev Throws if RFT collection is already configured for this contract.
- /// Throws if collection of wrong type (NFT, Fungible) is provided instead
- /// of RFT collection.
- /// Throws if `msg.sender` is not owner or admin of provided RFT collection.
- /// Can only be called by contract owner.
- /// @param _collection address of RFT collection.
- function setRFTCollection(address _collection) public onlyOwner {
- require(
- rftCollection == address(0),
- "RFT collection is already set"
- );
- UniqueRefungible refungibleContract = UniqueRefungible(_collection);
- string memory collectionType = refungibleContract.uniqueCollectionType();
-
- require(
- keccak256(bytes(collectionType)) == refungibleCollectionType,
- "Wrong collection type. Collection is not refungible."
- );
- require(
- refungibleContract.isOwnerOrAdmin(address(this)),
- "Fractionalizer contract should be an admin of the collection"
- );
- rftCollection = _collection;
- emit RFTCollectionSet(rftCollection);
- }
+ /// Set RFT collection that contract will work with. RFT tokens for fractionalized NFT tokens
+ /// would be created in this collection.
+ /// @dev Throws if RFT collection is already configured for this contract.
+ /// Throws if collection of wrong type (NFT, Fungible) is provided instead
+ /// of RFT collection.
+ /// Throws if `msg.sender` is not owner or admin of provided RFT collection.
+ /// Can only be called by contract owner.
+ /// @param _collection address of RFT collection.
+ function setRFTCollection(address _collection) public onlyOwner {
+ require(rftCollection == address(0), "RFT collection is already set");
+ UniqueRefungible refungibleContract = UniqueRefungible(_collection);
+ string memory collectionType = refungibleContract.uniqueCollectionType();
- /// Creates and sets RFT collection that contract will work with. RFT tokens for fractionalized NFT tokens
- /// would be created in this collection.
- /// @dev Throws if RFT collection is already configured for this contract.
- /// Can only be called by contract owner.
- /// @param _name name for created RFT collection.
- /// @param _description description for created RFT collection.
- /// @param _tokenPrefix token prefix for created RFT collection.
- function createAndSetRFTCollection(string calldata _name, string calldata _description, string calldata _tokenPrefix) public onlyOwner {
- require(
- rftCollection == address(0),
- "RFT collection is already set"
- );
- address collectionHelpers = 0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F;
- rftCollection = CollectionHelpers(collectionHelpers).createRefungibleCollection(_name, _description, _tokenPrefix);
- emit RFTCollectionSet(rftCollection);
- }
+ require(
+ keccak256(bytes(collectionType)) == refungibleCollectionType,
+ "Wrong collection type. Collection is not refungible."
+ );
+ require(
+ refungibleContract.isOwnerOrAdmin(address(this)),
+ "Fractionalizer contract should be an admin of the collection"
+ );
+ rftCollection = _collection;
+ emit RFTCollectionSet(rftCollection);
+ }
- /// Allow or disallow NFT collection tokens from being fractionalized by this contract.
- /// @dev Can only be called by contract owner.
- /// @param collection NFT token address.
- /// @param status `true` to allow and `false` to disallow NFT token.
- function setNftCollectionIsAllowed(address collection, bool status) public onlyOwner {
- nftCollectionAllowList[collection] = status;
- emit AllowListSet(collection, status);
- }
+ /// Creates and sets RFT collection that contract will work with. RFT tokens for fractionalized NFT tokens
+ /// would be created in this collection.
+ /// @dev Throws if RFT collection is already configured for this contract.
+ /// Can only be called by contract owner.
+ /// @param _name name for created RFT collection.
+ /// @param _description description for created RFT collection.
+ /// @param _tokenPrefix token prefix for created RFT collection.
+ function createAndSetRFTCollection(
+ string calldata _name,
+ string calldata _description,
+ string calldata _tokenPrefix
+ ) public onlyOwner {
+ require(rftCollection == address(0), "RFT collection is already set");
+ address collectionHelpers = 0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F;
+ rftCollection = CollectionHelpers(collectionHelpers).createRFTCollection(_name, _description, _tokenPrefix);
+ emit RFTCollectionSet(rftCollection);
+ }
- /// Fractionilize NFT token.
- /// @dev Takes NFT token from `msg.sender` and transfers RFT token to `msg.sender`
- /// instead. Creates new RFT token if provided NFT token never was fractionalized
- /// by this contract or existing RFT token if it was.
- /// Throws if RFT collection isn't configured for this contract.
- /// Throws if fractionalization of provided NFT token is not allowed
- /// Throws if `msg.sender` is not owner of provided NFT token
- /// @param _collection NFT collection address
- /// @param _token id of NFT token to be fractionalized
- /// @param _pieces number of pieces new RFT token would have
- function nft2rft(address _collection, uint256 _token, uint128 _pieces) public {
- require(
- rftCollection != address(0),
- "RFT collection is not set"
- );
- UniqueRefungible rftCollectionContract = UniqueRefungible(rftCollection);
- require(
- nftCollectionAllowList[_collection] == true,
- "Fractionalization of this collection is not allowed by admin"
- );
- require(
- UniqueNFT(_collection).ownerOf(_token) == msg.sender,
- "Only token owner could fractionalize it"
- );
- UniqueNFT(_collection).transferFrom(
- msg.sender,
- address(this),
- _token
- );
- uint256 rftTokenId;
- address rftTokenAddress;
- UniqueRefungibleToken rftTokenContract;
- if (nft2rftMapping[_collection][_token] == 0) {
- rftTokenId = rftCollectionContract.nextTokenId();
- rftCollectionContract.mint(address(this), rftTokenId);
- rftTokenAddress = rftCollectionContract.tokenContractAddress(rftTokenId);
- nft2rftMapping[_collection][_token] = rftTokenId;
- rft2nftMapping[rftTokenAddress] = Token(_collection, _token);
+ /// Allow or disallow NFT collection tokens from being fractionalized by this contract.
+ /// @dev Can only be called by contract owner.
+ /// @param collection NFT token address.
+ /// @param status `true` to allow and `false` to disallow NFT token.
+ function setNftCollectionIsAllowed(address collection, bool status) public onlyOwner {
+ nftCollectionAllowList[collection] = status;
+ emit AllowListSet(collection, status);
+ }
- rftTokenContract = UniqueRefungibleToken(rftTokenAddress);
- } else {
- rftTokenId = nft2rftMapping[_collection][_token];
- rftTokenAddress = rftCollectionContract.tokenContractAddress(rftTokenId);
- rftTokenContract = UniqueRefungibleToken(rftTokenAddress);
- }
- rftTokenContract.repartition(_pieces);
- rftTokenContract.transfer(msg.sender, _pieces);
- emit Fractionalized(_collection, _token, rftTokenAddress, _pieces);
- }
+ /// Fractionilize NFT token.
+ /// @dev Takes NFT token from `msg.sender` and transfers RFT token to `msg.sender`
+ /// instead. Creates new RFT token if provided NFT token never was fractionalized
+ /// by this contract or existing RFT token if it was.
+ /// Throws if RFT collection isn't configured for this contract.
+ /// Throws if fractionalization of provided NFT token is not allowed
+ /// Throws if `msg.sender` is not owner of provided NFT token
+ /// @param _collection NFT collection address
+ /// @param _token id of NFT token to be fractionalized
+ /// @param _pieces number of pieces new RFT token would have
+ function nft2rft(
+ address _collection,
+ uint256 _token,
+ uint128 _pieces
+ ) public {
+ require(rftCollection != address(0), "RFT collection is not set");
+ UniqueRefungible rftCollectionContract = UniqueRefungible(rftCollection);
+ require(
+ nftCollectionAllowList[_collection] == true,
+ "Fractionalization of this collection is not allowed by admin"
+ );
+ require(UniqueNFT(_collection).ownerOf(_token) == msg.sender, "Only token owner could fractionalize it");
+ UniqueNFT(_collection).transferFrom(msg.sender, address(this), _token);
+ uint256 rftTokenId;
+ address rftTokenAddress;
+ UniqueRefungibleToken rftTokenContract;
+ if (nft2rftMapping[_collection][_token] == 0) {
+ rftTokenId = rftCollectionContract.nextTokenId();
+ rftCollectionContract.mint(address(this), rftTokenId);
+ rftTokenAddress = rftCollectionContract.tokenContractAddress(rftTokenId);
+ nft2rftMapping[_collection][_token] = rftTokenId;
+ rft2nftMapping[rftTokenAddress] = Token(_collection, _token);
- /// Defrationalize NFT token.
- /// @dev Takes RFT token from `msg.sender` and transfers corresponding NFT token
- /// to `msg.sender` instead.
- /// Throws if RFT collection isn't configured for this contract.
- /// Throws if provided RFT token is no from configured RFT collection.
- /// Throws if RFT token was not created by this contract.
- /// Throws if `msg.sender` isn't owner of all RFT token pieces.
- /// @param _collection RFT collection address
- /// @param _token id of RFT token
- function rft2nft(address _collection, uint256 _token) public {
- require(
- rftCollection != address(0),
- "RFT collection is not set"
- );
- require(
- rftCollection == _collection,
- "Wrong RFT collection"
- );
- UniqueRefungible rftCollectionContract = UniqueRefungible(rftCollection);
- address rftTokenAddress = rftCollectionContract.tokenContractAddress(_token);
- Token memory nftToken = rft2nftMapping[rftTokenAddress];
- require(
- nftToken._collection != address(0),
- "No corresponding NFT token found"
- );
- UniqueRefungibleToken rftTokenContract = UniqueRefungibleToken(rftTokenAddress);
- require(
- rftTokenContract.balanceOf(msg.sender) == rftTokenContract.totalSupply(),
- "Not all pieces are owned by the caller"
- );
- rftCollectionContract.transferFrom(msg.sender, address(this), _token);
- UniqueNFT(nftToken._collection).transferFrom(
- address(this),
- msg.sender,
- nftToken._tokenId
- );
- emit Defractionalized(rftTokenAddress, nftToken._collection, nftToken._tokenId);
- }
-}
\ No newline at end of file
+ rftTokenContract = UniqueRefungibleToken(rftTokenAddress);
+ } else {
+ rftTokenId = nft2rftMapping[_collection][_token];
+ rftTokenAddress = rftCollectionContract.tokenContractAddress(rftTokenId);
+ rftTokenContract = UniqueRefungibleToken(rftTokenAddress);
+ }
+ rftTokenContract.repartition(_pieces);
+ rftTokenContract.transfer(msg.sender, _pieces);
+ emit Fractionalized(_collection, _token, rftTokenAddress, _pieces);
+ }
+
+ /// Defrationalize NFT token.
+ /// @dev Takes RFT token from `msg.sender` and transfers corresponding NFT token
+ /// to `msg.sender` instead.
+ /// Throws if RFT collection isn't configured for this contract.
+ /// Throws if provided RFT token is no from configured RFT collection.
+ /// Throws if RFT token was not created by this contract.
+ /// Throws if `msg.sender` isn't owner of all RFT token pieces.
+ /// @param _collection RFT collection address
+ /// @param _token id of RFT token
+ function rft2nft(address _collection, uint256 _token) public {
+ require(rftCollection != address(0), "RFT collection is not set");
+ require(rftCollection == _collection, "Wrong RFT collection");
+ UniqueRefungible rftCollectionContract = UniqueRefungible(rftCollection);
+ address rftTokenAddress = rftCollectionContract.tokenContractAddress(_token);
+ Token memory nftToken = rft2nftMapping[rftTokenAddress];
+ require(nftToken._collection != address(0), "No corresponding NFT token found");
+ UniqueRefungibleToken rftTokenContract = UniqueRefungibleToken(rftTokenAddress);
+ require(
+ rftTokenContract.balanceOf(msg.sender) == rftTokenContract.totalSupply(),
+ "Not all pieces are owned by the caller"
+ );
+ rftCollectionContract.transferFrom(msg.sender, address(this), _token);
+ UniqueNFT(nftToken._collection).transferFrom(address(this), msg.sender, nftToken._tokenId);
+ emit Defractionalized(rftTokenAddress, nftToken._collection, nftToken._tokenId);
+ }
+}
tests/src/eth/fractionalizer/fractionalizer.test.tsdiffbeforeafterboth--- a/tests/src/eth/fractionalizer/fractionalizer.test.ts
+++ b/tests/src/eth/fractionalizer/fractionalizer.test.ts
@@ -21,7 +21,7 @@
import {readFile} from 'fs/promises';
import {executeTransaction, submitTransactionAsync} from '../../substrate/substrate-api';
import {getCreateCollectionResult, getCreateItemResult, UNIQUE, requirePallets, Pallets} from '../../util/helpers';
-import {collectionIdToAddress, CompiledContract, createEthAccountWithBalance, createNonfungibleCollection, createRefungibleCollection, GAS_ARGS, itWeb3, tokenIdFromAddress, uniqueNFT, uniqueRefungible, uniqueRefungibleToken} from '../util/helpers';
+import {collectionIdToAddress, CompiledContract, createEthAccountWithBalance, createNonfungibleCollection, createRFTCollection, GAS_ARGS, itWeb3, tokenIdFromAddress, uniqueNFT, uniqueRefungible, uniqueRefungibleToken} from '../util/helpers';
import {Contract} from 'web3-eth-contract';
import * as solc from 'solc';
@@ -123,7 +123,7 @@
itWeb3('Set RFT collection', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const fractionalizer = await deployFractionalizer(web3, owner);
- const {collectionIdAddress} = await createRefungibleCollection(api, web3, owner);
+ const {collectionIdAddress} = await createRFTCollection(api, web3, owner);
const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);
await refungibleContract.methods.addCollectionAdmin(fractionalizer.options.address).send();
const result = await fractionalizer.methods.setRFTCollection(collectionIdAddress).send();
@@ -256,7 +256,7 @@
itWeb3('call setRFTCollection twice', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const {collectionIdAddress} = await createRefungibleCollection(api, web3, owner);
+ const {collectionIdAddress} = await createRFTCollection(api, web3, owner);
const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);
const fractionalizer = await deployFractionalizer(web3, owner);
@@ -282,7 +282,7 @@
itWeb3('call setRFTCollection while not collection admin', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const fractionalizer = await deployFractionalizer(web3, owner);
- const {collectionIdAddress} = await createRefungibleCollection(api, web3, owner);
+ const {collectionIdAddress} = await createRFTCollection(api, web3, owner);
await expect(fractionalizer.methods.setRFTCollection(collectionIdAddress).call())
.to.be.rejectedWith(/Fractionalizer contract should be an admin of the collection$/g);
@@ -368,7 +368,7 @@
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const fractionalizer = await deployFractionalizer(web3, owner);
- const {collectionIdAddress: rftCollectionAddress} = await createRefungibleCollection(api, web3, owner);
+ const {collectionIdAddress: rftCollectionAddress} = await createRFTCollection(api, web3, owner);
const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);
const rftTokenId = await refungibleContract.methods.nextTokenId().call();
await refungibleContract.methods.mint(owner, rftTokenId).send();
@@ -381,7 +381,7 @@
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);
- const {collectionIdAddress: rftCollectionAddress} = await createRefungibleCollection(api, web3, owner);
+ const {collectionIdAddress: rftCollectionAddress} = await createRFTCollection(api, web3, owner);
const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);
const rftTokenId = await refungibleContract.methods.nextTokenId().call();
await refungibleContract.methods.mint(owner, rftTokenId).send();
@@ -392,7 +392,7 @@
itWeb3('call rft2nft for RFT token that was not minted by fractionalizer contract', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const {collectionIdAddress: rftCollectionAddress} = await createRefungibleCollection(api, web3, owner);
+ const {collectionIdAddress: rftCollectionAddress} = await createRFTCollection(api, web3, owner);
const fractionalizer = await deployFractionalizer(web3, owner);
const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);
tests/src/eth/fungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/fungibleAbi.json
+++ b/tests/src/eth/fungibleAbi.json
@@ -78,6 +78,15 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "user", "type": "uint256" }
+ ],
+ "name": "addToCollectionAllowListSubstrate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "owner", "type": "address" },
{ "internalType": "address", "name": "spender", "type": "address" }
],
@@ -88,6 +97,15 @@
},
{
"inputs": [
+ { "internalType": "address", "name": "user", "type": "address" }
+ ],
+ "name": "allowed",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "spender", "type": "address" },
{ "internalType": "uint256", "name": "amount", "type": "uint256" }
],
@@ -116,6 +134,23 @@
"type": "function"
},
{
+ "inputs": [],
+ "name": "collectionOwner",
+ "outputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "field_0", "type": "address" },
+ { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple6",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
"inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
"name": "collectionProperty",
"outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],
@@ -261,6 +296,15 @@
"type": "function"
},
{
+ "inputs": [
+ { "internalType": "uint256", "name": "user", "type": "uint256" }
+ ],
+ "name": "removeFromCollectionAllowListSubstrate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],
"name": "setCollectionAccess",
"outputs": [],
tests/src/eth/nesting/nest.test.tsdiffbeforeafterboth--- a/tests/src/eth/nesting/nest.test.ts
+++ b/tests/src/eth/nesting/nest.test.ts
@@ -20,7 +20,7 @@
let donor: IKeyringPair;
before(async function() {
- await usingEthPlaygrounds(async (helper, privateKey) => {
+ await usingEthPlaygrounds(async (_, privateKey) => {
donor = privateKey('//Alice');
});
});
tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -109,6 +109,24 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "user", "type": "uint256" }
+ ],
+ "name": "addToCollectionAllowListSubstrate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "user", "type": "address" }
+ ],
+ "name": "allowed",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "approved", "type": "address" },
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }
],
@@ -146,6 +164,23 @@
"type": "function"
},
{
+ "inputs": [],
+ "name": "collectionOwner",
+ "outputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "field_0", "type": "address" },
+ { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple17",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
"inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
"name": "collectionProperty",
"outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],
@@ -376,6 +411,15 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "user", "type": "uint256" }
+ ],
+ "name": "removeFromCollectionAllowListSubstrate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "from", "type": "address" },
{ "internalType": "address", "name": "to", "type": "address" },
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }
tests/src/eth/payable.test.tsdiffbeforeafterboth--- a/tests/src/eth/payable.test.ts
+++ b/tests/src/eth/payable.test.ts
@@ -22,7 +22,7 @@
let donor: IKeyringPair;
before(async function() {
- await usingEthPlaygrounds(async (helper, privateKey) => {
+ await usingEthPlaygrounds(async (_, privateKey) => {
donor = privateKey('//Alice');
});
});
tests/src/eth/reFungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/reFungible.test.ts
+++ b/tests/src/eth/reFungible.test.ts
@@ -26,7 +26,7 @@
itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
const nextTokenId = await contract.methods.nextTokenId().call();
@@ -38,7 +38,7 @@
itWeb3('balanceOf', async ({api, web3, privateKeyWrapper}) => {
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
@@ -63,7 +63,7 @@
itWeb3('ownerOf', async ({api, web3, privateKeyWrapper}) => {
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
@@ -79,7 +79,7 @@
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const receiver = createEthAccount(web3);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
@@ -103,7 +103,7 @@
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const receiver = createEthAccount(web3);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
@@ -130,7 +130,7 @@
itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, owner);
- let result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ let result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
const receiver = createEthAccount(web3);
const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
@@ -163,7 +163,7 @@
itWeb3('Can perform mintBulk()', async ({web3, api, privateKeyWrapper}) => {
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
@@ -221,7 +221,7 @@
itWeb3('Can perform burn()', async ({web3, api, privateKeyWrapper}) => {
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
@@ -247,7 +247,7 @@
itWeb3('Can perform transferFrom()', async ({web3, api, privateKeyWrapper}) => {
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
@@ -304,7 +304,7 @@
itWeb3('Can perform transfer()', async ({web3, api, privateKeyWrapper}) => {
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
@@ -344,7 +344,7 @@
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const receiver = createEthAccount(web3);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
@@ -376,7 +376,7 @@
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const receiver = createEthAccount(web3);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
@@ -413,7 +413,7 @@
itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
@@ -430,7 +430,7 @@
itWeb3('transfer() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
tests/src/eth/reFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/reFungibleAbi.json
+++ b/tests/src/eth/reFungibleAbi.json
@@ -109,6 +109,24 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "user", "type": "uint256" }
+ ],
+ "name": "addToCollectionAllowListSubstrate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "user", "type": "address" }
+ ],
+ "name": "allowed",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "approved", "type": "address" },
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }
],
@@ -146,6 +164,23 @@
"type": "function"
},
{
+ "inputs": [],
+ "name": "collectionOwner",
+ "outputs": [
+ {
+ "components": [
+ { "internalType": "address", "name": "field_0", "type": "address" },
+ { "internalType": "uint256", "name": "field_1", "type": "uint256" }
+ ],
+ "internalType": "struct Tuple17",
+ "name": "",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
"inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
"name": "collectionProperty",
"outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }],
@@ -376,6 +411,15 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "user", "type": "uint256" }
+ ],
+ "name": "removeFromCollectionAllowListSubstrate",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "from", "type": "address" },
{ "internalType": "address", "name": "to", "type": "address" },
{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }
tests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth--- a/tests/src/eth/reFungibleToken.test.ts
+++ b/tests/src/eth/reFungibleToken.test.ts
@@ -15,7 +15,7 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE, requirePallets, Pallets} from '../util/helpers';
-import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, createRefungibleCollection, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth, uniqueRefungible, uniqueRefungibleToken} from './util/helpers';
+import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, createRFTCollection, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth, uniqueRefungible, uniqueRefungibleToken} from './util/helpers';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
@@ -458,7 +458,7 @@
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, caller);
- const result = await helper.methods.createRefungibleCollection('Mint collection', '6', '6').send();
+ const result = await helper.methods.createRFTCollection('Mint collection', '6', '6').send();
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const contract = evmCollection(web3, caller, collectionIdAddress, {type: 'ReFungible'});
@@ -658,7 +658,7 @@
itWeb3('Default parent token address and id', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
- const {collectionIdAddress, collectionId} = await createRefungibleCollection(api, web3, owner);
+ const {collectionIdAddress, collectionId} = await createRFTCollection(api, web3, owner);
const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);
const refungibleTokenId = await refungibleContract.methods.nextTokenId().call();
await refungibleContract.methods.mint(owner, refungibleTokenId).send();
tests/src/eth/util/contractHelpersAbi.jsondiffbeforeafterboth--- a/tests/src/eth/util/contractHelpersAbi.json
+++ b/tests/src/eth/util/contractHelpersAbi.json
@@ -134,6 +134,19 @@
"type": "address"
}
],
+ "name": "getSponsoringFeeLimit",
+ "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "contractAddress",
+ "type": "address"
+ }
+ ],
"name": "getSponsoringRateLimit",
"outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }],
"stateMutability": "view",
@@ -212,6 +225,20 @@
"name": "contractAddress",
"type": "address"
},
+ { "internalType": "uint256", "name": "feeLimit", "type": "uint256" }
+ ],
+ "name": "setSponsoringFeeLimit",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "contractAddress",
+ "type": "address"
+ },
{ "internalType": "uint8", "name": "mode", "type": "uint8" }
],
"name": "setSponsoringMode",
tests/src/eth/util/helpers.tsdiffbeforeafterboth--- a/tests/src/eth/util/helpers.ts
+++ b/tests/src/eth/util/helpers.ts
@@ -141,10 +141,10 @@
expect(result.success).to.be.true;
}
-export async function createRefungibleCollection(api: ApiPromise, web3: Web3, owner: string) {
+export async function createRFTCollection(api: ApiPromise, web3: Web3, owner: string) {
const collectionHelper = evmCollectionHelpers(web3, owner);
const result = await collectionHelper.methods
- .createRefungibleCollection('A', 'B', 'C')
+ .createRFTCollection('A', 'B', 'C')
.send();
return await getCollectionAddressFromResult(api, result);
}
tests/src/eth/util/playgrounds/unique.dev.d.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/util/playgrounds/unique.dev.d.ts
@@ -0,0 +1,17 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+declare module 'solc';
\ No newline at end of file
tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth--- a/tests/src/eth/util/playgrounds/unique.dev.ts
+++ b/tests/src/eth/util/playgrounds/unique.dev.ts
@@ -2,6 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
/* eslint-disable function-call-argument-newline */
+// eslint-disable-next-line @typescript-eslint/triple-slash-reference
+/// <reference path="unique.dev.d.ts" />
import {readFile} from 'fs/promises';
tests/src/fungible.test.tsdiffbeforeafterboth--- a/tests/src/fungible.test.ts
+++ b/tests/src/fungible.test.ts
@@ -16,14 +16,9 @@
import {IKeyringPair} from '@polkadot/types/types';
import {U128_MAX} from './util/helpers';
+import {itSub, usingPlaygrounds, expect} from './util/playgrounds';
-import {usingPlaygrounds} from './util/playgrounds';
-
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-chai.use(chaiAsPromised);
-const expect = chai.expect;
-
+// todo:playgrounds get rid of globals
let alice: IKeyringPair;
let bob: IKeyringPair;
@@ -35,131 +30,117 @@
});
});
- it('Create fungible collection and token', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'trest'});
- const defaultTokenId = await collection.getLastTokenId();
- expect(defaultTokenId).to.be.equal(0);
+ itSub('Create fungible collection and token', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'trest'});
+ const defaultTokenId = await collection.getLastTokenId();
+ expect(defaultTokenId).to.be.equal(0);
- await collection.mint(alice, {Substrate: alice.address}, U128_MAX);
- const aliceBalance = await collection.getBalance({Substrate: alice.address});
- const itemCountAfter = await collection.getLastTokenId();
+ await collection.mint(alice, U128_MAX);
+ const aliceBalance = await collection.getBalance({Substrate: alice.address});
+ const itemCountAfter = await collection.getLastTokenId();
- expect(itemCountAfter).to.be.equal(defaultTokenId);
- expect(aliceBalance).to.be.equal(U128_MAX);
- });
+ expect(itemCountAfter).to.be.equal(defaultTokenId);
+ expect(aliceBalance).to.be.equal(U128_MAX);
});
- it('RPC method tokenOnewrs for fungible collection and token', async () => {
- await usingPlaygrounds(async (helper, privateKey) => {
- const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
- const facelessCrowd = Array(7).fill(0).map((_, i) => ({Substrate: privateKey(`//Alice+${i}`).address}));
+ itSub('RPC method tokenOnewrs for fungible collection and token', async ({helper, privateKey}) => {
+ const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
+ const facelessCrowd = Array(7).fill(0).map((_, i) => ({Substrate: privateKey(`//Alice+${i}`).address}));
- const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- await collection.mint(alice, {Substrate: alice.address}, U128_MAX);
+ await collection.mint(alice, U128_MAX);
- await collection.transfer(alice, {Substrate: bob.address}, 1000n);
- await collection.transfer(alice, ethAcc, 900n);
-
- for (let i = 0; i < 7; i++) {
- await collection.transfer(alice, facelessCrowd[i], 1n);
- }
+ await collection.transfer(alice, {Substrate: bob.address}, 1000n);
+ await collection.transfer(alice, ethAcc, 900n);
+
+ for (let i = 0; i < 7; i++) {
+ await collection.transfer(alice, facelessCrowd[i], 1n);
+ }
- const owners = await collection.getTop10Owners();
+ const owners = await collection.getTop10Owners();
- // What to expect
- expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]);
- expect(owners.length).to.be.equal(10);
-
- const eleven = privateKey('//ALice+11');
- expect(await collection.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true;
- expect((await collection.getTop10Owners()).length).to.be.equal(10);
- });
+ // What to expect
+ expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]);
+ expect(owners.length).to.be.equal(10);
+
+ const eleven = privateKey('//ALice+11');
+ expect(await collection.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true;
+ expect((await collection.getTop10Owners()).length).to.be.equal(10);
});
- it('Transfer token', async () => {
- await usingPlaygrounds(async helper => {
- const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
- const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- await collection.mint(alice, {Substrate: alice.address}, 500n);
+ itSub('Transfer token', async ({helper}) => {
+ const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
+ const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ await collection.mint(alice, 500n);
- expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(500n);
- expect(await collection.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true;
- expect(await collection.transfer(alice, ethAcc, 140n)).to.be.true;
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(500n);
+ expect(await collection.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true;
+ expect(await collection.transfer(alice, ethAcc, 140n)).to.be.true;
- expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(300n);
- expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(60n);
- expect(await collection.getBalance(ethAcc)).to.be.equal(140n);
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(300n);
+ expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(60n);
+ expect(await collection.getBalance(ethAcc)).to.be.equal(140n);
- await expect(collection.transfer(alice, {Substrate: bob.address}, 350n)).to.eventually.be.rejected;
- });
+ await expect(collection.transfer(alice, {Substrate: bob.address}, 350n)).to.eventually.be.rejected;
});
- it('Tokens multiple creation', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ itSub('Tokens multiple creation', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- await collection.mintWithOneOwner(alice, {Substrate: alice.address}, [
- {value: 500n},
- {value: 400n},
- {value: 300n},
- ]);
+ await collection.mintWithOneOwner(alice, [
+ {value: 500n},
+ {value: 400n},
+ {value: 300n},
+ ]);
- expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1200n);
- });
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1200n);
});
- it('Burn some tokens ', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- await collection.mint(alice, {Substrate: alice.address}, 500n);
+ itSub('Burn some tokens ', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ await collection.mint(alice, 500n);
- expect(await collection.isTokenExists(0)).to.be.true;
- expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(500n);
- expect(await collection.burnTokens(alice, 499n)).to.be.true;
- expect(await collection.isTokenExists(0)).to.be.true;
- expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n);
- });
+ expect(await collection.isTokenExists(0)).to.be.true;
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(500n);
+ expect(await collection.burnTokens(alice, 499n)).to.be.true;
+ expect(await collection.isTokenExists(0)).to.be.true;
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n);
});
- it('Burn all tokens ', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- await collection.mint(alice, {Substrate: alice.address}, 500n);
+ itSub('Burn all tokens ', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ await collection.mint(alice, 500n);
- expect(await collection.isTokenExists(0)).to.be.true;
- expect(await collection.burnTokens(alice, 500n)).to.be.true;
- expect(await collection.isTokenExists(0)).to.be.true;
+ expect(await collection.isTokenExists(0)).to.be.true;
+ expect(await collection.burnTokens(alice, 500n)).to.be.true;
+ expect(await collection.isTokenExists(0)).to.be.true;
- expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(0n);
- expect(await collection.getTotalPieces()).to.be.equal(0n);
- });
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(0n);
+ expect(await collection.getTotalPieces()).to.be.equal(0n);
});
- it('Set allowance for token', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
- await collection.mint(alice, {Substrate: alice.address}, 100n);
+ itSub('Set allowance for token', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
+ await collection.mint(alice, 100n);
- expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(100n);
-
- expect(await collection.approveTokens(alice, {Substrate: bob.address}, 60n)).to.be.true;
- expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(60n);
- expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(0n);
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(100n);
+
+ expect(await collection.approveTokens(alice, {Substrate: bob.address}, 60n)).to.be.true;
+ expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(60n);
+ expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(0n);
- expect(await collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: bob.address}, 20n)).to.be.true;
- expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(80n);
- expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(20n);
- expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(40n);
+ expect(await collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: bob.address}, 20n)).to.be.true;
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(80n);
+ expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(20n);
+ expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(40n);
- await collection.burnTokensFrom(bob, {Substrate: alice.address}, 10n);
+ await collection.burnTokensFrom(bob, {Substrate: alice.address}, 10n);
- expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(70n);
- expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(30n);
- expect(await collection.transferFrom(bob, {Substrate: alice.address}, ethAcc, 10n)).to.be.true;
- expect(await collection.getBalance(ethAcc)).to.be.equal(10n);
- });
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(70n);
+ expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(30n);
+ expect(await collection.transferFrom(bob, {Substrate: alice.address}, ethAcc, 10n)).to.be.true;
+ expect(await collection.getBalance(ethAcc)).to.be.equal(10n);
});
});
tests/src/limits.test.tsdiffbeforeafterboth--- a/tests/src/limits.test.ts
+++ b/tests/src/limits.test.ts
@@ -15,54 +15,41 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
import {IKeyringPair} from '@polkadot/types/types';
-import usingApi from './substrate/substrate-api';
-import {
- createCollectionExpectSuccess,
- destroyCollectionExpectSuccess,
- setCollectionLimitsExpectSuccess,
- setCollectionSponsorExpectSuccess,
- confirmSponsorshipExpectSuccess,
- createItemExpectSuccess,
- createItemExpectFailure,
- transferExpectSuccess,
- getFreeBalance,
- waitNewBlocks, burnItemExpectSuccess,
- requirePallets,
- Pallets,
-} from './util/helpers';
-import {expect} from 'chai';
+import {expect, itSub, Pallets, requirePalletsOrSkip, usingPlaygrounds} from './util/playgrounds';
describe('Number of tokens per address (NFT)', () => {
let alice: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([10n], donor);
});
});
- it.skip('Collection limits allow greater number than chain limits, chain limits are enforced', async () => {
-
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 20});
+ itSub.skip('Collection limits allow greater number than chain limits, chain limits are enforced', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {});
+ await collection.setLimits(alice, {accountTokenOwnershipLimit: 20});
+
for(let i = 0; i < 10; i++){
- await createItemExpectSuccess(alice, collectionId, 'NFT');
+ await expect(collection.mintToken(alice)).to.be.not.rejected;
}
- await createItemExpectFailure(alice, collectionId, 'NFT');
+ await expect(collection.mintToken(alice)).to.be.rejectedWith(/common\.AccountTokenLimitExceeded/);
for(let i = 1; i < 11; i++) {
- await burnItemExpectSuccess(alice, collectionId, i);
+ await expect(collection.burnToken(alice, i)).to.be.not.rejected;
}
- await destroyCollectionExpectSuccess(collectionId);
+ await collection.burn(alice);
});
-
- it('Collection limits allow lower number than chain limits, collection limits are enforced', async () => {
+
+ itSub('Collection limits allow lower number than chain limits, collection limits are enforced', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {});
+ await collection.setLimits(alice, {accountTokenOwnershipLimit: 1});
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 1});
- await createItemExpectSuccess(alice, collectionId, 'NFT');
- await createItemExpectFailure(alice, collectionId, 'NFT');
- await burnItemExpectSuccess(alice, collectionId, 1);
- await destroyCollectionExpectSuccess(collectionId);
+ await collection.mintToken(alice);
+ await expect(collection.mintToken(alice)).to.be.rejectedWith(/common\.AccountTokenLimitExceeded/);
+
+ await collection.burnToken(alice, 1);
+ await expect(collection.burn(alice)).to.be.not.rejected;
});
});
@@ -70,38 +57,43 @@
let alice: IKeyringPair;
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ await usingPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
+ const donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([10n], donor);
});
});
- it.skip('Collection limits allow greater number than chain limits, chain limits are enforced', async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 20});
+ itSub.skip('Collection limits allow greater number than chain limits, chain limits are enforced', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {});
+ await collection.setLimits(alice, {accountTokenOwnershipLimit: 20});
+
for(let i = 0; i < 10; i++){
- await createItemExpectSuccess(alice, collectionId, 'ReFungible');
+ await expect(collection.mintToken(alice, 10n)).to.be.not.rejected;
}
- await createItemExpectFailure(alice, collectionId, 'ReFungible');
+ await expect(collection.mintToken(alice, 10n)).to.be.rejectedWith(/common\.AccountTokenLimitExceeded/);
for(let i = 1; i < 11; i++) {
- await burnItemExpectSuccess(alice, collectionId, i, 100);
+ await expect(collection.burnToken(alice, i, 10n)).to.be.not.rejected;
}
- await destroyCollectionExpectSuccess(collectionId);
+ await collection.burn(alice);
});
- it('Collection limits allow lower number than chain limits, collection limits are enforced', async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 1});
- await createItemExpectSuccess(alice, collectionId, 'ReFungible');
- await createItemExpectFailure(alice, collectionId, 'ReFungible');
- await burnItemExpectSuccess(alice, collectionId, 1, 100);
- await destroyCollectionExpectSuccess(collectionId);
+ itSub('Collection limits allow lower number than chain limits, collection limits are enforced', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {});
+ await collection.setLimits(alice, {accountTokenOwnershipLimit: 1});
+
+ await collection.mintToken(alice);
+ await expect(collection.mintToken(alice)).to.be.rejectedWith(/common\.AccountTokenLimitExceeded/);
+
+ await collection.burnToken(alice, 1);
+ await expect(collection.burn(alice)).to.be.not.rejected;
});
});
+// todo:playgrounds skipped ~ postponed
describe.skip('Sponsor timeout (NFT) (only for special chain limits test)', () => {
- let alice: IKeyringPair;
+ /*let alice: IKeyringPair;
let bob: IKeyringPair;
let charlie: IKeyringPair;
@@ -113,7 +105,7 @@
});
});
- it.skip('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {
+ itSub.skip('Collection limits have greater timeout value than chain limits, collection limits are enforced', async ({helper}) => {
const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 7});
const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');
@@ -137,7 +129,7 @@
await destroyCollectionExpectSuccess(collectionId);
});
- it('Collection limits have lower timeout value than chain limits, chain limits are enforced', async () => {
+ itSub('Collection limits have lower timeout value than chain limits, chain limits are enforced', async ({helper}) => {
const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 1});
@@ -176,7 +168,7 @@
});
});
- it('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {
+ itSub('Collection limits have greater timeout value than chain limits, collection limits are enforced', async ({helper}) => {
const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 7});
const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible');
@@ -202,7 +194,7 @@
await destroyCollectionExpectSuccess(collectionId);
});
- it('Collection limits have lower timeout value than chain limits, chain limits are enforced', async () => {
+ itSub('Collection limits have lower timeout value than chain limits, chain limits are enforced', async ({helper}) => {
const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 1});
@@ -243,7 +235,7 @@
});
});
- it('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {
+ itSub('Collection limits have greater timeout value than chain limits, collection limits are enforced', async ({helper}) => {
const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 7});
const tokenId = await createItemExpectSuccess(alice, collectionId, 'ReFungible');
@@ -267,7 +259,7 @@
await destroyCollectionExpectSuccess(collectionId);
});
- it('Collection limits have lower timeout value than chain limits, chain limits are enforced', async () => {
+ itSub('Collection limits have lower timeout value than chain limits, chain limits are enforced', async ({helper}) => {
const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 1});
@@ -290,7 +282,7 @@
expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;
//expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);
await destroyCollectionExpectSuccess(collectionId);
- });
+ });*/
});
describe('Collection zero limits (NFT)', () => {
@@ -299,38 +291,38 @@
let charlie: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- charlie = privateKeyWrapper('//Charlie');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
});
});
- it.skip('Limits have 0 in tokens per address field, the chain limits are applied', async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 0});
+ itSub.skip('Limits have 0 in tokens per address field, the chain limits are applied', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {});
+ await collection.setLimits(alice, {accountTokenOwnershipLimit: 0});
+
for(let i = 0; i < 10; i++){
- await createItemExpectSuccess(alice, collectionId, 'NFT');
+ await collection.mintToken(alice);
}
- await createItemExpectFailure(alice, collectionId, 'NFT');
+ await expect(collection.mintToken(alice)).to.be.rejectedWith(/common\.AccountTokenLimitExceeded/);
});
- it('Limits have 0 in sponsor timeout, no limits are applied', async () => {
+ itSub('Limits have 0 in sponsor timeout, no limits are applied', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {});
+ await collection.setLimits(alice, {sponsorTransferTimeout: 0});
+ const token = await collection.mintToken(alice);
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 0});
- const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');
- await setCollectionSponsorExpectSuccess(collectionId, alice.address);
- await confirmSponsorshipExpectSuccess(collectionId, '//Alice');
- await transferExpectSuccess(collectionId, tokenId, alice, bob);
- const aliceBalanceBefore = await getFreeBalance(alice);
+ await collection.setSponsor(alice, alice.address);
+ await collection.confirmSponsorship(alice);
+
+ await token.transfer(alice, {Substrate: bob.address});
+ const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);
// check setting SponsorTimeout = 0, success with next block
- await waitNewBlocks(1);
- await transferExpectSuccess(collectionId, tokenId, bob, charlie);
- const aliceBalanceAfterSponsoredTransaction1 = await getFreeBalance(alice);
+ await helper.wait.newBlocks(1);
+ await token.transfer(bob, {Substrate: charlie.address});
+ const aliceBalanceAfterSponsoredTransaction1 = await helper.balance.getSubstrate(alice.address);
expect(aliceBalanceAfterSponsoredTransaction1 < aliceBalanceBefore).to.be.true;
- //expect(aliceBalanceAfterSponsoredTransaction1).to.be.lessThan(aliceBalanceBefore);
});
});
@@ -340,29 +332,28 @@
let charlie: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- charlie = privateKeyWrapper('//Charlie');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
});
});
- it('Limits have 0 in sponsor timeout, no limits are applied', async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 0});
- const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible');
- await setCollectionSponsorExpectSuccess(collectionId, alice.address);
- await confirmSponsorshipExpectSuccess(collectionId, '//Alice');
- await transferExpectSuccess(collectionId, tokenId, alice, bob, 10, 'Fungible');
- const aliceBalanceBefore = await getFreeBalance(alice);
- await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');
+ itSub('Limits have 0 in sponsor timeout, no limits are applied', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {});
+ await collection.setLimits(alice, {sponsorTransferTimeout: 0});
+ await collection.mint(alice, 3n);
+
+ await collection.setSponsor(alice, alice.address);
+ await collection.confirmSponsorship(alice);
+
+ await collection.transfer(alice, {Substrate: bob.address}, 2n);
+ const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);
// check setting SponsorTimeout = 0, success with next block
- await waitNewBlocks(1);
- await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');
- const aliceBalanceAfterSponsoredTransaction1 = await getFreeBalance(alice);
+ await helper.wait.newBlocks(1);
+ await collection.transfer(bob, {Substrate: charlie.address});
+ const aliceBalanceAfterSponsoredTransaction1 = await helper.balance.getSubstrate(alice.address);
expect(aliceBalanceAfterSponsoredTransaction1 < aliceBalanceBefore).to.be.true;
- //expect(aliceBalanceAfterSponsoredTransaction1).to.be.lessThan(aliceBalanceBefore);
});
});
@@ -372,110 +363,112 @@
let charlie: IKeyringPair;
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ await usingPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- charlie = privateKeyWrapper('//Charlie');
+ const donor = privateKey('//Alice');
+ [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
});
});
- it.skip('Limits have 0 in tokens per address field, the chain limits are applied', async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 0});
+ itSub.skip('Limits have 0 in tokens per address field, the chain limits are applied', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {});
+ await collection.setLimits(alice, {accountTokenOwnershipLimit: 0});
for(let i = 0; i < 10; i++){
- await createItemExpectSuccess(alice, collectionId, 'ReFungible');
+ await collection.mintToken(alice);
}
- await createItemExpectFailure(alice, collectionId, 'ReFungible');
+ await expect(collection.mintToken(alice)).to.be.rejectedWith(/common\.AccountTokenLimitExceeded/);
});
- it('Limits have 0 in sponsor timeout, no limits are applied', async () => {
+ itSub('Limits have 0 in sponsor timeout, no limits are applied', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {});
+ await collection.setLimits(alice, {sponsorTransferTimeout: 0});
+ const token = await collection.mintToken(alice, 3n);
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 0});
- const tokenId = await createItemExpectSuccess(alice, collectionId, 'ReFungible');
- await setCollectionSponsorExpectSuccess(collectionId, alice.address);
- await confirmSponsorshipExpectSuccess(collectionId, '//Alice');
- await transferExpectSuccess(collectionId, tokenId, alice, bob, 100, 'ReFungible');
- await transferExpectSuccess(collectionId, tokenId, bob, charlie, 20, 'ReFungible');
- const aliceBalanceBefore = await getFreeBalance(alice);
+ await collection.setSponsor(alice, alice.address);
+ await collection.confirmSponsorship(alice);
+
+ await token.transfer(alice, {Substrate: bob.address}, 2n);
+ const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);
// check setting SponsorTimeout = 0, success with next block
- await waitNewBlocks(1);
- await transferExpectSuccess(collectionId, tokenId, bob, charlie, 20, 'ReFungible');
- const aliceBalanceAfterSponsoredTransaction1 = await getFreeBalance(alice);
+ await helper.wait.newBlocks(1);
+ await token.transfer(bob, {Substrate: charlie.address});
+ const aliceBalanceAfterSponsoredTransaction1 = await helper.balance.getSubstrate(alice.address);
expect(aliceBalanceAfterSponsoredTransaction1 < aliceBalanceBefore).to.be.true;
- //expect(aliceBalanceAfterSponsoredTransaction1).to.be.lessThan(aliceBalanceBefore);
});
-
- it('Effective collection limits', async () => {
- await usingApi(async (api) => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
-
- { // Check that limits is undefined
- const collection = await api.rpc.unique.collectionById(collectionId);
- expect(collection.isSome).to.be.true;
- const limits = collection.unwrap().limits;
- expect(limits).to.be.any;
-
- expect(limits.accountTokenOwnershipLimit.toHuman()).to.be.null;
- expect(limits.sponsoredDataSize.toHuman()).to.be.null;
- expect(limits.sponsoredDataRateLimit.toHuman()).to.be.null;
- expect(limits.tokenLimit.toHuman()).to.be.null;
- expect(limits.sponsorTransferTimeout.toHuman()).to.be.null;
- expect(limits.sponsorApproveTimeout.toHuman()).to.be.null;
- expect(limits.ownerCanTransfer.toHuman()).to.be.true;
- expect(limits.ownerCanDestroy.toHuman()).to.be.null;
- expect(limits.transfersEnabled.toHuman()).to.be.null;
- }
-
- { // Check that limits is undefined for non-existent collection
- const limits = await api.rpc.unique.effectiveCollectionLimits(11111);
- expect(limits.toHuman()).to.be.null;
- }
-
- { // Check that default values defined for collection limits
- const limitsOpt = await api.rpc.unique.effectiveCollectionLimits(collectionId);
- expect(limitsOpt.isNone).to.be.false;
- const limits = limitsOpt.unwrap();
-
- expect(limits.accountTokenOwnershipLimit.toHuman()).to.be.eq('100,000');
- expect(limits.sponsoredDataSize.toHuman()).to.be.eq('2,048');
- expect(limits.sponsoredDataRateLimit.toHuman()).to.be.eq('SponsoringDisabled');
- expect(limits.tokenLimit.toHuman()).to.be.eq('4,294,967,295');
- expect(limits.sponsorTransferTimeout.toHuman()).to.be.eq('5');
- expect(limits.sponsorApproveTimeout.toHuman()).to.be.eq('5');
- expect(limits.ownerCanTransfer.toHuman()).to.be.true;
- expect(limits.ownerCanDestroy.toHuman()).to.be.true;
- expect(limits.transfersEnabled.toHuman()).to.be.true;
- }
+});
- { //Check the values for collection limits
- await setCollectionLimitsExpectSuccess(alice, collectionId, {
- accountTokenOwnershipLimit: 99_999,
- sponsoredDataSize: 1024,
- tokenLimit: 123,
- transfersEnabled: false,
- });
+describe('Effective collection limits (NFT)', () => {
+ let alice: IKeyringPair;
- const limitsOpt = await api.rpc.unique.effectiveCollectionLimits(collectionId);
- expect(limitsOpt.isNone).to.be.false;
- const limits = limitsOpt.unwrap();
-
- expect(limits.accountTokenOwnershipLimit.toHuman()).to.be.eq('99,999');
- expect(limits.sponsoredDataSize.toHuman()).to.be.eq('1,024');
- expect(limits.sponsoredDataRateLimit.toHuman()).to.be.eq('SponsoringDisabled');
- expect(limits.tokenLimit.toHuman()).to.be.eq('123');
- expect(limits.sponsorTransferTimeout.toHuman()).to.be.eq('5');
- expect(limits.sponsorApproveTimeout.toHuman()).to.be.eq('5');
- expect(limits.ownerCanTransfer.toHuman()).to.be.true;
- expect(limits.ownerCanDestroy.toHuman()).to.be.true;
- expect(limits.transfersEnabled.toHuman()).to.be.false;
- }
+ before(async () => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice] = await helper.arrange.createAccounts([10n], donor);
});
});
-});
+
+ itSub('Effective collection limits', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {});
+ await collection.setLimits(alice, {ownerCanTransfer: true});
+
+ {
+ // Check that limits are undefined
+ const collectionInfo = await collection.getData();
+ const limits = collectionInfo?.raw.limits;
+ expect(limits).to.be.any;
+
+ expect(limits.accountTokenOwnershipLimit).to.be.null;
+ expect(limits.sponsoredDataSize).to.be.null;
+ expect(limits.sponsoredDataRateLimit).to.be.null;
+ expect(limits.tokenLimit).to.be.null;
+ expect(limits.sponsorTransferTimeout).to.be.null;
+ expect(limits.sponsorApproveTimeout).to.be.null;
+ expect(limits.ownerCanTransfer).to.be.true;
+ expect(limits.ownerCanDestroy).to.be.null;
+ expect(limits.transfersEnabled).to.be.null;
+ }
+
+ { // Check that limits is undefined for non-existent collection
+ const limits = await helper.collection.getEffectiveLimits(999999);
+ expect(limits).to.be.null;
+ }
+ { // Check that default values defined for collection limits
+ const limits = await collection.getEffectiveLimits();
+ expect(limits.accountTokenOwnershipLimit).to.be.eq(100000);
+ expect(limits.sponsoredDataSize).to.be.eq(2048);
+ expect(limits.sponsoredDataRateLimit).to.be.deep.eq({sponsoringDisabled: null});
+ expect(limits.tokenLimit).to.be.eq(4294967295);
+ expect(limits.sponsorTransferTimeout).to.be.eq(5);
+ expect(limits.sponsorApproveTimeout).to.be.eq(5);
+ expect(limits.ownerCanTransfer).to.be.true;
+ expect(limits.ownerCanDestroy).to.be.true;
+ expect(limits.transfersEnabled).to.be.true;
+ }
+
+ {
+ // Check the values for collection limits
+ await collection.setLimits(alice, {
+ accountTokenOwnershipLimit: 99_999,
+ sponsoredDataSize: 1024,
+ tokenLimit: 123,
+ transfersEnabled: false,
+ });
+
+ const limits = await collection.getEffectiveLimits();
+
+ expect(limits.accountTokenOwnershipLimit).to.be.eq(99999);
+ expect(limits.sponsoredDataSize).to.be.eq(1024);
+ expect(limits.sponsoredDataRateLimit).to.be.deep.eq({sponsoringDisabled: null});
+ expect(limits.tokenLimit).to.be.eq(123);
+ expect(limits.sponsorTransferTimeout).to.be.eq(5);
+ expect(limits.sponsorApproveTimeout).to.be.eq(5);
+ expect(limits.ownerCanTransfer).to.be.true;
+ expect(limits.ownerCanDestroy).to.be.true;
+ expect(limits.transfersEnabled).to.be.false;
+ }
+ });
+});
tests/src/nextSponsoring.test.tsdiffbeforeafterboth--- a/tests/src/nextSponsoring.test.ts
+++ b/tests/src/nextSponsoring.test.ts
@@ -14,100 +14,84 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import {ApiPromise} from '@polkadot/api';
import {IKeyringPair} from '@polkadot/types/types';
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import {default as usingApi} from './substrate/substrate-api';
-import {
- createCollectionExpectSuccess,
- setCollectionSponsorExpectSuccess,
- confirmSponsorshipExpectSuccess,
- createItemExpectSuccess,
- transferExpectSuccess,
- normalizeAccountId,
- getNextSponsored,
- requirePallets,
- Pallets,
-} from './util/helpers';
-
-chai.use(chaiAsPromised);
-const expect = chai.expect;
+import {expect, itSub, Pallets, usingPlaygrounds} from './util/playgrounds';
+const SPONSORING_TIMEOUT = 5;
-
describe('Integration Test getNextSponsored(collection_id, owner, item_id):', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([20n, 10n], donor);
});
});
- it('NFT', async () => {
- await usingApi(async (api: ApiPromise) => {
+ itSub('NFT', async ({helper}) => {
+ // Non-existing collection
+ expect(await helper.collection.getTokenNextSponsored(0, 0, {Substrate: alice.address})).to.be.null;
- // Not existing collection
- expect(await getNextSponsored(api, 0, normalizeAccountId(alice), 0)).to.be.equal(-1);
+ const collection = await helper.nft.mintCollection(alice, {});
+ const token = await collection.mintToken(alice);
- const collectionId = await createCollectionExpectSuccess();
- const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);
+ // Check with Disabled sponsoring state
+ expect(await token.getNextSponsored({Substrate: alice.address})).to.be.null;
+
+ // Check with Unconfirmed sponsoring state
+ await collection.setSponsor(alice, bob.address);
+ expect(await token.getNextSponsored({Substrate: alice.address})).to.be.null;
- // Check with Disabled sponsoring state
- expect(await getNextSponsored(api, collectionId, normalizeAccountId(alice), itemId)).to.be.equal(-1);
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+ // Check with Confirmed sponsoring state
+ await collection.confirmSponsorship(bob);
+ expect(await token.getNextSponsored({Substrate: alice.address})).to.be.equal(0);
- // Check with Unconfirmed sponsoring state
- expect(await getNextSponsored(api, collectionId, normalizeAccountId(alice), itemId)).to.be.equal(-1);
- await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
+ // Check after transfer
+ await token.transfer(alice, {Substrate: bob.address});
+ expect(await token.getNextSponsored({Substrate: alice.address})).to.be.lessThanOrEqual(SPONSORING_TIMEOUT);
- // Check with Confirmed sponsoring state
- expect(await getNextSponsored(api, collectionId, normalizeAccountId(alice), itemId)).to.be.equal(0);
+ // Non-existing token
+ expect(await collection.getTokenNextSponsored(0, {Substrate: alice.address})).to.be.null;
+ });
- // After transfer
- await transferExpectSuccess(collectionId, itemId, alice, bob, 1);
- expect(await getNextSponsored(api, collectionId, normalizeAccountId(alice), itemId)).to.be.lessThanOrEqual(5);
+ itSub('Fungible', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {});
+ await collection.mint(alice, 10n);
- // Not existing token
- expect(await getNextSponsored(api, collectionId, normalizeAccountId(alice), itemId+1)).to.be.equal(-1);
- });
- });
+ // Check with Disabled sponsoring state
+ expect(await collection.getTokenNextSponsored(0, {Substrate: alice.address})).to.be.null;
- it('Fungible', async () => {
- await usingApi(async (api: ApiPromise) => {
-
- const createMode = 'Fungible';
- const funCollectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});
- await createItemExpectSuccess(alice, funCollectionId, createMode);
- await setCollectionSponsorExpectSuccess(funCollectionId, bob.address);
- await confirmSponsorshipExpectSuccess(funCollectionId, '//Bob');
- expect(await getNextSponsored(api, funCollectionId, normalizeAccountId(alice), 0)).to.be.equal(0);
+ await collection.setSponsor(alice, bob.address);
+ await collection.confirmSponsorship(bob);
+
+ // Check with Confirmed sponsoring state
+ expect(await collection.getTokenNextSponsored(0, {Substrate: alice.address})).to.be.equal(0);
- await transferExpectSuccess(funCollectionId, 0, alice, bob, 10, 'Fungible');
- expect(await getNextSponsored(api, funCollectionId, normalizeAccountId(alice), 0)).to.be.lessThanOrEqual(5);
- });
+ // Check after transfer
+ await collection.transfer(alice, {Substrate: bob.address});
+ expect(await collection.getTokenNextSponsored(0, {Substrate: alice.address})).to.be.lessThanOrEqual(SPONSORING_TIMEOUT);
});
- it('ReFungible', async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ itSub.ifWithPallets('ReFungible', [Pallets.ReFungible], async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {});
+ const token = await collection.mintToken(alice, 10n);
- await usingApi(async (api: ApiPromise) => {
+ // Check with Disabled sponsoring state
+ expect(await token.getNextSponsored({Substrate: alice.address})).to.be.null;
- const createMode = 'ReFungible';
- const refunCollectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
- const refunItemId = await createItemExpectSuccess(alice, refunCollectionId, createMode);
- await setCollectionSponsorExpectSuccess(refunCollectionId, bob.address);
- await confirmSponsorshipExpectSuccess(refunCollectionId, '//Bob');
- expect(await getNextSponsored(api, refunCollectionId, normalizeAccountId(alice), refunItemId)).to.be.equal(0);
+ await collection.setSponsor(alice, bob.address);
+ await collection.confirmSponsorship(bob);
+
+ // Check with Confirmed sponsoring state
+ expect(await token.getNextSponsored({Substrate: alice.address})).to.be.equal(0);
- await transferExpectSuccess(refunCollectionId, refunItemId, alice, bob, 10, 'ReFungible');
- expect(await getNextSponsored(api, refunCollectionId, normalizeAccountId(alice), refunItemId)).to.be.lessThanOrEqual(5);
+ // Check after transfer
+ await token.transfer(alice, {Substrate: bob.address});
+ expect(await token.getNextSponsored({Substrate: alice.address})).to.be.lessThanOrEqual(SPONSORING_TIMEOUT);
- // Not existing token
- expect(await getNextSponsored(api, refunCollectionId, normalizeAccountId(alice), refunItemId+1)).to.be.equal(-1);
- });
+ // Non-existing token
+ expect(await collection.getTokenNextSponsored(0, {Substrate: alice.address})).to.be.null;
});
});
tests/src/overflow.test.tsdiffbeforeafterboth--- a/tests/src/overflow.test.ts
+++ b/tests/src/overflow.test.ts
@@ -23,6 +23,7 @@
chai.use(chaiAsPromised);
const expect = chai.expect;
+// todo:playgrounds skipped ~ postponed
describe.skip('Integration Test fungible overflows', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
tests/src/pallet-presence.test.tsdiffbeforeafterboth--- a/tests/src/pallet-presence.test.ts
+++ b/tests/src/pallet-presence.test.ts
@@ -14,13 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import {ApiPromise} from '@polkadot/api';
-import {expect} from 'chai';
-import usingApi from './substrate/substrate-api';
-
-function getModuleNames(api: ApiPromise): string[] {
- return api.runtimeMetadata.asLatest.pallets.map(m => m.name.toString().toLowerCase());
-}
+import {itSub, usingPlaygrounds, expect} from './util/playgrounds';
// Pallets that must always be present
const requiredPallets = [
@@ -62,8 +56,8 @@
describe('Pallet presence', () => {
before(async () => {
- await usingApi(async api => {
- const chain = await api.rpc.system.chain();
+ await usingPlaygrounds(async helper => {
+ const chain = await helper.api!.rpc.system.chain();
const refungible = 'refungible';
const scheduler = 'scheduler';
@@ -80,23 +74,15 @@
});
});
- it('Required pallets are present', async () => {
- await usingApi(async api => {
- for (let i=0; i<requiredPallets.length; i++) {
- expect(getModuleNames(api)).to.include(requiredPallets[i]);
- }
- });
+ itSub('Required pallets are present', async ({helper}) => {
+ expect(helper.fetchAllPalletNames()).to.contain.members([...requiredPallets]);
});
- it('Governance and consensus pallets are present', async () => {
- await usingApi(async api => {
- for (let i=0; i<consensusPallets.length; i++) {
- expect(getModuleNames(api)).to.include(consensusPallets[i]);
- }
- });
+
+ itSub('Governance and consensus pallets are present', async ({helper}) => {
+ expect(helper.fetchAllPalletNames()).to.contain.members([...consensusPallets]);
});
- it('No extra pallets are included', async () => {
- await usingApi(async api => {
- expect(getModuleNames(api).sort()).to.be.deep.equal([...requiredPallets, ...consensusPallets].sort());
- });
+
+ itSub('No extra pallets are included', async ({helper}) => {
+ expect(helper.fetchAllPalletNames().sort()).to.be.deep.equal([...requiredPallets, ...consensusPallets].sort());
});
});
tests/src/refungible.test.tsdiffbeforeafterboth--- a/tests/src/refungible.test.ts
+++ b/tests/src/refungible.test.ts
@@ -15,18 +15,7 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
import {IKeyringPair} from '@polkadot/types/types';
-
-import {usingPlaygrounds} from './util/playgrounds';
-import {
- getModuleNames,
- Pallets,
- requirePallets,
-} from './util/helpers';
-
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-chai.use(chaiAsPromised);
-const expect = chai.expect;
+import {itSub, Pallets, requirePalletsOrSkip, usingPlaygrounds, expect} from './util/playgrounds';
let alice: IKeyringPair;
let bob: IKeyringPair;
@@ -34,255 +23,231 @@
describe('integration test: Refungible functionality:', async () => {
before(async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ await usingPlaygrounds(async (helper, privateKey) => {
+ requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);
- await usingPlaygrounds(async (helper, privateKey) => {
alice = privateKey('//Alice');
bob = privateKey('//Bob');
- if (!getModuleNames(helper.api!).includes(Pallets.ReFungible)) this.skip();
});
});
- it('Create refungible collection and token', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ itSub('Create refungible collection and token', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- const itemCountBefore = await collection.getLastTokenId();
- const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);
-
- const itemCountAfter = await collection.getLastTokenId();
-
- // What to expect
- expect(token?.tokenId).to.be.gte(itemCountBefore);
- expect(itemCountAfter).to.be.equal(itemCountBefore + 1);
- expect(itemCountAfter.toString()).to.be.equal(token?.tokenId.toString());
- });
+ const itemCountBefore = await collection.getLastTokenId();
+ const token = await collection.mintToken(alice, 100n);
+
+ const itemCountAfter = await collection.getLastTokenId();
+
+ // What to expect
+ expect(token?.tokenId).to.be.gte(itemCountBefore);
+ expect(itemCountAfter).to.be.equal(itemCountBefore + 1);
+ expect(itemCountAfter.toString()).to.be.equal(token?.tokenId.toString());
});
- it('Checking RPC methods when interacting with maximum allowed values (MAX_REFUNGIBLE_PIECES)', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
-
- const token = await collection.mintToken(alice, {Substrate: alice.address}, MAX_REFUNGIBLE_PIECES);
-
- expect(await collection.getTokenBalance(token.tokenId, {Substrate: alice.address})).to.be.equal(MAX_REFUNGIBLE_PIECES);
-
- await collection.transferToken(alice, token.tokenId, {Substrate: bob.address}, MAX_REFUNGIBLE_PIECES);
- expect(await collection.getTokenBalance(token.tokenId, {Substrate: bob.address})).to.be.equal(MAX_REFUNGIBLE_PIECES);
- expect(await token.getTotalPieces()).to.be.equal(MAX_REFUNGIBLE_PIECES);
-
- await expect(collection.mintToken(alice, {Substrate: alice.address}, MAX_REFUNGIBLE_PIECES + 1n)).to.eventually.be.rejected;
- });
+ itSub('Checking RPC methods when interacting with maximum allowed values (MAX_REFUNGIBLE_PIECES)', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+
+ const token = await collection.mintToken(alice, MAX_REFUNGIBLE_PIECES);
+
+ expect(await collection.getTokenBalance(token.tokenId, {Substrate: alice.address})).to.be.equal(MAX_REFUNGIBLE_PIECES);
+
+ await collection.transferToken(alice, token.tokenId, {Substrate: bob.address}, MAX_REFUNGIBLE_PIECES);
+ expect(await collection.getTokenBalance(token.tokenId, {Substrate: bob.address})).to.be.equal(MAX_REFUNGIBLE_PIECES);
+ expect(await token.getTotalPieces()).to.be.equal(MAX_REFUNGIBLE_PIECES);
+
+ await expect(collection.mintToken(alice, MAX_REFUNGIBLE_PIECES + 1n))
+ .to.eventually.be.rejectedWith(/refungible\.WrongRefungiblePieces/);
});
- it('RPC method tokenOnewrs for refungible collection and token', async () => {
- await usingPlaygrounds(async (helper, privateKey) => {
- const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
- const facelessCrowd = Array(7).fill(0).map((_, i) => ({Substrate: privateKey(`//Alice+${i}`).address}));
+ itSub('RPC method tokenOnewrs for refungible collection and token', async ({helper, privateKey}) => {
+ const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
+ const facelessCrowd = Array(7).fill(0).map((_, i) => ({Substrate: privateKey(`//Alice+${i}`).address}));
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- const token = await collection.mintToken(alice, {Substrate: alice.address}, 10_000n);
+ const token = await collection.mintToken(alice, 10_000n);
- await token.transfer(alice, {Substrate: bob.address}, 1000n);
- await token.transfer(alice, ethAcc, 900n);
-
- for (let i = 0; i < 7; i++) {
- await token.transfer(alice, facelessCrowd[i], 50n * BigInt(i + 1));
- }
+ await token.transfer(alice, {Substrate: bob.address}, 1000n);
+ await token.transfer(alice, ethAcc, 900n);
+
+ for (let i = 0; i < 7; i++) {
+ await token.transfer(alice, facelessCrowd[i], 50n * BigInt(i + 1));
+ }
- const owners = await token.getTop10Owners();
+ const owners = await token.getTop10Owners();
- // What to expect
- expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]);
- expect(owners.length).to.be.equal(10);
-
- const eleven = privateKey('//ALice+11');
- expect(await token.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true;
- expect((await token.getTop10Owners()).length).to.be.equal(10);
- });
+ // What to expect
+ expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]);
+ expect(owners.length).to.be.equal(10);
+
+ const eleven = privateKey('//ALice+11');
+ expect(await token.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true;
+ expect((await token.getTop10Owners()).length).to.be.equal(10);
});
- it('Transfer token pieces', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);
+ itSub('Transfer token pieces', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ const token = await collection.mintToken(alice, 100n);
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
- expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true;
-
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n);
- expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n);
-
- await expect(token.transfer(alice, {Substrate: bob.address}, 41n)).to.eventually.be.rejected;
- });
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
+ expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true;
+
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n);
+ expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n);
+
+ await expect(token.transfer(alice, {Substrate: bob.address}, 41n))
+ .to.eventually.be.rejectedWith(/common\.TokenValueTooLow/);
});
- it('Create multiple tokens', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- // TODO: fix mintMultipleTokens
- // await collection.mintMultipleTokens(alice, [
- // {owner: {Substrate: alice.address}, pieces: 1n},
- // {owner: {Substrate: alice.address}, pieces: 2n},
- // {owner: {Substrate: alice.address}, pieces: 100n},
- // ]);
- await helper.rft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, [
- {pieces: 1n},
- {pieces: 2n},
- {pieces: 100n},
- ]);
- const lastTokenId = await collection.getLastTokenId();
- expect(lastTokenId).to.be.equal(3);
- expect(await collection.getTokenBalance(lastTokenId, {Substrate: alice.address})).to.be.equal(100n);
- });
+ itSub('Create multiple tokens', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ // TODO: fix mintMultipleTokens
+ // await collection.mintMultipleTokens(alice, [
+ // {owner: {Substrate: alice.address}, pieces: 1n},
+ // {owner: {Substrate: alice.address}, pieces: 2n},
+ // {owner: {Substrate: alice.address}, pieces: 100n},
+ // ]);
+ await helper.rft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, [
+ {pieces: 1n},
+ {pieces: 2n},
+ {pieces: 100n},
+ ]);
+ const lastTokenId = await collection.getLastTokenId();
+ expect(lastTokenId).to.be.equal(3);
+ expect(await collection.getTokenBalance(lastTokenId, {Substrate: alice.address})).to.be.equal(100n);
});
- it('Burn some pieces', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);
- expect(await collection.isTokenExists(token.tokenId)).to.be.true;
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
- expect((await token.burn(alice, 99n)).success).to.be.true;
- expect(await collection.isTokenExists(token.tokenId)).to.be.true;
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(1n);
- });
+ itSub('Burn some pieces', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ const token = await collection.mintToken(alice, 100n);
+ expect(await collection.isTokenExists(token.tokenId)).to.be.true;
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
+ expect((await token.burn(alice, 99n)).success).to.be.true;
+ expect(await collection.isTokenExists(token.tokenId)).to.be.true;
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(1n);
});
- it('Burn all pieces', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);
-
- expect(await collection.isTokenExists(token.tokenId)).to.be.true;
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
+ itSub('Burn all pieces', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ const token = await collection.mintToken(alice, 100n);
+
+ expect(await collection.isTokenExists(token.tokenId)).to.be.true;
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
- expect((await token.burn(alice, 100n)).success).to.be.true;
- expect(await collection.isTokenExists(token.tokenId)).to.be.false;
- });
+ expect((await token.burn(alice, 100n)).success).to.be.true;
+ expect(await collection.isTokenExists(token.tokenId)).to.be.false;
});
- it('Burn some pieces for multiple users', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);
+ itSub('Burn some pieces for multiple users', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ const token = await collection.mintToken(alice, 100n);
- expect(await collection.isTokenExists(token.tokenId)).to.be.true;
-
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
- expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true;
+ expect(await collection.isTokenExists(token.tokenId)).to.be.true;
+
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
+ expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true;
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n);
- expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n);
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n);
+ expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n);
- expect((await token.burn(alice, 40n)).success).to.be.true;
+ expect((await token.burn(alice, 40n)).success).to.be.true;
- expect(await collection.isTokenExists(token.tokenId)).to.be.true;
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n);
+ expect(await collection.isTokenExists(token.tokenId)).to.be.true;
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n);
- expect((await token.burn(bob, 59n)).success).to.be.true;
+ expect((await token.burn(bob, 59n)).success).to.be.true;
- expect(await token.getBalance({Substrate: bob.address})).to.be.equal(1n);
- expect(await collection.isTokenExists(token.tokenId)).to.be.true;
+ expect(await token.getBalance({Substrate: bob.address})).to.be.equal(1n);
+ expect(await collection.isTokenExists(token.tokenId)).to.be.true;
- expect((await token.burn(bob, 1n)).success).to.be.true;
+ expect((await token.burn(bob, 1n)).success).to.be.true;
- expect(await collection.isTokenExists(token.tokenId)).to.be.false;
- });
+ expect(await collection.isTokenExists(token.tokenId)).to.be.false;
});
- it('Set allowance for token', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);
-
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
+ itSub('Set allowance for token', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ const token = await collection.mintToken(alice, 100n);
+
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n);
- expect(await token.approve(alice, {Substrate: bob.address}, 60n)).to.be.true;
- expect(await token.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(60n);
+ expect(await token.approve(alice, {Substrate: bob.address}, 60n)).to.be.true;
+ expect(await token.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(60n);
- expect(await token.transferFrom(bob, {Substrate: alice.address}, {Substrate: bob.address}, 20n)).to.be.true;
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(80n);
- expect(await token.getBalance({Substrate: bob.address})).to.be.equal(20n);
- expect(await token.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(40n);
- });
+ expect(await token.transferFrom(bob, {Substrate: alice.address}, {Substrate: bob.address}, 20n)).to.be.true;
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(80n);
+ expect(await token.getBalance({Substrate: bob.address})).to.be.equal(20n);
+ expect(await token.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(40n);
});
- it('Repartition', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);
+ itSub('Repartition', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ const token = await collection.mintToken(alice, 100n);
- expect(await token.repartition(alice, 200n)).to.be.true;
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(200n);
- expect(await token.getTotalPieces()).to.be.equal(200n);
-
- expect(await token.transfer(alice, {Substrate: bob.address}, 110n)).to.be.true;
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(90n);
- expect(await token.getBalance({Substrate: bob.address})).to.be.equal(110n);
-
- await expect(token.repartition(alice, 80n)).to.eventually.be.rejected;
-
- expect(await token.transfer(alice, {Substrate: bob.address}, 90n)).to.be.true;
- expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n);
- expect(await token.getBalance({Substrate: bob.address})).to.be.equal(200n);
-
- expect(await token.repartition(bob, 150n)).to.be.true;
- await expect(token.transfer(bob, {Substrate: alice.address}, 160n)).to.eventually.be.rejected;
+ expect(await token.repartition(alice, 200n)).to.be.true;
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(200n);
+ expect(await token.getTotalPieces()).to.be.equal(200n);
+
+ expect(await token.transfer(alice, {Substrate: bob.address}, 110n)).to.be.true;
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(90n);
+ expect(await token.getBalance({Substrate: bob.address})).to.be.equal(110n);
+
+ await expect(token.repartition(alice, 80n))
+ .to.eventually.be.rejectedWith(/refungible\.RepartitionWhileNotOwningAllPieces/);
+
+ expect(await token.transfer(alice, {Substrate: bob.address}, 90n)).to.be.true;
+ expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n);
+ expect(await token.getBalance({Substrate: bob.address})).to.be.equal(200n);
- });
+ expect(await token.repartition(bob, 150n)).to.be.true;
+ await expect(token.transfer(bob, {Substrate: alice.address}, 160n))
+ .to.eventually.be.rejectedWith(/common\.TokenValueTooLow/);
});
- it('Repartition with increased amount', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);
- await token.repartition(alice, 200n);
- const chainEvents = helper.chainLog.slice(-1)[0].events.map((x: any) => x.event);
- expect(chainEvents).to.include.deep.members([{
- method: 'ItemCreated',
- section: 'common',
- index: '0x4202',
- data: [
- helper.api!.createType('u32', collection.collectionId).toHuman(),
- helper.api!.createType('u32', token.tokenId).toHuman(),
- {Substrate: alice.address},
- '100',
- ],
- }]);
- });
+ itSub('Repartition with increased amount', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ const token = await collection.mintToken(alice, 100n);
+ await token.repartition(alice, 200n);
+ const chainEvents = helper.chainLog.slice(-1)[0].events.map((x: any) => x.event);
+ expect(chainEvents).to.include.deep.members([{
+ method: 'ItemCreated',
+ section: 'common',
+ index: '0x4202',
+ data: [
+ helper.api!.createType('u32', collection.collectionId).toHuman(),
+ helper.api!.createType('u32', token.tokenId).toHuman(),
+ {Substrate: alice.address},
+ '100',
+ ],
+ }]);
});
- it('Repartition with decreased amount', async () => {
- await usingPlaygrounds(async helper => {
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n);
- await token.repartition(alice, 50n);
- const chainEvents = helper.chainLog.slice(-1)[0].events.map((x: any) => x.event);
- expect(chainEvents).to.include.deep.members([{
- method: 'ItemDestroyed',
- section: 'common',
- index: '0x4203',
- data: [
- helper.api!.createType('u32', collection.collectionId).toHuman(),
- helper.api!.createType('u32', token.tokenId).toHuman(),
- {Substrate: alice.address},
- '50',
- ],
- }]);
- });
+ itSub('Repartition with decreased amount', async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ const token = await collection.mintToken(alice, 100n);
+ await token.repartition(alice, 50n);
+ const chainEvents = helper.chainLog.slice(-1)[0].events.map((x: any) => x.event);
+ expect(chainEvents).to.include.deep.members([{
+ method: 'ItemDestroyed',
+ section: 'common',
+ index: '0x4203',
+ data: [
+ helper.api!.createType('u32', collection.collectionId).toHuman(),
+ helper.api!.createType('u32', token.tokenId).toHuman(),
+ {Substrate: alice.address},
+ '50',
+ ],
+ }]);
});
- it('Create new collection with properties', async () => {
- await usingPlaygrounds(async helper => {
- const properties = [{key: 'key1', value: 'val1'}];
- const tokenPropertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}];
- const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test', properties, tokenPropertyPermissions});
- const info = await collection.getData();
- expect(info?.raw.properties).to.be.deep.equal(properties);
- expect(info?.raw.tokenPropertyPermissions).to.be.deep.equal(tokenPropertyPermissions);
- });
+ itSub('Create new collection with properties', async ({helper}) => {
+ const properties = [{key: 'key1', value: 'val1'}];
+ const tokenPropertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}];
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test', properties, tokenPropertyPermissions});
+ const info = await collection.getData();
+ expect(info?.raw.properties).to.be.deep.equal(properties);
+ expect(info?.raw.tokenPropertyPermissions).to.be.deep.equal(tokenPropertyPermissions);
});
});
tests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -14,115 +14,99 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import {usingPlaygrounds} from './util/playgrounds';
+import {IKeyringPair} from '@polkadot/types/types';
+import {itSub, usingPlaygrounds, expect} from './util/playgrounds';
-chai.use(chaiAsPromised);
-const expect = chai.expect;
+describe('Integration Test removeCollectionAdmin(collection_id, account_id):', () => {
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
-describe('Integration Test removeCollectionAdmin(collection_id, account_id):', () => {
- it('Remove collection admin.', async () => {
+ before(async () => {
await usingPlaygrounds(async (helper, privateKey) => {
- const alice = privateKey('//Alice');
- const bob = privateKey('//Bob');
- const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
-
- const collectionInfo = await collection.getData();
- expect(collectionInfo?.raw.owner.toString()).to.be.deep.eq(alice.address);
- // first - add collection admin Bob
- await collection.addAdmin(alice, {Substrate: bob.address});
+ const donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([20n, 10n], donor);
+ });
+ });
+
+ itSub('Remove collection admin', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionAdmin-1', tokenPrefix: 'RCA'});
+ const collectionInfo = await collection.getData();
+ expect(collectionInfo?.raw.owner.toString()).to.be.deep.eq(alice.address);
+ // first - add collection admin Bob
+ await collection.addAdmin(alice, {Substrate: bob.address});
- const adminListAfterAddAdmin = await collection.getAdmins();
- expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)});
+ const adminListAfterAddAdmin = await collection.getAdmins();
+ expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: bob.address});
- // then remove bob from admins of collection
- await collection.removeAdmin(alice, {Substrate: bob.address});
+ // then remove bob from admins of collection
+ await collection.removeAdmin(alice, {Substrate: bob.address});
- const adminListAfterRemoveAdmin = await collection.getAdmins();
- expect(adminListAfterRemoveAdmin).not.to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)});
- });
+ const adminListAfterRemoveAdmin = await collection.getAdmins();
+ expect(adminListAfterRemoveAdmin).not.to.be.deep.contains({Substrate: bob.address});
});
- it('Remove admin from collection that has no admins', async () => {
- await usingPlaygrounds(async (helper, privateKey) => {
- const alice = privateKey('//Alice');
- const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ itSub('Remove admin from collection that has no admins', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionAdmin-2', tokenPrefix: 'RCA'});
- const adminListBeforeAddAdmin = await collection.getAdmins();
- expect(adminListBeforeAddAdmin).to.have.lengthOf(0);
+ const adminListBeforeAddAdmin = await collection.getAdmins();
+ expect(adminListBeforeAddAdmin).to.have.lengthOf(0);
- // await expect(collection.removeAdmin(alice, {Substrate: alice.address})).to.be.rejectedWith('Unable to remove collection admin');
- await collection.removeAdmin(alice, {Substrate: alice.address});
- });
+ await collection.removeAdmin(alice, {Substrate: alice.address});
});
});
describe('Negative Integration Test removeCollectionAdmin(collection_id, account_id):', () => {
- it('Can\'t remove collection admin from not existing collection', async () => {
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
+ let charlie: IKeyringPair;
+
+ before(async () => {
await usingPlaygrounds(async (helper, privateKey) => {
- // tslint:disable-next-line: no-bitwise
- const collectionId = (1 << 32) - 1;
- const alice = privateKey('//Alice');
- const bob = privateKey('//Bob');
+ const donor = privateKey('//Alice');
+ [alice, bob, charlie] = await helper.arrange.createAccounts([20n, 10n, 10n], donor);
+ });
+ });
- await expect(helper.collection.removeAdmin(alice, collectionId, {Substrate: bob.address})).to.be.rejected;
+ itSub('Can\'t remove collection admin from not existing collection', async ({helper}) => {
+ const collectionId = (1 << 32) - 1;
- // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
- await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- });
+ await expect(helper.collection.removeAdmin(alice, collectionId, {Substrate: bob.address}))
+ .to.be.rejectedWith(/common\.CollectionNotFound/);
});
- it('Can\'t remove collection admin from deleted collection', async () => {
- await usingPlaygrounds(async (helper, privateKey) => {
- const alice = privateKey('//Alice');
- const bob = privateKey('//Bob');
- const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ itSub('Can\'t remove collection admin from deleted collection', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionAdmin-Neg-2', tokenPrefix: 'RCA'});
- expect(await collection.burn(alice)).to.be.true;
+ expect(await collection.burn(alice)).to.be.true;
- await expect(helper.collection.removeAdmin(alice, collection.collectionId, {Substrate: bob.address})).to.be.rejected;
-
- // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
- await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- });
+ await expect(helper.collection.removeAdmin(alice, collection.collectionId, {Substrate: bob.address}))
+ .to.be.rejectedWith(/common\.CollectionNotFound/);
});
- it('Regular user can\'t remove collection admin', async () => {
- await usingPlaygrounds(async (helper, privateKey) => {
- const alice = privateKey('//Alice');
- const bob = privateKey('//Bob');
- const charlie = privateKey('//Charlie');
- const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ itSub('Regular user can\'t remove collection admin', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionAdmin-Neg-3', tokenPrefix: 'RCA'});
- await collection.addAdmin(alice, {Substrate: bob.address});
+ await collection.addAdmin(alice, {Substrate: bob.address});
- await expect(collection.removeAdmin(charlie, {Substrate: bob.address})).to.be.rejected;
-
- // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
- await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- });
+ await expect(collection.removeAdmin(charlie, {Substrate: bob.address}))
+ .to.be.rejectedWith(/common\.NoPermission/);
});
- it('Admin can\'t remove collection admin.', async () => {
- await usingPlaygrounds(async (helper, privateKey) => {
- const alice = privateKey('//Alice');
- const bob = privateKey('//Bob');
- const charlie = privateKey('//Charlie');
- const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
-
- await collection.addAdmin(alice, {Substrate: bob.address});
- await collection.addAdmin(alice, {Substrate: charlie.address});
+ itSub('Admin can\'t remove collection admin.', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionAdmin-Neg-4', tokenPrefix: 'RCA'});
+
+ await collection.addAdmin(alice, {Substrate: bob.address});
+ await collection.addAdmin(alice, {Substrate: charlie.address});
- const adminListAfterAddAdmin = await collection.getAdmins();
- expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)});
- expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(charlie.address)});
+ const adminListAfterAddAdmin = await collection.getAdmins();
+ expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: bob.address});
+ expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: charlie.address});
- await expect(collection.removeAdmin(charlie, {Substrate: bob.address})).to.be.rejected;
+ await expect(collection.removeAdmin(charlie, {Substrate: bob.address}))
+ .to.be.rejectedWith(/common\.NoPermission/);
- const adminListAfterRemoveAdmin = await collection.getAdmins();
- expect(adminListAfterRemoveAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)});
- expect(adminListAfterRemoveAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(charlie.address)});
- });
+ const adminListAfterRemoveAdmin = await collection.getAdmins();
+ expect(adminListAfterRemoveAdmin).to.be.deep.contains({Substrate: bob.address});
+ expect(adminListAfterRemoveAdmin).to.be.deep.contains({Substrate: charlie.address});
});
});
tests/src/removeCollectionSponsor.test.tsdiffbeforeafterboth--- a/tests/src/removeCollectionSponsor.test.ts
+++ b/tests/src/removeCollectionSponsor.test.ts
@@ -14,138 +14,112 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import {default as usingApi, submitTransactionExpectFailAsync} from './substrate/substrate-api';
-import {
- createCollectionExpectSuccess,
- setCollectionSponsorExpectSuccess,
- destroyCollectionExpectSuccess,
- confirmSponsorshipExpectSuccess,
- confirmSponsorshipExpectFailure,
- createItemExpectSuccess,
- findUnusedAddress,
- removeCollectionSponsorExpectSuccess,
- removeCollectionSponsorExpectFailure,
- normalizeAccountId,
- addCollectionAdminExpectSuccess,
- getCreatedCollectionCount,
-} from './util/helpers';
import {IKeyringPair} from '@polkadot/types/types';
-
-chai.use(chaiAsPromised);
-const expect = chai.expect;
+import {itSub, usingPlaygrounds, expect} from './util/playgrounds';
-let alice: IKeyringPair;
-let bob: IKeyringPair;
-
describe('integration test: ext. removeCollectionSponsor():', () => {
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor);
});
});
- it('Removing NFT collection sponsor stops sponsorship', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
- await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
- await removeCollectionSponsorExpectSuccess(collectionId);
+ itSub('Removing NFT collection sponsor stops sponsorship', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-1', tokenPrefix: 'RCS'});
+ await collection.setSponsor(alice, bob.address);
+ await collection.confirmSponsorship(bob);
+ await collection.removeSponsor(alice);
- await usingApi(async (api, privateKeyWrapper) => {
- // Find unused address
- const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);
+ // Find unused address
+ const [zeroBalance] = await helper.arrange.createAccounts([0n], donor);
- // Mint token for unused address
- const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', zeroBalance.address);
+ // Mint token for unused address
+ const token = await collection.mintToken(alice, {Substrate: zeroBalance.address});
- // Transfer this tokens from unused address to Alice - should fail
- const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();
- const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);
- const badTransaction = async function () {
- await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);
- };
- await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');
- const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();
+ // Transfer this tokens from unused address to Alice - should fail
+ const sponsorBalanceBefore = await helper.balance.getSubstrate(bob.address);
+ await expect(token.transfer(zeroBalance, {Substrate: alice.address}))
+ .to.be.rejectedWith('Inability to pay some fees');
+ const sponsorBalanceAfter = await helper.balance.getSubstrate(bob.address);
- expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore);
- });
+ expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore);
});
- it('Remove a sponsor after it was already removed', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
- await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
- await removeCollectionSponsorExpectSuccess(collectionId);
- await removeCollectionSponsorExpectSuccess(collectionId);
+ itSub('Remove a sponsor after it was already removed', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-2', tokenPrefix: 'RCS'});
+ await collection.setSponsor(alice, bob.address);
+ await collection.confirmSponsorship(bob);
+ await expect(collection.removeSponsor(alice)).to.not.be.rejected;
+ await expect(collection.removeSponsor(alice)).to.not.be.rejected;
});
- it('Remove sponsor in a collection that never had the sponsor set', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await removeCollectionSponsorExpectSuccess(collectionId);
+ itSub('Remove sponsor in a collection that never had the sponsor set', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-3', tokenPrefix: 'RCS'});
+ await expect(collection.removeSponsor(alice)).to.not.be.rejected;
});
- it('Remove sponsor for a collection that had the sponsor set, but not confirmed', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
- await removeCollectionSponsorExpectSuccess(collectionId);
+ itSub('Remove sponsor for a collection that had the sponsor set, but not confirmed', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-4', tokenPrefix: 'RCS'});
+ await collection.setSponsor(alice, bob.address);
+ await expect(collection.removeSponsor(alice)).to.not.be.rejected;
});
});
describe('(!negative test!) integration test: ext. removeCollectionSponsor():', () => {
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
+ let charlie: IKeyringPair;
+
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob, charlie] = await helper.arrange.createAccounts([20n, 10n, 10n], donor);
});
});
- it('(!negative test!) Remove sponsor for a collection that never existed', async () => {
- // Find the collection that never existed
- let collectionId = 0;
- await usingApi(async (api) => {
- collectionId = await getCreatedCollectionCount(api) + 1;
- });
-
- await removeCollectionSponsorExpectFailure(collectionId);
+ itSub('(!negative test!) Remove sponsor for a collection that never existed', async ({helper}) => {
+ const collectionId = (1 << 32) - 1;
+ await expect(helper.collection.removeSponsor(alice, collectionId)).to.be.rejectedWith(/common\.CollectionNotFound/);
});
- it('(!negative test!) Remove sponsor for a collection with collection admin permissions', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
- await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
- await removeCollectionSponsorExpectFailure(collectionId, '//Bob');
+ itSub('(!negative test!) Remove sponsor for a collection with collection admin permissions', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-1', tokenPrefix: 'RCS'});
+ await collection.setSponsor(alice, bob.address);
+ await collection.addAdmin(alice, {Substrate: charlie.address});
+ await expect(collection.removeSponsor(charlie)).to.be.rejectedWith(/common\.NoPermission/);
});
- it('(!negative test!) Remove sponsor for a collection by regular user', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
- await removeCollectionSponsorExpectFailure(collectionId, '//Bob');
+ itSub('(!negative test!) Remove sponsor for a collection by regular user', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-2', tokenPrefix: 'RCS'});
+ await collection.setSponsor(alice, bob.address);
+ await expect(collection.removeSponsor(charlie)).to.be.rejectedWith(/common\.NoPermission/);
});
- it('(!negative test!) Remove sponsor in a destroyed collection', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
- await destroyCollectionExpectSuccess(collectionId);
- await removeCollectionSponsorExpectFailure(collectionId);
+ itSub('(!negative test!) Remove sponsor in a destroyed collection', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-3', tokenPrefix: 'RCS'});
+ await collection.setSponsor(alice, bob.address);
+ await collection.burn(alice);
+ await expect(collection.removeSponsor(alice)).to.be.rejectedWith(/common\.CollectionNotFound/);
});
- it('Set - remove - confirm: fails', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
- await removeCollectionSponsorExpectSuccess(collectionId);
- await confirmSponsorshipExpectFailure(collectionId, '//Bob');
+ itSub('Set - remove - confirm: fails', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-4', tokenPrefix: 'RCS'});
+ await collection.setSponsor(alice, bob.address);
+ await collection.removeSponsor(alice);
+ await expect(collection.confirmSponsorship(bob)).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);
});
- it('Set - confirm - remove - confirm: Sponsor cannot come back', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
- await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
- await removeCollectionSponsorExpectSuccess(collectionId);
- await confirmSponsorshipExpectFailure(collectionId, '//Bob');
+ itSub('Set - confirm - remove - confirm: Sponsor cannot come back', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-5', tokenPrefix: 'RCS'});
+ await collection.setSponsor(alice, bob.address);
+ await collection.confirmSponsorship(bob);
+ await collection.removeSponsor(alice);
+ await expect(collection.confirmSponsorship(bob)).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/);
});
-
});
tests/src/removeFromAllowList.test.tsdiffbeforeafterboth--- a/tests/src/removeFromAllowList.test.ts
+++ b/tests/src/removeFromAllowList.test.ts
@@ -14,58 +14,45 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import {default as usingApi} from './substrate/substrate-api';
-import {
- createCollectionExpectSuccess,
- destroyCollectionExpectSuccess,
- enableAllowListExpectSuccess,
- addToAllowListExpectSuccess,
- removeFromAllowListExpectSuccess,
- isAllowlisted,
- findNotExistingCollection,
- removeFromAllowListExpectFailure,
- disableAllowListExpectSuccess,
- normalizeAccountId,
- addCollectionAdminExpectSuccess,
-} from './util/helpers';
import {IKeyringPair} from '@polkadot/types/types';
-
-chai.use(chaiAsPromised);
-const expect = chai.expect;
+import {itSub, usingPlaygrounds, expect} from './util/playgrounds';
describe('Integration Test removeFromAllowList', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor);
});
});
- it('ensure bob is not in allowlist after removal', async () => {
- await usingApi(async api => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await enableAllowListExpectSuccess(alice, collectionId);
- await addToAllowListExpectSuccess(alice, collectionId, bob.address);
+ itSub('ensure bob is not in allowlist after removal', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveFromAllowList-1', tokenPrefix: 'RFAL'});
- await removeFromAllowListExpectSuccess(alice, collectionId, normalizeAccountId(bob.address));
- expect(await isAllowlisted(api, collectionId, bob.address)).to.be.false;
- });
+ const collectionInfo = await collection.getData();
+ expect(collectionInfo!.raw.permissions.access).to.not.equal('AllowList');
+
+ await collection.setPermissions(alice, {access: 'AllowList', mintMode: true});
+ await collection.addToAllowList(alice, {Substrate: bob.address});
+ expect(await collection.getAllowList()).to.deep.contains({Substrate: bob.address});
+
+ await collection.removeFromAllowList(alice, {Substrate: bob.address});
+ expect(await collection.getAllowList()).to.be.empty;
});
- it('allows removal from collection with unset allowlist status', async () => {
- await usingApi(async () => {
- const collectionWithoutAllowlistId = await createCollectionExpectSuccess();
- await enableAllowListExpectSuccess(alice, collectionWithoutAllowlistId);
- await addToAllowListExpectSuccess(alice, collectionWithoutAllowlistId, bob.address);
- await disableAllowListExpectSuccess(alice, collectionWithoutAllowlistId);
+ itSub('allows removal from collection with unset allowlist status', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveFromAllowList-2', tokenPrefix: 'RFAL'});
+
+ await collection.setPermissions(alice, {access: 'AllowList', mintMode: true});
+ await collection.addToAllowList(alice, {Substrate: bob.address});
+ expect(await collection.getAllowList()).to.deep.contains({Substrate: bob.address});
- await removeFromAllowListExpectSuccess(alice, collectionWithoutAllowlistId, normalizeAccountId(bob.address));
- });
+ await collection.setPermissions(alice, {access: 'Normal'});
+
+ await collection.removeFromAllowList(alice, {Substrate: bob.address});
+ expect(await collection.getAllowList()).to.be.empty;
});
});
@@ -74,29 +61,26 @@
let bob: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor);
});
});
- it('fails on removal from not existing collection', async () => {
- await usingApi(async (api) => {
- const collectionId = await findNotExistingCollection(api);
-
- await removeFromAllowListExpectFailure(alice, collectionId, normalizeAccountId(bob.address));
- });
+ itSub('fails on removal from not existing collection', async ({helper}) => {
+ const nonExistentCollectionId = (1 << 32) - 1;
+ await expect(helper.collection.removeFromAllowList(alice, nonExistentCollectionId, {Substrate: alice.address}))
+ .to.be.rejectedWith(/common\.CollectionNotFound/);
});
- it('fails on removal from removed collection', async () => {
- await usingApi(async () => {
- const collectionId = await createCollectionExpectSuccess();
- await enableAllowListExpectSuccess(alice, collectionId);
- await addToAllowListExpectSuccess(alice, collectionId, bob.address);
- await destroyCollectionExpectSuccess(collectionId);
+ itSub('fails on removal from removed collection', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveFromAllowList-3', tokenPrefix: 'RFAL'});
+ await collection.setPermissions(alice, {access: 'AllowList', mintMode: true});
+ await collection.addToAllowList(alice, {Substrate: bob.address});
- await removeFromAllowListExpectFailure(alice, collectionId, normalizeAccountId(bob.address));
- });
+ await collection.burn(alice);
+ await expect(collection.removeFromAllowList(alice, {Substrate: bob.address}))
+ .to.be.rejectedWith(/common\.CollectionNotFound/);
});
});
@@ -106,41 +90,45 @@
let charlie: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- charlie = privateKeyWrapper('//Charlie');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
});
});
- it('ensure address is not in allowlist after removal', async () => {
- await usingApi(async api => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await enableAllowListExpectSuccess(alice, collectionId);
- await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
- await addToAllowListExpectSuccess(alice, collectionId, charlie.address);
- await removeFromAllowListExpectSuccess(bob, collectionId, normalizeAccountId(charlie.address));
- expect(await isAllowlisted(api, collectionId, charlie.address)).to.be.false;
- });
+ itSub('ensure address is not in allowlist after removal', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveFromAllowList-4', tokenPrefix: 'RFAL'});
+
+ await collection.setPermissions(alice, {access: 'AllowList', mintMode: true});
+ await collection.addAdmin(alice, {Substrate: bob.address});
+
+ await collection.addToAllowList(bob, {Substrate: charlie.address});
+ await collection.removeFromAllowList(bob, {Substrate: charlie.address});
+
+ expect(await collection.getAllowList()).to.be.empty;
});
- it('Collection admin allowed to remove from allowlist with unset allowlist status', async () => {
- await usingApi(async () => {
- const collectionWithoutAllowlistId = await createCollectionExpectSuccess();
- await enableAllowListExpectSuccess(alice, collectionWithoutAllowlistId);
- await addCollectionAdminExpectSuccess(alice, collectionWithoutAllowlistId, bob.address);
- await addToAllowListExpectSuccess(alice, collectionWithoutAllowlistId, charlie.address);
- await disableAllowListExpectSuccess(alice, collectionWithoutAllowlistId);
- await removeFromAllowListExpectSuccess(bob, collectionWithoutAllowlistId, normalizeAccountId(charlie.address));
- });
+ itSub('Collection admin allowed to remove from allowlist with unset allowlist status', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveFromAllowList-5', tokenPrefix: 'RFAL'});
+
+ await collection.setPermissions(alice, {access: 'AllowList', mintMode: true});
+ await collection.addAdmin(alice, {Substrate: bob.address});
+ await collection.addToAllowList(alice, {Substrate: charlie.address});
+
+ await collection.setPermissions(bob, {access: 'Normal'});
+ await collection.removeFromAllowList(bob, {Substrate: charlie.address});
+
+ expect(await collection.getAllowList()).to.be.empty;
});
- it('Regular user can`t remove from allowlist', async () => {
- await usingApi(async () => {
- const collectionWithoutAllowlistId = await createCollectionExpectSuccess();
- await enableAllowListExpectSuccess(alice, collectionWithoutAllowlistId);
- await addToAllowListExpectSuccess(alice, collectionWithoutAllowlistId, charlie.address);
- await removeFromAllowListExpectFailure(bob, collectionWithoutAllowlistId, normalizeAccountId(charlie.address));
- });
+ itSub('Regular user can`t remove from allowlist', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'RemoveFromAllowList-6', tokenPrefix: 'RFAL'});
+
+ await collection.setPermissions(alice, {access: 'AllowList', mintMode: true});
+ await collection.addToAllowList(alice, {Substrate: charlie.address});
+
+ await expect(collection.removeFromAllowList(bob, {Substrate: charlie.address}))
+ .to.be.rejectedWith(/common\.NoPermission/);
+ expect(await collection.getAllowList()).to.deep.contain({Substrate: charlie.address});
});
});
tests/src/removeFromContractAllowList.test.tsdiffbeforeafterboth--- a/tests/src/removeFromContractAllowList.test.ts
+++ b/tests/src/removeFromContractAllowList.test.ts
@@ -20,6 +20,7 @@
import {IKeyringPair} from '@polkadot/types/types';
import {expect} from 'chai';
+// todo:playgrounds skipped again
describe.skip('Integration Test removeFromContractAllowList', () => {
let bob: IKeyringPair;
tests/src/rpc.test.tsdiffbeforeafterboth--- a/tests/src/rpc.test.ts
+++ b/tests/src/rpc.test.ts
@@ -1,57 +1,68 @@
-import {IKeyringPair} from '@polkadot/types/types';
-import {expect} from 'chai';
-import usingApi from './substrate/substrate-api';
-import {createCollection, createCollectionExpectSuccess, createFungibleItemExpectSuccess, CrossAccountId, getTokenOwner, normalizeAccountId, transfer, U128_MAX} from './util/helpers';
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
-let alice: IKeyringPair;
-let bob: IKeyringPair;
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+import {IKeyringPair} from '@polkadot/types/types';
+import {usingPlaygrounds, itSub, expect} from './util/playgrounds';
+import {crossAccountIdFromLower} from './util/playgrounds/unique';
+
describe('integration test: RPC methods', () => {
+ let donor: IKeyringPair;
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
+
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([20n, 10n], donor);
});
});
-
- it('returns None for fungible collection', async () => {
- await usingApi(async api => {
- const collection = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- await expect(getTokenOwner(api, collection, 0)).to.be.rejectedWith(/^owner == null$/);
- });
+ itSub('returns None for fungible collection', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'RPC-1', tokenPrefix: 'RPC'});
+ const owner = (await helper.callRpc('api.rpc.unique.tokenOwner', [collection.collectionId, 0])).toJSON() as any;
+ expect(owner).to.be.null;
});
- it('RPC method tokenOwners for fungible collection and token', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
- const facelessCrowd = Array.from(Array(7).keys()).map(i => normalizeAccountId(privateKeyWrapper(i.toString())));
-
- const createCollectionResult = await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}});
- const collectionId = createCollectionResult.collectionId;
- const aliceTokenId = await createFungibleItemExpectSuccess(alice, collectionId, {Value: U128_MAX}, alice.address);
-
- await transfer(api, collectionId, aliceTokenId, alice, bob, 1000n);
- await transfer(api, collectionId, aliceTokenId, alice, ethAcc, 900n);
-
- for (let i = 0; i < 7; i++) {
- await transfer(api, collectionId, aliceTokenId, alice, facelessCrowd[i], 1);
- }
-
- const owners = await api.rpc.unique.tokenOwners(collectionId, aliceTokenId);
- const ids = (owners.toJSON() as CrossAccountId[]).map(s => normalizeAccountId(s));
- const aliceID = normalizeAccountId(alice);
- const bobId = normalizeAccountId(bob);
+ itSub('RPC method tokenOwners for fungible collection and token', async ({helper}) => {
+ // Set-up a few token owners of all stripes
+ const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
+ const facelessCrowd = (await helper.arrange.createAccounts([0n, 0n, 0n, 0n, 0n, 0n, 0n], donor))
+ .map(i => {return {Substrate: i.address};});
+
+ const collection = await helper.ft.mintCollection(alice, {name: 'RPC-2', tokenPrefix: 'RPC'});
+ // mint some maximum (u128) amounts of tokens possible
+ await collection.mint(alice, (1n << 128n) - 1n);
+
+ await collection.transfer(alice, {Substrate: bob.address}, 1000n);
+ await collection.transfer(alice, ethAcc, 900n);
+
+ for (let i = 0; i < facelessCrowd.length; i++) {
+ await collection.transfer(alice, facelessCrowd[i], 1n);
+ }
+ // Set-up over
+
+ const owners = await helper.callRpc('api.rpc.unique.tokenOwners', [collection.collectionId, 0]);
+ const ids = (owners.toJSON() as any[]).map(crossAccountIdFromLower);
- // What to expect
- // tslint:disable-next-line:no-unused-expression
- expect(ids).to.deep.include.members([aliceID, ethAcc, bobId, ...facelessCrowd]);
- expect(owners.length == 10).to.be.true;
-
- const eleven = privateKeyWrapper('11');
- expect(await transfer(api, collectionId, aliceTokenId, alice, eleven, 10n)).to.be.true;
- expect((await api.rpc.unique.tokenOwners(collectionId, aliceTokenId)).length).to.be.equal(10);
- });
+ expect(ids).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]);
+ expect(owners.length == 10).to.be.true;
+
+ // Make sure only 10 results are returned with this RPC
+ const [eleven] = await helper.arrange.createAccounts([0n], donor);
+ expect(await collection.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true;
+ expect((await helper.callRpc('api.rpc.unique.tokenOwners', [collection.collectionId, 0])).length).to.be.equal(10);
});
});
\ No newline at end of file
tests/src/scheduler.test.tsdiffbeforeafterboth--- a/tests/src/scheduler.test.ts
+++ b/tests/src/scheduler.test.ts
@@ -44,6 +44,7 @@
chai.use(chaiAsPromised);
+// todo:playgrounds skipped ~ postponed
describe.skip('Scheduling token and balance transfers', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
tests/src/setChainLimits.test.tsdiffbeforeafterboth--- a/tests/src/setChainLimits.test.ts
+++ b/tests/src/setChainLimits.test.ts
@@ -23,6 +23,7 @@
IChainLimits,
} from './util/helpers';
+// todo:playgrounds skipped ~ postponed
describe.skip('Negative Integration Test setChainLimits', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
tests/src/setCollectionLimits.test.tsdiffbeforeafterboth--- a/tests/src/setCollectionLimits.test.ts
+++ b/tests/src/setCollectionLimits.test.ts
@@ -15,26 +15,8 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
// https://unique-network.readthedocs.io/en/latest/jsapi.html#setchainlimits
-import {ApiPromise} from '@polkadot/api';
import {IKeyringPair} from '@polkadot/types/types';
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import usingApi, {submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';
-import {
- createCollectionExpectSuccess, getCreatedCollectionCount,
- getCreateItemResult,
- setCollectionLimitsExpectFailure,
- setCollectionLimitsExpectSuccess,
- addCollectionAdminExpectSuccess,
- queryCollectionExpectSuccess,
-} from './util/helpers';
-
-chai.use(chaiAsPromised);
-const expect = chai.expect;
-
-let alice: IKeyringPair;
-let bob: IKeyringPair;
-let collectionIdForTesting: number;
+import {itSub, usingPlaygrounds, expect} from './util/playgrounds';
const accountTokenOwnershipLimit = 0;
const sponsoredDataSize = 0;
@@ -42,197 +24,177 @@
const tokenLimit = 10;
describe('setCollectionLimits positive', () => {
- let tx;
- before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}});
- });
- });
- it('execute setCollectionLimits with predefined params ', async () => {
- await usingApi(async (api: ApiPromise) => {
- tx = api.tx.unique.setCollectionLimits(
- collectionIdForTesting,
- {
- accountTokenOwnershipLimit: accountTokenOwnershipLimit,
- sponsoredDataSize: sponsoredDataSize,
- tokenLimit: tokenLimit,
- sponsorTransferTimeout,
- ownerCanTransfer: true,
- ownerCanDestroy: true,
- },
- );
- const events = await submitTransactionAsync(alice, tx);
- const result = getCreateItemResult(events);
-
- // get collection limits defined previously
- const collectionInfo = await queryCollectionExpectSuccess(api, collectionIdForTesting);
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
- // tslint:disable-next-line:no-unused-expression
- expect(result.success).to.be.true;
- expect(collectionInfo.limits.accountTokenOwnershipLimit.unwrap().toNumber()).to.be.equal(accountTokenOwnershipLimit);
- expect(collectionInfo.limits.sponsoredDataSize.unwrap().toNumber()).to.be.equal(sponsoredDataSize);
- expect(collectionInfo.limits.tokenLimit.unwrap().toNumber()).to.be.equal(tokenLimit);
- expect(collectionInfo.limits.sponsorTransferTimeout.unwrap().toNumber()).to.be.equal(sponsorTransferTimeout);
- expect(collectionInfo.limits.ownerCanTransfer.unwrap().toJSON()).to.be.true;
- expect(collectionInfo.limits.ownerCanDestroy.unwrap().toJSON()).to.be.true;
+ before(async () => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([20n, 10n], donor);
});
});
- it('Set the same token limit twice', async () => {
- await usingApi(async (api: ApiPromise) => {
+ itSub('execute setCollectionLimits with predefined params', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-1', tokenPrefix: 'SCL'});
- const collectionLimits = {
- accountTokenOwnershipLimit: accountTokenOwnershipLimit,
- sponsoredMintSize: sponsoredDataSize,
- tokenLimit: tokenLimit,
+ await collection.setLimits(
+ alice,
+ {
+ accountTokenOwnershipLimit,
+ sponsoredDataSize,
+ tokenLimit,
sponsorTransferTimeout,
ownerCanTransfer: true,
ownerCanDestroy: true,
- };
+ },
+ );
- // The first time
- const tx1 = api.tx.unique.setCollectionLimits(
- collectionIdForTesting,
- collectionLimits,
- );
- const events1 = await submitTransactionAsync(alice, tx1);
- const result1 = getCreateItemResult(events1);
- expect(result1.success).to.be.true;
- const collectionInfo1 = await queryCollectionExpectSuccess(api, collectionIdForTesting);
- expect(collectionInfo1.limits.tokenLimit.unwrap().toNumber()).to.be.equal(tokenLimit);
+ // get collection limits defined previously
+ const collectionInfo = await collection.getEffectiveLimits();
+
+ expect(collectionInfo.accountTokenOwnershipLimit).to.be.equal(accountTokenOwnershipLimit);
+ expect(collectionInfo.sponsoredDataSize).to.be.equal(sponsoredDataSize);
+ expect(collectionInfo.tokenLimit).to.be.equal(tokenLimit);
+ expect(collectionInfo.sponsorTransferTimeout).to.be.equal(sponsorTransferTimeout);
+ expect(collectionInfo.ownerCanTransfer).to.be.true;
+ expect(collectionInfo.ownerCanDestroy).to.be.true;
+ });
+
+ itSub('Set the same token limit twice', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-2', tokenPrefix: 'SCL'});
+
+ const collectionLimits = {
+ accountTokenOwnershipLimit,
+ sponsoredDataSize,
+ tokenLimit,
+ sponsorTransferTimeout,
+ ownerCanTransfer: true,
+ ownerCanDestroy: true,
+ };
+
+ await collection.setLimits(alice, collectionLimits);
+
+ const collectionInfo1 = await collection.getEffectiveLimits();
+
+ expect(collectionInfo1.tokenLimit).to.be.equal(tokenLimit);
- // The second time
- const tx2 = api.tx.unique.setCollectionLimits(
- collectionIdForTesting,
- collectionLimits,
- );
- const events2 = await submitTransactionAsync(alice, tx2);
- const result2 = getCreateItemResult(events2);
- expect(result2.success).to.be.true;
- const collectionInfo2 = await queryCollectionExpectSuccess(api, collectionIdForTesting);
- expect(collectionInfo2.limits.tokenLimit.unwrap().toNumber()).to.be.equal(tokenLimit);
- });
+ await collection.setLimits(alice, collectionLimits);
+ const collectionInfo2 = await collection.getEffectiveLimits();
+ expect(collectionInfo2.tokenLimit).to.be.equal(tokenLimit);
});
- it('execute setCollectionLimits from admin collection', async () => {
- await addCollectionAdminExpectSuccess(alice, collectionIdForTesting, bob.address);
- await usingApi(async (api: ApiPromise) => {
- tx = api.tx.unique.setCollectionLimits(
- collectionIdForTesting,
- {
- accountTokenOwnershipLimit,
- sponsoredDataSize,
- // sponsoredMintSize,
- tokenLimit,
- },
- );
- await expect(submitTransactionAsync(bob, tx)).to.be.not.rejected;
- });
+ itSub('execute setCollectionLimits from admin collection', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-3', tokenPrefix: 'SCL'});
+ await collection.addAdmin(alice, {Substrate: bob.address});
+
+ const collectionLimits = {
+ accountTokenOwnershipLimit,
+ sponsoredDataSize,
+ // sponsoredMintSize,
+ tokenLimit,
+ };
+
+ await expect(collection.setLimits(alice, collectionLimits)).to.not.be.rejected;
});
});
describe('setCollectionLimits negative', () => {
- let tx;
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
+
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}});
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([20n, 10n], donor);
});
});
- it('execute setCollectionLimits for not exists collection', async () => {
- await usingApi(async (api: ApiPromise) => {
- const collectionCount = await getCreatedCollectionCount(api);
- const nonExistedCollectionId = collectionCount + 1;
- tx = api.tx.unique.setCollectionLimits(
- nonExistedCollectionId,
- {
- accountTokenOwnershipLimit,
- sponsoredDataSize,
- // sponsoredMintSize,
- tokenLimit,
- },
- );
- await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;
- });
+
+ itSub('execute setCollectionLimits for not exists collection', async ({helper}) => {
+ const nonExistentCollectionId = (1 << 32) - 1;
+ await expect(helper.collection.setLimits(
+ alice,
+ nonExistentCollectionId,
+ {
+ accountTokenOwnershipLimit,
+ sponsoredDataSize,
+ // sponsoredMintSize,
+ tokenLimit,
+ },
+ )).to.be.rejectedWith(/common\.CollectionNotFound/);
});
- it('execute setCollectionLimits from user who is not owner of this collection', async () => {
- await usingApi(async (api: ApiPromise) => {
- tx = api.tx.unique.setCollectionLimits(
- collectionIdForTesting,
- {
- accountTokenOwnershipLimit,
- sponsoredDataSize,
- // sponsoredMintSize,
- tokenLimit,
- },
- );
- await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;
- });
+
+ itSub('execute setCollectionLimits from user who is not owner of this collection', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-Neg-1', tokenPrefix: 'SCL'});
+
+ await expect(collection.setLimits(bob, {
+ accountTokenOwnershipLimit,
+ sponsoredDataSize,
+ // sponsoredMintSize,
+ tokenLimit,
+ })).to.be.rejectedWith(/common\.NoPermission/);
});
- it('fails when trying to enable OwnerCanTransfer after it was disabled', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionLimitsExpectSuccess(alice, collectionId, {
- accountTokenOwnershipLimit: accountTokenOwnershipLimit,
- sponsoredMintSize: sponsoredDataSize,
- tokenLimit: tokenLimit,
+ itSub('fails when trying to enable OwnerCanTransfer after it was disabled', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-Neg-2', tokenPrefix: 'SCL'});
+
+ await collection.setLimits(alice, {
+ accountTokenOwnershipLimit,
+ sponsoredDataSize,
+ tokenLimit,
sponsorTransferTimeout,
ownerCanTransfer: false,
ownerCanDestroy: true,
});
- await setCollectionLimitsExpectFailure(alice, collectionId, {
- accountTokenOwnershipLimit: accountTokenOwnershipLimit,
- sponsoredMintSize: sponsoredDataSize,
- tokenLimit: tokenLimit,
+
+ await expect(collection.setLimits(alice, {
+ accountTokenOwnershipLimit,
+ sponsoredDataSize,
+ tokenLimit,
sponsorTransferTimeout,
ownerCanTransfer: true,
ownerCanDestroy: true,
- });
+ })).to.be.rejectedWith(/common\.OwnerPermissionsCantBeReverted/);
});
- it('fails when trying to enable OwnerCanDestroy after it was disabled', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionLimitsExpectSuccess(alice, collectionId, {
- accountTokenOwnershipLimit: accountTokenOwnershipLimit,
- sponsoredMintSize: sponsoredDataSize,
- tokenLimit: tokenLimit,
+ itSub('fails when trying to enable OwnerCanDestroy after it was disabled', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-Neg-3', tokenPrefix: 'SCL'});
+
+ await collection.setLimits(alice, {
+ accountTokenOwnershipLimit,
+ sponsoredDataSize,
+ tokenLimit,
sponsorTransferTimeout,
ownerCanTransfer: true,
ownerCanDestroy: false,
});
- await setCollectionLimitsExpectFailure(alice, collectionId, {
+
+ await expect(collection.setLimits(alice, {
+ accountTokenOwnershipLimit,
+ sponsoredDataSize,
+ tokenLimit,
+ sponsorTransferTimeout,
+ ownerCanTransfer: true,
+ ownerCanDestroy: true,
+ })).to.be.rejectedWith(/common\.OwnerPermissionsCantBeReverted/);
+ });
+
+ itSub('Setting the higher token limit fails', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-Neg-4', tokenPrefix: 'SCL'});
+
+ const collectionLimits = {
accountTokenOwnershipLimit: accountTokenOwnershipLimit,
sponsoredMintSize: sponsoredDataSize,
tokenLimit: tokenLimit,
sponsorTransferTimeout,
ownerCanTransfer: true,
ownerCanDestroy: true,
- });
- });
-
- it('Setting the higher token limit fails', async () => {
- await usingApi(async () => {
-
- const collectionId = await createCollectionExpectSuccess();
- const collectionLimits = {
- accountTokenOwnershipLimit: accountTokenOwnershipLimit,
- sponsoredMintSize: sponsoredDataSize,
- tokenLimit: tokenLimit,
- sponsorTransferTimeout,
- ownerCanTransfer: true,
- ownerCanDestroy: true,
- };
+ };
- // The first time
- await setCollectionLimitsExpectSuccess(alice, collectionId, collectionLimits);
+ // The first time
+ await collection.setLimits(alice, collectionLimits);
- // The second time - higher token limit
- collectionLimits.tokenLimit += 1;
- await setCollectionLimitsExpectFailure(alice, collectionId, collectionLimits);
- });
+ // The second time - higher token limit
+ collectionLimits.tokenLimit += 1;
+ await expect(collection.setLimits(alice, collectionLimits)).to.be.rejectedWith(/common\.CollectionTokenLimitExceeded/);
});
-
});
tests/src/setCollectionSponsor.test.tsdiffbeforeafterboth--- a/tests/src/setCollectionSponsor.test.ts
+++ b/tests/src/setCollectionSponsor.test.ts
@@ -14,93 +14,106 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import {default as usingApi} from './substrate/substrate-api';
-import {createCollectionExpectSuccess,
- setCollectionSponsorExpectSuccess,
- destroyCollectionExpectSuccess,
- setCollectionSponsorExpectFailure,
- addCollectionAdminExpectSuccess,
- getCreatedCollectionCount,
- requirePallets,
- Pallets,
-} from './util/helpers';
import {IKeyringPair} from '@polkadot/types/types';
-
-chai.use(chaiAsPromised);
-
-let alice: IKeyringPair;
-let bob: IKeyringPair;
-let charlie: IKeyringPair;
+import {itSub, usingPlaygrounds, expect, Pallets} from './util/playgrounds';
describe('integration test: ext. setCollectionSponsor():', () => {
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
+ let charlie: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- charlie = privateKeyWrapper('//Charlie');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob, charlie] = await helper.arrange.createAccounts([20n, 10n, 10n], donor);
});
});
- it('Set NFT collection sponsor', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+ itSub('Set NFT collection sponsor', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-1-NFT', tokenPrefix: 'SCS'});
+ await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected;
+
+ expect((await collection.getData())?.raw.sponsorship).to.deep.equal({
+ Unconfirmed: bob.address,
+ });
});
- it('Set Fungible collection sponsor', async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+
+ itSub('Set Fungible collection sponsor', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'SetCollectionSponsor-1-FT', tokenPrefix: 'SCS'});
+ await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected;
+
+ expect((await collection.getData())?.raw.sponsorship).to.deep.equal({
+ Unconfirmed: bob.address,
+ });
});
- it('Set ReFungible collection sponsor', async function() {
- await requirePallets(this, [Pallets.ReFungible]);
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+ itSub.ifWithPallets('Set ReFungible collection sponsor', [Pallets.ReFungible], async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'SetCollectionSponsor-1-RFT', tokenPrefix: 'SCS'});
+ await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected;
+
+ expect((await collection.getData())?.raw.sponsorship).to.deep.equal({
+ Unconfirmed: bob.address,
+ });
});
- it('Set the same sponsor repeatedly', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
+ itSub('Set the same sponsor repeatedly', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-2', tokenPrefix: 'SCS'});
+ await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected;
+ await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected;
+
+ expect((await collection.getData())?.raw.sponsorship).to.deep.equal({
+ Unconfirmed: bob.address,
+ });
});
- it('Replace collection sponsor', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionSponsorExpectSuccess(collectionId, bob.address);
- await setCollectionSponsorExpectSuccess(collectionId, charlie.address);
+
+ itSub('Replace collection sponsor', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-3', tokenPrefix: 'SCS'});
+ await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected;
+ await expect(collection.setSponsor(alice, charlie.address)).to.be.not.rejected;
+
+ expect((await collection.getData())?.raw.sponsorship).to.deep.equal({
+ Unconfirmed: charlie.address,
+ });
});
- it('Collection admin add sponsor', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
- await setCollectionSponsorExpectSuccess(collectionId, charlie.address, '//Bob');
+
+ itSub('Collection admin add sponsor', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-4', tokenPrefix: 'SCS'});
+ await collection.addAdmin(alice, {Substrate: bob.address});
+ await expect(collection.setSponsor(bob, charlie.address)).to.be.not.rejected;
+
+ expect((await collection.getData())?.raw.sponsorship).to.deep.equal({
+ Unconfirmed: charlie.address,
+ });
});
});
describe('(!negative test!) integration test: ext. setCollectionSponsor():', () => {
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
+
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- charlie = privateKeyWrapper('//Charlie');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([10n, 5n], donor);
});
});
- it('(!negative test!) Add sponsor with a non-owner', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionSponsorExpectFailure(collectionId, bob.address, '//Bob');
+ itSub('(!negative test!) Add sponsor with a non-owner', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-Neg-1', tokenPrefix: 'SCS'});
+ await expect(collection.setSponsor(bob, bob.address))
+ .to.be.rejectedWith(/common\.NoPermission/);
});
- it('(!negative test!) Add sponsor to a collection that never existed', async () => {
- // Find the collection that never existed
- let collectionId = 0;
- await usingApi(async (api) => {
- collectionId = await getCreatedCollectionCount(api) + 1;
- });
- await setCollectionSponsorExpectFailure(collectionId, bob.address);
+ itSub('(!negative test!) Add sponsor to a collection that never existed', async ({helper}) => {
+ const collectionId = (1 << 32) - 1;
+ await expect(helper.collection.setSponsor(alice, collectionId, bob.address))
+ .to.be.rejectedWith(/common\.CollectionNotFound/);
});
- it('(!negative test!) Add sponsor to a collection that was destroyed', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await destroyCollectionExpectSuccess(collectionId);
- await setCollectionSponsorExpectFailure(collectionId, bob.address);
+
+ itSub('(!negative test!) Add sponsor to a collection that was destroyed', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-Neg-2', tokenPrefix: 'SCS'});
+ await collection.burn(alice);
+ await expect(collection.setSponsor(alice, bob.address))
+ .to.be.rejectedWith(/common\.CollectionNotFound/);
});
});
tests/src/setContractSponsoringRateLimit.test.tsdiffbeforeafterboth--- a/tests/src/setContractSponsoringRateLimit.test.ts
+++ b/tests/src/setContractSponsoringRateLimit.test.ts
@@ -25,6 +25,7 @@
setContractSponsoringRateLimitExpectSuccess,
} from './util/helpers';
+// todo:playgrounds postponed skipped test
describe.skip('Integration Test setContractSponsoringRateLimit', () => {
it('ensure sponsored contract can\'t be called twice without pause for free', async () => {
await usingApi(async (api, privateKeyWrapper) => {
tests/src/setMintPermission.test.tsdiffbeforeafterboth--- a/tests/src/setMintPermission.test.ts
+++ b/tests/src/setMintPermission.test.ts
@@ -15,65 +15,57 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
import {IKeyringPair} from '@polkadot/types/types';
-import usingApi from './substrate/substrate-api';
-import {
- addToAllowListExpectSuccess,
- createCollectionExpectSuccess,
- createItemExpectFailure,
- createItemExpectSuccess,
- destroyCollectionExpectSuccess,
- enableAllowListExpectSuccess,
- findNotExistingCollection,
- setMintPermissionExpectFailure,
- setMintPermissionExpectSuccess,
- addCollectionAdminExpectSuccess,
-} from './util/helpers';
+import {itSub, usingPlaygrounds, expect} from './util/playgrounds';
describe('Integration Test setMintPermission', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor);
});
});
- it('ensure allow-listed non-privileged address can mint tokens', async () => {
- await usingApi(async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await enableAllowListExpectSuccess(alice, collectionId);
- await setMintPermissionExpectSuccess(alice, collectionId, true);
- await addToAllowListExpectSuccess(alice, collectionId, bob.address);
+ itSub('ensure allow-listed non-privileged address can mint tokens', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-1', description: '', tokenPrefix: 'SMP'});
+ await collection.setPermissions(alice, {access: 'AllowList', mintMode: true});
+ await collection.addToAllowList(alice, {Substrate: bob.address});
- await createItemExpectSuccess(bob, collectionId, 'NFT');
- });
+ await expect(collection.mintToken(bob, {Substrate: bob.address})).to.not.be.rejected;
});
- it('can be enabled twice', async () => {
- await usingApi(async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await setMintPermissionExpectSuccess(alice, collectionId, true);
- await setMintPermissionExpectSuccess(alice, collectionId, true);
- });
+ itSub('can be enabled twice', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-2', description: '', tokenPrefix: 'SMP'});
+ expect((await collection.getData())?.raw.permissions.access).to.not.equal('AllowList');
+
+ await collection.setPermissions(alice, {mintMode: true});
+ await collection.setPermissions(alice, {mintMode: true});
+ expect((await collection.getData())?.raw.permissions.mintMode).to.be.true;
});
- it('can be disabled twice', async () => {
- await usingApi(async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await setMintPermissionExpectSuccess(alice, collectionId, true);
- await setMintPermissionExpectSuccess(alice, collectionId, false);
- await setMintPermissionExpectSuccess(alice, collectionId, false);
- });
+ itSub('can be disabled twice', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-3', description: '', tokenPrefix: 'SMP'});
+ expect((await collection.getData())?.raw.permissions.access).to.equal('Normal');
+
+ await collection.setPermissions(alice, {access: 'AllowList', mintMode: true});
+ expect((await collection.getData())?.raw.permissions.access).to.equal('AllowList');
+ expect((await collection.getData())?.raw.permissions.mintMode).to.equal(true);
+
+ await collection.setPermissions(alice, {access: 'Normal', mintMode: false});
+ await collection.setPermissions(alice, {access: 'Normal', mintMode: false});
+ expect((await collection.getData())?.raw.permissions.access).to.equal('Normal');
+ expect((await collection.getData())?.raw.permissions.mintMode).to.equal(false);
});
- it('Collection admin success on set', async () => {
- await usingApi(async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
- await setMintPermissionExpectSuccess(bob, collectionId, true);
- });
+ itSub('Collection admin success on set', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-4', description: '', tokenPrefix: 'SMP'});
+ await collection.addAdmin(alice, {Substrate: bob.address});
+ await collection.setPermissions(bob, {access: 'AllowList', mintMode: true});
+
+ expect((await collection.getData())?.raw.permissions.access).to.equal('AllowList');
+ expect((await collection.getData())?.raw.permissions.mintMode).to.equal(true);
});
});
@@ -82,41 +74,38 @@
let bob: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor);
});
});
- it('fails on not existing collection', async () => {
- await usingApi(async (api) => {
- const nonExistingCollection = await findNotExistingCollection(api);
- await setMintPermissionExpectFailure(alice, nonExistingCollection, true);
- });
+ itSub('fails on not existing collection', async ({helper}) => {
+ const collectionId = (1 << 32) - 1;
+ await expect(helper.collection.setPermissions(alice, collectionId, {mintMode: true}))
+ .to.be.rejectedWith(/common\.CollectionNotFound/);
});
- it('fails on removed collection', async () => {
- await usingApi(async () => {
- const removedCollectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await destroyCollectionExpectSuccess(removedCollectionId);
+ itSub('fails on removed collection', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-Neg-1', tokenPrefix: 'SMP'});
+ await collection.burn(alice);
- await setMintPermissionExpectFailure(alice, removedCollectionId, true);
- });
+ await expect(collection.setPermissions(alice, {mintMode: true}))
+ .to.be.rejectedWith(/common\.CollectionNotFound/);
});
- it('fails when not collection owner tries to set mint status', async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await enableAllowListExpectSuccess(alice, collectionId);
- await setMintPermissionExpectFailure(bob, collectionId, true);
+ itSub('fails when non-owner tries to set mint status', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-Neg-2', tokenPrefix: 'SMP'});
+
+ await expect(collection.setPermissions(bob, {mintMode: true}))
+ .to.be.rejectedWith(/common\.NoPermission/);
});
- it('ensure non-allow-listed non-privileged address can\'t mint tokens', async () => {
- await usingApi(async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await enableAllowListExpectSuccess(alice, collectionId);
- await setMintPermissionExpectSuccess(alice, collectionId, true);
+ itSub('ensure non-allow-listed non-privileged address can\'t mint tokens', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-Neg-3', tokenPrefix: 'SMP'});
+ await collection.setPermissions(alice, {mintMode: true});
- await createItemExpectFailure(bob, collectionId, 'NFT');
- });
+ await expect(collection.mintToken(bob, {Substrate: bob.address}))
+ .to.be.rejectedWith(/common\.AddressNotInAllowlist/);
});
});
tests/src/setPublicAccessMode.test.tsdiffbeforeafterboth--- a/tests/src/setPublicAccessMode.test.ts
+++ b/tests/src/setPublicAccessMode.test.ts
@@ -15,111 +15,79 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
// https://unique-network.readthedocs.io/en/latest/jsapi.html#setschemaversion
-import {ApiPromise} from '@polkadot/api';
import {IKeyringPair} from '@polkadot/types/types';
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import usingApi, {submitTransactionExpectFailAsync} from './substrate/substrate-api';
-import {
- addToAllowListExpectSuccess,
- createCollectionExpectSuccess,
- createItemExpectSuccess,
- destroyCollectionExpectSuccess,
- enablePublicMintingExpectSuccess,
- enableAllowListExpectSuccess,
- normalizeAccountId,
- addCollectionAdminExpectSuccess,
- getCreatedCollectionCount,
-} from './util/helpers';
-
-chai.use(chaiAsPromised);
-const expect = chai.expect;
-
-let alice: IKeyringPair;
-let bob: IKeyringPair;
+import {itSub, usingPlaygrounds, expect} from './util/playgrounds';
describe('Integration Test setPublicAccessMode(): ', () => {
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
+
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor);
});
});
- it('Run extrinsic with collection id parameters, set the allowlist mode for the collection', async () => {
- await usingApi(async () => {
- const collectionId: number = await createCollectionExpectSuccess();
- await enableAllowListExpectSuccess(alice, collectionId);
- await enablePublicMintingExpectSuccess(alice, collectionId);
- await addToAllowListExpectSuccess(alice, collectionId, bob.address);
- await createItemExpectSuccess(bob, collectionId, 'NFT', bob.address);
- });
+ itSub('Runs extrinsic with collection id parameters, sets the allowlist mode for the collection', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'PublicAccess-1', tokenPrefix: 'TF'});
+ await collection.setPermissions(alice, {access: 'AllowList', mintMode: true});
+ await collection.addToAllowList(alice, {Substrate: bob.address});
+
+ await expect(collection.mintToken(bob, {Substrate: bob.address})).to.be.not.rejected;
+ });
+
+ itSub('Allowlisted collection limits', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'PublicAccess-2', tokenPrefix: 'TF'});
+ await collection.setPermissions(alice, {access: 'AllowList', mintMode: true});
+
+ await expect(collection.mintToken(bob, {Substrate: bob.address}))
+ .to.be.rejectedWith(/common\.AddressNotInAllowlist/);
});
- it('Allowlisted collection limits', async () => {
- await usingApi(async (api: ApiPromise) => {
- const collectionId = await createCollectionExpectSuccess();
- await enableAllowListExpectSuccess(alice, collectionId);
- await enablePublicMintingExpectSuccess(alice, collectionId);
- const tx = api.tx.unique.createItem(collectionId, normalizeAccountId(bob.address), 'NFT');
- await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;
- });
+ itSub('setPublicAccessMode by collection admin', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'PublicAccess-Neg-4', tokenPrefix: 'TF'});
+ await collection.addAdmin(alice, {Substrate: bob.address});
+
+ await expect(collection.setPermissions(bob, {access: 'AllowList'})).to.be.not.rejected;
});
});
describe('Negative Integration Test ext. setPublicAccessMode(): ', () => {
- it('Set a non-existent collection', async () => {
- await usingApi(async (api: ApiPromise) => {
- // tslint:disable-next-line: radix
- const collectionId = await getCreatedCollectionCount(api) + 1;
- const tx = api.tx.unique.setCollectionPermissions(collectionId, {access: 'AllowList'});
- await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;
+ let alice: IKeyringPair;
+ let bob: IKeyringPair;
+
+ before(async () => {
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor);
});
});
- it('Set the collection that has been deleted', async () => {
- await usingApi(async (api: ApiPromise) => {
- // tslint:disable-next-line: no-bitwise
- const collectionId = await createCollectionExpectSuccess();
- await destroyCollectionExpectSuccess(collectionId);
- const tx = api.tx.unique.setCollectionPermissions(collectionId, {access: 'AllowList'});
- await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected;
- });
+ itSub('Sets a non-existent collection', async ({helper}) => {
+ const collectionId = (1 << 32) - 1;
+ await expect(helper.collection.setPermissions(alice, collectionId, {access: 'AllowList'}))
+ .to.be.rejectedWith(/common\.CollectionNotFound/);
});
- it('Re-set the list mode already set in quantity', async () => {
- await usingApi(async () => {
- const collectionId: number = await createCollectionExpectSuccess();
- await enableAllowListExpectSuccess(alice, collectionId);
- await enableAllowListExpectSuccess(alice, collectionId);
- });
- });
+ itSub('Sets the collection that has been deleted', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'PublicAccess-Neg-1', tokenPrefix: 'TF'});
+ await collection.burn(alice);
- it('Execute method not on behalf of the collection owner', async () => {
- await usingApi(async (api: ApiPromise) => {
- // tslint:disable-next-line: no-bitwise
- const collectionId = await createCollectionExpectSuccess();
- const tx = api.tx.unique.setCollectionPermissions(collectionId, {access: 'AllowList'});
- await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;
- });
+ await expect(collection.setPermissions(alice, {access: 'AllowList'}))
+ .to.be.rejectedWith(/common\.CollectionNotFound/);
});
- it('setPublicAccessMode by collection admin', async () => {
- await usingApi(async (api: ApiPromise) => {
- // tslint:disable-next-line: no-bitwise
- const collectionId = await createCollectionExpectSuccess();
- await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
- const tx = api.tx.unique.setCollectionPermissions(collectionId, {access: 'AllowList'});
- await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.not.rejected;
- });
+ itSub('Re-sets the list mode already set in quantity', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'PublicAccess-Neg-2', tokenPrefix: 'TF'});
+ await collection.setPermissions(alice, {access: 'AllowList'});
+ await collection.setPermissions(alice, {access: 'AllowList'});
});
-});
-describe('Negative Integration Test ext. collection admin setPublicAccessMode(): ', () => {
- before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- });
+ itSub('Executes method as a malefactor', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'PublicAccess-Neg-3', tokenPrefix: 'TF'});
+
+ await expect(collection.setPermissions(bob, {access: 'AllowList'}))
+ .to.be.rejectedWith(/common\.NoPermission/);
});
});
tests/src/toggleContractAllowList.test.tsdiffbeforeafterboth--- a/tests/src/toggleContractAllowList.test.ts
+++ b/tests/src/toggleContractAllowList.test.ts
@@ -31,6 +31,7 @@
const value = 0;
const gasLimit = 3000n * 1000000n;
+// todo:playgrounds skipped ~ postpone
describe.skip('Integration Test toggleContractAllowList', () => {
it('Enable allow list contract mode', async () => {
tests/src/transfer.test.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {ApiPromise} from '@polkadot/api';18import {IKeyringPair} from '@polkadot/types/types';19import {expect} from 'chai';20import getBalance from './substrate/get-balance';21import {default as usingApi, submitTransactionAsync} from './substrate/substrate-api';22import {23 burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess,24 destroyCollectionExpectSuccess,25 findUnusedAddress,26 getCreateCollectionResult,27 getCreateItemResult,28 transferExpectFailure,29 transferExpectSuccess,30 addCollectionAdminExpectSuccess,31 getCreatedCollectionCount,32 toSubstrateAddress,33 getTokenOwner,34 normalizeAccountId,35 getBalance as getTokenBalance,36 transferFromExpectSuccess,37 transferFromExpectFail,38 requirePallets,39 Pallets,40} from './util/helpers';41import {42 subToEth,43 itWeb3, 44} from './eth/util/helpers';45import {request} from 'https';4647let alice: IKeyringPair;48let bob: IKeyringPair;49let charlie: IKeyringPair;5051describe('Integration Test Transfer(recipient, collection_id, item_id, value)', () => {52 before(async () => {53 await usingApi(async (api, privateKeyWrapper) => {54 alice = privateKeyWrapper('//Alice');55 bob = privateKeyWrapper('//Bob');56 });57 });58 59 it('Balance transfers and check balance', async () => {60 await usingApi(async (api, privateKeyWrapper) => {61 const [alicesBalanceBefore, bobsBalanceBefore] = await getBalance(api, [alice.address, bob.address]);6263 const transfer = api.tx.balances.transfer(bob.address, 1n);64 const events = await submitTransactionAsync(alice, transfer);65 const result = getCreateItemResult(events);66 // tslint:disable-next-line:no-unused-expression67 expect(result.success).to.be.true;6869 const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alice.address, bob.address]);7071 // tslint:disable-next-line:no-unused-expression72 expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true;73 // tslint:disable-next-line:no-unused-expression74 expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true;75 });76 });7778 it('Inability to pay fees error message is correct', async () => {79 await usingApi(async (api, privateKeyWrapper) => {80 // Find unused address81 const pk = await findUnusedAddress(api, privateKeyWrapper);8283 const badTransfer = api.tx.balances.transfer(bob.address, 1n);84 // const events = await submitTransactionAsync(pk, badTransfer);85 const badTransaction = async () => {86 const events = await submitTransactionAsync(pk, badTransfer);87 const result = getCreateCollectionResult(events);88 // tslint:disable-next-line:no-unused-expression89 expect(result.success).to.be.false;90 };91 await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees , e.g. account balance too low');92 });93 });9495 it('[nft] User can transfer owned token', async () => {96 const nftCollectionId = await createCollectionExpectSuccess();97 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');98 await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 'NFT');99 });100101 it('[fungible] User can transfer owned token', async () => {102 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});103 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');104 await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob, 1, 'Fungible');105 });106107 it('[refungible] User can transfer owned token', async function() {108 await requirePallets(this, [Pallets.ReFungible]);109110 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});111 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');112 await transferExpectSuccess(113 reFungibleCollectionId,114 newReFungibleTokenId,115 alice,116 bob,117 100,118 'ReFungible',119 );120 });121122 it('[nft] Collection admin can transfer owned token', async () => {123 const nftCollectionId = await createCollectionExpectSuccess();124 await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);125 const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT', bob.address);126 await transferExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, 1, 'NFT');127 });128129 it('[fungible] Collection admin can transfer owned token', async () => {130 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});131 await addCollectionAdminExpectSuccess(alice, fungibleCollectionId, bob.address);132 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible', bob.address);133 await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, 1, 'Fungible');134 });135136 it('[refungible] Collection admin can transfer owned token', async function() {137 await requirePallets(this, [Pallets.ReFungible]);138139 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});140 await addCollectionAdminExpectSuccess(alice, reFungibleCollectionId, bob.address);141 const newReFungibleTokenId = await createItemExpectSuccess(bob, reFungibleCollectionId, 'ReFungible', bob.address);142 await transferExpectSuccess(143 reFungibleCollectionId,144 newReFungibleTokenId,145 bob,146 alice,147 100,148 'ReFungible',149 );150 });151});152153describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => {154 before(async () => {155 await usingApi(async (api, privateKeyWrapper) => {156 alice = privateKeyWrapper('//Alice');157 bob = privateKeyWrapper('//Bob');158 charlie = privateKeyWrapper('//Charlie');159 });160 });161162 it('[nft] Transfer with not existed collection_id', async () => {163 await usingApi(async (api) => {164 const nftCollectionCount = await getCreatedCollectionCount(api);165 await transferExpectFailure(nftCollectionCount + 1, 1, alice, bob, 1);166 });167 });168169 it('[fungible] Transfer with not existed collection_id', async () => {170 await usingApi(async (api) => {171 const fungibleCollectionCount = await getCreatedCollectionCount(api);172 await transferExpectFailure(fungibleCollectionCount + 1, 0, alice, bob, 1);173 });174 });175176 it('[refungible] Transfer with not existed collection_id', async function() {177 await requirePallets(this, [Pallets.ReFungible]);178179 await usingApi(async (api) => {180 const reFungibleCollectionCount = await getCreatedCollectionCount(api);181 await transferExpectFailure(reFungibleCollectionCount + 1, 1, alice, bob, 1);182 });183 });184185 it('[nft] Transfer with deleted collection_id', async () => {186 const nftCollectionId = await createCollectionExpectSuccess();187 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');188 await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId);189 await destroyCollectionExpectSuccess(nftCollectionId);190 await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);191 });192193 it('[fungible] Transfer with deleted collection_id', async () => {194 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});195 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');196 await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);197 await destroyCollectionExpectSuccess(fungibleCollectionId);198 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);199 });200201 it('[refungible] Transfer with deleted collection_id', async function() {202 await requirePallets(this, [Pallets.ReFungible]);203204 const reFungibleCollectionId = await205 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});206 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');207 await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100);208 await destroyCollectionExpectSuccess(reFungibleCollectionId);209 await transferExpectFailure(210 reFungibleCollectionId,211 newReFungibleTokenId,212 alice,213 bob,214 1,215 );216 });217218 it('[nft] Transfer with not existed item_id', async () => {219 const nftCollectionId = await createCollectionExpectSuccess();220 await transferExpectFailure(nftCollectionId, 2, alice, bob, 1);221 });222223 it('[fungible] Transfer with not existed item_id', async () => {224 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});225 await transferExpectFailure(fungibleCollectionId, 2, alice, bob, 1);226 });227228 it('[refungible] Transfer with not existed item_id', async function() {229 await requirePallets(this, [Pallets.ReFungible]);230231 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});232 await transferExpectFailure(233 reFungibleCollectionId,234 2,235 alice,236 bob,237 1,238 );239 });240241 it('[nft] Transfer with deleted item_id', async () => {242 const nftCollectionId = await createCollectionExpectSuccess();243 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');244 await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);245 await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);246 });247248 it('[fungible] Transfer with deleted item_id', async () => {249 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});250 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');251 await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);252 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);253 });254255 it('[refungible] Transfer with deleted item_id', async function() {256 await requirePallets(this, [Pallets.ReFungible]);257258 const reFungibleCollectionId = await259 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});260 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');261 await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100);262 await transferExpectFailure(263 reFungibleCollectionId,264 newReFungibleTokenId,265 alice,266 bob,267 1,268 );269 });270271 it('[nft] Transfer with recipient that is not owner', async () => {272 const nftCollectionId = await createCollectionExpectSuccess();273 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');274 await transferExpectFailure(nftCollectionId, newNftTokenId, charlie, bob, 1);275 });276277 it('[fungible] Transfer with recipient that is not owner', async () => {278 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});279 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');280 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, charlie, bob, 1);281 });282283 it('[refungible] Transfer with recipient that is not owner', async function() {284 await requirePallets(this, [Pallets.ReFungible]);285286 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});287 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');288 await transferExpectFailure(289 reFungibleCollectionId,290 newReFungibleTokenId,291 charlie,292 bob,293 1,294 );295 });296});297298describe('Zero value transfer(From)', () => {299 before(async () => {300 await usingApi(async (api, privateKeyWrapper) => {301 alice = privateKeyWrapper('//Alice');302 bob = privateKeyWrapper('//Bob');303 });304 });305306 it('NFT', async () => {307 await usingApi(async (api: ApiPromise) => {308 const nftCollectionId = await createCollectionExpectSuccess();309 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');310311 const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), nftCollectionId, newNftTokenId, 0);312 await submitTransactionAsync(alice, transferTx);313 const address = normalizeAccountId(await getTokenOwner(api, nftCollectionId, newNftTokenId));314315 expect(toSubstrateAddress(address)).to.be.equal(alice.address);316 });317 });318319 it('RFT', async function() {320 await requirePallets(this, [Pallets.ReFungible]);321322 await usingApi(async (api: ApiPromise) => {323 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});324 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');325 const balanceBeforeAlice = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(alice), newReFungibleTokenId);326 const balanceBeforeBob = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(bob), newReFungibleTokenId);327328 const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), reFungibleCollectionId, newReFungibleTokenId, 0);329 await submitTransactionAsync(alice, transferTx);330331 const balanceAfterAlice = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(alice), newReFungibleTokenId);332 const balanceAfterBob = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(bob), newReFungibleTokenId);333334 expect((balanceBeforeAlice)).to.be.equal(balanceAfterAlice);335 expect((balanceBeforeBob)).to.be.equal(balanceAfterBob);336 });337 });338339 it('Fungible', async () => {340 await usingApi(async (api: ApiPromise) => {341 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});342 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');343 const balanceBeforeAlice = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(alice), newFungibleTokenId);344 const balanceBeforeBob = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(bob), newFungibleTokenId);345346 const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), fungibleCollectionId, newFungibleTokenId, 0);347 await submitTransactionAsync(alice, transferTx);348349 const balanceAfterAlice = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(alice), newFungibleTokenId);350 const balanceAfterBob = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(bob), newFungibleTokenId);351352 expect((balanceBeforeAlice)).to.be.equal(balanceAfterAlice);353 expect((balanceBeforeBob)).to.be.equal(balanceAfterBob);354 });355 });356});357358describe('Transfers to self (potentially over substrate-evm boundary)', () => {359 itWeb3('Transfers to self. In case of same frontend', async ({api, privateKeyWrapper}) => {360 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});361 const aliceProxy = subToEth(alice.address);362 const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});363 await transferExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, 10, 'Fungible');364 const balanceAliceBefore = await getTokenBalance(api, collectionId, {Ethereum: aliceProxy}, tokenId);365 await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, {Ethereum: aliceProxy}, 10, 'Fungible');366 const balanceAliceAfter = await getTokenBalance(api, collectionId, {Ethereum: aliceProxy}, tokenId);367 expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);368 });369370 itWeb3('Transfers to self. In case of substrate-evm boundary', async ({api, privateKeyWrapper}) => {371 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});372 const aliceProxy = subToEth(alice.address);373 const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});374 const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);375 await transferExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy} , 10, 'Fungible');376 await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, alice, 10, 'Fungible');377 const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);378 expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);379 });380381 itWeb3('Transfers to self. In case of inside substrate-evm', async ({api, privateKeyWrapper}) => {382 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});383 const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});384 const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);385 await transferExpectSuccess(collectionId, tokenId, alice, alice , 10, 'Fungible');386 await transferFromExpectSuccess(collectionId, tokenId, alice, alice, alice, 10, 'Fungible');387 const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);388 expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);389 });390391 itWeb3('Transfers to self. In case of inside substrate-evm when not enought "Fungibles"', async ({api, privateKeyWrapper}) => {392 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});393 const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});394 const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);395 await transferExpectFailure(collectionId, tokenId, alice, alice , 11);396 await transferFromExpectFail(collectionId, tokenId, alice, alice, alice, 11);397 const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);398 expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);399 });400});1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {IKeyringPair} from '@polkadot/types/types';18import {itEth, usingEthPlaygrounds} from './eth/util/playgrounds';19import {itSub, Pallets, usingPlaygrounds, expect} from './util/playgrounds';2021describe('Integration Test Transfer(recipient, collection_id, item_id, value)', () => {22 let alice: IKeyringPair;23 let bob: IKeyringPair;2425 before(async () => {26 await usingPlaygrounds(async (helper, privateKey) => {27 const donor = privateKey('//Alice');28 [alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor);29 });30 });31 32 itSub('Balance transfers and check balance', async ({helper}) => {33 const alicesBalanceBefore = await helper.balance.getSubstrate(alice.address);34 const bobsBalanceBefore = await helper.balance.getSubstrate(bob.address);3536 expect(await helper.balance.transferToSubstrate(alice, bob.address, 1n)).to.be.true;3738 const alicesBalanceAfter = await helper.balance.getSubstrate(alice.address);39 const bobsBalanceAfter = await helper.balance.getSubstrate(bob.address);4041 expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true;42 expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true;43 });4445 itSub('Inability to pay fees error message is correct', async ({helper, privateKey}) => {46 const donor = privateKey('//Alice');47 const [zero] = await helper.arrange.createAccounts([0n], donor);4849 // console.error = () => {};50 // The following operation throws an error into the console and the logs. Pay it no heed as long as the test succeeds.51 await expect(helper.balance.transferToSubstrate(zero, donor.address, 1n))52 .to.be.rejectedWith('Inability to pay some fees , e.g. account balance too low');53 });5455 itSub('[nft] User can transfer owned token', async ({helper}) => {56 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-1-NFT', description: '', tokenPrefix: 'T'});57 const nft = await collection.mintToken(alice);5859 await nft.transfer(alice, {Substrate: bob.address});60 expect(await nft.getOwner()).to.be.deep.equal({Substrate: bob.address});61 });6263 itSub('[fungible] User can transfer owned token', async ({helper}) => {64 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-1-FT', description: '', tokenPrefix: 'T'});65 await collection.mint(alice, 10n);6667 await collection.transfer(alice, {Substrate: bob.address}, 9n);68 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(9n);69 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n);70 });7172 itSub.ifWithPallets('[refungible] User can transfer owned token', [Pallets.ReFungible], async ({helper}) => {73 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-1-RFT', description: '', tokenPrefix: 'T'});74 const rft = await collection.mintToken(alice, 10n);7576 await rft.transfer(alice, {Substrate: bob.address}, 9n);77 expect(await rft.getBalance({Substrate: bob.address})).to.be.equal(9n);78 expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(1n);79 });8081 itSub('[nft] Collection admin can transfer owned token', async ({helper}) => {82 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-2-NFT', description: '', tokenPrefix: 'T'});83 await collection.addAdmin(alice, {Substrate: bob.address});8485 const nft = await collection.mintToken(bob, {Substrate: bob.address});86 await nft.transfer(bob, {Substrate: alice.address});8788 expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address});89 });9091 itSub('[fungible] Collection admin can transfer owned token', async ({helper}) => {92 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-2-FT', description: '', tokenPrefix: 'T'});93 await collection.addAdmin(alice, {Substrate: bob.address});9495 await collection.mint(bob, 10n, {Substrate: bob.address});96 await collection.transfer(bob, {Substrate: alice.address}, 1n);9798 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(9n);99 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n);100 });101102 itSub.ifWithPallets('[refungible] Collection admin can transfer owned token', [Pallets.ReFungible], async ({helper}) => {103 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-2-RFT', description: '', tokenPrefix: 'T'});104 await collection.addAdmin(alice, {Substrate: bob.address});105106 const rft = await collection.mintToken(bob, 10n, {Substrate: bob.address});107 await rft.transfer(bob, {Substrate: alice.address}, 1n);108109 expect(await rft.getBalance({Substrate: bob.address})).to.be.equal(9n);110 expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(1n);111 });112});113114describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => {115 let alice: IKeyringPair;116 let bob: IKeyringPair;117118 before(async () => {119 await usingPlaygrounds(async (helper, privateKey) => {120 const donor = privateKey('//Alice');121 [alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor);122 });123 });124125 itSub('[nft] Transfer with not existed collection_id', async ({helper}) => {126 const collectionId = (1 << 32) - 1;127 await expect(helper.nft.transferToken(alice, collectionId, 1, {Substrate: bob.address}))128 .to.be.rejectedWith(/common\.CollectionNotFound/);129 });130131 itSub('[fungible] Transfer with not existed collection_id', async ({helper}) => {132 const collectionId = (1 << 32) - 1;133 await expect(helper.ft.transfer(alice, collectionId, {Substrate: bob.address}))134 .to.be.rejectedWith(/common\.CollectionNotFound/);135 });136137 itSub.ifWithPallets('[refungible] Transfer with not existed collection_id', [Pallets.ReFungible], async ({helper}) => {138 const collectionId = (1 << 32) - 1;139 await expect(helper.rft.transferToken(alice, collectionId, 1, {Substrate: bob.address}))140 .to.be.rejectedWith(/common\.CollectionNotFound/);141 });142143 itSub('[nft] Transfer with deleted collection_id', async ({helper}) => {144 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-1-NFT', description: '', tokenPrefix: 'T'});145 const nft = await collection.mintToken(alice);146147 await nft.burn(alice);148 await collection.burn(alice);149150 await expect(nft.transfer(alice, {Substrate: bob.address}))151 .to.be.rejectedWith(/common\.CollectionNotFound/);152 });153154 itSub('[fungible] Transfer with deleted collection_id', async ({helper}) => {155 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-1-FT', description: '', tokenPrefix: 'T'});156 await collection.mint(alice, 10n);157158 await collection.burnTokens(alice, 10n);159 await collection.burn(alice);160161 await expect(collection.transfer(alice, {Substrate: bob.address}))162 .to.be.rejectedWith(/common\.CollectionNotFound/);163 });164 165 itSub.ifWithPallets('[refungible] Transfer with deleted collection_id', [Pallets.ReFungible], async ({helper}) => {166 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-1-RFT', description: '', tokenPrefix: 'T'});167 const rft = await collection.mintToken(alice, 10n);168169 await rft.burn(alice, 10n);170 await collection.burn(alice);171172 await expect(rft.transfer(alice, {Substrate: bob.address}))173 .to.be.rejectedWith(/common\.CollectionNotFound/);174 });175176 itSub('[nft] Transfer with not existed item_id', async ({helper}) => {177 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-2-NFT', description: '', tokenPrefix: 'T'});178 await expect(collection.transferToken(alice, 1, {Substrate: bob.address}))179 .to.be.rejectedWith(/common\.TokenNotFound/);180 });181182 itSub('[fungible] Transfer with not existed item_id', async ({helper}) => {183 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-2-FT', description: '', tokenPrefix: 'T'});184 await expect(collection.transfer(alice, {Substrate: bob.address}))185 .to.be.rejectedWith(/common\.TokenValueTooLow/);186 });187188 itSub.ifWithPallets('[refungible] Transfer with not existed item_id', [Pallets.ReFungible], async ({helper}) => {189 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-2-RFT', description: '', tokenPrefix: 'T'});190 await expect(collection.transferToken(alice, 1, {Substrate: bob.address}))191 .to.be.rejectedWith(/common\.TokenValueTooLow/);192 });193194 itSub('[nft] Transfer with deleted item_id', async ({helper}) => {195 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-3-NFT', description: '', tokenPrefix: 'T'});196 const nft = await collection.mintToken(alice);197198 await nft.burn(alice);199200 await expect(nft.transfer(alice, {Substrate: bob.address}))201 .to.be.rejectedWith(/common\.TokenNotFound/);202 });203204 itSub('[fungible] Transfer with deleted item_id', async ({helper}) => {205 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-3-FT', description: '', tokenPrefix: 'T'});206 await collection.mint(alice, 10n);207208 await collection.burnTokens(alice, 10n);209210 await expect(collection.transfer(alice, {Substrate: bob.address}))211 .to.be.rejectedWith(/common\.TokenValueTooLow/);212 });213214 itSub.ifWithPallets('[refungible] Transfer with deleted item_id', [Pallets.ReFungible], async ({helper}) => {215 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-3-RFT', description: '', tokenPrefix: 'T'});216 const rft = await collection.mintToken(alice, 10n);217218 await rft.burn(alice, 10n);219220 await expect(rft.transfer(alice, {Substrate: bob.address}))221 .to.be.rejectedWith(/common\.TokenValueTooLow/);222 });223224 itSub('[nft] Transfer with recipient that is not owner', async ({helper}) => {225 const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-4-NFT', description: '', tokenPrefix: 'T'});226 const nft = await collection.mintToken(alice);227228 await expect(nft.transfer(bob, {Substrate: bob.address}))229 .to.be.rejectedWith(/common\.NoPermission/);230 expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address});231 });232233 itSub('[fungible] Transfer with recipient that is not owner', async ({helper}) => {234 const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-4-FT', description: '', tokenPrefix: 'T'});235 await collection.mint(alice, 10n);236237 await expect(collection.transfer(bob, {Substrate: bob.address}, 9n))238 .to.be.rejectedWith(/common\.TokenValueTooLow/);239 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(0n);240 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(10n);241 });242243 itSub.ifWithPallets('[refungible] Transfer with recipient that is not owner', [Pallets.ReFungible], async ({helper}) => {244 const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-1-RFT', description: '', tokenPrefix: 'T'});245 const rft = await collection.mintToken(alice, 10n);246247 await expect(rft.transfer(bob, {Substrate: bob.address}, 9n))248 .to.be.rejectedWith(/common\.TokenValueTooLow/);249 expect(await rft.getBalance({Substrate: bob.address})).to.be.equal(0n);250 expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(10n);251 });252});253254describe('Transfers to self (potentially over substrate-evm boundary)', () => {255 let donor: IKeyringPair;256257 before(async function() {258 await usingEthPlaygrounds(async (_, privateKey) => {259 donor = privateKey('//Alice');260 });261 });262 263 itEth('Transfers to self. In case of same frontend', async ({helper}) => {264 const [owner] = await helper.arrange.createAccounts([10n], donor);265 const collection = await helper.ft.mintCollection(owner, {});266 await collection.mint(owner, 100n);267268 const ownerProxy = helper.address.substrateToEth(owner.address);269270 // transfer to own proxy271 await collection.transfer(owner, {Ethereum: ownerProxy}, 10n);272 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(90n);273 expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(10n);274275 // transfer-from own proxy to own proxy again276 await collection.transferFrom(owner, {Ethereum: ownerProxy}, {Ethereum: ownerProxy}, 5n);277 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(90n);278 expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(10n);279 });280281 itEth('Transfers to self. In case of substrate-evm boundary', async ({helper}) => {282 const [owner] = await helper.arrange.createAccounts([10n], donor);283 const collection = await helper.ft.mintCollection(owner, {});284 await collection.mint(owner, 100n);285286 const ownerProxy = helper.address.substrateToEth(owner.address);287288 // transfer to own proxy289 await collection.transfer(owner, {Ethereum: ownerProxy}, 10n);290 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(90n);291 expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(10n);292293 // transfer-from own proxy to self294 await collection.transferFrom(owner, {Ethereum: ownerProxy}, {Substrate: owner.address}, 5n);295 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(95n);296 expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(5n);297 });298299 itEth('Transfers to self. In case of inside substrate-evm', async ({helper}) => {300 const [owner] = await helper.arrange.createAccounts([10n], donor);301 const collection = await helper.ft.mintCollection(owner, {});302 await collection.mint(owner, 100n);303304 // transfer to self again305 await collection.transfer(owner, {Substrate: owner.address}, 10n);306 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(100n);307308 // transfer-from self to self again309 await collection.transferFrom(owner, {Substrate: owner.address}, {Substrate: owner.address}, 5n);310 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(100n);311 });312313 itEth('Transfers to self. In case of inside substrate-evm when not enought "Fungibles"', async ({helper}) => {314 const [owner] = await helper.arrange.createAccounts([10n], donor);315 const collection = await helper.ft.mintCollection(owner, {});316 await collection.mint(owner, 10n);317318 // transfer to self again319 await expect(collection.transfer(owner, {Substrate: owner.address}, 11n))320 .to.be.rejectedWith(/common\.TokenValueTooLow/);321322 // transfer-from self to self again323 await expect(collection.transferFrom(owner, {Substrate: owner.address}, {Substrate: owner.address}, 12n))324 .to.be.rejectedWith(/common\.TokenValueTooLow/);325 expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(10n);326 });327});tests/src/transferFrom.test.tsdiffbeforeafterboth--- a/tests/src/transferFrom.test.ts
+++ b/tests/src/transferFrom.test.ts
@@ -14,97 +14,73 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-import {ApiPromise} from '@polkadot/api';
import {IKeyringPair} from '@polkadot/types/types';
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import {default as usingApi} from './substrate/substrate-api';
-import {
- approveExpectFail,
- approveExpectSuccess,
- createCollectionExpectSuccess,
- createFungibleItemExpectSuccess,
- createItemExpectSuccess,
- getAllowance,
- transferFromExpectFail,
- transferFromExpectSuccess,
- burnItemExpectSuccess,
- setCollectionLimitsExpectSuccess,
- getCreatedCollectionCount,
- requirePallets,
- Pallets,
-} from './util/helpers';
+import {itSub, Pallets, usingPlaygrounds, expect} from './util/playgrounds';
-chai.use(chaiAsPromised);
-const expect = chai.expect;
-
describe('Integration Test transferFrom(from, recipient, collection_id, item_id, value):', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
let charlie: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- charlie = privateKeyWrapper('//Charlie');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob, charlie] = await helper.arrange.createAccounts([20n, 10n, 10n], donor);
});
});
- it('[nft] Execute the extrinsic and check nftItemList - owner of token', async () => {
- const nftCollectionId = await createCollectionExpectSuccess();
- const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
- await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
+ itSub('[nft] Execute the extrinsic and check nftItemList - owner of token', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-1', description: '', tokenPrefix: 'TF'});
+ const nft = await collection.mintToken(alice);
+ await nft.approve(alice, {Substrate: bob.address});
+ expect(await nft.isApproved({Substrate: bob.address})).to.be.true;
- await transferFromExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, charlie, 1, 'NFT');
+ await nft.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address});
+ expect(await nft.getOwner()).to.be.deep.equal({Substrate: charlie.address});
});
- it('[fungible] Execute the extrinsic and check nftItemList - owner of token', async () => {
- const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
- await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
- await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1, 'Fungible');
+ itSub('[fungible] Execute the extrinsic and check nftItemList - owner of token', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-2', description: '', tokenPrefix: 'TF'});
+ await collection.mint(alice, 10n);
+ await collection.approveTokens(alice, {Substrate: bob.address}, 7n);
+ expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(7n);
+
+ await collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 6n);
+ expect(await collection.getBalance({Substrate: charlie.address})).to.be.equal(6n);
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(4n);
+ expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(1n);
});
-
- it('[refungible] Execute the extrinsic and check nftItemList - owner of token', async function() {
- await requirePallets(this, [Pallets.ReFungible]);
- const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
- await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 100);
- await transferFromExpectSuccess(
- reFungibleCollectionId,
- newReFungibleTokenId,
- bob,
- alice,
- charlie,
- 100,
- 'ReFungible',
- );
+ itSub.ifWithPallets('[refungible] Execute the extrinsic and check nftItemList - owner of token', [Pallets.ReFungible], async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'TransferFrom-3', description: '', tokenPrefix: 'TF'});
+ const rft = await collection.mintToken(alice, 10n);
+ await rft.approve(alice, {Substrate: bob.address}, 7n);
+ expect(await rft.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(7n);
+
+ await rft.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 6n);
+ expect(await rft.getBalance({Substrate: charlie.address})).to.be.equal(6n);
+ expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(4n);
+ expect(await rft.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(1n);
});
- it('Should reduce allowance if value is big', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- const alice = privateKeyWrapper('//Alice');
- const bob = privateKeyWrapper('//Bob');
- const charlie = privateKeyWrapper('//Charlie');
-
- // fungible
- const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- const newFungibleTokenId = await createFungibleItemExpectSuccess(alice, fungibleCollectionId, {Value: 500000n});
+ itSub('Should reduce allowance if value is big', async ({helper}) => {
+ // fungible
+ const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-4', description: '', tokenPrefix: 'TF'});
+ await collection.mint(alice, 500000n);
- await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 500000n);
- await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 500000n, 'Fungible');
- expect(await getAllowance(api, fungibleCollectionId, alice.address, bob.address, newFungibleTokenId)).to.equal(0n);
- });
+ await collection.approveTokens(alice, {Substrate: bob.address}, 500000n);
+ expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(500000n);
+ await collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 500000n);
+ expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(0n);
});
- it('can be called by collection owner on non-owned item when OwnerCanTransfer == true', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
- const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);
+ itSub('can be called by collection owner on non-owned item when OwnerCanTransfer == true', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-5', description: '', tokenPrefix: 'TF'});
+ await collection.setLimits(alice, {ownerCanTransfer: true});
- await transferFromExpectSuccess(collectionId, itemId, alice, bob, charlie);
+ const nft = await collection.mintToken(alice, {Substrate: bob.address});
+ await nft.transferFrom(alice, {Substrate: bob.address}, {Substrate: charlie.address});
+ expect(await nft.getOwner()).to.be.deep.equal({Substrate: charlie.address});
});
});
@@ -114,245 +90,263 @@
let charlie: IKeyringPair;
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- charlie = privateKeyWrapper('//Charlie');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const donor = privateKey('//Alice');
+ [alice, bob, charlie] = await helper.arrange.createAccounts([50n, 10n, 10n], donor);
});
});
- it('[nft] transferFrom for a collection that does not exist', async () => {
- await usingApi(async (api: ApiPromise) => {
- const nftCollectionCount = await getCreatedCollectionCount(api);
- await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);
+ itSub('transferFrom for a collection that does not exist', async ({helper}) => {
+ const collectionId = (1 << 32) - 1;
+ await expect(helper.collection.approveToken(alice, collectionId, 0, {Substrate: bob.address}, 1n))
+ .to.be.rejectedWith(/common\.CollectionNotFound/);
+ await expect(helper.collection.transferTokenFrom(bob, collectionId, 0, {Substrate: alice.address}, {Substrate: bob.address}, 1n))
+ .to.be.rejectedWith(/common\.CollectionNotFound/);
+ });
+
+ /* itSub('transferFrom for a collection that was destroyed', async ({helper}) => {
+ this test copies approve negative test
+ }); */
+
+ /* itSub('transferFrom a token that does not exist', async ({helper}) => {
+ this test copies approve negative test
+ }); */
+
+ /* itSub('transferFrom a token that was deleted', async ({helper}) => {
+ this test copies approve negative test
+ }); */
+
+ itSub('[nft] transferFrom for not approved address', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-Neg-1', description: '', tokenPrefix: 'TF'});
+ const nft = await collection.mintToken(alice);
+
+ await expect(nft.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}))
+ .to.be.rejectedWith(/common\.ApprovedValueTooLow/);
+ expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address});
+ });
+
+ itSub('[fungible] transferFrom for not approved address', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-Neg-1', description: '', tokenPrefix: 'TF'});
+ await collection.mint(alice, 10n);
- await transferFromExpectFail(nftCollectionCount + 1, 1, bob, alice, charlie, 1);
- });
+ await expect(collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 5n))
+ .to.be.rejectedWith(/common\.ApprovedValueTooLow/);
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.deep.equal(10n);
+ expect(await collection.getBalance({Substrate: bob.address})).to.be.deep.equal(0n);
+ expect(await collection.getBalance({Substrate: charlie.address})).to.be.deep.equal(0n);
});
- it('[fungible] transferFrom for a collection that does not exist', async () => {
- await usingApi(async (api: ApiPromise) => {
- const fungibleCollectionCount = await getCreatedCollectionCount(api);
- await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);
+ itSub.ifWithPallets('[refungible] transferFrom for not approved address', [Pallets.ReFungible], async({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'TransferFrom-Neg-3', description: '', tokenPrefix: 'TF'});
+ const rft = await collection.mintToken(alice, 10n);
- await transferFromExpectFail(fungibleCollectionCount + 1, 0, bob, alice, charlie, 1);
- });
+ await expect(rft.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}))
+ .to.be.rejectedWith(/common\.ApprovedValueTooLow/);
+ expect(await rft.getBalance({Substrate: alice.address})).to.be.deep.equal(10n);
+ expect(await rft.getBalance({Substrate: bob.address})).to.be.deep.equal(0n);
+ expect(await rft.getBalance({Substrate: charlie.address})).to.be.deep.equal(0n);
});
- it('[refungible] transferFrom for a collection that does not exist', async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ itSub('[nft] transferFrom incorrect token count', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-Neg-4', description: '', tokenPrefix: 'TF'});
+ const nft = await collection.mintToken(alice);
- await usingApi(async (api: ApiPromise) => {
- const reFungibleCollectionCount = await getCreatedCollectionCount(api);
- await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);
+ await nft.approve(alice, {Substrate: bob.address});
+ expect(await nft.isApproved({Substrate: bob.address})).to.be.true;
- await transferFromExpectFail(reFungibleCollectionCount + 1, 1, bob, alice, charlie, 1);
- });
+ await expect(helper.collection.transferTokenFrom(
+ bob,
+ collection.collectionId,
+ nft.tokenId,
+ {Substrate: alice.address},
+ {Substrate: charlie.address},
+ 2n,
+ )).to.be.rejectedWith(/nonfungible\.NonfungibleItemsHaveNoAmount/);
+ expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address});
});
- /* it('transferFrom for a collection that was destroyed', async () => {
- await usingApi(async (api: ApiPromise) => {
- this test copies approve negative test
- });
- }); */
+ itSub('[fungible] transferFrom incorrect token count', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-Neg-5', description: '', tokenPrefix: 'TF'});
+ await collection.mint(alice, 10n);
- /* it('transferFrom a token that does not exist', async () => {
- await usingApi(async (api: ApiPromise) => {
- this test copies approve negative test
- });
- }); */
+ await collection.approveTokens(alice, {Substrate: bob.address}, 2n);
+ expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.eq(2n);
- /* it('transferFrom a token that was deleted', async () => {
- await usingApi(async (api: ApiPromise) => {
- this test copies approve negative test
- });
- }); */
+ await expect(collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 5n))
+ .to.be.rejectedWith(/common\.ApprovedValueTooLow/);
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.deep.equal(10n);
+ expect(await collection.getBalance({Substrate: bob.address})).to.be.deep.equal(0n);
+ expect(await collection.getBalance({Substrate: charlie.address})).to.be.deep.equal(0n);
+ });
+
+ itSub.ifWithPallets('[refungible] transferFrom incorrect token count', [Pallets.ReFungible], async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'TransferFrom-Neg-6', description: '', tokenPrefix: 'TF'});
+ const rft = await collection.mintToken(alice, 10n);
- it('[nft] transferFrom for not approved address', async () => {
- const nftCollectionId = await createCollectionExpectSuccess();
- const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
+ await rft.approve(alice, {Substrate: bob.address}, 5n);
+ expect(await rft.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.eq(5n);
- await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1);
+ await expect(rft.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 7n))
+ .to.be.rejectedWith(/common\.ApprovedValueTooLow/);
+ expect(await rft.getBalance({Substrate: alice.address})).to.be.deep.equal(10n);
+ expect(await rft.getBalance({Substrate: bob.address})).to.be.deep.equal(0n);
+ expect(await rft.getBalance({Substrate: charlie.address})).to.be.deep.equal(0n);
});
- it('[fungible] transferFrom for not approved address', async () => {
- const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
- await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1);
+ itSub('[nft] execute transferFrom from account that is not owner of collection', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-Neg-7', description: '', tokenPrefix: 'TF'});
+ const nft = await collection.mintToken(alice);
+
+ await expect(nft.approve(charlie, {Substrate: bob.address})).to.be.rejectedWith(/common\.CantApproveMoreThanOwned/);
+ expect(await nft.isApproved({Substrate: bob.address})).to.be.false;
+
+ await expect(nft.transferFrom(
+ charlie,
+ {Substrate: alice.address},
+ {Substrate: charlie.address},
+ )).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
+ expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address});
});
- it('[refungible] transferFrom for not approved address', async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ itSub('[fungible] execute transferFrom from account that is not owner of collection', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-Neg-8', description: '', tokenPrefix: 'TF'});
+ await collection.mint(alice, 10000n);
+
+ await expect(collection.approveTokens(charlie, {Substrate: bob.address}, 1n)).to.be.rejectedWith(/common\.CantApproveMoreThanOwned/);
+ expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.eq(0n);
+ expect(await collection.getApprovedTokens({Substrate: charlie.address}, {Substrate: bob.address})).to.be.eq(0n);
- const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
- await transferFromExpectFail(
- reFungibleCollectionId,
- newReFungibleTokenId,
- bob,
- alice,
+ await expect(collection.transferFrom(
charlie,
- 1,
- );
+ {Substrate: alice.address},
+ {Substrate: charlie.address},
+ )).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.deep.equal(10000n);
+ expect(await collection.getBalance({Substrate: bob.address})).to.be.deep.equal(0n);
+ expect(await collection.getBalance({Substrate: charlie.address})).to.be.deep.equal(0n);
});
- it('[nft] transferFrom incorrect token count', async () => {
- const nftCollectionId = await createCollectionExpectSuccess();
- const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
- await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
+ itSub.ifWithPallets('[refungible] execute transferFrom from account that is not owner of collection', [Pallets.ReFungible], async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'TransferFrom-Neg-9', description: '', tokenPrefix: 'TF'});
+ const rft = await collection.mintToken(alice, 10000n);
- await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 2);
- });
+ await expect(rft.approve(charlie, {Substrate: bob.address}, 1n)).to.be.rejectedWith(/common\.CantApproveMoreThanOwned/);
+ expect(await rft.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.eq(0n);
+ expect(await rft.getApprovedPieces({Substrate: charlie.address}, {Substrate: bob.address})).to.be.eq(0n);
- it('[fungible] transferFrom incorrect token count', async () => {
- const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
- await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
- await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 2);
+ await expect(rft.transferFrom(
+ charlie,
+ {Substrate: alice.address},
+ {Substrate: charlie.address},
+ )).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
+ expect(await rft.getBalance({Substrate: alice.address})).to.be.deep.equal(10000n);
+ expect(await rft.getBalance({Substrate: bob.address})).to.be.deep.equal(0n);
+ expect(await rft.getBalance({Substrate: charlie.address})).to.be.deep.equal(0n);
});
- it('[refungible] transferFrom incorrect token count', async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ itSub('transferFrom burnt token before approve NFT', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-Neg-10', description: '', tokenPrefix: 'TF'});
+ await collection.setLimits(alice, {ownerCanTransfer: true});
+ const nft = await collection.mintToken(alice);
- const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
- await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);
- await transferFromExpectFail(
- reFungibleCollectionId,
- newReFungibleTokenId,
+ await nft.burn(alice);
+ await expect(nft.approve(alice, {Substrate: bob.address})).to.be.rejectedWith(/common\.TokenNotFound/);
+
+ await expect(nft.transferFrom(
bob,
+ {Substrate: alice.address},
+ {Substrate: charlie.address},
+ )).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
+ });
+
+ itSub('transferFrom burnt token before approve Fungible', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-Neg-11', description: '', tokenPrefix: 'TF'});
+ await collection.setLimits(alice, {ownerCanTransfer: true});
+ await collection.mint(alice, 10n);
+
+ await collection.burnTokens(alice, 10n);
+ await expect(collection.approveTokens(alice, {Substrate: bob.address})).to.be.not.rejected;
+
+ await expect(collection.transferFrom(
alice,
- charlie,
- 2,
- );
+ {Substrate: alice.address},
+ {Substrate: charlie.address},
+ )).to.be.rejectedWith(/common\.TokenValueTooLow/);
});
- it('[nft] execute transferFrom from account that is not owner of collection', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- const dave = privateKeyWrapper('//Dave');
- const nftCollectionId = await createCollectionExpectSuccess();
- const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
- try {
- await approveExpectFail(nftCollectionId, newNftTokenId, dave, bob);
- await transferFromExpectFail(nftCollectionId, newNftTokenId, dave, alice, charlie, 1);
- } catch (e) {
- // tslint:disable-next-line:no-unused-expression
- expect(e).to.be.exist;
- }
+ itSub.ifWithPallets('transferFrom burnt token before approve ReFungible', [Pallets.ReFungible], async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'TransferFrom-Neg-12', description: '', tokenPrefix: 'TF'});
+ await collection.setLimits(alice, {ownerCanTransfer: true});
+ const rft = await collection.mintToken(alice, 10n);
+
+ await rft.burn(alice, 10n);
+ await expect(rft.approve(alice, {Substrate: bob.address})).to.be.rejectedWith(/common\.CantApproveMoreThanOwned/);
- // await transferFromExpectFail(nftCollectionId, newNftTokenId, Dave, Alice, Charlie, 1);
- });
+ await expect(rft.transferFrom(
+ alice,
+ {Substrate: alice.address},
+ {Substrate: charlie.address},
+ )).to.be.rejectedWith(/common\.TokenValueTooLow/);
});
- it('[fungible] execute transferFrom from account that is not owner of collection', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- const dave = privateKeyWrapper('//Dave');
+ itSub('transferFrom burnt token after approve NFT', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-Neg-13', description: '', tokenPrefix: 'TF'});
+ const nft = await collection.mintToken(alice);
- const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
- try {
- await approveExpectFail(fungibleCollectionId, newFungibleTokenId, dave, bob);
- await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, dave, alice, charlie, 1);
- } catch (e) {
- // tslint:disable-next-line:no-unused-expression
- expect(e).to.be.exist;
- }
- });
- });
+ await nft.approve(alice, {Substrate: bob.address});
+ expect(await nft.isApproved({Substrate: bob.address})).to.be.true;
- it('[refungible] execute transferFrom from account that is not owner of collection', async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ await nft.burn(alice);
- await usingApi(async (api, privateKeyWrapper) => {
- const dave = privateKeyWrapper('//Dave');
- const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
- try {
- await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, dave, bob);
- await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, dave, alice, charlie, 1);
- } catch (e) {
- // tslint:disable-next-line:no-unused-expression
- expect(e).to.be.exist;
- }
- });
- });
- it('transferFrom burnt token before approve NFT', async () => {
- await usingApi(async () => {
- // nft
- const nftCollectionId = await createCollectionExpectSuccess();
- await setCollectionLimitsExpectSuccess(alice, nftCollectionId, {ownerCanTransfer: true});
- const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
- await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);
- await approveExpectFail(nftCollectionId, newNftTokenId, alice, bob);
- await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1);
- });
+ await expect(nft.transferFrom(
+ bob,
+ {Substrate: alice.address},
+ {Substrate: charlie.address},
+ )).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
});
- it('transferFrom burnt token before approve Fungible', async () => {
- await usingApi(async () => {
- const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- await setCollectionLimitsExpectSuccess(alice, fungibleCollectionId, {ownerCanTransfer: true});
- const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
- await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);
- await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
- await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1);
- });
- });
- it('transferFrom burnt token before approve ReFungible', async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ itSub('transferFrom burnt token after approve Fungible', async ({helper}) => {
+ const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-Neg-14', description: '', tokenPrefix: 'TF'});
+ await collection.mint(alice, 10n);
- await usingApi(async () => {
- const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- await setCollectionLimitsExpectSuccess(alice, reFungibleCollectionId, {ownerCanTransfer: true});
- const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
- await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100);
- await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, alice, bob);
- await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, alice, charlie, 1);
+ await collection.approveTokens(alice, {Substrate: bob.address});
+ expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.eq(1n);
- });
- });
+ await collection.burnTokens(alice, 10n);
- it('transferFrom burnt token after approve NFT', async () => {
- await usingApi(async () => {
- // nft
- const nftCollectionId = await createCollectionExpectSuccess();
- const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
- await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
- await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);
- await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1);
- });
+ await expect(collection.transferFrom(
+ bob,
+ {Substrate: alice.address},
+ {Substrate: charlie.address},
+ )).to.be.rejectedWith(/common\.TokenValueTooLow/);
});
- it('transferFrom burnt token after approve Fungible', async () => {
- await usingApi(async () => {
- const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
- await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
- await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);
- await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1);
- });
- });
- it('transferFrom burnt token after approve ReFungible', async function() {
- await requirePallets(this, [Pallets.ReFungible]);
+ itSub.ifWithPallets('transferFrom burnt token after approve ReFungible', [Pallets.ReFungible], async ({helper}) => {
+ const collection = await helper.rft.mintCollection(alice, {name: 'TransferFrom-Neg-15', description: '', tokenPrefix: 'TF'});
+ const rft = await collection.mintToken(alice, 10n);
- await usingApi(async () => {
- const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
- await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);
- await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100);
- await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, alice, charlie, 1);
+ await rft.approve(alice, {Substrate: bob.address}, 10n);
+ expect(await rft.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.eq(10n);
+
+ await rft.burn(alice, 10n);
- });
+ await expect(rft.transferFrom(
+ bob,
+ {Substrate: alice.address},
+ {Substrate: charlie.address},
+ )).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
});
- it('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {
- const collectionId = await createCollectionExpectSuccess();
- const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);
- await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: false});
+ itSub('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', async ({helper}) => {
+ const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-Neg-16', description: '', tokenPrefix: 'TF'});
+ const nft = await collection.mintToken(alice, {Substrate: bob.address});
- await transferFromExpectFail(collectionId, itemId, alice, bob, charlie);
+ await collection.setLimits(alice, {ownerCanTransfer: false});
+
+ await expect(nft.transferFrom(
+ alice,
+ {Substrate: bob.address},
+ {Substrate: charlie.address},
+ )).to.be.rejectedWith(/common\.ApprovedValueTooLow/);
});
});
tests/src/util/helpers.tsdiffbeforeafterboth--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -1651,7 +1651,7 @@
});
}
-export async function isAllowlisted(api: ApiPromise, collectionId: number, address: string | CrossAccountId) {
+export async function isAllowlisted(api: ApiPromise, collectionId: number, address: string | CrossAccountId | IKeyringPair) {
return (await api.rpc.unique.allowed(collectionId, normalizeAccountId(address))).toJSON();
}
tests/src/util/playgrounds/index.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/index.ts
+++ b/tests/src/util/playgrounds/index.ts
@@ -2,12 +2,17 @@
// SPDX-License-Identifier: Apache-2.0
import {IKeyringPair} from '@polkadot/types/types';
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
import {Context} from 'mocha';
import config from '../../config';
import '../../interfaces/augment-api-events';
import {DevUniqueHelper, SilentLogger, SilentConsole} from './unique.dev';
+chai.use(chaiAsPromised);
+export const expect = chai.expect;
+
export const usingPlaygrounds = async (code: (helper: DevUniqueHelper, privateKey: (seed: string) => IKeyringPair) => Promise<void>) => {
const silentConsole = new SilentConsole();
silentConsole.enable();
tests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/unique.dev.ts
+++ b/tests/src/util/playgrounds/unique.dev.ts
@@ -257,6 +257,7 @@
}
async forParachainBlockNumber(blockNumber: bigint) {
+ // eslint-disable-next-line no-async-promise-executor
return new Promise<void>(async (resolve) => {
const unsubscribe = await this.helper.api!.rpc.chain.subscribeNewHeads(async (data: any) => {
if (data.number.toNumber() >= blockNumber) {
@@ -268,6 +269,7 @@
}
async forRelayBlockNumber(blockNumber: bigint) {
+ // eslint-disable-next-line no-async-promise-executor
return new Promise<void>(async (resolve) => {
const unsubscribe = await this.helper.api!.query.parachainSystem.validationData(async (data: any) => {
if (data.value.relayParentNumber.toNumber() >= blockNumber) {
tests/src/util/playgrounds/unique.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -730,6 +730,18 @@
}
/**
+ * Check if user is in allow list.
+ *
+ * @param collectionId ID of collection
+ * @param user Account to check
+ * @example await getAdmins(1)
+ * @returns is user in allow list
+ */
+ async allowed(collectionId: number, user: ICrossAccountId): Promise<boolean> {
+ return (await this.helper.callRpc('api.rpc.unique.allowed', [collectionId, user])).toJSON();
+ }
+
+ /**
* Adds an address to allow list
* @param signer keyring of signer
* @param collectionId ID of collection
@@ -1666,7 +1678,7 @@
* @example mintTokens(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq"}, 1000n);
* @returns ```true``` if extrinsic success, otherwise ```false```
*/
- async mintTokens(signer: TSigner, collectionId: number, owner: ICrossAccountId | string, amount: bigint): Promise<boolean> {
+ async mintTokens(signer: TSigner, collectionId: number, amount: bigint, owner: ICrossAccountId | string): Promise<boolean> {
const creationResult = await this.helper.executeExtrinsic(
signer,
'api.tx.unique.createItem', [collectionId, (typeof owner === 'string') ? {Substrate: owner} : owner, {
@@ -1687,7 +1699,7 @@
* @param tokens array of tokens with properties and pieces
* @returns ```true``` if extrinsic success, otherwise ```false```
*/
- async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {value: bigint}[]): Promise<boolean> {
+ async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, tokens: {value: bigint}[], owner: ICrossAccountId): Promise<boolean> {
const rawTokens = [];
for (const token of tokens) {
const raw = {Fungible: {Value: token.value}};
@@ -2114,10 +2126,6 @@
async addAdmin(signer: TSigner, adminAddressObj: ICrossAccountId) {
return await this.helper.collection.addAdmin(signer, this.collectionId, adminAddressObj);
- }
-
- async enableCertainPermissions(signer: TSigner, accessMode: 'AllowList' | 'Normal' | undefined = 'AllowList', mintMode: boolean | undefined = true) {
- return await this.setPermissions(signer, {access: accessMode, mintMode: mintMode});
}
async addToAllowList(signer: TSigner, addressObj: ICrossAccountId) {
@@ -2203,7 +2211,7 @@
return await this.helper.nft.isTokenApproved(this.collectionId, tokenId, toAddressObj);
}
- async mintToken(signer: TSigner, owner: ICrossAccountId, properties?: IProperty[]) {
+ async mintToken(signer: TSigner, owner: ICrossAccountId = {Substrate: signer.address}, properties?: IProperty[]) {
return await this.helper.nft.mintToken(signer, {collectionId: this.collectionId, owner, properties});
}
@@ -2278,11 +2286,11 @@
return await this.helper.rft.repartitionToken(signer, this.collectionId, tokenId, amount);
}
- async mintToken(signer: TSigner, owner: ICrossAccountId, pieces=100n, properties?: IProperty[]) {
+ async mintToken(signer: TSigner, pieces=1n, owner: ICrossAccountId = {Substrate: signer.address}, properties?: IProperty[]) {
return await this.helper.rft.mintToken(signer, {collectionId: this.collectionId, owner, pieces, properties});
}
- async mintMultipleTokens(signer: TSigner, tokens: {owner: ICrossAccountId, pieces: bigint, properties?: IProperty[]}[]) {
+ async mintMultipleTokens(signer: TSigner, tokens: {pieces: bigint, owner: ICrossAccountId, properties?: IProperty[]}[]) {
return await this.helper.rft.mintMultipleTokens(signer, this.collectionId, tokens);
}
@@ -2305,12 +2313,12 @@
class UniqueFTCollection extends UniqueCollectionBase {
- async mint(signer: TSigner, owner: ICrossAccountId, amount: bigint) {
- return await this.helper.ft.mintTokens(signer, this.collectionId, owner, amount);
+ async mint(signer: TSigner, amount=1n, owner: ICrossAccountId = {Substrate: signer.address}) {
+ return await this.helper.ft.mintTokens(signer, this.collectionId, amount, owner);
}
- async mintWithOneOwner(signer: TSigner, owner: ICrossAccountId, tokens: {value: bigint}[]) {
- return await this.helper.ft.mintMultipleTokensWithOneOwner(signer, this.collectionId, owner, tokens);
+ async mintWithOneOwner(signer: TSigner, tokens: {value: bigint}[], owner: ICrossAccountId = {Substrate: signer.address}) {
+ return await this.helper.ft.mintMultipleTokensWithOneOwner(signer, this.collectionId, tokens, owner);
}
async getBalance(addressObj: ICrossAccountId) {
tests/src/xcmTransfer.test.tsdiffbeforeafterboth--- a/tests/src/xcmTransfer.test.ts
+++ b/tests/src/xcmTransfer.test.ts
@@ -33,6 +33,7 @@
const KARURA_PORT = '9946';
const TRANSFER_AMOUNT = 2000000000000000000000000n;
+// todo:playgrounds refit when XCM drops
describe.skip('Integration test: Exchanging QTZ with Karura', () => {
let alice: IKeyringPair;
tests/yarn.lockdiffbeforeafterboth--- a/tests/yarn.lock
+++ b/tests/yarn.lock
@@ -17,47 +17,47 @@
dependencies:
"@babel/highlight" "^7.18.6"
-"@babel/compat-data@^7.18.8":
- version "7.18.8"
- resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d"
- integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==
+"@babel/compat-data@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.0.tgz#2a592fd89bacb1fcde68de31bee4f2f2dacb0e86"
+ integrity sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==
"@babel/core@^7.18.10":
- version "7.18.10"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.10.tgz#39ad504991d77f1f3da91be0b8b949a5bc466fb8"
- integrity sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.0.tgz#d2f5f4f2033c00de8096be3c9f45772563e150c3"
+ integrity sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==
dependencies:
"@ampproject/remapping" "^2.1.0"
"@babel/code-frame" "^7.18.6"
- "@babel/generator" "^7.18.10"
- "@babel/helper-compilation-targets" "^7.18.9"
- "@babel/helper-module-transforms" "^7.18.9"
- "@babel/helpers" "^7.18.9"
- "@babel/parser" "^7.18.10"
+ "@babel/generator" "^7.19.0"
+ "@babel/helper-compilation-targets" "^7.19.0"
+ "@babel/helper-module-transforms" "^7.19.0"
+ "@babel/helpers" "^7.19.0"
+ "@babel/parser" "^7.19.0"
"@babel/template" "^7.18.10"
- "@babel/traverse" "^7.18.10"
- "@babel/types" "^7.18.10"
+ "@babel/traverse" "^7.19.0"
+ "@babel/types" "^7.19.0"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.2"
json5 "^2.2.1"
semver "^6.3.0"
-"@babel/generator@^7.18.10":
- version "7.18.12"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.12.tgz#fa58daa303757bd6f5e4bbca91b342040463d9f4"
- integrity sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==
+"@babel/generator@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.0.tgz#785596c06425e59334df2ccee63ab166b738419a"
+ integrity sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==
dependencies:
- "@babel/types" "^7.18.10"
+ "@babel/types" "^7.19.0"
"@jridgewell/gen-mapping" "^0.3.2"
jsesc "^2.5.1"
-"@babel/helper-compilation-targets@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz#69e64f57b524cde3e5ff6cc5a9f4a387ee5563bf"
- integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==
+"@babel/helper-compilation-targets@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz#537ec8339d53e806ed422f1e06c8f17d55b96bb0"
+ integrity sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==
dependencies:
- "@babel/compat-data" "^7.18.8"
+ "@babel/compat-data" "^7.19.0"
"@babel/helper-validator-option" "^7.18.6"
browserslist "^4.20.2"
semver "^6.3.0"
@@ -67,13 +67,13 @@
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be"
integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
-"@babel/helper-function-name@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz#940e6084a55dee867d33b4e487da2676365e86b0"
- integrity sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==
+"@babel/helper-function-name@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c"
+ integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==
dependencies:
- "@babel/template" "^7.18.6"
- "@babel/types" "^7.18.9"
+ "@babel/template" "^7.18.10"
+ "@babel/types" "^7.19.0"
"@babel/helper-hoist-variables@^7.18.6":
version "7.18.6"
@@ -89,19 +89,19 @@
dependencies:
"@babel/types" "^7.18.6"
-"@babel/helper-module-transforms@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz#5a1079c005135ed627442df31a42887e80fcb712"
- integrity sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==
+"@babel/helper-module-transforms@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30"
+ integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==
dependencies:
"@babel/helper-environment-visitor" "^7.18.9"
"@babel/helper-module-imports" "^7.18.6"
"@babel/helper-simple-access" "^7.18.6"
"@babel/helper-split-export-declaration" "^7.18.6"
"@babel/helper-validator-identifier" "^7.18.6"
- "@babel/template" "^7.18.6"
- "@babel/traverse" "^7.18.9"
- "@babel/types" "^7.18.9"
+ "@babel/template" "^7.18.10"
+ "@babel/traverse" "^7.19.0"
+ "@babel/types" "^7.19.0"
"@babel/helper-simple-access@^7.18.6":
version "7.18.6"
@@ -132,14 +132,14 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==
-"@babel/helpers@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.9.tgz#4bef3b893f253a1eced04516824ede94dcfe7ff9"
- integrity sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==
+"@babel/helpers@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.0.tgz#f30534657faf246ae96551d88dd31e9d1fa1fc18"
+ integrity sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==
dependencies:
- "@babel/template" "^7.18.6"
- "@babel/traverse" "^7.18.9"
- "@babel/types" "^7.18.9"
+ "@babel/template" "^7.18.10"
+ "@babel/traverse" "^7.19.0"
+ "@babel/types" "^7.19.0"
"@babel/highlight@^7.18.6":
version "7.18.6"
@@ -150,10 +150,10 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@babel/parser@^7.18.10", "@babel/parser@^7.18.11":
- version "7.18.11"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.11.tgz#68bb07ab3d380affa9a3f96728df07969645d2d9"
- integrity sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==
+"@babel/parser@^7.18.10", "@babel/parser@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.0.tgz#497fcafb1d5b61376959c1c338745ef0577aa02c"
+ integrity sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==
"@babel/register@^7.18.9":
version "7.18.9"
@@ -167,13 +167,13 @@
source-map-support "^0.5.16"
"@babel/runtime@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
- integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
+ integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
dependencies:
regenerator-runtime "^0.13.4"
-"@babel/template@^7.18.10", "@babel/template@^7.18.6":
+"@babel/template@^7.18.10":
version "7.18.10"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71"
integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==
@@ -182,26 +182,26 @@
"@babel/parser" "^7.18.10"
"@babel/types" "^7.18.10"
-"@babel/traverse@^7.18.10", "@babel/traverse@^7.18.9":
- version "7.18.11"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.11.tgz#3d51f2afbd83ecf9912bcbb5c4d94e3d2ddaa16f"
- integrity sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==
+"@babel/traverse@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.0.tgz#eb9c561c7360005c592cc645abafe0c3c4548eed"
+ integrity sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==
dependencies:
"@babel/code-frame" "^7.18.6"
- "@babel/generator" "^7.18.10"
+ "@babel/generator" "^7.19.0"
"@babel/helper-environment-visitor" "^7.18.9"
- "@babel/helper-function-name" "^7.18.9"
+ "@babel/helper-function-name" "^7.19.0"
"@babel/helper-hoist-variables" "^7.18.6"
"@babel/helper-split-export-declaration" "^7.18.6"
- "@babel/parser" "^7.18.11"
- "@babel/types" "^7.18.10"
+ "@babel/parser" "^7.19.0"
+ "@babel/types" "^7.19.0"
debug "^4.1.0"
globals "^11.1.0"
-"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9":
- version "7.18.10"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.10.tgz#4908e81b6b339ca7c6b7a555a5fc29446f26dde6"
- integrity sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==
+"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.0.tgz#75f21d73d73dc0351f3368d28db73465f4814600"
+ integrity sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==
dependencies:
"@babel/helper-string-parser" "^7.18.10"
"@babel/helper-validator-identifier" "^7.18.6"
@@ -214,14 +214,14 @@
dependencies:
"@jridgewell/trace-mapping" "0.3.9"
-"@eslint/eslintrc@^1.3.0":
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f"
- integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==
+"@eslint/eslintrc@^1.3.1":
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.1.tgz#de0807bfeffc37b964a7d0400e0c348ce5a2543d"
+ integrity sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ==
dependencies:
ajv "^6.12.4"
debug "^4.3.2"
- espree "^9.3.2"
+ espree "^9.4.0"
globals "^13.15.0"
ignore "^5.2.0"
import-fresh "^3.2.1"
@@ -246,180 +246,181 @@
ethereumjs-util "^7.1.5"
"@ethersproject/abi@^5.6.3":
- version "5.6.4"
- resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.6.4.tgz#f6e01b6ed391a505932698ecc0d9e7a99ee60362"
- integrity sha512-TTeZUlCeIHG6527/2goZA6gW5F8Emoc7MrZDC7hhP84aRGvW3TEdTnZR08Ls88YXM1m2SuK42Osw/jSi3uO8gg==
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449"
+ integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==
dependencies:
- "@ethersproject/address" "^5.6.1"
- "@ethersproject/bignumber" "^5.6.2"
- "@ethersproject/bytes" "^5.6.1"
- "@ethersproject/constants" "^5.6.1"
- "@ethersproject/hash" "^5.6.1"
- "@ethersproject/keccak256" "^5.6.1"
- "@ethersproject/logger" "^5.6.0"
- "@ethersproject/properties" "^5.6.0"
- "@ethersproject/strings" "^5.6.1"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/hash" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
-"@ethersproject/abstract-provider@^5.6.1":
- version "5.6.1"
- resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.6.1.tgz#02ddce150785caf0c77fe036a0ebfcee61878c59"
- integrity sha512-BxlIgogYJtp1FS8Muvj8YfdClk3unZH0vRMVX791Z9INBNT/kuACZ9GzaY1Y4yFq+YSy6/w4gzj3HCRKrK9hsQ==
+"@ethersproject/abstract-provider@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef"
+ integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==
dependencies:
- "@ethersproject/bignumber" "^5.6.2"
- "@ethersproject/bytes" "^5.6.1"
- "@ethersproject/logger" "^5.6.0"
- "@ethersproject/networks" "^5.6.3"
- "@ethersproject/properties" "^5.6.0"
- "@ethersproject/transactions" "^5.6.2"
- "@ethersproject/web" "^5.6.1"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/networks" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/transactions" "^5.7.0"
+ "@ethersproject/web" "^5.7.0"
-"@ethersproject/abstract-signer@^5.6.2":
- version "5.6.2"
- resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.6.2.tgz#491f07fc2cbd5da258f46ec539664713950b0b33"
- integrity sha512-n1r6lttFBG0t2vNiI3HoWaS/KdOt8xyDjzlP2cuevlWLG6EX0OwcKLyG/Kp/cuwNxdy/ous+R/DEMdTUwWQIjQ==
+"@ethersproject/abstract-signer@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2"
+ integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==
dependencies:
- "@ethersproject/abstract-provider" "^5.6.1"
- "@ethersproject/bignumber" "^5.6.2"
- "@ethersproject/bytes" "^5.6.1"
- "@ethersproject/logger" "^5.6.0"
- "@ethersproject/properties" "^5.6.0"
+ "@ethersproject/abstract-provider" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
-"@ethersproject/address@^5.6.1":
- version "5.6.1"
- resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.6.1.tgz#ab57818d9aefee919c5721d28cd31fd95eff413d"
- integrity sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==
+"@ethersproject/address@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37"
+ integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==
dependencies:
- "@ethersproject/bignumber" "^5.6.2"
- "@ethersproject/bytes" "^5.6.1"
- "@ethersproject/keccak256" "^5.6.1"
- "@ethersproject/logger" "^5.6.0"
- "@ethersproject/rlp" "^5.6.1"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/rlp" "^5.7.0"
-"@ethersproject/base64@^5.6.1":
- version "5.6.1"
- resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.6.1.tgz#2c40d8a0310c9d1606c2c37ae3092634b41d87cb"
- integrity sha512-qB76rjop6a0RIYYMiB4Eh/8n+Hxu2NIZm8S/Q7kNo5pmZfXhHGHmS4MinUainiBC54SCyRnwzL+KZjj8zbsSsw==
+"@ethersproject/base64@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c"
+ integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==
dependencies:
- "@ethersproject/bytes" "^5.6.1"
+ "@ethersproject/bytes" "^5.7.0"
-"@ethersproject/bignumber@^5.6.2":
- version "5.6.2"
- resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.6.2.tgz#72a0717d6163fab44c47bcc82e0c550ac0315d66"
- integrity sha512-v7+EEUbhGqT3XJ9LMPsKvXYHFc8eHxTowFCG/HgJErmq4XHJ2WR7aeyICg3uTOAQ7Icn0GFHAohXEhxQHq4Ubw==
+"@ethersproject/bignumber@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2"
+ integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==
dependencies:
- "@ethersproject/bytes" "^5.6.1"
- "@ethersproject/logger" "^5.6.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
bn.js "^5.2.1"
-"@ethersproject/bytes@^5.6.1":
- version "5.6.1"
- resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.6.1.tgz#24f916e411f82a8a60412344bf4a813b917eefe7"
- integrity sha512-NwQt7cKn5+ZE4uDn+X5RAXLp46E1chXoaMmrxAyA0rblpxz8t58lVkrHXoRIn0lz1joQElQ8410GqhTqMOwc6g==
+"@ethersproject/bytes@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d"
+ integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==
dependencies:
- "@ethersproject/logger" "^5.6.0"
+ "@ethersproject/logger" "^5.7.0"
-"@ethersproject/constants@^5.6.1":
- version "5.6.1"
- resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.6.1.tgz#e2e974cac160dd101cf79fdf879d7d18e8cb1370"
- integrity sha512-QSq9WVnZbxXYFftrjSjZDUshp6/eKp6qrtdBtUCm0QxCV5z1fG/w3kdlcsjMCQuQHUnAclKoK7XpXMezhRDOLg==
+"@ethersproject/constants@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e"
+ integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==
dependencies:
- "@ethersproject/bignumber" "^5.6.2"
+ "@ethersproject/bignumber" "^5.7.0"
-"@ethersproject/hash@^5.6.1":
- version "5.6.1"
- resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.6.1.tgz#224572ea4de257f05b4abf8ae58b03a67e99b0f4"
- integrity sha512-L1xAHurbaxG8VVul4ankNX5HgQ8PNCTrnVXEiFnE9xoRnaUcgfD12tZINtDinSllxPLCtGwguQxJ5E6keE84pA==
+"@ethersproject/hash@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7"
+ integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==
dependencies:
- "@ethersproject/abstract-signer" "^5.6.2"
- "@ethersproject/address" "^5.6.1"
- "@ethersproject/bignumber" "^5.6.2"
- "@ethersproject/bytes" "^5.6.1"
- "@ethersproject/keccak256" "^5.6.1"
- "@ethersproject/logger" "^5.6.0"
- "@ethersproject/properties" "^5.6.0"
- "@ethersproject/strings" "^5.6.1"
+ "@ethersproject/abstract-signer" "^5.7.0"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/base64" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
-"@ethersproject/keccak256@^5.6.1":
- version "5.6.1"
- resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.6.1.tgz#b867167c9b50ba1b1a92bccdd4f2d6bd168a91cc"
- integrity sha512-bB7DQHCTRDooZZdL3lk9wpL0+XuG3XLGHLh3cePnybsO3V0rdCAOQGpn/0R3aODmnTOOkCATJiD2hnL+5bwthA==
+"@ethersproject/keccak256@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a"
+ integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==
dependencies:
- "@ethersproject/bytes" "^5.6.1"
+ "@ethersproject/bytes" "^5.7.0"
js-sha3 "0.8.0"
-"@ethersproject/logger@^5.6.0":
- version "5.6.0"
- resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.6.0.tgz#d7db1bfcc22fd2e4ab574cba0bb6ad779a9a3e7a"
- integrity sha512-BiBWllUROH9w+P21RzoxJKzqoqpkyM1pRnEKG69bulE9TSQD8SAIvTQqIMZmmCO8pUNkgLP1wndX1gKghSpBmg==
+"@ethersproject/logger@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892"
+ integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==
-"@ethersproject/networks@^5.6.3":
- version "5.6.4"
- resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.6.4.tgz#51296d8fec59e9627554f5a8a9c7791248c8dc07"
- integrity sha512-KShHeHPahHI2UlWdtDMn2lJETcbtaJge4k7XSjDR9h79QTd6yQJmv6Cp2ZA4JdqWnhszAOLSuJEd9C0PRw7hSQ==
+"@ethersproject/networks@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.0.tgz#df72a392f1a63a57f87210515695a31a245845ad"
+ integrity sha512-MG6oHSQHd4ebvJrleEQQ4HhVu8Ichr0RDYEfHzsVAVjHNM+w36x9wp9r+hf1JstMXtseXDtkiVoARAG6M959AA==
dependencies:
- "@ethersproject/logger" "^5.6.0"
+ "@ethersproject/logger" "^5.7.0"
-"@ethersproject/properties@^5.6.0":
- version "5.6.0"
- resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.6.0.tgz#38904651713bc6bdd5bdd1b0a4287ecda920fa04"
- integrity sha512-szoOkHskajKePTJSZ46uHUWWkbv7TzP2ypdEK6jGMqJaEt2sb0jCgfBo0gH0m2HBpRixMuJ6TBRaQCF7a9DoCg==
+"@ethersproject/properties@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30"
+ integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==
dependencies:
- "@ethersproject/logger" "^5.6.0"
+ "@ethersproject/logger" "^5.7.0"
-"@ethersproject/rlp@^5.6.1":
- version "5.6.1"
- resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.6.1.tgz#df8311e6f9f24dcb03d59a2bac457a28a4fe2bd8"
- integrity sha512-uYjmcZx+DKlFUk7a5/W9aQVaoEC7+1MOBgNtvNg13+RnuUwT4F0zTovC0tmay5SmRslb29V1B7Y5KCri46WhuQ==
+"@ethersproject/rlp@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304"
+ integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==
dependencies:
- "@ethersproject/bytes" "^5.6.1"
- "@ethersproject/logger" "^5.6.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
-"@ethersproject/signing-key@^5.6.2":
- version "5.6.2"
- resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.6.2.tgz#8a51b111e4d62e5a62aee1da1e088d12de0614a3"
- integrity sha512-jVbu0RuP7EFpw82vHcL+GP35+KaNruVAZM90GxgQnGqB6crhBqW/ozBfFvdeImtmb4qPko0uxXjn8l9jpn0cwQ==
+"@ethersproject/signing-key@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3"
+ integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==
dependencies:
- "@ethersproject/bytes" "^5.6.1"
- "@ethersproject/logger" "^5.6.0"
- "@ethersproject/properties" "^5.6.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
bn.js "^5.2.1"
elliptic "6.5.4"
hash.js "1.1.7"
-"@ethersproject/strings@^5.6.1":
- version "5.6.1"
- resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.6.1.tgz#dbc1b7f901db822b5cafd4ebf01ca93c373f8952"
- integrity sha512-2X1Lgk6Jyfg26MUnsHiT456U9ijxKUybz8IM1Vih+NJxYtXhmvKBcHOmvGqpFSVJ0nQ4ZCoIViR8XlRw1v/+Cw==
+"@ethersproject/strings@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2"
+ integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==
dependencies:
- "@ethersproject/bytes" "^5.6.1"
- "@ethersproject/constants" "^5.6.1"
- "@ethersproject/logger" "^5.6.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
-"@ethersproject/transactions@^5.6.2":
- version "5.6.2"
- resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.6.2.tgz#793a774c01ced9fe7073985bb95a4b4e57a6370b"
- integrity sha512-BuV63IRPHmJvthNkkt9G70Ullx6AcM+SDc+a8Aw/8Yew6YwT51TcBKEp1P4oOQ/bP25I18JJr7rcFRgFtU9B2Q==
+"@ethersproject/transactions@^5.6.2", "@ethersproject/transactions@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b"
+ integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==
dependencies:
- "@ethersproject/address" "^5.6.1"
- "@ethersproject/bignumber" "^5.6.2"
- "@ethersproject/bytes" "^5.6.1"
- "@ethersproject/constants" "^5.6.1"
- "@ethersproject/keccak256" "^5.6.1"
- "@ethersproject/logger" "^5.6.0"
- "@ethersproject/properties" "^5.6.0"
- "@ethersproject/rlp" "^5.6.1"
- "@ethersproject/signing-key" "^5.6.2"
+ "@ethersproject/address" "^5.7.0"
+ "@ethersproject/bignumber" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/constants" "^5.7.0"
+ "@ethersproject/keccak256" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/rlp" "^5.7.0"
+ "@ethersproject/signing-key" "^5.7.0"
-"@ethersproject/web@^5.6.1":
- version "5.6.1"
- resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.6.1.tgz#6e2bd3ebadd033e6fe57d072db2b69ad2c9bdf5d"
- integrity sha512-/vSyzaQlNXkO1WV+RneYKqCJwualcUdx/Z3gseVovZP0wIlOFcCE1hkRhKBH8ImKbGQbMl9EAAyJFrJu7V0aqA==
+"@ethersproject/web@^5.7.0":
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.0.tgz#40850c05260edad8b54827923bbad23d96aac0bc"
+ integrity sha512-ApHcbbj+muRASVDSCl/tgxaH2LBkRMEYfLOLVa0COipx0+nlu0QKet7U2lEg0vdkh8XRSLf2nd1f1Uk9SrVSGA==
dependencies:
- "@ethersproject/base64" "^5.6.1"
- "@ethersproject/bytes" "^5.6.1"
- "@ethersproject/logger" "^5.6.0"
- "@ethersproject/properties" "^5.6.0"
- "@ethersproject/strings" "^5.6.1"
+ "@ethersproject/base64" "^5.7.0"
+ "@ethersproject/bytes" "^5.7.0"
+ "@ethersproject/logger" "^5.7.0"
+ "@ethersproject/properties" "^5.7.0"
+ "@ethersproject/strings" "^5.7.0"
"@humanwhocodes/config-array@^0.10.4":
version "0.10.4"
@@ -435,6 +436,11 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d"
integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==
+"@humanwhocodes/module-importer@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
+ integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
+
"@humanwhocodes/object-schema@^1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
@@ -597,31 +603,22 @@
rxjs "^7.5.6"
"@polkadot/keyring@^10.1.4":
- version "10.1.4"
- resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-10.1.4.tgz#7c60002cb442d2a160ee215b21c1319e85d97eaf"
- integrity sha512-dCMejp5heZwKSFeO+1vCHFoo1h1KgNvu4AaKQdNxpyr/3eCINrCFI74/qT9XGypblxd61caOpJcMl8B1R/UWFA==
+ version "10.1.7"
+ resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-10.1.7.tgz#d51be1dc5807c961889847d8f0e10e4bbdd19d3f"
+ integrity sha512-lArwaAS3hDs+HHupDIC4r2mFaAfmNQV2YzwL2wM5zhOqB2RugN03BFrgwNll0y9/Bg8rYDqM3Y5BvVMzgMZ6XA==
dependencies:
"@babel/runtime" "^7.18.9"
- "@polkadot/util" "10.1.4"
- "@polkadot/util-crypto" "10.1.4"
+ "@polkadot/util" "10.1.7"
+ "@polkadot/util-crypto" "10.1.7"
-"@polkadot/networks@10.1.1":
- version "10.1.1"
- resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-10.1.1.tgz#d3deeff5c4cfad8c1eec85732351d80d1b2d0934"
- integrity sha512-upM8r0mrsCVA+vPVbJUjtnkAfdleBMHB+Fbxvy3xtbK1IFpzQTUhSOQb6lBnBAPBFGyxMtQ3TytnInckAdYZeg==
+"@polkadot/networks@10.1.7", "@polkadot/networks@^10.1.4":
+ version "10.1.7"
+ resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-10.1.7.tgz#33b38d70409e2daf0990ef18ff150c6718ffb700"
+ integrity sha512-ol864SZ/GwAF72GQOPRy+Y9r6NtgJJjMBlDLESvV5VK64eEB0MRSSyiOdd7y/4SumR9crrrNimx3ynACFgxZ8A==
dependencies:
"@babel/runtime" "^7.18.9"
- "@polkadot/util" "10.1.1"
- "@substrate/ss58-registry" "^1.24.0"
-
-"@polkadot/networks@10.1.4", "@polkadot/networks@^10.1.4":
- version "10.1.4"
- resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-10.1.4.tgz#d8b375aad8f858f611165d8288eb5eab7275ca24"
- integrity sha512-5wMwqD+DeVMh29OZZBVkA4DQE9EBsUj5FjmUS2CloA8RzE6SV0qL34zhTwOdq95KJV1OoDbp9aGjCBqhEuozKw==
- dependencies:
- "@babel/runtime" "^7.18.9"
- "@polkadot/util" "10.1.4"
- "@substrate/ss58-registry" "^1.25.0"
+ "@polkadot/util" "10.1.7"
+ "@substrate/ss58-registry" "^1.28.0"
"@polkadot/rpc-augment@9.2.2":
version "9.2.2"
@@ -758,64 +755,34 @@
"@polkadot/util-crypto" "^10.1.4"
rxjs "^7.5.6"
-"@polkadot/util-crypto@10.1.1":
- version "10.1.1"
- resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-10.1.1.tgz#c6e16e626e55402fdb44c8bb20ce4a9d7c50b9db"
- integrity sha512-R0V++xXbL2pvnCFIuXnKc/TlNhBkyxcno1u8rmjYNuH9S5GOmi2jY/8cNhbrwk6wafBsi+xMPHrEbUnduk82Ag==
+"@polkadot/util-crypto@10.1.7", "@polkadot/util-crypto@^10.1.4":
+ version "10.1.7"
+ resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-10.1.7.tgz#fe5ea006bf23ae19319f3ac9236905a984a65e2f"
+ integrity sha512-zGmSU7a0wdWfpDtfc+Q7fUuW+extu9o1Uh4JpkuwwZ/dxmyW5xlfqVsIScM1pdPyjJsyamX8KwsKiVsW4slasg==
dependencies:
"@babel/runtime" "^7.18.9"
"@noble/hashes" "1.1.2"
"@noble/secp256k1" "1.6.3"
- "@polkadot/networks" "10.1.1"
- "@polkadot/util" "10.1.1"
+ "@polkadot/networks" "10.1.7"
+ "@polkadot/util" "10.1.7"
"@polkadot/wasm-crypto" "^6.3.1"
- "@polkadot/x-bigint" "10.1.1"
- "@polkadot/x-randomvalues" "10.1.1"
- "@scure/base" "1.1.1"
- ed2curve "^0.3.0"
- tweetnacl "^1.0.3"
-
-"@polkadot/util-crypto@10.1.4", "@polkadot/util-crypto@^10.1.4":
- version "10.1.4"
- resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-10.1.4.tgz#1d65a9b3d979f1cb078636a413cdf664db760a8b"
- integrity sha512-6rdUwCdbwmQ0PBWBNYh55RsXAcFjhco/TGLuM7GJ7YufrN9qqv1sr40HlneLbtpiZnfukZ3q/qOpj0h7Hrw2JQ==
- dependencies:
- "@babel/runtime" "^7.18.9"
- "@noble/hashes" "1.1.2"
- "@noble/secp256k1" "1.6.3"
- "@polkadot/networks" "10.1.4"
- "@polkadot/util" "10.1.4"
- "@polkadot/wasm-crypto" "^6.3.1"
- "@polkadot/x-bigint" "10.1.4"
- "@polkadot/x-randomvalues" "10.1.4"
+ "@polkadot/x-bigint" "10.1.7"
+ "@polkadot/x-randomvalues" "10.1.7"
"@scure/base" "1.1.1"
ed2curve "^0.3.0"
tweetnacl "^1.0.3"
-"@polkadot/util@10.1.1":
- version "10.1.1"
- resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-10.1.1.tgz#5aa20eac03806e70dc21e618a7f8cd767dac0fd0"
- integrity sha512-/g0sEqOOXfiNmQnWcFK3H1+wKBjbJEfGj6lTmbQ0xnL4TS5mFFQ7ZZEvxD60EkoXVMuCmSSh9E54goNLzh+Zyg==
- dependencies:
- "@babel/runtime" "^7.18.9"
- "@polkadot/x-bigint" "10.1.1"
- "@polkadot/x-global" "10.1.1"
- "@polkadot/x-textdecoder" "10.1.1"
- "@polkadot/x-textencoder" "10.1.1"
- "@types/bn.js" "^5.1.0"
- bn.js "^5.2.1"
-
-"@polkadot/util@10.1.4", "@polkadot/util@^10.1.4":
- version "10.1.4"
- resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-10.1.4.tgz#29654dd52d5028fd9ca175e9cebad605fa79396c"
- integrity sha512-MHz1UxYXuV+XxPl+GR++yOUE0OCiVd+eJBqLgpjpVJNRkudbAmfGAbB2TNR0+76M0fevIeHj4DGEd0gY6vqKLw==
+"@polkadot/util@10.1.7", "@polkadot/util@^10.1.4":
+ version "10.1.7"
+ resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-10.1.7.tgz#c54ca2a5b29cb834b40d8a876baefa3a0efb93af"
+ integrity sha512-s7gDLdNb4HUpoe3faXwoO6HwiUp8pi66voYKiUYRh1kEtW1o9vGBgyZPHPGC/FBgILzTJKii/9XxnSex60zBTA==
dependencies:
"@babel/runtime" "^7.18.9"
- "@polkadot/x-bigint" "10.1.4"
- "@polkadot/x-global" "10.1.4"
- "@polkadot/x-textdecoder" "10.1.4"
- "@polkadot/x-textencoder" "10.1.4"
- "@types/bn.js" "^5.1.0"
+ "@polkadot/x-bigint" "10.1.7"
+ "@polkadot/x-global" "10.1.7"
+ "@polkadot/x-textdecoder" "10.1.7"
+ "@polkadot/x-textencoder" "10.1.7"
+ "@types/bn.js" "^5.1.1"
bn.js "^5.2.1"
"@polkadot/wasm-bridge@6.3.1":
@@ -869,101 +836,62 @@
dependencies:
"@babel/runtime" "^7.18.9"
-"@polkadot/x-bigint@10.1.1":
- version "10.1.1"
- resolved "https://registry.yarnpkg.com/@polkadot/x-bigint/-/x-bigint-10.1.1.tgz#c084cfdfe48633da07423f4d9916563882947563"
- integrity sha512-YNYN64N4icKyqiDIw0tcGyWwz3g/282Kk0ozfcA5TM0wGRe2BwmoB4gYrZ7pJDxvsHnRPR6Dw0r9Xxh8DNIzHQ==
+"@polkadot/x-bigint@10.1.7", "@polkadot/x-bigint@^10.1.4":
+ version "10.1.7"
+ resolved "https://registry.yarnpkg.com/@polkadot/x-bigint/-/x-bigint-10.1.7.tgz#1338689476ffdbb9f9cb243df1954ae8186134b9"
+ integrity sha512-uaClHpI6cnDumIfejUKvNTkB43JleEb0V6OIufDKJ/e1aCLE3f/Ws9ggwL8ea05lQP5k5xqOzbPdizi/UvrgKQ==
dependencies:
"@babel/runtime" "^7.18.9"
- "@polkadot/x-global" "10.1.1"
-
-"@polkadot/x-bigint@10.1.4", "@polkadot/x-bigint@^10.1.4":
- version "10.1.4"
- resolved "https://registry.yarnpkg.com/@polkadot/x-bigint/-/x-bigint-10.1.4.tgz#a084a9d2f80f25ffd529faafdf95cd6c3044ef74"
- integrity sha512-qgLetTukFhkxNxNcUWMmnrfE9bp4TNbrqNoVBVH7wqSuEVpDPITBXsQ/78LbaaZGWD80Ew0wGxcZ/rqX+dLVUA==
- dependencies:
- "@babel/runtime" "^7.18.9"
- "@polkadot/x-global" "10.1.4"
+ "@polkadot/x-global" "10.1.7"
"@polkadot/x-fetch@^10.1.4":
- version "10.1.4"
- resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-10.1.4.tgz#72db88007c74f3aee47f72091a33d553f7ca241a"
- integrity sha512-hVhLpOvx+ys6klkqWJnINi9FU/JcDnc+6cyU9fa+Dum3mqO1XnngOYDO9mpf5HODIwrFNFmohll9diRP+TW0yQ==
+ version "10.1.7"
+ resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-10.1.7.tgz#1b76051a495563403a20ef235a8558c6d91b11a6"
+ integrity sha512-NL+xrlqUoCLwCIAvQLwOA189gSUgeSGOFjCmZ9uMkBqf35KXeZoHWse6YaoseTSlnAal3dQOGbXnYWZ4Ck2OSA==
dependencies:
"@babel/runtime" "^7.18.9"
- "@polkadot/x-global" "10.1.4"
+ "@polkadot/x-global" "10.1.7"
"@types/node-fetch" "^2.6.2"
node-fetch "^3.2.10"
-"@polkadot/x-global@10.1.1":
- version "10.1.1"
- resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-10.1.1.tgz#d0d90ef71fd94f59605e8c73dcd1aa3e3dd4fc37"
- integrity sha512-wB3rZTTNN14umLSfR2GLL0dJrlGM1YRUNw7XvbA+3B8jxGCIOmjSyAkdZBeiCxg2XIbJD3EkB0hBhga2mNuS6g==
+"@polkadot/x-global@10.1.7", "@polkadot/x-global@^10.1.4":
+ version "10.1.7"
+ resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-10.1.7.tgz#91a472ac2f83fd0858dcd0df528844a5b650790e"
+ integrity sha512-k2ZUZyBVgDnP/Ysxapa0mthn63j6gsN2V0kZejEQPyOfCHtQQkse3jFvAWdslpWoR8j2k8SN5O6reHc0F4f7mA==
dependencies:
"@babel/runtime" "^7.18.9"
-"@polkadot/x-global@10.1.4", "@polkadot/x-global@^10.1.4":
- version "10.1.4"
- resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-10.1.4.tgz#657f7054fe07a7c027b4d18fcfa3438d2ffaef07"
- integrity sha512-67f53H872wHvmjmL96DvhC3dG7gKRG1ghEbHXeFIGwkix+9zGEMV9krYW1+OAvGAuCQZqUIUGiJ7lad4Zjb7wQ==
+"@polkadot/x-randomvalues@10.1.7":
+ version "10.1.7"
+ resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-10.1.7.tgz#d537f1f7bf3fb03e6c08ae6e6ac36e069c1f9844"
+ integrity sha512-3er4UYOlozLGgFYWwcbmcFslmO8m82u4cAGR4AaEag0VdV7jLO/M5lTmivT/3rtLSww6sjkEfr522GM2Q5lmFg==
dependencies:
"@babel/runtime" "^7.18.9"
+ "@polkadot/x-global" "10.1.7"
-"@polkadot/x-randomvalues@10.1.1":
- version "10.1.1"
- resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-10.1.1.tgz#3b1f590e6641e322e3a28bb4f17f0a53005d9ada"
- integrity sha512-opVFNEnzCir7cWsFfyDqNlrGazkpjnL+JpkxE/b9WmSco6y0IUzn/Q7rL3EaBzBEvxY0/J8KeSGGs3W+mf6tBQ==
+"@polkadot/x-textdecoder@10.1.7":
+ version "10.1.7"
+ resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-10.1.7.tgz#1dd4e6141b1669acdd321a4da1fc6fdc271b7908"
+ integrity sha512-iAFOHludmZFOyVL8sQFv4TDqbcqQU5gwwYv74duTA+WQBgbSITJrBahSCV/rXOjUqds9pzQO3qBFzziznNnkiQ==
dependencies:
"@babel/runtime" "^7.18.9"
- "@polkadot/x-global" "10.1.1"
+ "@polkadot/x-global" "10.1.7"
-"@polkadot/x-randomvalues@10.1.4":
- version "10.1.4"
- resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-10.1.4.tgz#de337a046826223081697e6fc1991c547f685787"
- integrity sha512-sfYz3GmyG739anj07Y+8PUX+95upO1zlsADAEfK1w1mMpTw97xEoMZf66CduAQOe43gEwQXc/JuKq794C/Hr7Q==
+"@polkadot/x-textencoder@10.1.7":
+ version "10.1.7"
+ resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-10.1.7.tgz#b208601f33b936c7a059f126dbb6b26a87f45864"
+ integrity sha512-GzjaWZDbgzZ0IQT60xuZ7cZ0wnlNVYMqpfI9KvBc58X9dPI3TIMwzbXDVzZzpjY1SAqJGs4hJse9HMWZazfhew==
dependencies:
"@babel/runtime" "^7.18.9"
- "@polkadot/x-global" "10.1.4"
-
-"@polkadot/x-textdecoder@10.1.1":
- version "10.1.1"
- resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-10.1.1.tgz#536d0093749fcc14a60d4ae29c35f699dea7e651"
- integrity sha512-a52ah/sUS+aGZcCCL7BhrytAeV/7kiqu1zbuCoZtIzxP6x34a2vcic3bLPoyynLcX2ruzvLKFhJDGOJ4Bq5lcA==
- dependencies:
- "@babel/runtime" "^7.18.9"
- "@polkadot/x-global" "10.1.1"
-
-"@polkadot/x-textdecoder@10.1.4":
- version "10.1.4"
- resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-10.1.4.tgz#d85028f6fcd00adc1e3581ab97668a61299270f9"
- integrity sha512-B8XcAmJLnuppSr4RUNPevh5MH3tWZBwBR0wUsSdIyiGXuncgnkj9jmpbGLgV1tSn+BGxX3SNsRho3/4CNmndWQ==
- dependencies:
- "@babel/runtime" "^7.18.9"
- "@polkadot/x-global" "10.1.4"
-
-"@polkadot/x-textencoder@10.1.1":
- version "10.1.1"
- resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-10.1.1.tgz#c1a86b3d0fe0ca65d30c8ce5c6f75c4035e95847"
- integrity sha512-prTzUXXW9OxFyf17EwGSBxe2GvVFG60cmKV8goC50nghhNMl1y0GdGpvKNQTFG6hIk5fIon9/pBpWsas4iAf+Q==
- dependencies:
- "@babel/runtime" "^7.18.9"
- "@polkadot/x-global" "10.1.1"
-
-"@polkadot/x-textencoder@10.1.4":
- version "10.1.4"
- resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-10.1.4.tgz#253e828bb571eb2a92a8377acd57d9bfcbe52fe8"
- integrity sha512-vDpo0rVV4jBmr0L2tCZPZzxmzV2vZhpH1Dw9H7MpmZSPePz4ZF+o4RBJz/ocwQh3+1qV1SKQm7+fj4lPwUZdEw==
- dependencies:
- "@babel/runtime" "^7.18.9"
- "@polkadot/x-global" "10.1.4"
+ "@polkadot/x-global" "10.1.7"
"@polkadot/x-ws@^10.1.4":
- version "10.1.4"
- resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-10.1.4.tgz#b3fa515598bc6f8e85d92754d5f1c4be19ca44a1"
- integrity sha512-hi7hBRRCLlHgqVW2p5TkoJuTxV7sVprl+aAnmcIpPU4J8Ai6PKQvXR+fLK01T8moBYmH5ztHrBWvY/XRzmQ8Vg==
+ version "10.1.7"
+ resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-10.1.7.tgz#b1fbfe3e16fa809f35f24ef47fde145b018d8cdc"
+ integrity sha512-aNkotxHx3qPVjiItD9lbNONs4GNzqeeZ98wHtCjd9JWl/g+xNkOVF3xQ8++1qSHPBEYSwKh9URjQH2+CD2XlvQ==
dependencies:
"@babel/runtime" "^7.18.9"
- "@polkadot/x-global" "10.1.4"
+ "@polkadot/x-global" "10.1.7"
"@types/websocket" "^1.0.5"
websocket "^1.0.34"
@@ -972,7 +900,7 @@
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938"
integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==
-"@sindresorhus/is@^4.6.0":
+"@sindresorhus/is@^4.0.0", "@sindresorhus/is@^4.6.0":
version "4.6.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f"
integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==
@@ -999,10 +927,17 @@
pako "^2.0.4"
websocket "^1.0.32"
-"@substrate/ss58-registry@^1.24.0", "@substrate/ss58-registry@^1.25.0":
- version "1.25.0"
- resolved "https://registry.yarnpkg.com/@substrate/ss58-registry/-/ss58-registry-1.25.0.tgz#0fcd8c9c0e53963a88fbed41f2cbd8a1a5c74cde"
- integrity sha512-LmCH4QJRdHaeLsLTPSgJaXguMoIW+Ig9fA9LRPpeya9HefVAJ7gZuUYinldv+QmX7evNm5CL0rspNUS8l1DvXg==
+"@substrate/ss58-registry@^1.28.0":
+ version "1.29.0"
+ resolved "https://registry.yarnpkg.com/@substrate/ss58-registry/-/ss58-registry-1.29.0.tgz#0dea078271b5318c5eff7176e1df1f9b2c27e43f"
+ integrity sha512-KTqwZgTjtWPhCAUJJx9qswP/p9cRKUU9GOHYUDKNdISFDiFafWmpI54JHfYLkgjvkSKEUgRZnvLpe0LMF1fXvw==
+
+"@szmarczak/http-timer@^4.0.5":
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807"
+ integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==
+ dependencies:
+ defer-to-connect "^2.0.0"
"@szmarczak/http-timer@^5.0.1":
version "5.0.1"
@@ -1031,14 +966,14 @@
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e"
integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==
-"@types/bn.js@^5.1.0":
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68"
- integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==
+"@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1":
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682"
+ integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==
dependencies:
"@types/node" "*"
-"@types/cacheable-request@^6.0.2":
+"@types/cacheable-request@^6.0.1", "@types/cacheable-request@^6.0.2":
version "6.0.2"
resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.2.tgz#c324da0197de0a98a2312156536ae262429ff6b9"
integrity sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==
@@ -1096,11 +1031,6 @@
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812"
integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==
-
-"@types/json-buffer@~3.0.0":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@types/json-buffer/-/json-buffer-3.0.0.tgz#85c1ff0f0948fc159810d4b5be35bf8c20875f64"
- integrity sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ==
"@types/json-schema@^7.0.9":
version "7.0.11"
@@ -1128,9 +1058,9 @@
form-data "^3.0.0"
"@types/node@*":
- version "18.7.5"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.5.tgz#f1c1d4b7d8231c0278962347163656f9c36f3e83"
- integrity sha512-NcKK6Ts+9LqdHJaW6HQmgr7dT/i3GOHG+pt6BiWv++5SnjtRd4NXeiuN2kA153SjhXPR/AhHIPHPbrsbpUVOww==
+ version "18.7.16"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.16.tgz#0eb3cce1e37c79619943d2fd903919fc30850601"
+ integrity sha512-EQHhixfu+mkqHMZl1R2Ovuvn47PUw18azMJOTwSZr9/fhzHNGXAJ0ma0dayRVchprpCj0Kc1K1xKoWaATWF1qg==
"@types/node@^12.12.6":
version "12.20.55"
@@ -1171,13 +1101,13 @@
"@types/node" "*"
"@typescript-eslint/eslint-plugin@^5.26.0":
- version "5.33.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.1.tgz#c0a480d05211660221eda963cc844732fe9b1714"
- integrity sha512-S1iZIxrTvKkU3+m63YUOxYPKaP+yWDQrdhxTglVDVEVBf+aCSw85+BmJnyUaQQsk5TXFG/LpBu9fa+LrAQ91fQ==
+ version "5.36.2"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.36.2.tgz#6df092a20e0f9ec748b27f293a12cb39d0c1fe4d"
+ integrity sha512-OwwR8LRwSnI98tdc2z7mJYgY60gf7I9ZfGjN5EjCwwns9bdTuQfAXcsjSB2wSQ/TVNYSGKf4kzVXbNGaZvwiXw==
dependencies:
- "@typescript-eslint/scope-manager" "5.33.1"
- "@typescript-eslint/type-utils" "5.33.1"
- "@typescript-eslint/utils" "5.33.1"
+ "@typescript-eslint/scope-manager" "5.36.2"
+ "@typescript-eslint/type-utils" "5.36.2"
+ "@typescript-eslint/utils" "5.36.2"
debug "^4.3.4"
functional-red-black-tree "^1.0.1"
ignore "^5.2.0"
@@ -1186,68 +1116,69 @@
tsutils "^3.21.0"
"@typescript-eslint/parser@^5.26.0":
- version "5.33.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.33.1.tgz#e4b253105b4d2a4362cfaa4e184e2d226c440ff3"
- integrity sha512-IgLLtW7FOzoDlmaMoXdxG8HOCByTBXrB1V2ZQYSEV1ggMmJfAkMWTwUjjzagS6OkfpySyhKFkBw7A9jYmcHpZA==
+ version "5.36.2"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.36.2.tgz#3ddf323d3ac85a25295a55fcb9c7a49ab4680ddd"
+ integrity sha512-qS/Kb0yzy8sR0idFspI9Z6+t7mqk/oRjnAYfewG+VN73opAUvmYL3oPIMmgOX6CnQS6gmVIXGshlb5RY/R22pA==
dependencies:
- "@typescript-eslint/scope-manager" "5.33.1"
- "@typescript-eslint/types" "5.33.1"
- "@typescript-eslint/typescript-estree" "5.33.1"
+ "@typescript-eslint/scope-manager" "5.36.2"
+ "@typescript-eslint/types" "5.36.2"
+ "@typescript-eslint/typescript-estree" "5.36.2"
debug "^4.3.4"
-"@typescript-eslint/scope-manager@5.33.1":
- version "5.33.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.33.1.tgz#8d31553e1b874210018ca069b3d192c6d23bc493"
- integrity sha512-8ibcZSqy4c5m69QpzJn8XQq9NnqAToC8OdH/W6IXPXv83vRyEDPYLdjAlUx8h/rbusq6MkW4YdQzURGOqsn3CA==
+"@typescript-eslint/scope-manager@5.36.2":
+ version "5.36.2"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.36.2.tgz#a75eb588a3879ae659514780831370642505d1cd"
+ integrity sha512-cNNP51L8SkIFSfce8B1NSUBTJTu2Ts4nWeWbFrdaqjmn9yKrAaJUBHkyTZc0cL06OFHpb+JZq5AUHROS398Orw==
dependencies:
- "@typescript-eslint/types" "5.33.1"
- "@typescript-eslint/visitor-keys" "5.33.1"
+ "@typescript-eslint/types" "5.36.2"
+ "@typescript-eslint/visitor-keys" "5.36.2"
-"@typescript-eslint/type-utils@5.33.1":
- version "5.33.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.33.1.tgz#1a14e94650a0ae39f6e3b77478baff002cec4367"
- integrity sha512-X3pGsJsD8OiqhNa5fim41YtlnyiWMF/eKsEZGsHID2HcDqeSC5yr/uLOeph8rNF2/utwuI0IQoAK3fpoxcLl2g==
+"@typescript-eslint/type-utils@5.36.2":
+ version "5.36.2"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.36.2.tgz#752373f4babf05e993adf2cd543a763632826391"
+ integrity sha512-rPQtS5rfijUWLouhy6UmyNquKDPhQjKsaKH0WnY6hl/07lasj8gPaH2UD8xWkePn6SC+jW2i9c2DZVDnL+Dokw==
dependencies:
- "@typescript-eslint/utils" "5.33.1"
+ "@typescript-eslint/typescript-estree" "5.36.2"
+ "@typescript-eslint/utils" "5.36.2"
debug "^4.3.4"
tsutils "^3.21.0"
-"@typescript-eslint/types@5.33.1":
- version "5.33.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.33.1.tgz#3faef41793d527a519e19ab2747c12d6f3741ff7"
- integrity sha512-7K6MoQPQh6WVEkMrMW5QOA5FO+BOwzHSNd0j3+BlBwd6vtzfZceJ8xJ7Um2XDi/O3umS8/qDX6jdy2i7CijkwQ==
+"@typescript-eslint/types@5.36.2":
+ version "5.36.2"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.36.2.tgz#a5066e500ebcfcee36694186ccc57b955c05faf9"
+ integrity sha512-9OJSvvwuF1L5eS2EQgFUbECb99F0mwq501w0H0EkYULkhFa19Qq7WFbycdw1PexAc929asupbZcgjVIe6OK/XQ==
-"@typescript-eslint/typescript-estree@5.33.1":
- version "5.33.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.1.tgz#a573bd360790afdcba80844e962d8b2031984f34"
- integrity sha512-JOAzJ4pJ+tHzA2pgsWQi4804XisPHOtbvwUyqsuuq8+y5B5GMZs7lI1xDWs6V2d7gE/Ez5bTGojSK12+IIPtXA==
+"@typescript-eslint/typescript-estree@5.36.2":
+ version "5.36.2"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.2.tgz#0c93418b36c53ba0bc34c61fe9405c4d1d8fe560"
+ integrity sha512-8fyH+RfbKc0mTspfuEjlfqA4YywcwQK2Amcf6TDOwaRLg7Vwdu4bZzyvBZp4bjt1RRjQ5MDnOZahxMrt2l5v9w==
dependencies:
- "@typescript-eslint/types" "5.33.1"
- "@typescript-eslint/visitor-keys" "5.33.1"
+ "@typescript-eslint/types" "5.36.2"
+ "@typescript-eslint/visitor-keys" "5.36.2"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
-"@typescript-eslint/utils@5.33.1":
- version "5.33.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.33.1.tgz#171725f924fe1fe82bb776522bb85bc034e88575"
- integrity sha512-uphZjkMaZ4fE8CR4dU7BquOV6u0doeQAr8n6cQenl/poMaIyJtBu8eys5uk6u5HiDH01Mj5lzbJ5SfeDz7oqMQ==
+"@typescript-eslint/utils@5.36.2":
+ version "5.36.2"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.36.2.tgz#b01a76f0ab244404c7aefc340c5015d5ce6da74c"
+ integrity sha512-uNcopWonEITX96v9pefk9DC1bWMdkweeSsewJ6GeC7L6j2t0SJywisgkr9wUTtXk90fi2Eljj90HSHm3OGdGRg==
dependencies:
"@types/json-schema" "^7.0.9"
- "@typescript-eslint/scope-manager" "5.33.1"
- "@typescript-eslint/types" "5.33.1"
- "@typescript-eslint/typescript-estree" "5.33.1"
+ "@typescript-eslint/scope-manager" "5.36.2"
+ "@typescript-eslint/types" "5.36.2"
+ "@typescript-eslint/typescript-estree" "5.36.2"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
-"@typescript-eslint/visitor-keys@5.33.1":
- version "5.33.1"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.1.tgz#0155c7571c8cd08956580b880aea327d5c34a18b"
- integrity sha512-nwIxOK8Z2MPWltLKMLOEZwmfBZReqUdbEoHQXeCpa+sRVARe5twpJGHCB4dk9903Yaf0nMAlGbQfaAH92F60eg==
+"@typescript-eslint/visitor-keys@5.36.2":
+ version "5.36.2"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.2.tgz#2f8f78da0a3bad3320d2ac24965791ac39dace5a"
+ integrity sha512-BtRvSR6dEdrNt7Net2/XDjbYKU5Ml6GqJgVfXT0CxTCJlnIqK7rAGreuWKMT2t8cFUT2Msv5oxw0GMRD7T5J7A==
dependencies:
- "@typescript-eslint/types" "5.33.1"
+ "@typescript-eslint/types" "5.36.2"
eslint-visitor-keys "^3.3.0"
"@ungap/promise-all-settled@1.1.2":
@@ -1621,6 +1552,11 @@
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
+cacheable-lookup@^5.0.3:
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005"
+ integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==
+
cacheable-lookup@^6.0.4:
version "6.1.0"
resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-6.1.0.tgz#0330a543471c61faa4e9035db583aad753b36385"
@@ -1658,9 +1594,9 @@
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001370:
- version "1.0.30001377"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001377.tgz#fa446cef27f25decb0c7420759c9ea17a2221a70"
- integrity sha512-I5XeHI1x/mRSGl96LFOaSk528LA/yZG3m3iQgImGujjO8gotd/DL8QaI1R1h1dg5ATeI2jqPblMpKq4Tr5iKfQ==
+ version "1.0.30001393"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz#1aa161e24fe6af2e2ccda000fc2b94be0b0db356"
+ integrity sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==
caseless@~0.12.0:
version "0.12.0"
@@ -1834,14 +1770,6 @@
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
-compress-brotli@^1.3.8:
- version "1.3.8"
- resolved "https://registry.yarnpkg.com/compress-brotli/-/compress-brotli-1.3.8.tgz#0c0a60c97a989145314ec381e84e26682e7b38db"
- integrity sha512-lVcQsjhxhIXsuupfy9fmZUFtAIdBmXA7EGY6GBdgZ++qkM9zG4YFT8iU7FoBxzryNDMOpD1HIFHUSX4D87oqhQ==
- dependencies:
- "@types/json-buffer" "~3.0.0"
- json-buffer "~3.0.1"
-
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -2016,13 +1944,6 @@
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==
-decompress-response@^3.2.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
- integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==
- dependencies:
- mimic-response "^1.0.0"
-
decompress-response@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
@@ -2042,7 +1963,7 @@
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
-defer-to-connect@^2.0.1:
+defer-to-connect@^2.0.0, defer-to-connect@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587"
integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==
@@ -2115,11 +2036,6 @@
version "0.1.2"
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84"
integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==
-
-duplexer3@^0.1.4:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e"
- integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==
ecc-jsbn@~0.1.1:
version "0.1.2"
@@ -2142,9 +2058,9 @@
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
electron-to-chromium@^1.4.202:
- version "1.4.221"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.221.tgz#1ff8425d257a8bfc8269d552a426993c5b525471"
- integrity sha512-aWg2mYhpxZ6Q6Xvyk7B2ziBca4YqrCDlXzmcD7wuRs65pVEVkMT1u2ifdjpAQais2O2o0rW964ZWWWYRlAL/kw==
+ version "1.4.246"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.246.tgz#802132d1bbd3ff32ce82fcd6a6ed6ab59b4366dc"
+ integrity sha512-/wFCHUE+Hocqr/LlVGsuKLIw4P2lBWwFIDcNMDpJGzyIysQV4aycpoOitAs32FT94EHKnNqDR/CVZJFbXEufJA==
elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.3, elliptic@^6.5.4:
version "6.5.4"
@@ -2177,15 +2093,15 @@
once "^1.4.0"
es-abstract@^1.19.0, es-abstract@^1.19.5, es-abstract@^1.20.0:
- version "1.20.1"
- resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814"
- integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==
+ version "1.20.2"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.2.tgz#8495a07bc56d342a3b8ea3ab01bd986700c2ccb3"
+ integrity sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ==
dependencies:
call-bind "^1.0.2"
es-to-primitive "^1.2.1"
function-bind "^1.1.1"
function.prototype.name "^1.1.5"
- get-intrinsic "^1.1.1"
+ get-intrinsic "^1.1.2"
get-symbol-description "^1.0.0"
has "^1.0.3"
has-property-descriptors "^1.0.0"
@@ -2197,9 +2113,9 @@
is-shared-array-buffer "^1.0.2"
is-string "^1.0.7"
is-weakref "^1.0.2"
- object-inspect "^1.12.0"
+ object-inspect "^1.12.2"
object-keys "^1.1.1"
- object.assign "^4.1.2"
+ object.assign "^4.1.4"
regexp.prototype.flags "^1.4.3"
string.prototype.trimend "^1.0.5"
string.prototype.trimstart "^1.0.5"
@@ -2299,13 +2215,14 @@
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
eslint@^8.16.0:
- version "8.22.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.22.0.tgz#78fcb044196dfa7eef30a9d65944f6f980402c48"
- integrity sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==
+ version "8.23.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.23.0.tgz#a184918d288820179c6041bb3ddcc99ce6eea040"
+ integrity sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==
dependencies:
- "@eslint/eslintrc" "^1.3.0"
+ "@eslint/eslintrc" "^1.3.1"
"@humanwhocodes/config-array" "^0.10.4"
"@humanwhocodes/gitignore-to-minimatch" "^1.0.2"
+ "@humanwhocodes/module-importer" "^1.0.1"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
@@ -2315,7 +2232,7 @@
eslint-scope "^7.1.1"
eslint-utils "^3.0.0"
eslint-visitor-keys "^3.3.0"
- espree "^9.3.3"
+ espree "^9.4.0"
esquery "^1.4.0"
esutils "^2.0.2"
fast-deep-equal "^3.1.3"
@@ -2341,12 +2258,11 @@
strip-ansi "^6.0.1"
strip-json-comments "^3.1.0"
text-table "^0.2.0"
- v8-compile-cache "^2.0.3"
-espree@^9.3.2, espree@^9.3.3:
- version "9.3.3"
- resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.3.tgz#2dd37c4162bb05f433ad3c1a52ddf8a49dc08e9d"
- integrity sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==
+espree@^9.4.0:
+ version "9.4.0"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.0.tgz#cd4bc3d6e9336c433265fc0aa016fc1aaf182f8a"
+ integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==
dependencies:
acorn "^8.8.0"
acorn-jsx "^5.3.2"
@@ -2518,11 +2434,11 @@
vary "~1.1.2"
ext@^1.1.2:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52"
- integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f"
+ integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==
dependencies:
- type "^2.5.0"
+ type "^2.7.2"
extend@~3.0.2:
version "3.0.2"
@@ -2545,9 +2461,9 @@
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-glob@^3.2.9:
- version "3.2.11"
- resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
- integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==
+ version "3.2.12"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
+ integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
dependencies:
"@nodelib/fs.stat" "^2.0.2"
"@nodelib/fs.walk" "^1.2.3"
@@ -2654,9 +2570,9 @@
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
flatted@^3.1.0:
- version "3.2.6"
- resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2"
- integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
+ integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
follow-redirects@^1.12.1:
version "1.15.1"
@@ -2781,7 +2697,7 @@
resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==
-get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
+get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598"
integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==
@@ -2789,11 +2705,6 @@
function-bind "^1.1.1"
has "^1.0.3"
has-symbols "^1.0.3"
-
-get-stream@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
- integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==
get-stream@^5.1.0:
version "5.2.0"
@@ -2911,25 +2822,22 @@
p-cancelable "^3.0.0"
responselike "^2.0.0"
-got@^7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a"
- integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==
+got@^11.8.5:
+ version "11.8.5"
+ resolved "https://registry.yarnpkg.com/got/-/got-11.8.5.tgz#ce77d045136de56e8f024bebb82ea349bc730046"
+ integrity sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==
dependencies:
- decompress-response "^3.2.0"
- duplexer3 "^0.1.4"
- get-stream "^3.0.0"
- is-plain-obj "^1.1.0"
- is-retry-allowed "^1.0.0"
- is-stream "^1.0.0"
- isurl "^1.0.0-alpha5"
- lowercase-keys "^1.0.0"
- p-cancelable "^0.3.0"
- p-timeout "^1.1.1"
- safe-buffer "^5.0.1"
- timed-out "^4.0.0"
- url-parse-lax "^1.0.0"
- url-to-options "^1.0.1"
+ "@sindresorhus/is" "^4.0.0"
+ "@szmarczak/http-timer" "^4.0.5"
+ "@types/cacheable-request" "^6.0.1"
+ "@types/responselike" "^1.0.0"
+ cacheable-lookup "^5.0.3"
+ cacheable-request "^7.0.2"
+ decompress-response "^6.0.0"
+ http2-wrapper "^1.0.0-beta.5.2"
+ lowercase-keys "^2.0.0"
+ p-cancelable "^2.0.0"
+ responselike "^2.0.0"
graceful-fs@^4.1.2, graceful-fs@^4.1.6:
version "4.2.10"
@@ -2988,22 +2896,10 @@
dependencies:
get-intrinsic "^1.1.1"
-has-symbol-support-x@^1.4.1:
- version "1.4.2"
- resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455"
- integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==
-
has-symbols@^1.0.2, has-symbols@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
-
-has-to-string-tag-x@^1.2.0:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d"
- integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==
- dependencies:
- has-symbol-support-x "^1.4.1"
has-tostringtag@^1.0.0:
version "1.0.0"
@@ -3080,6 +2976,14 @@
jsprim "^1.2.2"
sshpk "^1.7.0"
+http2-wrapper@^1.0.0-beta.5.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d"
+ integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==
+ dependencies:
+ quick-lru "^5.1.1"
+ resolve-alpn "^1.0.0"
+
http2-wrapper@^2.1.10:
version "2.1.11"
resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.1.11.tgz#d7c980c7ffb85be3859b6a96c800b2951ae257ef"
@@ -3244,16 +3148,6 @@
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
-
-is-object@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf"
- integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==
-
-is-plain-obj@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
- integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==
is-plain-obj@^2.1.0:
version "2.1.0"
@@ -3274,11 +3168,6 @@
dependencies:
call-bind "^1.0.2"
has-tostringtag "^1.0.0"
-
-is-retry-allowed@^1.0.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4"
- integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==
is-shared-array-buffer@^1.0.2:
version "1.0.2"
@@ -3287,11 +3176,6 @@
dependencies:
call-bind "^1.0.2"
-is-stream@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
- integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==
-
is-string@^1.0.5, is-string@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
@@ -3348,14 +3232,6 @@
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==
-
-isurl@^1.0.0-alpha5:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67"
- integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==
- dependencies:
- has-to-string-tag-x "^1.2.0"
- is-object "^1.0.1"
js-sha3@0.8.0, js-sha3@^0.8.0:
version "0.8.0"
@@ -3389,7 +3265,7 @@
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
-json-buffer@3.0.1, json-buffer@~3.0.1:
+json-buffer@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
@@ -3446,11 +3322,10 @@
readable-stream "^3.6.0"
keyv@^4.0.0:
- version "4.3.3"
- resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.3.3.tgz#6c1bcda6353a9e96fc1b4e1aeb803a6e35090ba9"
- integrity sha512-AcysI17RvakTh8ir03+a3zJr5r0ovnAH/XTXei/4HIv3bL2K/jzvgivLK9UuI/JbU1aJjM3NSAnVvVVd3n+4DQ==
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.0.tgz#dbce9ade79610b6e641a9a65f2f6499ba06b9bc6"
+ integrity sha512-2YvuMsA+jnFGtBareKqgANOEKe1mk3HKiXu2fRmAfyxG0MJAywNhi5ttWA3PMjl4NmpyjZNbFifR2vNjW1znfA==
dependencies:
- compress-brotli "^1.3.8"
json-buffer "3.0.1"
kind-of@^6.0.2:
@@ -3505,11 +3380,6 @@
integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==
dependencies:
get-func-name "^2.0.0"
-
-lowercase-keys@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
- integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
lowercase-keys@^2.0.0:
version "2.0.0"
@@ -3885,7 +3755,7 @@
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
-object-inspect@^1.12.0, object-inspect@^1.9.0:
+object-inspect@^1.12.2, object-inspect@^1.9.0:
version "1.12.2"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
@@ -3895,10 +3765,10 @@
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
-object.assign@^4.1.2:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.3.tgz#d36b7700ddf0019abb6b1df1bb13f6445f79051f"
- integrity sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==
+object.assign@^4.1.4:
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
+ integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.4"
@@ -3943,21 +3813,16 @@
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
-p-cancelable@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa"
- integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==
+p-cancelable@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"
+ integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==
p-cancelable@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050"
integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==
-p-finally@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
- integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==
-
p-limit@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
@@ -3985,13 +3850,6 @@
integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
dependencies:
p-limit "^3.0.2"
-
-p-timeout@^1.1.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386"
- integrity sha512-gb0ryzr+K2qFqFv6qi3khoeqMZF/+ajxQipEF6NteZVnvz9tzdsfAVj3lYtn1gAXvH5lfLwfxEII799gt/mRIA==
- dependencies:
- p-finally "^1.0.0"
p-try@^2.0.0:
version "2.2.0"
@@ -4113,11 +3971,6 @@
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
-
-prepend-http@^1.0.1:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
- integrity sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==
process@^0.11.10:
version "0.11.10"
@@ -4299,7 +4152,7 @@
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
-resolve-alpn@^1.2.0:
+resolve-alpn@^1.0.0, resolve-alpn@^1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9"
integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==
@@ -4641,15 +4494,15 @@
has-flag "^4.0.0"
swarm-js@^0.1.40:
- version "0.1.40"
- resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.40.tgz#b1bc7b6dcc76061f6c772203e004c11997e06b99"
- integrity sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA==
+ version "0.1.42"
+ resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.42.tgz#497995c62df6696f6e22372f457120e43e727979"
+ integrity sha512-BV7c/dVlA3R6ya1lMlSSNPLYrntt0LUq4YMgy3iwpCIc6rZnS5W2wUoctarZ5pXlpKtxDDf9hNziEkcfrxdhqQ==
dependencies:
bluebird "^3.5.0"
buffer "^5.0.5"
eth-lib "^0.1.26"
fs-extra "^4.0.2"
- got "^7.1.0"
+ got "^11.8.5"
mime-types "^2.1.16"
mkdirp-promise "^5.0.1"
mock-fs "^4.1.0"
@@ -4675,7 +4528,7 @@
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
-timed-out@^4.0.0, timed-out@^4.0.1:
+timed-out@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==
@@ -4800,7 +4653,7 @@
resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
-type@^2.5.0:
+type@^2.7.2:
version "2.7.2"
resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0"
integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==
@@ -4813,14 +4666,14 @@
is-typedarray "^1.0.0"
typescript@^4.7.2:
- version "4.7.4"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235"
- integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
+ version "4.8.3"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.3.tgz#d59344522c4bc464a65a730ac695007fdb66dd88"
+ integrity sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==
uglify-js@^3.1.4:
- version "3.16.3"
- resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.16.3.tgz#94c7a63337ee31227a18d03b8a3041c210fd1f1d"
- integrity sha512-uVbFqx9vvLhQg0iBaau9Z75AxWJ8tqM9AV890dIZCLApF4rTcyHwmAvLeEdYRs+BzYWu8Iw81F79ah0EfTXbaw==
+ version "3.17.0"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.0.tgz#55bd6e9d19ce5eef0d5ad17cd1f587d85b180a85"
+ integrity sha512-aTeNPVmgIMPpm1cxXr2Q/nEbvkmV8yq66F3om7X3P/cvOXQ0TMQ64Wk63iyT1gPlmdmGzjGpyLh1f3y8MZWXGg==
ultron@~1.1.0:
version "1.1.1"
@@ -4848,9 +4701,9 @@
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
update-browserslist-db@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38"
- integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.7.tgz#16279639cff1d0f800b14792de43d97df2d11b7d"
+ integrity sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==
dependencies:
escalade "^3.1.1"
picocolors "^1.0.0"
@@ -4862,23 +4715,11 @@
dependencies:
punycode "^2.1.0"
-url-parse-lax@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73"
- integrity sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==
- dependencies:
- prepend-http "^1.0.1"
-
url-set-query@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339"
integrity sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg==
-url-to-options@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9"
- integrity sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A==
-
utf-8-validate@^5.0.2:
version "5.0.9"
resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.9.tgz#ba16a822fbeedff1a58918f2a6a6b36387493ea3"
@@ -4927,11 +4768,6 @@
version "3.0.1"
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
-
-v8-compile-cache@^2.0.3:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
- integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
varint@^5.0.0:
version "5.0.2"