difftreelog
Merge branch 'develop' into CI-40-int-test-parachain-mode-v1
in: master
189 files changed
.docker/Dockerfile-chain-devdiffbeforeafterboth--- a/.docker/Dockerfile-chain-dev
+++ b/.docker/Dockerfile-chain-dev
@@ -11,6 +11,7 @@
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
ARG RUST_TOOLCHAIN=
+ARG POLKADOT_BUILD_BRANCH=
ARG BRANCH=
ARG REPO_URL=
ARG FEATURE=
@@ -25,4 +26,4 @@
RUN cargo build --release
-CMD cargo run --release $FEATURE -- --dev -linfo --unsafe-ws-external --rpc-cors=all --unsafe-rpc-external
+CMD cargo run --release --features=$FEATURE -- --dev -linfo --unsafe-ws-external --rpc-cors=all --unsafe-rpc-external
.docker/Dockerfile-parachaindiffbeforeafterboth--- a/.docker/Dockerfile-parachain
+++ b/.docker/Dockerfile-parachain
@@ -38,9 +38,8 @@
RUN mkdir /unique_parachain
WORKDIR /unique_parachain
-RUN git clone $REPO_URL -b $BRANCH
-RUN cargo build --features=$FEATURE --$PROFILE
-
+RUN git clone $REPO_URL -b $BRANCH && \
+ cargo build --features=$FEATURE --$PROFILE
# ===== BUILD POLKADOT =====
FROM rust-builder as builder-polkadot
.docker/Dockerfile-parachain-upgradediffbeforeafterboth--- /dev/null
+++ b/.docker/Dockerfile-parachain-upgrade
@@ -0,0 +1,110 @@
+# ===== Rust builder =====
+FROM ubuntu:20.04 as rust-builder
+LABEL maintainer="Unique.Network"
+
+ARG RUST_TOOLCHAIN=
+
+ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN
+ENV CARGO_HOME="/cargo-home"
+ENV PATH="/cargo-home/bin:$PATH"
+ENV TZ=UTC
+RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
+
+RUN apt-get update && \
+ apt-get install -y curl cmake pkg-config libssl-dev git clang && \
+ apt-get clean && \
+ rm -r /var/lib/apt/lists/*
+
+RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
+
+RUN rustup toolchain uninstall $(rustup toolchain list) && \
+ rustup toolchain install $RUST_TOOLCHAIN && \
+ rustup default $RUST_TOOLCHAIN && \
+ rustup target list --installed && \
+ rustup show
+RUN rustup target add wasm32-unknown-unknown --toolchain $RUST_TOOLCHAIN
+
+
+#RUN mkdir /unique_parachain
+#WORKDIR /unique_parachain
+
+
+# ===== BUILD current version ======
+FROM rust-builder as builder-unique-current
+
+ARG PROFILE=release
+ARG FEATURE=
+ARG MAINNET_BRANCH=
+ARG REPO_URL=
+
+RUN mkdir /unique_parachain
+WORKDIR /unique_parachain
+
+RUN git clone $REPO_URL -b $MAINNET_BRANCH . && \
+ cargo build --features=$FEATURE --$PROFILE
+
+
+# ===== BUILD target version ======
+FROM rust-builder as builder-unique-target
+
+ARG PROFILE=release
+ARG FEATURE=
+ARG BRANCH=
+ARG REPO_URL=
+
+RUN mkdir /unique_parachain
+WORKDIR /unique_parachain
+
+RUN git clone $REPO_URL -b $BRANCH . && \
+ cargo build --features=$FEATURE --$PROFILE
+
+# ===== BUILD POLKADOT =====
+FROM rust-builder as builder-polkadot
+
+ARG POLKADOT_BUILD_BRANCH=
+ENV POLKADOT_BUILD_BRANCH $POLKADOT_BUILD_BRANCH
+
+RUN mkdir /unique_parachain
+WORKDIR /unique_parachain
+
+RUN git clone -b $POLKADOT_BUILD_BRANCH --depth 1 https://github.com/paritytech/polkadot.git && \
+ cd polkadot && \
+ cargo build --release
+
+# ===== RUN ======
+
+FROM ubuntu:20.04
+
+ARG RUNTIME=
+ENV RUNTIME $RUNTIME
+
+RUN apt-get -y update && \
+ apt-get -y install curl git && \
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash && \
+ export NVM_DIR="$HOME/.nvm" && \
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
+ nvm install v16.16.0 && \
+ nvm use v16.16.0
+
+RUN git clone https://github.com/uniquenetwork/polkadot-launch -b feature/runtime-upgrade-testing
+
+RUN export NVM_DIR="$HOME/.nvm" && \
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
+ cd /polkadot-launch && \
+ npm install --global yarn && \
+ yarn install
+
+RUN echo "$RUNTIME"
+
+COPY --from=builder-unique-current /unique_parachain/target/release/unique-collator /unique-chain/current/release/
+COPY --from=builder-unique-target /unique_parachain/target/release/unique-collator /unique-chain/target/release/
+COPY --from=builder-unique-target /unique_parachain/target/release/wbuild/"$RUNTIME"-runtime/"$RUNTIME"_runtime.compact.compressed.wasm /unique-chain/target/release/wbuild/"$RUNTIME"-runtime/"$RUNTIME"_runtime.compact.compressed.wasm
+
+COPY --from=builder-polkadot /unique_parachain/polkadot/target/release/polkadot /polkadot/target/release/
+COPY --from=builder-polkadot /unique_parachain/polkadot/target/release/wbuild/westend-runtime/westend_runtime.compact.compressed.wasm /polkadot/target/release/wbuild/westend-runtime/westend_runtime.compact.compressed.wasm
+
+
+CMD export NVM_DIR="$HOME/.nvm" && \
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
+ cd /polkadot-launch && \
+ yarn start launch-config.json --test-upgrade-parachains
.docker/docker-compose-forkless.yamldiffbeforeafterboth--- /dev/null
+++ b/.docker/docker-compose-forkless.yaml
@@ -0,0 +1,24 @@
+version: "3.5"
+
+services:
+ node-parachain:
+ build:
+ context: ../
+ dockerfile: .docker/Dockerfile-parachain-upgrade
+ image: node-parachain
+ container_name: node-parachain
+ volumes:
+ - type: bind
+ source: ./launch-config-forkless.json
+ target: /polkadot-launch/launch-config.json
+ read_only: true
+ expose:
+ - 9944
+ - 9933
+ ports:
+ - 127.0.0.1:9944:9944
+ - 127.0.0.1:9933:9933
+ logging:
+ options:
+ max-size: "1m"
+ max-file: "3"
.docker/docker-compose.tmp-forkless.j2diffbeforeafterboth--- /dev/null
+++ b/.docker/docker-compose.tmp-forkless.j2
@@ -0,0 +1,14 @@
+version: "3.5"
+
+services:
+ node-parachain:
+ build:
+ args:
+ - "RUST_TOOLCHAIN={{ RUST_TOOLCHAIN }}"
+ - "BRANCH={{ BRANCH }}"
+ - "REPO_URL={{ REPO_URL }}"
+ - "FEATURE={{ FEATURE }}"
+ - "RUNTIME={{ RUNTIME }}"
+ - "POLKADOT_BUILD_BRANCH={{ POLKADOT_BUILD_BRANCH }}"
+ - "MAINNET_TAG={{ MAINNET_TAG }}"
+ - "MAINNET_BRANCH={{ MAINNET_BRANCH }}"
.docker/docker-compose.tmp.j2diffbeforeafterboth--- a/.docker/docker-compose.tmp.j2
+++ b/.docker/docker-compose.tmp.j2
@@ -10,4 +10,4 @@
- "FEATURE={{ FEATURE }}"
- "POLKADOT_BUILD_BRANCH={{ POLKADOT_BUILD_BRANCH }}"
- command: cargo run --release {{ FEATURE }} -- --dev -linfo --unsafe-ws-external --rpc-cors=all --unsafe-rpc-external
+ command: cargo run --release --features=$FEATURE -- --dev -linfo --unsafe-ws-external --rpc-cors=all --unsafe-rpc-external
.docker/forking/Dockerfile-parachain-live-forkdiffbeforeafterboth--- /dev/null
+++ b/.docker/forking/Dockerfile-parachain-live-fork
@@ -0,0 +1,102 @@
+# ===== Rust builder =====
+FROM ubuntu:20.04 as rust-builder
+LABEL maintainer="Unique.Network"
+
+ARG RUST_TOOLCHAIN=
+
+ENV RUST_TOOLCHAIN $RUST_TOOLCHAIN
+
+ENV CARGO_HOME="/cargo-home"
+ENV PATH="/cargo-home/bin:$PATH"
+ENV TZ=UTC
+RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
+
+RUN apt-get update && \
+ apt-get install -y curl cmake pkg-config libssl-dev git clang && \
+ apt-get clean && \
+ rm -r /var/lib/apt/lists/*
+
+RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain none
+
+RUN rustup toolchain uninstall $(rustup toolchain list) && \
+ rustup toolchain install $RUST_TOOLCHAIN && \
+ rustup default $RUST_TOOLCHAIN && \
+ rustup target list --installed && \
+ rustup show
+RUN rustup target add wasm32-unknown-unknown --toolchain $RUST_TOOLCHAIN
+
+# ===== BUILD target version ======
+FROM rust-builder as builder-unique-target
+
+ARG PROFILE=release
+ARG FEATURE=
+ARG BRANCH=
+ARG REPO_URL=
+
+RUN mkdir /unique_parachain
+WORKDIR /unique_parachain
+
+RUN git clone $REPO_URL -b $BRANCH . && \
+ cargo build --features=$FEATURE --$PROFILE
+
+# ===== BUILD POLKADOT =====
+FROM rust-builder as builder-polkadot
+
+ARG POLKADOT_BUILD_BRANCH=
+ENV POLKADOT_BUILD_BRANCH $POLKADOT_BUILD_BRANCH
+
+RUN mkdir /unique_parachain
+WORKDIR /unique_parachain
+
+RUN git clone -b $POLKADOT_BUILD_BRANCH --depth 1 https://github.com/paritytech/polkadot.git && \
+ cd polkadot && \
+ cargo build --release
+
+# ===== BUILD CHAINQL =====
+FROM rust-builder as builder-chainql
+
+RUN mkdir chainql
+WORKDIR /chainql
+
+RUN git clone --depth 1 https://github.com/CertainLach/chainql.git . && \
+ cargo build --release
+
+# ===== RUN ======
+
+FROM ubuntu:20.04
+
+ARG RUNTIME=
+ENV RUNTIME $RUNTIME
+
+RUN apt-get -y update && \
+ apt-get -y install curl git && \
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash && \
+ export NVM_DIR="$HOME/.nvm" && \
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
+ nvm install v16.16.0 && \
+ nvm use v16.16.0
+
+RUN git clone https://github.com/uniquenetwork/polkadot-launch -b feature/parachain-forking
+
+RUN export NVM_DIR="$HOME/.nvm" && \
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
+ cd /polkadot-launch && \
+ npm install --global yarn && \
+ yarn install
+
+RUN echo "$RUNTIME"
+
+COPY --from=builder-unique-target /unique_parachain/target/release/unique-collator /unique-chain/target/release/
+
+COPY --from=builder-polkadot /unique_parachain/polkadot/target/release/polkadot /polkadot/target/release/
+
+COPY --from=builder-chainql /chainql/target/release/chainql /chainql/target/release/
+
+ARG FORK_FROM=
+ENV FORK_FROM=$FORK_FROM
+CMD export NVM_DIR="$HOME/.nvm" PATH="$PATH:/chainql/target/release" FORK_FROM && \
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \
+ cd /polkadot-launch && \
+ yarn start launch-config.json
+
+
.docker/forking/docker-compose-fork.yamldiffbeforeafterboth--- /dev/null
+++ b/.docker/forking/docker-compose-fork.yaml
@@ -0,0 +1,28 @@
+version: "3.5"
+
+services:
+ parachain-fork:
+ build:
+ context: ./
+ dockerfile: ./Dockerfile-parachain-live-fork
+ image: parachain-fork
+ container_name: parachain-fork
+ volumes:
+ - type: bind
+ source: ./launch-config-fork.json
+ target: /polkadot-launch/launch-config.json
+ read_only: true
+ - type: bind
+ source: ./fork.jsonnet
+ target: /polkadot-launch/fork.jsonnet
+ read_only: true
+ expose:
+ - 9944
+ - 9933
+ ports:
+ - 127.0.0.1:9944:9944
+ - 127.0.0.1:9933:9933
+ logging:
+ options:
+ max-size: "1m"
+ max-file: "3"
.docker/forking/docker-compose.tmp-fork.j2diffbeforeafterboth--- /dev/null
+++ b/.docker/forking/docker-compose.tmp-fork.j2
@@ -0,0 +1,13 @@
+version: "3.5"
+
+services:
+ parachain-fork:
+ build:
+ args:
+ - "RUST_TOOLCHAIN={{ RUST_TOOLCHAIN }}"
+ - "BRANCH={{ BRANCH }}"
+ - "REPO_URL={{ REPO_URL }}"
+ - "FEATURE={{ FEATURE }}"
+ - "RUNTIME={{ RUNTIME }}"
+ - "POLKADOT_BUILD_BRANCH={{ POLKADOT_BUILD_BRANCH }}"
+ - "FORK_FROM={{ FORK_FROM }}"
.docker/forking/fork.jsonnetdiffbeforeafterboth--- /dev/null
+++ b/.docker/forking/fork.jsonnet
@@ -0,0 +1,59 @@
+
+function(rawSpec, forkFrom)
+local sourceChain = cql.chain(forkFrom).latest;
+
+local raw = local sourceRaw = sourceChain._raw._preloadKeys; {
+ [key]: cql.toHex(sourceRaw[key])
+ for key in std.objectFields(sourceRaw)
+ if sourceRaw[key] != null
+};
+
+local
+auraKeys = [
+ // AuraExt.Authorities, we don't have aura pallet enabled for some reason, to refer using cql api
+ '0x3c311d57d4daf52904616cf69648081e5e0621c4869aa60c02be9adcc98a0d1d',
+ // Aura.Authorities
+ '0x57f8dc2f5ab09467896f47300f0424385e0621c4869aa60c02be9adcc98a0d1d',
+],
+
+// Keys, which should be migrated from passed spec, rather than from forked chain
+wantedKeys = [
+ sourceChain.ParachainInfo._key.ParachainId,
+ sourceChain.Sudo._key.Key,
+ sourceChain.System.BlockHash._key['0'],
+ sourceChain.System._key.ParentHash,
+] + auraKeys,
+
+// Keys to remove from original chain
+unwantedPrefixes = [
+ // Aura.CurrentSlot
+ '0x57f8dc2f5ab09467896f47300f04243806155b3cd9a8c9e5e9a23fd5dc13a5ed',
+ // Ensure there will be no panics caused by unexpected kept state
+ sourceChain.ParachainSystem._key.ValidationData,
+ sourceChain.ParachainSystem._key.RelayStateProof,
+ sourceChain.ParachainSystem._key.HostConfiguration,
+ sourceChain.ParachainSystem._key.LastDmqMqcHead,
+ // Part of head
+ sourceChain.System._key.BlockHash,
+ sourceChain.System._key.Number,
+ sourceChain.System._key.Digest,
+] + auraKeys,
+
+cleanupRaw(raw) = {
+ [key]: raw[key]
+ for key in std.objectFields(raw)
+ if std.all(std.map(function(prefix) !std.startsWith(key, prefix), unwantedPrefixes))
+};
+
+local originalRaw = rawSpec.genesis.raw.top;
+local outSpec = rawSpec {
+ genesis+: {
+ raw+: {
+ top: cleanupRaw(raw) {
+ [key]: originalRaw[key]
+ for key in wantedKeys
+ },
+ },
+ },
+};
+outSpec
.docker/forking/launch-config-fork.j2diffbeforeafterboth--- /dev/null
+++ b/.docker/forking/launch-config-fork.j2
@@ -0,0 +1,128 @@
+{
+ "relaychain": {
+ "bin": "/polkadot/target/release/polkadot",
+ "chain": "westend-local",
+ "nodes": [
+ {
+ "name": "alice",
+ "wsPort": 9844,
+ "rpcPort": 9843,
+ "port": 30444,
+ "flags": [
+ "-lparachain::candidate_validation=debug",
+ "-lxcm=trace",
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external"
+ ]
+ },
+ {
+ "name": "bob",
+ "wsPort": 9855,
+ "rpcPort": 9854,
+ "port": 30555,
+ "flags": [
+ "-lparachain::candidate_validation=debug",
+ "-lxcm=trace",
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external"
+ ]
+ },
+ {
+ "name": "charlie",
+ "wsPort": 9866,
+ "rpcPort": 9865,
+ "port": 30666,
+ "flags": [
+ "-lparachain::candidate_validation=debug",
+ "-lxcm=trace",
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external"
+ ]
+ },
+ {
+ "name": "dave",
+ "wsPort": 9877,
+ "rpcPort": 9876,
+ "port": 30777,
+ "flags": [
+ "-lparachain::candidate_validation=debug",
+ "-lxcm=trace",
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external"
+ ]
+ },
+ {
+ "name": "eve",
+ "wsPort": 9888,
+ "rpcPort": 9887,
+ "port": 30888,
+ "flags": [
+ "-lparachain::candidate_validation=debug",
+ "-lxcm=trace",
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external"
+ ]
+ }
+ ],
+ "genesis": {
+ "runtime": {
+ "runtime_genesis_config": {
+ "parachainsConfiguration": {
+ "config": {
+ "validation_upgrade_frequency": 1,
+ "validation_upgrade_delay": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "parachains": [
+ {
+ "bin": "/unique-chain/current/release/unique-collator",
+ "id": "1000",
+ "balance": "1000000000000000000000000",
+ "chainRawInitializer": [
+ "chainql",
+ "--ext-str=FORK_FROM",
+ "--tla-code=rawSpec=import '${rawSpec}'",
+ "--tla-code=forkFrom=std.extVar('FORK_FROM')",
+ "fork.jsonnet"
+ ],
+ "nodes": [
+ {
+ "port": 31200,
+ "wsPort": 9944,
+ "rpcPort": 9933,
+ "name": "alice",
+ "flags": [
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external",
+ "-lxcm=trace"
+ ]
+ },
+ {
+ "port": 31201,
+ "wsPort": 9945,
+ "rpcPort": 9934,
+ "name": "bob",
+ "flags": [
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external",
+ "-lxcm=trace"
+ ]
+ }
+ ]
+ }
+ ],
+ "simpleParachains": [],
+ "hrmpChannels": [],
+ "finalization": false
+}
.docker/launch-config.j2diffbeforeafterboth--- /dev/null
+++ b/.docker/launch-config.j2
@@ -0,0 +1,125 @@
+{
+ "relaychain": {
+ "bin": "/polkadot/target/release/polkadot",
+ "upgradeBin": "/polkadot/target/release/polkadot",
+ "upgradeWasm": "/polkadot/target/release/wbuild/westend-runtime/westend_runtime.compact.compressed.wasm",
+ "chain": "westend-local",
+ "nodes": [
+ {
+ "name": "alice",
+ "wsPort": 9844,
+ "rpcPort": 9843,
+ "port": 30444,
+ "flags": [
+ "-lparachain::candidate_validation=debug",
+ "-lxcm=trace",
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external"
+ ]
+ },
+ {
+ "name": "bob",
+ "wsPort": 9855,
+ "rpcPort": 9854,
+ "port": 30555,
+ "flags": [
+ "-lparachain::candidate_validation=debug",
+ "-lxcm=trace",
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external"
+ ]
+ },
+ {
+ "name": "charlie",
+ "wsPort": 9866,
+ "rpcPort": 9865,
+ "port": 30666,
+ "flags": [
+ "-lparachain::candidate_validation=debug",
+ "-lxcm=trace",
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external"
+ ]
+ },
+ {
+ "name": "dave",
+ "wsPort": 9877,
+ "rpcPort": 9876,
+ "port": 30777,
+ "flags": [
+ "-lparachain::candidate_validation=debug",
+ "-lxcm=trace",
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external"
+ ]
+ },
+ {
+ "name": "eve",
+ "wsPort": 9888,
+ "rpcPort": 9887,
+ "port": 30888,
+ "flags": [
+ "-lparachain::candidate_validation=debug",
+ "-lxcm=trace",
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external"
+ ]
+ }
+ ],
+ "genesis": {
+ "runtime": {
+ "runtime_genesis_config": {
+ "parachainsConfiguration": {
+ "config": {
+ "validation_upgrade_frequency": 1,
+ "validation_upgrade_delay": 1
+ }
+ }
+ }
+ }
+ }
+ },
+ "parachains": [
+ {
+ "bin": "/unique-chain/current/release/unique-collator",
+ "upgradeBin": "/unique-chain/target/release/unique-collator",
+ "upgradeWasm": "/unique-chain/target/release/wbuild/{{ FEATURE }}/{{ RUNTIME }}_runtime.compact.compressed.wasm",
+ "id": "1000",
+ "balance": "1000000000000000000000000",
+ "nodes": [
+ {
+ "port": 31200,
+ "wsPort": 9944,
+ "rpcPort": 9933,
+ "name": "alice",
+ "flags": [
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external",
+ "-lxcm=trace"
+ ]
+ },
+ {
+ "port": 31201,
+ "wsPort": 9945,
+ "rpcPort": 9934,
+ "name": "bob",
+ "flags": [
+ "--rpc-cors=all",
+ "--unsafe-rpc-external",
+ "--unsafe-ws-external",
+ "-lxcm=trace"
+ ]
+ }
+ ]
+ }
+ ],
+ "simpleParachains": [],
+ "hrmpChannels": [],
+ "finalization": false
+}
.dockerignorediffbeforeafterboth--- a/.dockerignore
+++ b/.dockerignore
@@ -1,6 +1,5 @@
.git/
.github/
-.docker/
doc/
target/
tests/
.envdiffbeforeafterboth--- a/.env
+++ b/.env
@@ -5,4 +5,4 @@
UNIQUE_MAINNET_TAG=v924010
KUSAMA_MAINNET_BRANCH=release-v0.9.26
-QUARTZ_MAINNET_TAG=v924012
\ No newline at end of file
+QUARTZ_MAINNET_TAG=quartz-v924012-2
.gitattributesdiffbeforeafterboth--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,3 @@
* text=auto
*.sh text eol=lf
+*.ts linguist-detectable=false
\ No newline at end of file
.github/workflows/fork-update-withdata.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/fork-update-withdata.yml
@@ -0,0 +1,164 @@
+name: Fork Parachain update with data
+
+# 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
+
+ # 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:
+
+ fork-update-withdata:
+ # The type of runner that the job will run on
+ runs-on: self-hosted-ci
+
+ name: Build Container, Spin it Up an test
+
+ 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
+ runtime: opal
+ fork_from_address: wss://eu-ws-opal.unique.network:443
+ - network: Quartz
+ features: quartz-runtime
+ runtime: quartz
+ fork_from_address: wss://eu-ws-quartz.unique.network:443
+ - network: Unique
+ features: unique-runtime
+ runtime: unique
+ fork_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/forking/docker-compose.tmp-fork.j2
+ output_file: .docker/forking/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 }}
+ FEATURE=${{ matrix.features }}
+ RUNTIME=${{ matrix.runtime }}
+ BRANCH=${{ github.head_ref }}
+ FORK_FROM=${{ matrix.fork_from_address }}
+
+ - name: Show build configuration
+ run: cat .docker/forking/docker-compose.${{ matrix.network }}.yml
+
+ - name: Generate launch-config-fork.json
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/forking/launch-config-fork.j2
+ output_file: .docker/forking/launch-config-fork.json
+ variables: |
+ FEATURE=${{ matrix.features }}
+ RUNTIME=${{ matrix.runtime }}
+
+ - name: Show launch-config-fork configuration
+ run: cat .docker/forking/launch-config-fork.json
+
+
+ - name: Build the stack
+ run: docker-compose -f ".docker/forking/docker-compose-fork.yaml" -f ".docker/forking/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 do_docker_logs {
+ docker logs --details parachain-fork 2>&1
+ }
+ function is_started {
+ 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
+ exit 0
+ fi
+ echo "Function is_started: Return 1"
+ return 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
+ exit 1
+ shell: bash
+
+ - name: Collect Docker Logs
+ if: success() || failure()
+ uses: jwalton/gh-docker-logs@v2.2.0
+ with:
+ dest: './fork-parachain-update-withdata-logs.${{ matrix.features }}'
+ images: 'parachain-fork'
+
+ - name: Tar logs
+ if: success() || failure()
+ run: tar cvzf ./fork-parachain-update-withdata-logs.${{ matrix.features }}.tgz ./fork-parachain-update-withdata-logs.${{ matrix.features }}
+
+ - name: Upload logs to GitHub
+ if: success() || failure()
+ uses: actions/upload-artifact@master
+ with:
+ name: fork-parachain-update-withdata-logs.${{ matrix.features }}.tgz
+ path: ./fork-parachain-update-withdata-logs.${{ matrix.features }}.tgz
+
+ - name: Stop running containers
+ if: always() # run this step always
+ run: docker-compose -f ".docker/forking/docker-compose-fork.yaml" -f ".docker/forking/docker-compose.${{ matrix.network }}.yml" down
.github/workflows/forkless-update-nodata.ymldiffbeforeafterboth--- /dev/null
+++ b/.github/workflows/forkless-update-nodata.yml
@@ -0,0 +1,200 @@
+name: Forkless Parachain update with no data
+
+# 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
+
+ # 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: 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
+
+ name: Build Container, Spin it Up an test
+
+ 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.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.json
+ uses: cuchi/jinja2-action@v1.2.0
+ with:
+ template: .docker/launch-config.j2
+ output_file: .docker/launch-config-forkless.json
+ variables: |
+ FEATURE=${{ matrix.features }}
+ RUNTIME=${{ matrix.runtime }}
+
+ - name: Show launch-config-forkless configuration
+ run: cat .docker/launch-config-forkless.json
+
+
+ - name: Build the stack
+ run: docker-compose -f ".docker/docker-compose-forkless.yaml" -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
+ exit 1
+ else
+ echo "🛸 PARACHAINS' RUNTIME UPGRADE TESTING COMPLETE 🛸 - Not found in logs output."
+ return 1
+ exit 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 1
+ shell: bash
+
+ - name: Collect Docker Logs
+ if: success() || failure()
+ uses: jwalton/gh-docker-logs@v2.2.0
+ with:
+ dest: './forkless-parachain-update-nodata-logs.${{ matrix.features }}'
+ images: 'node-parachain'
+
+ - name: Tar logs
+ if: success() || failure()
+ run: tar cvzf ./forkless-parachain-update-nodata-logs.${{ matrix.features }}.tgz ./forkless-parachain-update-nodata-logs.${{ matrix.features }}
+
+ - name: Upload logs to GitHub
+ if: success() || failure()
+ uses: actions/upload-artifact@master
+ with:
+ name: forkless-parachain-update-nodata-logs.${{ matrix.features }}.tgz
+ path: ./forkless-parachain-update-nodata-logs.${{ matrix.features }}.tgz
+
+ - name: Stop running containers
+ if: always() # run this step always
+ run: docker-compose -f ".docker/docker-compose-forkless.yaml" -f ".docker/docker-compose.${{ matrix.network }}.yml" down
.github/workflows/node_build_test.ymldiffbeforeafterboth--- a/.github/workflows/node_build_test.yml
+++ b/.github/workflows/node_build_test.yml
@@ -18,10 +18,9 @@
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:
- build:
+ dev_build_test:
# The type of runner that the job will run on
runs-on: self-hosted-ci
.github/workflows/tests_codestyle.ymldiffbeforeafterboth--- a/.github/workflows/tests_codestyle.yml
+++ b/.github/workflows/tests_codestyle.yml
@@ -9,7 +9,7 @@
- reopened
- synchronize
jobs:
- build:
+ code_style:
runs-on: self-hosted-ci
steps:
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5291,6 +5291,7 @@
"cumulus-primitives-timestamp",
"cumulus-primitives-utility",
"derivative",
+ "evm-coder",
"fp-evm-mapping",
"fp-rpc",
"fp-self-contained",
@@ -5308,6 +5309,7 @@
"pallet-balances",
"pallet-base-fee",
"pallet-common",
+ "pallet-configuration",
"pallet-ethereum",
"pallet-evm",
"pallet-evm-coder-substrate",
@@ -5352,9 +5354,10 @@
"sp-transaction-pool",
"sp-version",
"substrate-wasm-builder",
- "unique-runtime-common",
+ "up-common",
"up-data-structs",
"up-rpc",
+ "up-sponsorship",
"xcm",
"xcm-builder",
"xcm-executor",
@@ -5742,6 +5745,22 @@
]
[[package]]
+name = "pallet-configuration"
+version = "0.1.0"
+dependencies = [
+ "fp-evm",
+ "frame-support",
+ "frame-system",
+ "parity-scale-codec 3.1.5",
+ "scale-info",
+ "smallvec",
+ "sp-arithmetic",
+ "sp-core",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
name = "pallet-democracy"
version = "4.0.0-dev"
source = "git+https://github.com/uniquenetwork/substrate?branch=polkadot-v0.9.24-hack-substitute#1fa76b0665d32b1e28c36da67e54da1816db3fa2"
@@ -5869,7 +5888,7 @@
[[package]]
name = "pallet-evm-coder-substrate"
-version = "0.1.1"
+version = "0.1.2"
dependencies = [
"ethereum",
"evm-coder",
@@ -8605,6 +8624,7 @@
"cumulus-primitives-timestamp",
"cumulus-primitives-utility",
"derivative",
+ "evm-coder",
"fp-evm-mapping",
"fp-rpc",
"fp-self-contained",
@@ -8622,6 +8642,7 @@
"pallet-balances",
"pallet-base-fee",
"pallet-common",
+ "pallet-configuration",
"pallet-ethereum",
"pallet-evm",
"pallet-evm-coder-substrate",
@@ -8666,9 +8687,10 @@
"sp-transaction-pool",
"sp-version",
"substrate-wasm-builder",
- "unique-runtime-common",
+ "up-common",
"up-data-structs",
"up-rpc",
+ "up-sponsorship",
"xcm",
"xcm-builder",
"xcm-executor",
@@ -11881,6 +11903,7 @@
name = "tests"
version = "0.1.0"
dependencies = [
+ "evm-coder",
"fp-evm-mapping",
"frame-support",
"frame-system",
@@ -11902,8 +11925,8 @@
"sp-io",
"sp-runtime",
"sp-std",
- "unique-runtime-common",
"up-data-structs",
+ "up-sponsorship",
]
[[package]]
@@ -12374,7 +12397,7 @@
[[package]]
name = "uc-rpc"
-version = "0.1.1"
+version = "0.1.2"
dependencies = [
"anyhow",
"jsonrpsee",
@@ -12387,7 +12410,6 @@
"sp-core",
"sp-rpc",
"sp-runtime",
- "unique-runtime-common",
"up-data-structs",
"up-rpc",
]
@@ -12541,7 +12563,7 @@
"try-runtime-cli",
"unique-rpc",
"unique-runtime",
- "unique-runtime-common",
+ "up-common",
"up-data-structs",
"up-rpc",
]
@@ -12590,7 +12612,7 @@
"substrate-frame-rpc-system",
"tokio 0.2.25",
"uc-rpc",
- "unique-runtime-common",
+ "up-common",
"up-data-structs",
"up-rpc",
]
@@ -12608,6 +12630,7 @@
"cumulus-primitives-timestamp",
"cumulus-primitives-utility",
"derivative",
+ "evm-coder",
"fp-evm-mapping",
"fp-rpc",
"fp-self-contained",
@@ -12625,6 +12648,7 @@
"pallet-balances",
"pallet-base-fee",
"pallet-common",
+ "pallet-configuration",
"pallet-ethereum",
"pallet-evm",
"pallet-evm-coder-substrate",
@@ -12669,41 +12693,16 @@
"sp-transaction-pool",
"sp-version",
"substrate-wasm-builder",
- "unique-runtime-common",
+ "up-common",
"up-data-structs",
"up-rpc",
+ "up-sponsorship",
"xcm",
"xcm-builder",
"xcm-executor",
]
[[package]]
-name = "unique-runtime-common"
-version = "0.9.24"
-dependencies = [
- "evm-coder",
- "fp-rpc",
- "frame-support",
- "frame-system",
- "pallet-common",
- "pallet-evm",
- "pallet-fungible",
- "pallet-nonfungible",
- "pallet-refungible",
- "pallet-unique",
- "pallet-unique-scheduler",
- "parity-scale-codec 3.1.5",
- "rmrk-rpc",
- "scale-info",
- "sp-consensus-aura",
- "sp-core",
- "sp-runtime",
- "sp-std",
- "up-data-structs",
- "up-sponsorship",
-]
-
-[[package]]
name = "universal-hash"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -12732,6 +12731,19 @@
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
+name = "up-common"
+version = "0.9.24"
+dependencies = [
+ "fp-rpc",
+ "frame-support",
+ "pallet-evm",
+ "sp-consensus-aura",
+ "sp-core",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
name = "up-data-structs"
version = "0.2.1"
dependencies = [
README.mddiffbeforeafterboth--- a/README.md
+++ b/README.md
@@ -23,8 +23,8 @@
Wider Unique Ecosystem (most of it was developed during Hackusama):
-- [SubstraPunks Game hosted on IPFS](https://github.com/usetech-llc/substrapunks)
-- [Unique Wallet and UI](https://uniqueapps.usetech.com/#/nft)
+- [SubstraPunks Game hosted on IPFS](https://github.com/UniqueNetwork/substrapunks)
+- [Unique Wallet and UI](https://wallet.unique.network)
- [NFT Asset for Unity Framework](https://github.com/usetech-llc/nft_unity)
Please see our [walk-through instructions](doc/hackusama_walk_through.md) to try everything out!
client/rpc/CHANGELOG.mddiffbeforeafterboth--- a/client/rpc/CHANGELOG.md
+++ b/client/rpc/CHANGELOG.md
@@ -2,10 +2,15 @@
All notable changes to this project will be documented in this file.
+## [0.1.2] - 2022-08-12
+
+### Fixed
+
+- Method signature `total_pieces`. Before that the number of pieces greater than 2^53 -1 caused an error when calling this method.
+
## [0.1.1] - 2022-07-14
### Added
- - Implementation of RPC method `token_owners` returning 10 owners in no particular order.
- This was an internal request to improve the web interface and support fractionalization event.
-
\ No newline at end of file
+- Implementation of RPC method `token_owners` returning 10 owners in no particular order.
+ This was an internal request to improve the web interface and support fractionalization event.
client/rpc/Cargo.tomldiffbeforeafterboth--- a/client/rpc/Cargo.toml
+++ b/client/rpc/Cargo.toml
@@ -1,11 +1,10 @@
[package]
name = "uc-rpc"
-version = "0.1.1"
+version = "0.1.2"
license = "GPLv3"
edition = "2021"
[dependencies]
-unique-runtime-common = { default-features = false, path = "../../runtime/common" }
pallet-common = { default-features = false, path = '../../pallets/common' }
up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
up-rpc = { path = "../../primitives/rpc" }
client/rpc/src/lib.rsdiffbeforeafterboth--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -242,7 +242,7 @@
collection_id: CollectionId,
token_id: TokenId,
at: Option<BlockHash>,
- ) -> Result<Option<u128>>;
+ ) -> Result<Option<String>>;
}
mod rmrk_unique_rpc {
@@ -518,7 +518,7 @@
pass_method!(collection_stats() -> CollectionStats, unique_api);
pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>, unique_api);
pass_method!(effective_collection_limits(collection_id: CollectionId) -> Option<CollectionLimits>, unique_api);
- pass_method!(total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option<u128>, unique_api);
+ pass_method!(total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option<String> => |o| o.map(|number| number.to_string()) , unique_api);
pass_method!(token_owners(collection: CollectionId, token: TokenId) -> Vec<CrossAccountId>, unique_api);
}
node/cli/Cargo.tomldiffbeforeafterboth--- a/node/cli/Cargo.toml
+++ b/node/cli/Cargo.toml
@@ -253,9 +253,8 @@
################################################################################
# Local dependencies
-[dependencies.unique-runtime-common]
-default-features = false
-path = "../../runtime/common"
+[dependencies.up-common]
+path = "../../primitives/common"
[dependencies.unique-runtime]
path = '../../runtime/unique'
node/cli/src/chain_spec.rsdiffbeforeafterboth--- a/node/cli/src/chain_spec.rs
+++ b/node/cli/src/chain_spec.rs
@@ -23,7 +23,7 @@
use serde::{Deserialize, Serialize};
use serde_json::map::Map;
-use unique_runtime_common::types::*;
+use up_common::types::opaque::*;
#[cfg(feature = "unique-runtime")]
pub use unique_runtime as default_runtime;
node/cli/src/command.rsdiffbeforeafterboth--- a/node/cli/src/command.rs
+++ b/node/cli/src/command.rs
@@ -64,7 +64,7 @@
use sp_runtime::traits::{AccountIdConversion, Block as BlockT};
use std::{io::Write, net::SocketAddr, time::Duration};
-use unique_runtime_common::types::Block;
+use up_common::types::opaque::Block;
macro_rules! no_runtime_err {
($chain_name:expr) => {
node/cli/src/service.rsdiffbeforeafterboth--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -63,7 +63,7 @@
use fc_rpc_core::types::FilterPool;
use fc_mapping_sync::{MappingSyncWorker, SyncStrategy};
-use unique_runtime_common::types::{AuraId, RuntimeInstance, AccountId, Balance, Index, Hash, Block};
+use up_common::types::opaque::{AuraId, RuntimeInstance, AccountId, Balance, Index, Hash, Block};
// RMRK
use up_data_structs::{
node/rpc/Cargo.tomldiffbeforeafterboth--- a/node/rpc/Cargo.toml
+++ b/node/rpc/Cargo.toml
@@ -49,7 +49,7 @@
fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
pallet-common = { default-features = false, path = "../../pallets/common" }
-unique-runtime-common = { default-features = false, path = "../../runtime/common" }
+up-common = { path = "../../primitives/common" }
pallet-unique = { path = "../../pallets/unique" }
uc-rpc = { path = "../../client/rpc" }
up-rpc = { path = "../../primitives/rpc" }
node/rpc/src/lib.rsdiffbeforeafterboth--- a/node/rpc/src/lib.rs
+++ b/node/rpc/src/lib.rs
@@ -40,9 +40,8 @@
use sc_service::TransactionPool;
use std::{collections::BTreeMap, sync::Arc};
-use unique_runtime_common::types::{
- Hash, AccountId, RuntimeInstance, Index, Block, BlockNumber, Balance,
-};
+use up_common::types::opaque::{Hash, AccountId, RuntimeInstance, Index, Block, BlockNumber, Balance};
+
// RMRK
use up_data_structs::{
RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo, RmrkBaseInfo,
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -25,7 +25,8 @@
use pallet_evm_coder_substrate::dispatch_to_evm;
use sp_std::vec::Vec;
use up_data_structs::{
- Property, SponsoringRateLimit, OwnerRestrictedSet, AccessMode, CollectionPermissions,
+ AccessMode, CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property,
+ SponsoringRateLimit,
};
use alloc::format;
@@ -408,6 +409,28 @@
save(self)
}
+
+ /// Check that account is the owner or admin of the collection
+ ///
+ /// @param user account to verify
+ /// @return "true" if account is the owner or admin
+ fn verify_owner_or_admin(&self, user: address) -> Result<bool> {
+ Ok(check_is_owner_or_admin(user, self)
+ .map(|_| true)
+ .unwrap_or(false))
+ }
+
+ /// Returns collection type
+ ///
+ /// @return `Fungible` or `NFT` or `ReFungible`
+ fn unique_collection_type(&mut self) -> Result<string> {
+ let mode = match self.collection.mode {
+ CollectionMode::Fungible(_) => "Fungible",
+ CollectionMode::NFT => "NFT",
+ CollectionMode::ReFungible => "ReFungible",
+ };
+ Ok(mode.into())
+ }
}
fn check_is_owner_or_admin<T: Config>(
@@ -462,6 +485,11 @@
pub fn suffix() -> up_data_structs::PropertyKey {
property_key_from_bytes(b"suffix").expect(EXPECT_CONVERT_ERROR)
}
+
+ /// Key "parentNft".
+ pub fn parent_nft() -> up_data_structs::PropertyKey {
+ property_key_from_bytes(b"parentNft").expect(EXPECT_CONVERT_ERROR)
+ }
}
/// Values.
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -535,7 +535,8 @@
/// Can't transfer tokens to ethereum zero address
AddressIsZero,
- /// Target collection doesn't support this operation
+
+ /// The operation is not supported
UnsupportedOperation,
/// Insufficient funds to perform an action
@@ -1112,6 +1113,26 @@
sender: &T::CrossAccountId,
property_permission: PropertyKeyPermission,
) -> DispatchResult {
+ Self::set_scoped_property_permission(
+ collection,
+ sender,
+ PropertyScope::None,
+ property_permission,
+ )
+ }
+
+ /// Set collection property permission with scope.
+ ///
+ /// * `collection` - Collection handler.
+ /// * `sender` - The owner or administrator of the collection.
+ /// * `scope` - Property scope.
+ /// * `property_permission` - Property permission.
+ pub fn set_scoped_property_permission(
+ collection: &CollectionHandle<T>,
+ sender: &T::CrossAccountId,
+ scope: PropertyScope,
+ property_permission: PropertyKeyPermission,
+ ) -> DispatchResult {
collection.check_is_owner_or_admin(sender)?;
let all_permissions = CollectionPropertyPermissions::<T>::get(collection.id);
@@ -1125,7 +1146,11 @@
CollectionPropertyPermissions::<T>::try_mutate(collection.id, |permissions| {
let property_permission = property_permission.clone();
- permissions.try_set(property_permission.key, property_permission.permission)
+ permissions.try_scoped_set(
+ scope,
+ property_permission.key,
+ property_permission.permission,
+ )
})
.map_err(<Error<T>>::from)?;
@@ -1148,8 +1173,29 @@
sender: &T::CrossAccountId,
property_permissions: Vec<PropertyKeyPermission>,
) -> DispatchResult {
+ Self::set_scoped_token_property_permissions(
+ collection,
+ sender,
+ PropertyScope::None,
+ property_permissions,
+ )
+ }
+
+ /// Set token property permission with scope.
+ ///
+ /// * `collection` - Collection handler.
+ /// * `sender` - The owner or administrator of the collection.
+ /// * `scope` - Property scope.
+ /// * `property_permissions` - Property permissions.
+ #[transactional]
+ pub fn set_scoped_token_property_permissions(
+ collection: &CollectionHandle<T>,
+ sender: &T::CrossAccountId,
+ scope: PropertyScope,
+ property_permissions: Vec<PropertyKeyPermission>,
+ ) -> DispatchResult {
for prop_pemission in property_permissions {
- Self::set_property_permission(collection, sender, prop_pemission)?;
+ Self::set_scoped_property_permission(collection, sender, scope, prop_pemission)?;
}
Ok(())
@@ -1353,8 +1399,8 @@
/// Indicates unsupported methods by returning [Error::UnsupportedOperation].
#[macro_export]
macro_rules! unsupported {
- () => {
- Err(<Error<T>>::UnsupportedOperation.into())
+ ($runtime:path) => {
+ Err($crate::Error::<$runtime>::UnsupportedOperation.into())
};
}
@@ -1429,6 +1475,9 @@
.saturating_mul(max_selfs.max(1) as u64)
.saturating_add(Self::burn_recursively_breadth_raw(max_breadth))
}
+
+ /// The price of retrieving token owner
+ fn token_owner() -> Weight;
}
/// Weight info extension trait for refungible pallet.
@@ -1567,7 +1616,7 @@
///
/// * `sender` - Must be either the owner of the token or its admin.
/// * `token_id` - The token for which the properties are being set.
- /// * `properties` - Properties to be set.
+ /// * `property_permissions` - Property permissions to be set.
/// * `budget` - Budget for setting properties.
fn set_token_property_permissions(
&self,
pallets/configuration/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/pallets/configuration/Cargo.toml
@@ -0,0 +1,33 @@
+[package]
+name = "pallet-configuration"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+parity-scale-codec = { version = "3.1.5", features = [
+ "derive",
+], default-features = false }
+scale-info = { version = "2.0.1", default-features = false, features = [
+ "derive",
+] }
+frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }
+frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }
+sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }
+sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }
+sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }
+sp-arithmetic = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }
+fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
+smallvec = "1.6.1"
+
+[features]
+default = ["std"]
+std = [
+ "parity-scale-codec/std",
+ "frame-support/std",
+ "frame-system/std",
+ "sp-runtime/std",
+ "sp-std/std",
+ "sp-core/std",
+ "sp-arithmetic/std",
+ "fp-evm/std",
+]
pallets/configuration/src/lib.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/configuration/src/lib.rs
@@ -0,0 +1,124 @@
+// 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/>.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+use core::marker::PhantomData;
+
+use frame_support::{
+ pallet,
+ weights::{WeightToFeePolynomial, WeightToFeeCoefficients, WeightToFeeCoefficient},
+ traits::Get,
+};
+use sp_arithmetic::traits::{BaseArithmetic, Unsigned};
+use smallvec::smallvec;
+
+pub use pallet::*;
+use sp_core::U256;
+use sp_runtime::Perbill;
+
+#[pallet]
+mod pallet {
+ use super::*;
+ use frame_support::{
+ traits::Get,
+ pallet_prelude::{StorageValue, ValueQuery, DispatchResult},
+ };
+ use frame_system::{pallet_prelude::OriginFor, ensure_root};
+
+ #[pallet::config]
+ pub trait Config: frame_system::Config {
+ #[pallet::constant]
+ type DefaultWeightToFeeCoefficient: Get<u32>;
+ #[pallet::constant]
+ type DefaultMinGasPrice: Get<u64>;
+ }
+
+ #[pallet::storage]
+ pub type WeightToFeeCoefficientOverride<T: Config> = StorageValue<
+ Value = u32,
+ QueryKind = ValueQuery,
+ OnEmpty = T::DefaultWeightToFeeCoefficient,
+ >;
+
+ #[pallet::storage]
+ pub type MinGasPriceOverride<T: Config> =
+ StorageValue<Value = u64, QueryKind = ValueQuery, OnEmpty = T::DefaultMinGasPrice>;
+
+ #[pallet::call]
+ impl<T: Config> Pallet<T> {
+ #[pallet::weight(T::DbWeight::get().writes(1))]
+ pub fn set_weight_to_fee_coefficient_override(
+ origin: OriginFor<T>,
+ coeff: Option<u32>,
+ ) -> DispatchResult {
+ let _sender = ensure_root(origin)?;
+ if let Some(coeff) = coeff {
+ <WeightToFeeCoefficientOverride<T>>::set(coeff);
+ } else {
+ <WeightToFeeCoefficientOverride<T>>::kill();
+ }
+ Ok(())
+ }
+
+ #[pallet::weight(T::DbWeight::get().writes(1))]
+ pub fn set_min_gas_price_override(
+ origin: OriginFor<T>,
+ coeff: Option<u64>,
+ ) -> DispatchResult {
+ let _sender = ensure_root(origin)?;
+ if let Some(coeff) = coeff {
+ <MinGasPriceOverride<T>>::set(coeff);
+ } else {
+ <MinGasPriceOverride<T>>::kill();
+ }
+ Ok(())
+ }
+ }
+
+ #[pallet::pallet]
+ #[pallet::generate_store(pub(super) trait Store)]
+ pub struct Pallet<T>(_);
+}
+
+pub struct WeightToFee<T, B>(PhantomData<(T, B)>);
+
+impl<T, B> WeightToFeePolynomial for WeightToFee<T, B>
+where
+ T: Config,
+ B: BaseArithmetic + From<u32> + Copy + Unsigned,
+{
+ type Balance = B;
+
+ fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
+ smallvec!(WeightToFeeCoefficient {
+ coeff_integer: <WeightToFeeCoefficientOverride<T>>::get().into(),
+ coeff_frac: Perbill::zero(),
+ negative: false,
+ degree: 1,
+ })
+ }
+}
+
+pub struct FeeCalculator<T>(PhantomData<T>);
+impl<T: Config> fp_evm::FeeCalculator for FeeCalculator<T> {
+ fn min_gas_price() -> (U256, u64) {
+ (
+ <MinGasPriceOverride<T>>::get().into(),
+ T::DbWeight::get().reads(1),
+ )
+ }
+}
pallets/evm-coder-substrate/CHANGELOG.mddiffbeforeafterboth--- /dev/null
+++ b/pallets/evm-coder-substrate/CHANGELOG.md
@@ -0,0 +1,12 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+
+## [0.1.2] - 2022-08-12
+
+### Fixed
+
+ - Issue with error not being thrown when non existing function is called on collection contract
+
+
+
\ No newline at end of file
pallets/evm-coder-substrate/Cargo.tomldiffbeforeafterboth--- a/pallets/evm-coder-substrate/Cargo.toml
+++ b/pallets/evm-coder-substrate/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "pallet-evm-coder-substrate"
-version = "0.1.1"
+version = "0.1.2"
license = "GPLv3"
edition = "2021"
pallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-coder-substrate/src/lib.rs
+++ b/pallets/evm-coder-substrate/src/lib.rs
@@ -261,7 +261,8 @@
let (selector, mut reader) = AbiReader::new_call(input)?;
let call = C::parse(selector, &mut reader)?;
if call.is_none() {
- return Ok(None);
+ let selector = u32::from_be_bytes(selector);
+ return Err(format!("unrecognized selector: 0x{selector:0<8x}").into());
}
let call = call.unwrap();
pallets/fungible/src/common.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -103,6 +103,10 @@
// Fungible tokens can't have children
0
}
+
+ fn token_owner() -> Weight {
+ 0
+ }
}
/// Implementation of `CommonCollectionOperations` for `FungibleHandle`. It wraps FungibleHandle Pallete
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
@@ -31,19 +31,7 @@
);
}
-// Selector: 79cc6790
-contract ERC20UniqueExtensions is Dummy, ERC165 {
- // Selector: burnFrom(address,uint256) 79cc6790
- function burnFrom(address from, uint256 amount) public returns (bool) {
- require(false, stub_error);
- from;
- amount;
- dummy = 0;
- return false;
- }
-}
-
-// Selector: 7d9262e6
+// Selector: 6cf113cd
contract Collection is Dummy, ERC165 {
// Set collection property.
//
@@ -268,6 +256,42 @@
mode;
dummy = 0;
}
+
+ // Check that account is the owner or admin of the collection
+ //
+ // @param user account to verify
+ // @return "true" if account is the owner or admin
+ //
+ // Selector: verifyOwnerOrAdmin(address) c2282493
+ function verifyOwnerOrAdmin(address user) public view returns (bool) {
+ require(false, stub_error);
+ user;
+ dummy;
+ return false;
+ }
+
+ // Returns collection type
+ //
+ // @return `Fungible` or `NFT` or `ReFungible`
+ //
+ // Selector: uniqueCollectionType() d34b55b8
+ function uniqueCollectionType() public returns (string memory) {
+ require(false, stub_error);
+ dummy = 0;
+ return "";
+ }
+}
+
+// Selector: 79cc6790
+contract ERC20UniqueExtensions is Dummy, ERC165 {
+ // Selector: burnFrom(address,uint256) 79cc6790
+ function burnFrom(address from, uint256 amount) public returns (bool) {
+ require(false, stub_error);
+ from;
+ amount;
+ dummy = 0;
+ return false;
+ }
}
// Selector: 942e8b22
pallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/benchmarking.rs
+++ b/pallets/nonfungible/src/benchmarking.rs
@@ -17,11 +17,14 @@
use super::*;
use crate::{Pallet, Config, NonfungibleHandle};
-use sp_std::prelude::*;
-use pallet_common::benchmarking::{create_collection_raw, property_key, property_value};
use frame_benchmarking::{benchmarks, account};
+use pallet_common::{
+ bench_init,
+ benchmarking::{create_collection_raw, property_key, property_value},
+ CommonCollectionOperations,
+};
+use sp_std::prelude::*;
use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, MAX_PROPERTIES_PER_ITEM, budget::Unlimited};
-use pallet_common::bench_init;
const SEED: u32 = 1;
@@ -208,4 +211,13 @@
<Pallet<T>>::set_token_properties(&collection, &owner, item, props.into_iter(), false, &Unlimited)?;
let to_delete = (0..b).map(|k| property_key(k as usize)).collect::<Vec<_>>();
}: {<Pallet<T>>::delete_token_properties(&collection, &owner, item, to_delete.into_iter(), &Unlimited)?}
+
+ token_owner {
+ bench_init!{
+ owner: sub; collection: collection(owner);
+ owner: cross_from_sub;
+ };
+ let item = create_max_item(&collection, &owner, owner.clone())?;
+
+ }: {collection.token_owner(item)}
}
pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -118,6 +118,10 @@
<SelfWeightOf<T>>::burn_recursively_breadth_plus_self_plus_self_per_each_raw(amount)
.saturating_sub(Self::burn_recursively_self_raw().saturating_mul(amount as u64 + 1))
}
+
+ fn token_owner() -> Weight {
+ <SelfWeightOf<T>>::token_owner()
+ }
}
fn map_create_data<T: Config>(
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -784,6 +784,23 @@
<PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)
}
+ /// Set property permissions for the token with scope.
+ ///
+ /// Sender should be the owner or admin of token's collection.
+ pub fn set_scoped_token_property_permissions(
+ collection: &CollectionHandle<T>,
+ sender: &T::CrossAccountId,
+ scope: PropertyScope,
+ property_permissions: Vec<PropertyKeyPermission>,
+ ) -> DispatchResult {
+ <PalletCommon<T>>::set_scoped_token_property_permissions(
+ collection,
+ sender,
+ scope,
+ property_permissions,
+ )
+ }
+
/// Set property permissions for the collection.
///
/// Sender should be the owner or admin of the collection.
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
@@ -373,49 +373,7 @@
}
}
-// Selector: 780e9d63
-contract ERC721Enumerable is Dummy, ERC165 {
- // @notice Enumerate valid NFTs
- // @param index A counter less than `totalSupply()`
- // @return The token identifier for the `index`th NFT,
- // (sort order not specified)
- //
- // Selector: tokenByIndex(uint256) 4f6ccce7
- function tokenByIndex(uint256 index) public view returns (uint256) {
- require(false, stub_error);
- index;
- dummy;
- return 0;
- }
-
- // @dev Not implemented
- //
- // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
- function tokenOfOwnerByIndex(address owner, uint256 index)
- public
- view
- returns (uint256)
- {
- require(false, stub_error);
- owner;
- index;
- dummy;
- return 0;
- }
-
- // @notice Count NFTs tracked by this contract
- // @return A count of valid NFTs tracked by this contract, where each one of
- // them has an assigned and queryable owner not equal to the zero address
- //
- // Selector: totalSupply() 18160ddd
- function totalSupply() public view returns (uint256) {
- require(false, stub_error);
- dummy;
- return 0;
- }
-}
-
-// Selector: 7d9262e6
+// Selector: 6cf113cd
contract Collection is Dummy, ERC165 {
// Set collection property.
//
@@ -640,6 +598,72 @@
mode;
dummy = 0;
}
+
+ // Check that account is the owner or admin of the collection
+ //
+ // @param user account to verify
+ // @return "true" if account is the owner or admin
+ //
+ // Selector: verifyOwnerOrAdmin(address) c2282493
+ function verifyOwnerOrAdmin(address user) public view returns (bool) {
+ require(false, stub_error);
+ user;
+ dummy;
+ return false;
+ }
+
+ // Returns collection type
+ //
+ // @return `Fungible` or `NFT` or `ReFungible`
+ //
+ // Selector: uniqueCollectionType() d34b55b8
+ function uniqueCollectionType() public returns (string memory) {
+ require(false, stub_error);
+ dummy = 0;
+ return "";
+ }
+}
+
+// Selector: 780e9d63
+contract ERC721Enumerable is Dummy, ERC165 {
+ // @notice Enumerate valid NFTs
+ // @param index A counter less than `totalSupply()`
+ // @return The token identifier for the `index`th NFT,
+ // (sort order not specified)
+ //
+ // Selector: tokenByIndex(uint256) 4f6ccce7
+ function tokenByIndex(uint256 index) public view returns (uint256) {
+ require(false, stub_error);
+ index;
+ dummy;
+ return 0;
+ }
+
+ // @dev Not implemented
+ //
+ // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
+ function tokenOfOwnerByIndex(address owner, uint256 index)
+ public
+ view
+ returns (uint256)
+ {
+ require(false, stub_error);
+ owner;
+ index;
+ dummy;
+ return 0;
+ }
+
+ // @notice Count NFTs tracked by this contract
+ // @return A count of valid NFTs tracked by this contract, where each one of
+ // them has an assigned and queryable owner not equal to the zero address
+ //
+ // Selector: totalSupply() 18160ddd
+ function totalSupply() public view returns (uint256) {
+ require(false, stub_error);
+ dummy;
+ return 0;
+ }
}
// Selector: d74d154f
pallets/nonfungible/src/weights.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/weights.rs
+++ b/pallets/nonfungible/src/weights.rs
@@ -3,7 +3,7 @@
//! Autogenerated weights for pallet_nonfungible
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2022-07-20, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2022-08-01, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
// Executed Command:
@@ -46,6 +46,7 @@
fn set_token_property_permissions(b: u32, ) -> Weight;
fn set_token_properties(b: u32, ) -> Weight;
fn delete_token_properties(b: u32, ) -> Weight;
+ fn token_owner() -> Weight;
}
/// Weights for pallet_nonfungible using the Substrate node and recommended hardware.
@@ -56,7 +57,7 @@
// Storage: Nonfungible TokenData (r:0 w:1)
// Storage: Nonfungible Owned (r:0 w:1)
fn create_item() -> Weight {
- (20_328_000 as Weight)
+ (20_909_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
@@ -65,9 +66,9 @@
// Storage: Nonfungible TokenData (r:0 w:4)
// Storage: Nonfungible Owned (r:0 w:4)
fn create_multiple_items(b: u32, ) -> Weight {
- (10_134_000 as Weight)
- // Standard Error: 3_000
- .saturating_add((4_927_000 as Weight).saturating_mul(b as Weight))
+ (12_601_000 as Weight)
+ // Standard Error: 1_000
+ .saturating_add((4_920_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
.saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(b as Weight)))
@@ -77,9 +78,9 @@
// Storage: Nonfungible TokenData (r:0 w:4)
// Storage: Nonfungible Owned (r:0 w:4)
fn create_multiple_items_ex(b: u32, ) -> Weight {
- (5_710_000 as Weight)
- // Standard Error: 4_000
- .saturating_add((7_578_000 as Weight).saturating_mul(b as Weight))
+ (0 as Weight)
+ // Standard Error: 3_000
+ .saturating_add((7_734_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
@@ -93,7 +94,7 @@
// Storage: Nonfungible Owned (r:0 w:1)
// Storage: Nonfungible TokenProperties (r:0 w:1)
fn burn_item() -> Weight {
- (28_433_000 as Weight)
+ (29_746_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
@@ -105,7 +106,7 @@
// Storage: Nonfungible Owned (r:0 w:1)
// Storage: Nonfungible TokenProperties (r:0 w:1)
fn burn_recursively_self_raw() -> Weight {
- (34_435_000 as Weight)
+ (36_077_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
@@ -119,8 +120,8 @@
// Storage: Common CollectionById (r:1 w:0)
fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 1_539_000
- .saturating_add((304_456_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 1_605_000
+ .saturating_add((312_391_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(7 as Weight))
.saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(b as Weight)))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
@@ -131,14 +132,14 @@
// Storage: Nonfungible Allowance (r:1 w:0)
// Storage: Nonfungible Owned (r:0 w:2)
fn transfer() -> Weight {
- (24_376_000 as Weight)
+ (25_248_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
// Storage: Nonfungible TokenData (r:1 w:0)
// Storage: Nonfungible Allowance (r:1 w:1)
fn approve() -> Weight {
- (15_890_000 as Weight)
+ (16_321_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
@@ -147,7 +148,7 @@
// Storage: Nonfungible AccountBalance (r:2 w:2)
// Storage: Nonfungible Owned (r:0 w:2)
fn transfer_from() -> Weight {
- (28_634_000 as Weight)
+ (29_325_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
@@ -159,15 +160,15 @@
// Storage: Nonfungible Owned (r:0 w:1)
// Storage: Nonfungible TokenProperties (r:0 w:1)
fn burn_from() -> Weight {
- (32_201_000 as Weight)
+ (33_323_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
// Storage: Common CollectionPropertyPermissions (r:1 w:1)
fn set_token_property_permissions(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 57_000
- .saturating_add((15_232_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 62_000
+ .saturating_add((16_222_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
@@ -175,8 +176,8 @@
// Storage: Nonfungible TokenProperties (r:1 w:1)
fn set_token_properties(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 1_648_000
- .saturating_add((288_654_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 1_750_000
+ .saturating_add((304_476_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
@@ -184,11 +185,16 @@
// Storage: Nonfungible TokenProperties (r:1 w:1)
fn delete_token_properties(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 1_632_000
- .saturating_add((289_190_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 1_638_000
+ .saturating_add((294_096_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
+ // Storage: Nonfungible TokenData (r:1 w:0)
+ fn token_owner() -> Weight {
+ (2_986_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(1 as Weight))
+ }
}
// For backwards compatibility and tests
@@ -198,7 +204,7 @@
// Storage: Nonfungible TokenData (r:0 w:1)
// Storage: Nonfungible Owned (r:0 w:1)
fn create_item() -> Weight {
- (20_328_000 as Weight)
+ (20_909_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
@@ -207,9 +213,9 @@
// Storage: Nonfungible TokenData (r:0 w:4)
// Storage: Nonfungible Owned (r:0 w:4)
fn create_multiple_items(b: u32, ) -> Weight {
- (10_134_000 as Weight)
- // Standard Error: 3_000
- .saturating_add((4_927_000 as Weight).saturating_mul(b as Weight))
+ (12_601_000 as Weight)
+ // Standard Error: 1_000
+ .saturating_add((4_920_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
.saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(b as Weight)))
@@ -219,9 +225,9 @@
// Storage: Nonfungible TokenData (r:0 w:4)
// Storage: Nonfungible Owned (r:0 w:4)
fn create_multiple_items_ex(b: u32, ) -> Weight {
- (5_710_000 as Weight)
- // Standard Error: 4_000
- .saturating_add((7_578_000 as Weight).saturating_mul(b as Weight))
+ (0 as Weight)
+ // Standard Error: 3_000
+ .saturating_add((7_734_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
@@ -235,7 +241,7 @@
// Storage: Nonfungible Owned (r:0 w:1)
// Storage: Nonfungible TokenProperties (r:0 w:1)
fn burn_item() -> Weight {
- (28_433_000 as Weight)
+ (29_746_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
@@ -247,7 +253,7 @@
// Storage: Nonfungible Owned (r:0 w:1)
// Storage: Nonfungible TokenProperties (r:0 w:1)
fn burn_recursively_self_raw() -> Weight {
- (34_435_000 as Weight)
+ (36_077_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
@@ -261,8 +267,8 @@
// Storage: Common CollectionById (r:1 w:0)
fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 1_539_000
- .saturating_add((304_456_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 1_605_000
+ .saturating_add((312_391_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(7 as Weight))
.saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(b as Weight)))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
@@ -273,14 +279,14 @@
// Storage: Nonfungible Allowance (r:1 w:0)
// Storage: Nonfungible Owned (r:0 w:2)
fn transfer() -> Weight {
- (24_376_000 as Weight)
+ (25_248_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
// Storage: Nonfungible TokenData (r:1 w:0)
// Storage: Nonfungible Allowance (r:1 w:1)
fn approve() -> Weight {
- (15_890_000 as Weight)
+ (16_321_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
@@ -289,7 +295,7 @@
// Storage: Nonfungible AccountBalance (r:2 w:2)
// Storage: Nonfungible Owned (r:0 w:2)
fn transfer_from() -> Weight {
- (28_634_000 as Weight)
+ (29_325_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
@@ -301,15 +307,15 @@
// Storage: Nonfungible Owned (r:0 w:1)
// Storage: Nonfungible TokenProperties (r:0 w:1)
fn burn_from() -> Weight {
- (32_201_000 as Weight)
+ (33_323_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
// Storage: Common CollectionPropertyPermissions (r:1 w:1)
fn set_token_property_permissions(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 57_000
- .saturating_add((15_232_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 62_000
+ .saturating_add((16_222_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
@@ -317,8 +323,8 @@
// Storage: Nonfungible TokenProperties (r:1 w:1)
fn set_token_properties(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 1_648_000
- .saturating_add((288_654_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 1_750_000
+ .saturating_add((304_476_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
@@ -326,9 +332,14 @@
// Storage: Nonfungible TokenProperties (r:1 w:1)
fn delete_token_properties(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 1_632_000
- .saturating_add((289_190_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 1_638_000
+ .saturating_add((294_096_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
+ // Storage: Nonfungible TokenData (r:1 w:0)
+ fn token_owner() -> Weight {
+ (2_986_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(1 as Weight))
+ }
}
pallets/refungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/refungible/src/benchmarking.rs
+++ b/pallets/refungible/src/benchmarking.rs
@@ -17,25 +17,26 @@
use super::*;
use crate::{Pallet, Config, RefungibleHandle};
-use sp_std::prelude::*;
-use pallet_common::benchmarking::{create_collection_raw, property_key, property_value, create_data};
+use core::convert::TryInto;
+use core::iter::IntoIterator;
use frame_benchmarking::{benchmarks, account};
+use pallet_common::{
+ bench_init,
+ benchmarking::{create_collection_raw, property_key, property_value, create_data},
+};
+use sp_core::H160;
+use sp_std::prelude::*;
use up_data_structs::{
CollectionMode, MAX_ITEMS_PER_BATCH, MAX_PROPERTIES_PER_ITEM, CUSTOM_DATA_LIMIT,
budget::Unlimited,
};
-use pallet_common::bench_init;
-use core::convert::TryInto;
-use core::iter::IntoIterator;
const SEED: u32 = 1;
fn create_max_item_data<CrossAccountId: Ord>(
users: impl IntoIterator<Item = (CrossAccountId, u128)>,
-) -> CreateRefungibleExData<CrossAccountId> {
- let const_data = create_data::<CUSTOM_DATA_LIMIT>();
- CreateRefungibleExData {
- const_data,
+) -> CreateItemData<CrossAccountId> {
+ CreateItemData {
users: users
.into_iter()
.collect::<BTreeMap<_, _>>()
@@ -44,12 +45,13 @@
properties: Default::default(),
}
}
+
fn create_max_item<T: Config>(
collection: &RefungibleHandle<T>,
sender: &T::CrossAccountId,
users: impl IntoIterator<Item = (T::CrossAccountId, u128)>,
) -> Result<TokenId, DispatchError> {
- let data: CreateRefungibleExData<T::CrossAccountId> = create_max_item_data(users);
+ let data: CreateItemData<T::CrossAccountId> = create_max_item_data(users);
<Pallet<T>>::create_item(&collection, sender, data, &Unlimited)?;
Ok(TokenId(<TokensMinted<T>>::get(&collection.id)))
}
@@ -59,11 +61,12 @@
) -> Result<RefungibleHandle<T>, DispatchError> {
create_collection_raw(
owner,
- CollectionMode::NFT,
+ CollectionMode::ReFungible,
<Pallet<T>>::init_collection,
RefungibleHandle::cast,
)
}
+
benchmarks! {
create_item {
bench_init!{
@@ -277,4 +280,21 @@
};
let item = create_max_item(&collection, &sender, [(owner.clone(), 100)])?;
}: {<Pallet<T>>::repartition(&collection, &owner, item, 200)?}
+
+ set_parent_nft_unchecked {
+ bench_init!{
+ owner: sub; collection: collection(owner);
+ sender: cross_from_sub(owner); owner: cross_sub;
+ };
+ let item = create_max_item(&collection, &sender, [(owner.clone(), 100)])?;
+
+ }: {<Pallet<T>>::set_parent_nft_unchecked(&collection, item, owner, T::CrossAccountId::from_eth(H160::default()))?}
+
+ token_owner {
+ bench_init!{
+ owner: sub; collection: collection(owner);
+ sender: cross_from_sub(owner); owner: cross_sub;
+ };
+ let item = create_max_item(&collection, &sender, [(owner.clone(), 100)])?;
+ }: {<Pallet<T>>::token_owner(collection.id, item)}
}
pallets/refungible/src/common.rsdiffbeforeafterboth--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -148,6 +148,10 @@
// Refungible token can't have children
0
}
+
+ fn token_owner() -> Weight {
+ <SelfWeightOf<T>>::token_owner()
+ }
}
fn map_create_data<T: Config>(
pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -41,8 +41,8 @@
use sp_core::H160;
use sp_std::{collections::btree_map::BTreeMap, vec::Vec, vec};
use up_data_structs::{
- CollectionId, CollectionPropertiesVec, Property, PropertyKey, PropertyKeyPermission,
- PropertyPermission, TokenId,
+ CollectionId, CollectionPropertiesVec, mapping::TokenAddressMapping, Property, PropertyKey,
+ PropertyKeyPermission, PropertyPermission, TokenId,
};
use crate::{
@@ -413,7 +413,7 @@
}
/// Returns amount of pieces of `token` that `owner` have
-fn balance<T: Config>(
+pub fn balance<T: Config>(
collection: &RefungibleHandle<T>,
token: TokenId,
owner: &T::CrossAccountId,
@@ -424,7 +424,7 @@
}
/// Throws if `owner_balance` is lower than total amount of `token` pieces
-fn ensure_single_owner<T: Config>(
+pub fn ensure_single_owner<T: Config>(
collection: &RefungibleHandle<T>,
token: TokenId,
owner_balance: u128,
@@ -788,6 +788,16 @@
.map_err(dispatch_to_evm::<T>)?;
Ok(true)
}
+
+ /// Returns EVM address for refungible token
+ ///
+ /// @param token ID of the token
+ fn token_contract_address(&self, token: uint256) -> Result<address> {
+ Ok(T::EvmTokenAddressMapping::token_to_address(
+ self.id,
+ token.try_into().map_err(|_| "token id overflow")?,
+ ))
+ }
}
#[solidity_interface(
pallets/refungible/src/erc_token.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc_token.rs
+++ b/pallets/refungible/src/erc_token.rs
@@ -20,29 +20,95 @@
//! Method implementations are mostly doing parameter conversion and calling Nonfungible Pallet methods.
extern crate alloc;
+
+#[cfg(not(feature = "std"))]
+use alloc::format;
+
use core::{
char::{REPLACEMENT_CHARACTER, decode_utf16},
convert::TryInto,
ops::Deref,
};
-use evm_coder::{ToLog, execution::*, generate_stubgen, solidity_interface, types::*, weight};
+use evm_coder::{ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight};
use pallet_common::{
CommonWeightInfo,
- erc::{CommonEvmHandler, PrecompileResult},
+ erc::{CommonEvmHandler, PrecompileResult, static_property::key},
+ eth::map_eth_to_id,
};
use pallet_evm::{account::CrossAccountId, PrecompileHandle};
use pallet_evm_coder_substrate::{call, dispatch_to_evm, WithRecorder};
use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};
+use sp_core::H160;
use sp_std::vec::Vec;
-use up_data_structs::TokenId;
+use up_data_structs::{mapping::TokenAddressMapping, PropertyScope, TokenId};
use crate::{
Allowance, Balance, common::CommonWeights, Config, Pallet, RefungibleHandle, SelfWeightOf,
- weights::WeightInfo, TotalSupply,
+ TokenProperties, TotalSupply, weights::WeightInfo,
};
pub struct RefungibleTokenHandle<T: Config>(pub RefungibleHandle<T>, pub TokenId);
+#[solidity_interface(name = "ERC1633")]
+impl<T: Config> RefungibleTokenHandle<T> {
+ fn parent_token(&self) -> Result<address> {
+ self.consume_store_reads(2)?;
+ let props = <TokenProperties<T>>::get((self.id, self.1));
+ let key = key::parent_nft();
+
+ let key_scoped = PropertyScope::Eth
+ .apply(key)
+ .expect("property key shouldn't exceed length limit");
+ if let Some(value) = props.get(&key_scoped) {
+ Ok(H160::from_slice(value.as_slice()))
+ } else {
+ Ok(*T::CrossTokenAddressMapping::token_to_address(self.id, self.1).as_eth())
+ }
+ }
+
+ fn parent_token_id(&self) -> Result<uint256> {
+ self.consume_store_reads(2)?;
+ let props = <TokenProperties<T>>::get((self.id, self.1));
+ let key = key::parent_nft();
+
+ let key_scoped = PropertyScope::Eth
+ .apply(key)
+ .expect("property key shouldn't exceed length limit");
+ if let Some(value) = props.get(&key_scoped) {
+ let nft_token_address = H160::from_slice(value.as_slice());
+ let nft_token_account = T::CrossAccountId::from_eth(nft_token_address);
+ let (_, token_id) = T::CrossTokenAddressMapping::address_to_token(&nft_token_account)
+ .ok_or("parent NFT should contain NFT token address")?;
+
+ Ok(token_id.into())
+ } else {
+ Ok(self.1.into())
+ }
+ }
+}
+
+#[solidity_interface(name = "ERC1633UniqueExtensions")]
+impl<T: Config> RefungibleTokenHandle<T> {
+ #[solidity(rename_selector = "setParentNFT")]
+ #[weight(<CommonWeights<T>>::token_owner() + <SelfWeightOf<T>>::set_parent_nft_unchecked())]
+ fn set_parent_nft(
+ &mut self,
+ caller: caller,
+ collection: address,
+ nft_id: uint256,
+ ) -> Result<bool> {
+ self.consume_store_reads(1)?;
+ let caller = T::CrossAccountId::from_eth(caller);
+ let nft_collection = map_eth_to_id(&collection).ok_or("collection not found")?;
+ let nft_token = nft_id.try_into()?;
+
+ <Pallet<T>>::set_parent_nft(&self.0, self.1, caller, nft_collection, nft_token)
+ .map_err(dispatch_to_evm::<T>)?;
+
+ Ok(true)
+ }
+}
+
#[derive(ToLog)]
pub enum ERC20Events {
/// @dev This event is emitted when the amount of tokens (value) is sent
@@ -120,7 +186,7 @@
.weight_calls_budget(<StructureWeight<T>>::find_parent());
<Pallet<T>>::transfer(self, &caller, &to, self.1, amount, &budget)
- .map_err(|_| "transfer error")?;
+ .map_err(dispatch_to_evm::<T>)?;
Ok(true)
}
@@ -239,7 +305,10 @@
}
}
-#[solidity_interface(name = "UniqueRefungibleToken", is(ERC20, ERC20UniqueExtensions,))]
+#[solidity_interface(
+ name = "UniqueRefungibleToken",
+ is(ERC20, ERC20UniqueExtensions, ERC1633, ERC1633UniqueExtensions)
+)]
impl<T: Config> RefungibleTokenHandle<T> where T::AccountId: From<[u8; 32]> {}
generate_stubgen!(gen_impl, UniqueRefungibleTokenCall<()>, true);
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -99,8 +99,12 @@
use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};
use pallet_evm_coder_substrate::WithRecorder;
use pallet_common::{
- CommonCollectionOperations, Error as CommonError, Event as CommonEvent,
- eth::collection_id_to_address, Pallet as PalletCommon,
+ CollectionHandle, CommonCollectionOperations,
+ dispatch::CollectionDispatch,
+ erc::static_property::{key, property_value_from_bytes},
+ Error as CommonError,
+ eth::collection_id_to_address,
+ Event as CommonEvent, Pallet as PalletCommon,
};
use pallet_structure::Pallet as PalletStructure;
use scale_info::TypeInfo;
@@ -108,10 +112,10 @@
use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};
use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
use up_data_structs::{
- AccessMode, budget::Budget, CollectionId, CreateCollectionData, CustomDataLimit,
- mapping::TokenAddressMapping, MAX_REFUNGIBLE_PIECES, MAX_ITEMS_PER_BATCH, TokenId, Property,
- PropertyKey, PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue,
- TrySetProperty, CollectionPropertiesVec,
+ AccessMode, budget::Budget, CollectionId, CollectionMode, CollectionPropertiesVec,
+ CreateCollectionData, CustomDataLimit, mapping::TokenAddressMapping, MAX_ITEMS_PER_BATCH,
+ MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission, PropertyPermission,
+ PropertyScope, PropertyValue, TokenId, TrySetProperty,
};
use frame_support::BoundedBTreeMap;
use derivative::Derivative;
@@ -1341,6 +1345,20 @@
<PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)
}
+ pub fn set_scoped_token_property_permissions(
+ collection: &RefungibleHandle<T>,
+ sender: &T::CrossAccountId,
+ scope: PropertyScope,
+ property_permissions: Vec<PropertyKeyPermission>,
+ ) -> DispatchResult {
+ <PalletCommon<T>>::set_scoped_token_property_permissions(
+ collection,
+ sender,
+ scope,
+ property_permissions,
+ )
+ }
+
/// Returns 10 token in no particular order.
///
/// There is no direct way to get token holders in ascending order,
@@ -1362,4 +1380,68 @@
Some(res)
}
}
+
+ /// Sets the NFT token as a parent for the RFT token
+ ///
+ /// Throws if `sender` is not the owner of the NFT token.
+ /// Throws if `sender` is not the owner of all of the RFT token pieces.
+ pub fn set_parent_nft(
+ collection: &RefungibleHandle<T>,
+ rft_token_id: TokenId,
+ sender: T::CrossAccountId,
+ nft_collection: CollectionId,
+ nft_token: TokenId,
+ ) -> DispatchResult {
+ let handle = <CollectionHandle<T>>::try_get(nft_collection)?;
+ if handle.mode != CollectionMode::NFT {
+ return Err("Only NFT token could be parent to RFT".into());
+ }
+ let dispatch = T::CollectionDispatch::dispatch(handle);
+ let dispatch = dispatch.as_dyn();
+
+ let owner = dispatch.token_owner(nft_token).ok_or("owner not found")?;
+ if owner != sender {
+ return Err("Only owned token could be set as parent".into());
+ }
+
+ let nft_token_address =
+ T::CrossTokenAddressMapping::token_to_address(nft_collection, nft_token);
+
+ Self::set_parent_nft_unchecked(collection, rft_token_id, sender, nft_token_address)
+ }
+
+ /// Sets the NFT token as a parent for the RFT token
+ ///
+ /// `sender` should be the owner of the NFT token.
+ /// Throws if `sender` is not the owner of all of the RFT token pieces.
+ pub fn set_parent_nft_unchecked(
+ collection: &RefungibleHandle<T>,
+ rft_token_id: TokenId,
+ sender: T::CrossAccountId,
+ nft_token_address: T::CrossAccountId,
+ ) -> DispatchResult {
+ let owner_balance = <Balance<T>>::get((collection.id, rft_token_id, &sender));
+ let total_supply = <TotalSupply<T>>::get((collection.id, rft_token_id));
+ if total_supply != owner_balance {
+ return Err("token has multiple owners".into());
+ }
+
+ let parent_nft_property_key = key::parent_nft();
+
+ let parent_nft_property_value =
+ property_value_from_bytes(&nft_token_address.as_eth().to_fixed_bytes())
+ .expect("address should fit in value length limit");
+
+ <Pallet<T>>::set_scoped_token_property(
+ collection.id,
+ rft_token_id,
+ PropertyScope::Eth,
+ Property {
+ key: parent_nft_property_key,
+ value: parent_nft_property_value,
+ },
+ )?;
+
+ Ok(())
+ }
}
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
@@ -371,49 +371,7 @@
}
}
-// Selector: 780e9d63
-contract ERC721Enumerable is Dummy, ERC165 {
- // @notice Enumerate valid RFTs
- // @param index A counter less than `totalSupply()`
- // @return The token identifier for the `index`th NFT,
- // (sort order not specified)
- //
- // Selector: tokenByIndex(uint256) 4f6ccce7
- function tokenByIndex(uint256 index) public view returns (uint256) {
- require(false, stub_error);
- index;
- dummy;
- return 0;
- }
-
- // Not implemented
- //
- // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
- function tokenOfOwnerByIndex(address owner, uint256 index)
- public
- view
- returns (uint256)
- {
- require(false, stub_error);
- owner;
- index;
- dummy;
- return 0;
- }
-
- // @notice Count RFTs tracked by this contract
- // @return A count of valid RFTs tracked by this contract, where each one of
- // them has an assigned and queryable owner not equal to the zero address
- //
- // Selector: totalSupply() 18160ddd
- function totalSupply() public view returns (uint256) {
- require(false, stub_error);
- dummy;
- return 0;
- }
-}
-
-// Selector: 7d9262e6
+// Selector: 6cf113cd
contract Collection is Dummy, ERC165 {
// Set collection property.
//
@@ -638,9 +596,75 @@
mode;
dummy = 0;
}
+
+ // Check that account is the owner or admin of the collection
+ //
+ // @param user account to verify
+ // @return "true" if account is the owner or admin
+ //
+ // Selector: verifyOwnerOrAdmin(address) c2282493
+ function verifyOwnerOrAdmin(address user) public view returns (bool) {
+ require(false, stub_error);
+ user;
+ dummy;
+ return false;
+ }
+
+ // Returns collection type
+ //
+ // @return `Fungible` or `NFT` or `ReFungible`
+ //
+ // Selector: uniqueCollectionType() d34b55b8
+ function uniqueCollectionType() public returns (string memory) {
+ require(false, stub_error);
+ dummy = 0;
+ return "";
+ }
+}
+
+// Selector: 780e9d63
+contract ERC721Enumerable is Dummy, ERC165 {
+ // @notice Enumerate valid RFTs
+ // @param index A counter less than `totalSupply()`
+ // @return The token identifier for the `index`th NFT,
+ // (sort order not specified)
+ //
+ // Selector: tokenByIndex(uint256) 4f6ccce7
+ function tokenByIndex(uint256 index) public view returns (uint256) {
+ require(false, stub_error);
+ index;
+ dummy;
+ return 0;
+ }
+
+ // Not implemented
+ //
+ // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
+ function tokenOfOwnerByIndex(address owner, uint256 index)
+ public
+ view
+ returns (uint256)
+ {
+ require(false, stub_error);
+ owner;
+ index;
+ dummy;
+ return 0;
+ }
+
+ // @notice Count RFTs tracked by this contract
+ // @return A count of valid RFTs tracked by this contract, where each one of
+ // them has an assigned and queryable owner not equal to the zero address
+ //
+ // Selector: totalSupply() 18160ddd
+ function totalSupply() public view returns (uint256) {
+ require(false, stub_error);
+ dummy;
+ return 0;
+ }
}
-// Selector: d74d154f
+// Selector: 7c3bef89
contract ERC721UniqueExtensions is Dummy, ERC165 {
// @notice Transfer ownership of an RFT
// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
@@ -719,6 +743,18 @@
dummy = 0;
return false;
}
+
+ // Returns EVM address for refungible token
+ //
+ // @param token ID of the token
+ //
+ // Selector: tokenContractAddress(uint256) ab76fac6
+ function tokenContractAddress(uint256 token) public view returns (address) {
+ require(false, stub_error);
+ token;
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
+ }
}
contract UniqueRefungible is
pallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungibleToken.soldiffbeforeafterboth--- a/pallets/refungible/src/stubs/UniqueRefungibleToken.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungibleToken.sol
@@ -31,6 +31,38 @@
);
}
+// Selector: 042f1106
+contract ERC1633UniqueExtensions is Dummy, ERC165 {
+ // Selector: setParentNFT(address,uint256) 042f1106
+ function setParentNFT(address collection, uint256 nftId)
+ public
+ returns (bool)
+ {
+ require(false, stub_error);
+ collection;
+ nftId;
+ dummy = 0;
+ return false;
+ }
+}
+
+// Selector: 5755c3f2
+contract ERC1633 is Dummy, ERC165 {
+ // Selector: parentToken() 80a54001
+ function parentToken() public view returns (address) {
+ require(false, stub_error);
+ dummy;
+ return 0x0000000000000000000000000000000000000000;
+ }
+
+ // Selector: parentTokenId() d7f083f3
+ function parentTokenId() public view returns (uint256) {
+ require(false, stub_error);
+ dummy;
+ return 0;
+ }
+}
+
// Selector: 942e8b22
contract ERC20 is Dummy, ERC165, ERC20Events {
// @return the name of the token.
@@ -178,4 +210,11 @@
}
}
-contract UniqueRefungibleToken is Dummy, ERC165, ERC20, ERC20UniqueExtensions {}
+contract UniqueRefungibleToken is
+ Dummy,
+ ERC165,
+ ERC20,
+ ERC20UniqueExtensions,
+ ERC1633,
+ ERC1633UniqueExtensions
+{}
pallets/refungible/src/weights.rsdiffbeforeafterboth--- a/pallets/refungible/src/weights.rs
+++ b/pallets/refungible/src/weights.rs
@@ -3,7 +3,7 @@
//! Autogenerated weights for pallet_refungible
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2022-07-20, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! DATE: 2022-08-01, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
// Executed Command:
@@ -53,6 +53,8 @@
fn set_token_properties(b: u32, ) -> Weight;
fn delete_token_properties(b: u32, ) -> Weight;
fn repartition_item() -> Weight;
+ fn set_parent_nft_unchecked() -> Weight;
+ fn token_owner() -> Weight;
}
/// Weights for pallet_refungible using the Substrate node and recommended hardware.
@@ -65,7 +67,7 @@
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn create_item() -> Weight {
- (21_310_000 as Weight)
+ (25_197_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
@@ -76,9 +78,9 @@
// Storage: Refungible TokenData (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items(b: u32, ) -> Weight {
- (9_552_000 as Weight)
+ (10_852_000 as Weight)
// Standard Error: 2_000
- .saturating_add((7_056_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add((8_087_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
.saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))
@@ -90,9 +92,9 @@
// Storage: Refungible TokenData (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {
- (4_857_000 as Weight)
+ (9_978_000 as Weight)
// Standard Error: 2_000
- .saturating_add((9_838_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add((10_848_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
@@ -105,9 +107,9 @@
// Storage: Refungible Balance (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {
- (11_335_000 as Weight)
+ (15_419_000 as Weight)
// Standard Error: 2_000
- .saturating_add((6_784_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add((7_813_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
@@ -118,7 +120,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn burn_item_partial() -> Weight {
- (21_239_000 as Weight)
+ (25_578_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
@@ -130,13 +132,13 @@
// Storage: Refungible Owned (r:0 w:1)
// Storage: Refungible TokenProperties (r:0 w:1)
fn burn_item_fully() -> Weight {
- (29_426_000 as Weight)
+ (33_593_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(7 as Weight))
}
// Storage: Refungible Balance (r:2 w:2)
fn transfer_normal() -> Weight {
- (17_743_000 as Weight)
+ (21_049_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
@@ -144,7 +146,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_creating() -> Weight {
- (20_699_000 as Weight)
+ (24_646_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
@@ -152,7 +154,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_removing() -> Weight {
- (22_833_000 as Weight)
+ (26_570_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(4 as Weight))
}
@@ -160,21 +162,21 @@
// Storage: Refungible AccountBalance (r:2 w:2)
// Storage: Refungible Owned (r:0 w:2)
fn transfer_creating_removing() -> Weight {
- (24_936_000 as Weight)
+ (28_906_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
// Storage: Refungible Balance (r:1 w:0)
// Storage: Refungible Allowance (r:0 w:1)
fn approve() -> Weight {
- (13_446_000 as Weight)
+ (16_451_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Refungible Allowance (r:1 w:1)
// Storage: Refungible Balance (r:2 w:2)
fn transfer_from_normal() -> Weight {
- (24_777_000 as Weight)
+ (29_545_000 as Weight)
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
@@ -183,7 +185,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_from_creating() -> Weight {
- (28_483_000 as Weight)
+ (33_392_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
@@ -192,7 +194,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_from_removing() -> Weight {
- (29_896_000 as Weight)
+ (35_446_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
}
@@ -201,7 +203,7 @@
// Storage: Refungible AccountBalance (r:2 w:2)
// Storage: Refungible Owned (r:0 w:2)
fn transfer_from_creating_removing() -> Weight {
- (32_070_000 as Weight)
+ (37_762_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(7 as Weight))
}
@@ -214,15 +216,15 @@
// Storage: Refungible Owned (r:0 w:1)
// Storage: Refungible TokenProperties (r:0 w:1)
fn burn_from() -> Weight {
- (36_789_000 as Weight)
+ (42_620_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(8 as Weight))
}
// Storage: Common CollectionPropertyPermissions (r:1 w:1)
fn set_token_property_permissions(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 62_000
- .saturating_add((15_803_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 65_000
+ .saturating_add((16_513_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
@@ -230,8 +232,8 @@
// Storage: Refungible TokenProperties (r:1 w:1)
fn set_token_properties(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 1_668_000
- .saturating_add((302_308_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 1_583_000
+ .saturating_add((291_392_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
@@ -239,18 +241,31 @@
// Storage: Refungible TokenProperties (r:1 w:1)
fn delete_token_properties(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 1_619_000
- .saturating_add((294_574_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 1_699_000
+ .saturating_add((293_270_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Refungible TotalSupply (r:1 w:1)
// Storage: Refungible Balance (r:1 w:1)
fn repartition_item() -> Weight {
- (8_325_000 as Weight)
+ (19_206_000 as Weight)
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
+ // Storage: Refungible Balance (r:1 w:0)
+ // Storage: Refungible TotalSupply (r:1 w:0)
+ // Storage: Refungible TokenProperties (r:1 w:1)
+ fn set_parent_nft_unchecked() -> Weight {
+ (10_189_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(3 as Weight))
+ .saturating_add(T::DbWeight::get().writes(1 as Weight))
+ }
+ // Storage: Refungible Balance (r:2 w:0)
+ fn token_owner() -> Weight {
+ (8_205_000 as Weight)
+ .saturating_add(T::DbWeight::get().reads(2 as Weight))
+ }
}
// For backwards compatibility and tests
@@ -262,7 +277,7 @@
// Storage: Refungible TokenData (r:0 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn create_item() -> Weight {
- (21_310_000 as Weight)
+ (25_197_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
@@ -273,9 +288,9 @@
// Storage: Refungible TokenData (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items(b: u32, ) -> Weight {
- (9_552_000 as Weight)
+ (10_852_000 as Weight)
// Standard Error: 2_000
- .saturating_add((7_056_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add((8_087_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
.saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))
@@ -287,9 +302,9 @@
// Storage: Refungible TokenData (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {
- (4_857_000 as Weight)
+ (9_978_000 as Weight)
// Standard Error: 2_000
- .saturating_add((9_838_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add((10_848_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
@@ -302,9 +317,9 @@
// Storage: Refungible Balance (r:0 w:4)
// Storage: Refungible Owned (r:0 w:4)
fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {
- (11_335_000 as Weight)
+ (15_419_000 as Weight)
// Standard Error: 2_000
- .saturating_add((6_784_000 as Weight).saturating_mul(b as Weight))
+ .saturating_add((7_813_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
@@ -315,7 +330,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn burn_item_partial() -> Weight {
- (21_239_000 as Weight)
+ (25_578_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
@@ -327,13 +342,13 @@
// Storage: Refungible Owned (r:0 w:1)
// Storage: Refungible TokenProperties (r:0 w:1)
fn burn_item_fully() -> Weight {
- (29_426_000 as Weight)
+ (33_593_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(7 as Weight))
}
// Storage: Refungible Balance (r:2 w:2)
fn transfer_normal() -> Weight {
- (17_743_000 as Weight)
+ (21_049_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
@@ -341,7 +356,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_creating() -> Weight {
- (20_699_000 as Weight)
+ (24_646_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
@@ -349,7 +364,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_removing() -> Weight {
- (22_833_000 as Weight)
+ (26_570_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
}
@@ -357,21 +372,21 @@
// Storage: Refungible AccountBalance (r:2 w:2)
// Storage: Refungible Owned (r:0 w:2)
fn transfer_creating_removing() -> Weight {
- (24_936_000 as Weight)
+ (28_906_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(6 as Weight))
}
// Storage: Refungible Balance (r:1 w:0)
// Storage: Refungible Allowance (r:0 w:1)
fn approve() -> Weight {
- (13_446_000 as Weight)
+ (16_451_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Refungible Allowance (r:1 w:1)
// Storage: Refungible Balance (r:2 w:2)
fn transfer_from_normal() -> Weight {
- (24_777_000 as Weight)
+ (29_545_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
@@ -380,7 +395,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_from_creating() -> Weight {
- (28_483_000 as Weight)
+ (33_392_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
@@ -389,7 +404,7 @@
// Storage: Refungible AccountBalance (r:1 w:1)
// Storage: Refungible Owned (r:0 w:1)
fn transfer_from_removing() -> Weight {
- (29_896_000 as Weight)
+ (35_446_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
}
@@ -398,7 +413,7 @@
// Storage: Refungible AccountBalance (r:2 w:2)
// Storage: Refungible Owned (r:0 w:2)
fn transfer_from_creating_removing() -> Weight {
- (32_070_000 as Weight)
+ (37_762_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(7 as Weight))
}
@@ -411,15 +426,15 @@
// Storage: Refungible Owned (r:0 w:1)
// Storage: Refungible TokenProperties (r:0 w:1)
fn burn_from() -> Weight {
- (36_789_000 as Weight)
+ (42_620_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(8 as Weight))
}
// Storage: Common CollectionPropertyPermissions (r:1 w:1)
fn set_token_property_permissions(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 62_000
- .saturating_add((15_803_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 65_000
+ .saturating_add((16_513_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
@@ -427,8 +442,8 @@
// Storage: Refungible TokenProperties (r:1 w:1)
fn set_token_properties(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 1_668_000
- .saturating_add((302_308_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 1_583_000
+ .saturating_add((291_392_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
@@ -436,16 +451,29 @@
// Storage: Refungible TokenProperties (r:1 w:1)
fn delete_token_properties(b: u32, ) -> Weight {
(0 as Weight)
- // Standard Error: 1_619_000
- .saturating_add((294_574_000 as Weight).saturating_mul(b as Weight))
+ // Standard Error: 1_699_000
+ .saturating_add((293_270_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Refungible TotalSupply (r:1 w:1)
// Storage: Refungible Balance (r:1 w:1)
fn repartition_item() -> Weight {
- (8_325_000 as Weight)
+ (19_206_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(2 as Weight))
}
+ // Storage: Refungible Balance (r:1 w:0)
+ // Storage: Refungible TotalSupply (r:1 w:0)
+ // Storage: Refungible TokenProperties (r:1 w:1)
+ fn set_parent_nft_unchecked() -> Weight {
+ (10_189_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(3 as Weight))
+ .saturating_add(RocksDbWeight::get().writes(1 as Weight))
+ }
+ // Storage: Refungible Balance (r:2 w:0)
+ fn token_owner() -> Weight {
+ (8_205_000 as Weight)
+ .saturating_add(RocksDbWeight::get().reads(2 as Weight))
+ }
}
pallets/unique/src/eth/mod.rsdiffbeforeafterboth--- a/pallets/unique/src/eth/mod.rs
+++ b/pallets/unique/src/eth/mod.rs
@@ -17,26 +17,29 @@
//! Implementation of CollectionHelpers contract.
use core::marker::PhantomData;
-use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*};
use ethereum as _;
-use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
-use pallet_evm::{OnMethodCall, PrecompileResult, account::CrossAccountId, PrecompileHandle};
-use up_data_structs::{
- CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,
- CollectionMode, PropertyValue,
-};
+use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*};
use frame_support::traits::Get;
use pallet_common::{
- CollectionById,
+ CollectionById, CollectionHandle,
+ dispatch::CollectionDispatch,
erc::{
+ CollectionHelpersEvents,
static_property::{key, value as property_value},
- CollectionHelpersEvents,
},
- dispatch::CollectionDispatch,
+ Pallet as PalletCommon,
};
-use crate::{SelfWeightOf, Config, weights::WeightInfo};
+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,
+};
+
+use crate::{Config, SelfWeightOf, weights::WeightInfo};
-use sp_std::vec::Vec;
+use sp_std::{vec, vec::Vec};
use alloc::format;
/// See [`CollectionHelpersCall`]
@@ -151,6 +154,54 @@
Ok(data)
}
+fn parent_nft_property_permissions() -> PropertyKeyPermission {
+ PropertyKeyPermission {
+ key: key::parent_nft(),
+ permission: PropertyPermission {
+ mutable: false,
+ collection_admin: false,
+ token_owner: true,
+ },
+ }
+}
+
+fn create_refungible_collection_internal<
+ T: Config + pallet_nonfungible::Config + pallet_refungible::Config,
+>(
+ caller: caller,
+ name: string,
+ description: string,
+ token_prefix: string,
+ base_uri: string,
+ add_properties: bool,
+) -> Result<address> {
+ let (caller, name, description, token_prefix, base_uri_value) =
+ convert_data::<T>(caller, name, description, token_prefix, base_uri)?;
+ let data = make_data::<T>(
+ name,
+ CollectionMode::ReFungible,
+ description,
+ token_prefix,
+ base_uri_value,
+ add_properties,
+ )?;
+
+ let collection_id = T::CollectionDispatch::create(caller.clone(), data)
+ .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
+
+ let handle = <CollectionHandle<T>>::try_get(collection_id).map_err(dispatch_to_evm::<T>)?;
+ <PalletCommon<T>>::set_scoped_token_property_permissions(
+ &handle,
+ &caller,
+ PropertyScope::Eth,
+ vec![parent_nft_property_permissions()],
+ )
+ .map_err(dispatch_to_evm::<T>)?;
+
+ let address = pallet_common::eth::collection_id_to_address(collection_id);
+ Ok(address)
+}
+
/// @title Contract, which allows users to operate with collections
#[solidity_interface(name = "CollectionHelpers", events(CollectionHelpersEvents))]
impl<T> EvmCollectionHelpers<T>
@@ -216,27 +267,20 @@
#[weight(<SelfWeightOf<T>>::create_collection())]
fn create_refungible_collection(
- &self,
+ &mut self,
caller: caller,
name: string,
description: string,
token_prefix: string,
) -> Result<address> {
- let (caller, name, description, token_prefix, _base_uri) =
- convert_data::<T>(caller, name, description, token_prefix, "".into())?;
- let data = make_data::<T>(
+ create_refungible_collection_internal::<T>(
+ caller,
name,
- CollectionMode::ReFungible,
description,
token_prefix,
Default::default(),
false,
- )?;
- let collection_id = T::CollectionDispatch::create(caller, data)
- .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
-
- let address = pallet_common::eth::collection_id_to_address(collection_id);
- Ok(address)
+ )
}
#[weight(<SelfWeightOf<T>>::create_collection())]
@@ -249,21 +293,14 @@
token_prefix: string,
base_uri: string,
) -> Result<address> {
- let (caller, name, description, token_prefix, base_uri_value) =
- convert_data::<T>(caller, name, description, token_prefix, base_uri)?;
- let data = make_data::<T>(
+ create_refungible_collection_internal::<T>(
+ caller,
name,
- CollectionMode::NFT,
description,
token_prefix,
- base_uri_value,
+ base_uri,
true,
- )?;
- let collection_id = T::CollectionDispatch::create(caller, data)
- .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
-
- let address = pallet_common::eth::collection_id_to_address(collection_id);
- Ok(address)
+ )
}
/// Check if a collection exists
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
@@ -72,12 +72,12 @@
string memory name,
string memory description,
string memory tokenPrefix
- ) public view returns (address) {
+ ) public returns (address) {
require(false, stub_error);
name;
description;
tokenPrefix;
- dummy;
+ dummy = 0;
return 0x0000000000000000000000000000000000000000;
}
primitives/common/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/primitives/common/Cargo.toml
@@ -0,0 +1,56 @@
+[package]
+authors = ['Unique Network <support@uniquenetwork.io>']
+description = 'Unique Runtime Common Primitives'
+edition = '2021'
+homepage = 'https://unique.network'
+license = 'All Rights Reserved'
+name = 'up-common'
+repository = 'https://github.com/UniqueNetwork/unique-chain'
+version = '0.9.24'
+
+[features]
+default = ['std']
+std = [
+ 'sp-std/std',
+ 'frame-support/std',
+ 'sp-runtime/std',
+ 'sp-core/std',
+ 'sp-consensus-aura/std',
+ 'fp-rpc/std',
+ 'pallet-evm/std',
+]
+
+[dependencies.sp-std]
+default-features = false
+git = "https://github.com/paritytech/substrate"
+branch = "polkadot-v0.9.24"
+
+[dependencies.frame-support]
+default-features = false
+git = "https://github.com/paritytech/substrate"
+branch = "polkadot-v0.9.24"
+
+[dependencies.sp-runtime]
+default-features = false
+git = "https://github.com/paritytech/substrate"
+branch = "polkadot-v0.9.24"
+
+[dependencies.sp-core]
+default-features = false
+git = "https://github.com/paritytech/substrate"
+branch = "polkadot-v0.9.24"
+
+[dependencies.sp-consensus-aura]
+default-features = false
+git = "https://github.com/paritytech/substrate"
+branch = "polkadot-v0.9.24"
+
+[dependencies.fp-rpc]
+default-features = false
+git = "https://github.com/uniquenetwork/frontier"
+branch = "unique-polkadot-v0.9.24"
+
+[dependencies.pallet-evm]
+default-features = false
+git = "https://github.com/uniquenetwork/frontier"
+branch = "unique-polkadot-v0.9.24"
primitives/common/src/constants.rsdiffbeforeafterboth--- /dev/null
+++ b/primitives/common/src/constants.rs
@@ -0,0 +1,55 @@
+// 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/>.
+
+use sp_runtime::Perbill;
+use frame_support::{
+ parameter_types,
+ weights::{Weight, constants::WEIGHT_PER_SECOND},
+};
+use crate::types::{BlockNumber, Balance};
+
+pub const MILLISECS_PER_BLOCK: u64 = 12000;
+
+pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
+
+// These time units are defined in number of blocks.
+pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
+pub const HOURS: BlockNumber = MINUTES * 60;
+pub const DAYS: BlockNumber = HOURS * 24;
+
+pub const MICROUNIQUE: Balance = 1_000_000_000_000;
+pub const MILLIUNIQUE: Balance = 1_000 * MICROUNIQUE;
+pub const CENTIUNIQUE: Balance = 10 * MILLIUNIQUE;
+pub const UNIQUE: Balance = 100 * CENTIUNIQUE;
+
+// Targeting 0.1 UNQ per transfer
+pub const WEIGHT_TO_FEE_COEFF: u32 = /*<weight2fee>*/207_267_232/*</weight2fee>*/;
+
+// Targeting 0.15 UNQ per transfer via ETH
+pub const MIN_GAS_PRICE: u64 = /*<mingasprice>*/1_019_488_372_383/*</mingasprice>*/;
+
+/// We assume that ~10% of the block weight is consumed by `on_initalize` handlers.
+/// This is used to limit the maximal weight of a single extrinsic.
+pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
+/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used
+/// by Operational extrinsics.
+pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
+/// We allow for 2 seconds of compute with a 6 second average block time.
+pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND / 2;
+
+parameter_types! {
+ pub const TransactionByteFee: Balance = 501 * MICROUNIQUE;
+}
primitives/common/src/lib.rsdiffbeforeafterboth--- /dev/null
+++ b/primitives/common/src/lib.rs
@@ -0,0 +1,20 @@
+// 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/>.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+pub mod constants;
+pub mod types;
primitives/common/src/types.rsdiffbeforeafterboth--- /dev/null
+++ b/primitives/common/src/types.rs
@@ -0,0 +1,81 @@
+// 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/>.
+
+use sp_runtime::{
+ generic,
+ traits::{Verify, IdentifyAccount},
+ MultiSignature,
+};
+
+/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
+/// the specifics of the runtime. They can then be made to be agnostic over specific formats
+/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
+/// to even the core data structures.
+pub mod opaque {
+ pub use sp_runtime::{generic, traits::BlakeTwo256, OpaqueExtrinsic as UncheckedExtrinsic};
+
+ pub use super::{BlockNumber, Signature, AccountId, Balance, Index, Hash, AuraId};
+
+ /// Opaque block header type.
+ pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
+
+ /// Opaque block type.
+ pub type Block = generic::Block<Header, UncheckedExtrinsic>;
+
+ pub trait RuntimeInstance {
+ type CrossAccountId: pallet_evm::account::CrossAccountId<sp_runtime::AccountId32>
+ + Send
+ + Sync
+ + 'static;
+
+ type TransactionConverter: fp_rpc::ConvertTransaction<UncheckedExtrinsic>
+ + Send
+ + Sync
+ + 'static;
+
+ fn get_transaction_converter() -> Self::TransactionConverter;
+ }
+}
+
+pub type SessionHandlers = ();
+
+/// An index to a block.
+pub type BlockNumber = u32;
+
+/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
+pub type Signature = MultiSignature;
+
+/// Some way of identifying an account on the chain. We intentionally make it equivalent
+/// to the public key of our transaction signing scheme.
+pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
+
+/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
+/// never know...
+pub type AccountIndex = u32;
+
+/// Balance of an account.
+pub type Balance = u128;
+
+/// Index of a transaction in the chain.
+pub type Index = u32;
+
+/// A hash of some data used by the chain.
+pub type Hash = sp_core::H256;
+
+/// Digest item type.
+pub type DigestItem = generic::DigestItem;
+
+pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -1050,6 +1050,7 @@
pub enum PropertyScope {
None,
Rmrk,
+ Eth,
}
impl PropertyScope {
@@ -1058,6 +1059,7 @@
let scope_str: &[u8] = match self {
Self::None => return Ok(key),
Self::Rmrk => b"rmrk",
+ Self::Eth => b"eth",
};
[scope_str, b":", key.as_slice()]
runtime/common/CHANGELOG.mddiffbeforeafterboth--- a/runtime/common/CHANGELOG.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Change Log
-
-All notable changes to this project will be documented in this file.
-
-## [0.9.25] - 2022-07-14
-
-### Added
-
- - Implementation of RPC method `token_owners` returning 10 owners in no particular order.
- This was an internal request to improve the web interface and support fractionalization event.
-
-
-
\ No newline at end of file
runtime/common/Cargo.tomldiffbeforeafterboth--- a/runtime/common/Cargo.toml
+++ /dev/null
@@ -1,115 +0,0 @@
-[package]
-authors = ['Unique Network <support@uniquenetwork.io>']
-description = 'Unique Runtime Common'
-edition = '2021'
-homepage = 'https://unique.network'
-license = 'All Rights Reserved'
-name = 'unique-runtime-common'
-repository = 'https://github.com/UniqueNetwork/unique-chain'
-version = '0.9.24'
-
-[features]
-default = ['std']
-std = [
- 'sp-core/std',
- 'sp-std/std',
- 'sp-runtime/std',
- 'codec/std',
- 'frame-support/std',
- 'frame-system/std',
- 'sp-consensus-aura/std',
- 'pallet-common/std',
- 'pallet-unique/std',
- 'pallet-fungible/std',
- 'pallet-nonfungible/std',
- 'pallet-refungible/std',
- 'up-data-structs/std',
- 'pallet-evm/std',
- 'fp-rpc/std',
-]
-runtime-benchmarks = [
- 'sp-runtime/runtime-benchmarks',
- 'frame-support/runtime-benchmarks',
- 'frame-system/runtime-benchmarks',
-]
-
-[dependencies.sp-core]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.24"
-
-[dependencies.sp-std]
-default-features = false
-git = 'https://github.com/paritytech/substrate'
-branch = 'polkadot-v0.9.24'
-
-[dependencies.sp-runtime]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.24"
-
-[dependencies.codec]
-default-features = false
-features = ['derive']
-package = 'parity-scale-codec'
-version = '3.1.2'
-
-[dependencies.scale-info]
-default-features = false
-features = ["derive"]
-version = "2.0.1"
-
-[dependencies.frame-support]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.24"
-
-[dependencies.frame-system]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.24"
-
-[dependencies.pallet-common]
-default-features = false
-path = "../../pallets/common"
-
-[dependencies.pallet-unique]
-default-features = false
-path = "../../pallets/unique"
-
-[dependencies.pallet-fungible]
-default-features = false
-path = "../../pallets/fungible"
-
-[dependencies.pallet-nonfungible]
-default-features = false
-path = "../../pallets/nonfungible"
-
-[dependencies.pallet-refungible]
-default-features = false
-path = "../../pallets/refungible"
-
-[dependencies.pallet-unique-scheduler]
-default-features = false
-path = "../../pallets/scheduler"
-
-[dependencies.up-data-structs]
-default-features = false
-path = "../../primitives/data-structs"
-
-[dependencies.sp-consensus-aura]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.24"
-
-[dependencies.fp-rpc]
-default-features = false
-git = "https://github.com/uniquenetwork/frontier"
-branch = "unique-polkadot-v0.9.24"
-
-[dependencies]
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
-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.24' }
-
-rmrk-rpc = { default-features = false, path = "../../primitives/rmrk-rpc" }
runtime/common/config/ethereum.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/config/ethereum.rs
@@ -0,0 +1,124 @@
+use sp_core::{U256, H160};
+use frame_support::{
+ weights::{Weight, constants::WEIGHT_PER_SECOND},
+ traits::{FindAuthor},
+ parameter_types, ConsensusEngineId,
+};
+use sp_runtime::{RuntimeAppPublic, Perbill};
+use crate::{
+ runtime_common::{
+ dispatch::CollectionDispatchT, ethereum::sponsoring::EvmSponsorshipHandler,
+ config::sponsoring::DefaultSponsoringRateLimit, DealWithFees,
+ },
+ Runtime, Aura, Balances, Event, ChainId,
+};
+use pallet_evm::{EnsureAddressTruncated, HashedAddressMapping};
+use up_common::constants::*;
+
+pub type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;
+
+impl pallet_evm::account::Config for Runtime {
+ type CrossAccountId = CrossAccountId;
+ type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;
+ type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;
+}
+
+// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case
+// (contract, which only writes a lot of data),
+// approximating on top of our real store write weight
+parameter_types! {
+ pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;
+ pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;
+ pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();
+}
+
+/// Limiting EVM execution to 50% of block for substrate users and management tasks
+/// EVM transaction consumes more weight than substrate's, so we can't rely on them being
+/// scheduled fairly
+const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);
+parameter_types! {
+ pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());
+}
+
+pub enum FixedGasWeightMapping {}
+impl pallet_evm::GasWeightMapping for FixedGasWeightMapping {
+ fn gas_to_weight(gas: u64) -> Weight {
+ gas.saturating_mul(WeightPerGas::get())
+ }
+ fn weight_to_gas(weight: Weight) -> u64 {
+ weight / WeightPerGas::get()
+ }
+}
+
+pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);
+impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {
+ fn find_author<'a, I>(digests: I) -> Option<H160>
+ where
+ I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
+ {
+ if let Some(author_index) = F::find_author(digests) {
+ let authority_id = Aura::authorities()[author_index as usize].clone();
+ return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));
+ }
+ None
+ }
+}
+
+impl pallet_evm::Config for Runtime {
+ type BlockGasLimit = BlockGasLimit;
+ type FeeCalculator = pallet_configuration::FeeCalculator<Self>;
+ type GasWeightMapping = FixedGasWeightMapping;
+ type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
+ type CallOrigin = EnsureAddressTruncated<Self>;
+ type WithdrawOrigin = EnsureAddressTruncated<Self>;
+ type AddressMapping = HashedAddressMapping<Self::Hashing>;
+ type PrecompilesType = ();
+ type PrecompilesValue = ();
+ type Currency = Balances;
+ type Event = Event;
+ type OnMethodCall = (
+ pallet_evm_migration::OnMethodCall<Self>,
+ pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,
+ CollectionDispatchT<Self>,
+ pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,
+ );
+ type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
+ type ChainId = ChainId;
+ type Runner = pallet_evm::runner::stack::Runner<Self>;
+ type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;
+ type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;
+ type FindAuthor = EthereumFindAuthor<Aura>;
+}
+
+impl pallet_evm_migration::Config for Runtime {
+ type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;
+}
+
+impl pallet_ethereum::Config for Runtime {
+ type Event = Event;
+ type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;
+}
+
+parameter_types! {
+ // 0x842899ECF380553E8a4de75bF534cdf6fBF64049
+ pub const HelpersContractAddress: H160 = H160([
+ 0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,
+ ]);
+
+ // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f
+ pub const EvmCollectionHelpersAddress: H160 = H160([
+ 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,
+ ]);
+}
+
+impl pallet_evm_contract_helpers::Config for Runtime {
+ type ContractAddress = HelpersContractAddress;
+ type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
+}
+
+impl pallet_evm_coder_substrate::Config for Runtime {}
+
+impl pallet_evm_transaction_payment::Config for Runtime {
+ type EvmSponsorshipHandler = EvmSponsorshipHandler;
+ type Currency = Balances;
+}
runtime/common/config/mod.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/config/mod.rs
@@ -0,0 +1,23 @@
+// 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/>.
+
+pub mod ethereum;
+pub mod orml;
+pub mod pallets;
+pub mod parachain;
+pub mod sponsoring;
+pub mod substrate;
+pub mod xcm;
runtime/common/config/orml.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/config/orml.rs
@@ -0,0 +1,38 @@
+// 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/>.
+
+use frame_support::parameter_types;
+use frame_system::EnsureSigned;
+use crate::{Runtime, Event, RelayChainBlockNumberProvider};
+use up_common::{
+ types::{AccountId, Balance},
+ constants::*,
+};
+
+parameter_types! {
+ pub const MinVestedTransfer: Balance = 10 * UNIQUE;
+ pub const MaxVestingSchedules: u32 = 28;
+}
+
+impl orml_vesting::Config for Runtime {
+ type Event = Event;
+ type Currency = pallet_balances::Pallet<Runtime>;
+ type MinVestedTransfer = MinVestedTransfer;
+ type VestedTransferOrigin = EnsureSigned<AccountId>;
+ type WeightInfo = ();
+ type MaxVestingSchedules = MaxVestingSchedules;
+ type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
+}
runtime/common/config/pallets/mod.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/config/pallets/mod.rs
@@ -0,0 +1,99 @@
+// 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/>.
+
+use frame_support::parameter_types;
+use sp_runtime::traits::AccountIdConversion;
+use crate::{
+ runtime_common::{
+ dispatch::CollectionDispatchT,
+ config::{substrate::TreasuryModuleId, ethereum::EvmCollectionHelpersAddress},
+ weights::CommonWeights,
+ RelayChainBlockNumberProvider,
+ },
+ Runtime, Event, Call, Balances,
+};
+use frame_support::traits::{ConstU32, ConstU64};
+use up_common::{
+ types::{AccountId, Balance, BlockNumber},
+ constants::*,
+};
+use up_data_structs::{
+ mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},
+};
+
+#[cfg(feature = "rmrk")]
+pub mod rmrk;
+
+#[cfg(feature = "scheduler")]
+pub mod scheduler;
+
+parameter_types! {
+ pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();
+ pub const CollectionCreationPrice: Balance = 2 * UNIQUE;
+}
+
+impl pallet_common::Config for Runtime {
+ type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;
+ type Event = Event;
+ type Currency = Balances;
+ type CollectionCreationPrice = CollectionCreationPrice;
+ type TreasuryAccountId = TreasuryAccountId;
+ type CollectionDispatch = CollectionDispatchT<Self>;
+
+ type EvmTokenAddressMapping = EvmTokenAddressMapping;
+ type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
+ type ContractAddress = EvmCollectionHelpersAddress;
+}
+
+impl pallet_structure::Config for Runtime {
+ type Event = Event;
+ type Call = Call;
+ type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;
+}
+
+impl pallet_fungible::Config for Runtime {
+ type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;
+}
+impl pallet_refungible::Config for Runtime {
+ type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;
+}
+impl pallet_nonfungible::Config for Runtime {
+ type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;
+}
+
+parameter_types! {
+ pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied
+}
+
+/// Used for the pallet inflation
+impl pallet_inflation::Config for Runtime {
+ type Currency = Balances;
+ type TreasuryAccountId = TreasuryAccountId;
+ type InflationBlockInterval = InflationBlockInterval;
+ type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
+}
+
+impl pallet_unique::Config for Runtime {
+ type Event = Event;
+ type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
+ type CommonWeightInfo = CommonWeights<Self>;
+ type RefungibleExtensionsWeightInfo = CommonWeights<Self>;
+}
+
+impl pallet_configuration::Config for Runtime {
+ type DefaultWeightToFeeCoefficient = ConstU32<{ up_common::constants::WEIGHT_TO_FEE_COEFF }>;
+ type DefaultMinGasPrice = ConstU64<{ up_common::constants::MIN_GAS_PRICE }>;
+}
runtime/common/config/pallets/rmrk.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/config/pallets/rmrk.rs
@@ -0,0 +1,27 @@
+// 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/>.
+
+use crate::{Runtime, Event};
+
+impl pallet_proxy_rmrk_core::Config for Runtime {
+ type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
+ type Event = Event;
+}
+
+impl pallet_proxy_rmrk_equip::Config for Runtime {
+ type WeightInfo = pallet_proxy_rmrk_equip::weights::SubstrateWeight<Self>;
+ type Event = Event;
+}
runtime/common/config/pallets/scheduler.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/config/pallets/scheduler.rs
@@ -0,0 +1,59 @@
+// 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/>.
+
+use frame_support::{traits::PrivilegeCmp, weights::Weight, parameter_types};
+use frame_system::EnsureSigned;
+use sp_runtime::Perbill;
+use sp_std::cmp::Ordering;
+use crate::{
+ runtime_common::{scheduler::SchedulerPaymentExecutor, config::substrate::RuntimeBlockWeights},
+ Runtime, Call, Event, Origin, OriginCaller, Balances,
+};
+use up_common::types::AccountId;
+
+parameter_types! {
+ pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *
+ RuntimeBlockWeights::get().max_block;
+ pub const MaxScheduledPerBlock: u32 = 50;
+
+ pub const NoPreimagePostponement: Option<u32> = Some(10);
+ pub const Preimage: Option<u32> = Some(10);
+}
+
+/// Used the compare the privilege of an origin inside the scheduler.
+pub struct OriginPrivilegeCmp;
+
+impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {
+ fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {
+ Some(Ordering::Equal)
+ }
+}
+
+impl pallet_unique_scheduler::Config for Runtime {
+ type Event = Event;
+ type Origin = Origin;
+ type Currency = Balances;
+ type PalletsOrigin = OriginCaller;
+ type Call = Call;
+ type MaximumWeight = MaximumSchedulerWeight;
+ type ScheduleOrigin = EnsureSigned<AccountId>;
+ type MaxScheduledPerBlock = MaxScheduledPerBlock;
+ type WeightInfo = ();
+ type CallExecutor = SchedulerPaymentExecutor;
+ type OriginPrivilegeCmp = OriginPrivilegeCmp;
+ type PreimageProvider = ();
+ type NoPreimagePostponement = NoPreimagePostponement;
+}
runtime/common/config/parachain.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/config/parachain.rs
@@ -0,0 +1,44 @@
+// 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/>.
+
+use frame_support::{weights::Weight, parameter_types};
+use crate::{Runtime, Event, XcmpQueue, DmpQueue};
+use up_common::constants::*;
+
+parameter_types! {
+ pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
+ pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
+}
+
+impl cumulus_pallet_parachain_system::Config for Runtime {
+ type Event = Event;
+ type SelfParaId = parachain_info::Pallet<Self>;
+ type OnSystemEvent = ();
+ // type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<
+ // MaxDownwardMessageWeight,
+ // XcmExecutor<XcmConfig>,
+ // Call,
+ // >;
+ type OutboundXcmpMessageSource = XcmpQueue;
+ type DmpMessageHandler = DmpQueue;
+ type ReservedDmpWeight = ReservedDmpWeight;
+ type ReservedXcmpWeight = ReservedXcmpWeight;
+ type XcmpMessageHandler = XcmpQueue;
+}
+
+impl parachain_info::Config for Runtime {}
+
+impl cumulus_pallet_aura_ext::Config for Runtime {}
runtime/common/config/sponsoring.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/config/sponsoring.rs
@@ -0,0 +1,35 @@
+// 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/>.
+
+use frame_support::parameter_types;
+use crate::{
+ runtime_common::{sponsoring::UniqueSponsorshipHandler},
+ Runtime,
+};
+use up_common::{types::BlockNumber, constants::*};
+
+parameter_types! {
+ pub const DefaultSponsoringRateLimit: BlockNumber = 1 * DAYS;
+}
+
+type SponsorshipHandler = (
+ UniqueSponsorshipHandler<Runtime>,
+ pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,
+);
+
+impl pallet_charge_transaction::Config for Runtime {
+ type SponsorshipHandler = SponsorshipHandler;
+}
runtime/common/config/substrate.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/config/substrate.rs
@@ -0,0 +1,215 @@
+// 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/>.
+
+use frame_support::{
+ traits::{Everything, ConstU32},
+ weights::{
+ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight},
+ DispatchClass, ConstantMultiplier,
+ },
+ parameter_types, PalletId,
+};
+use sp_runtime::{
+ generic,
+ traits::{BlakeTwo256, AccountIdLookup},
+ Perbill, Permill, Percent,
+};
+use frame_system::{
+ limits::{BlockLength, BlockWeights},
+ EnsureRoot,
+};
+use crate::{
+ runtime_common::DealWithFees, Runtime, Event, Call, Origin, PalletInfo, System, Balances,
+ Treasury, SS58Prefix, Version,
+};
+use up_common::{types::*, constants::*};
+
+parameter_types! {
+ pub const BlockHashCount: BlockNumber = 2400;
+ pub RuntimeBlockLength: BlockLength =
+ BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
+ pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
+ pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
+ pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
+ .base_block(BlockExecutionWeight::get())
+ .for_class(DispatchClass::all(), |weights| {
+ weights.base_extrinsic = ExtrinsicBaseWeight::get();
+ })
+ .for_class(DispatchClass::Normal, |weights| {
+ weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
+ })
+ .for_class(DispatchClass::Operational, |weights| {
+ weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
+ // Operational transactions have some extra reserved space, so that they
+ // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
+ weights.reserved = Some(
+ MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
+ );
+ })
+ .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
+ .build_or_panic();
+}
+
+impl frame_system::Config for Runtime {
+ /// The data to be stored in an account.
+ type AccountData = pallet_balances::AccountData<Balance>;
+ /// The identifier used to distinguish between accounts.
+ type AccountId = AccountId;
+ /// The basic call filter to use in dispatchable.
+ type BaseCallFilter = Everything;
+ /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
+ type BlockHashCount = BlockHashCount;
+ /// The maximum length of a block (in bytes).
+ type BlockLength = RuntimeBlockLength;
+ /// The index type for blocks.
+ type BlockNumber = BlockNumber;
+ /// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.
+ type BlockWeights = RuntimeBlockWeights;
+ /// The aggregated dispatch type that is available for extrinsics.
+ type Call = Call;
+ /// The weight of database operations that the runtime can invoke.
+ type DbWeight = RocksDbWeight;
+ /// The ubiquitous event type.
+ type Event = Event;
+ /// The type for hashing blocks and tries.
+ type Hash = Hash;
+ /// The hashing algorithm used.
+ type Hashing = BlakeTwo256;
+ /// The header type.
+ type Header = generic::Header<BlockNumber, BlakeTwo256>;
+ /// The index type for storing how many extrinsics an account has signed.
+ type Index = Index;
+ /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
+ type Lookup = AccountIdLookup<AccountId, ()>;
+ /// What to do if an account is fully reaped from the system.
+ type OnKilledAccount = ();
+ /// What to do if a new account is created.
+ type OnNewAccount = ();
+ type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
+ /// The ubiquitous origin type.
+ type Origin = Origin;
+ /// This type is being generated by `construct_runtime!`.
+ type PalletInfo = PalletInfo;
+ /// This is used as an identifier of the chain. 42 is the generic substrate prefix.
+ type SS58Prefix = SS58Prefix;
+ /// Weight information for the extrinsics of this pallet.
+ type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;
+ /// Version of the runtime.
+ type Version = Version;
+ type MaxConsumers = ConstU32<16>;
+}
+
+impl pallet_randomness_collective_flip::Config for Runtime {}
+
+parameter_types! {
+ pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
+}
+
+impl pallet_timestamp::Config for Runtime {
+ /// A timestamp: milliseconds since the unix epoch.
+ type Moment = u64;
+ type OnTimestampSet = ();
+ type MinimumPeriod = MinimumPeriod;
+ type WeightInfo = ();
+}
+
+parameter_types! {
+ // pub const ExistentialDeposit: u128 = 500;
+ pub const ExistentialDeposit: u128 = 0;
+ pub const MaxLocks: u32 = 50;
+ pub const MaxReserves: u32 = 50;
+}
+
+impl pallet_balances::Config for Runtime {
+ type MaxLocks = MaxLocks;
+ type MaxReserves = MaxReserves;
+ type ReserveIdentifier = [u8; 16];
+ /// The type for recording an account's balance.
+ type Balance = Balance;
+ /// The ubiquitous event type.
+ type Event = Event;
+ type DustRemoval = Treasury;
+ type ExistentialDeposit = ExistentialDeposit;
+ type AccountStore = System;
+ type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;
+}
+
+parameter_types! {
+ /// This value increases the priority of `Operational` transactions by adding
+ /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.
+ pub const OperationalFeeMultiplier: u8 = 5;
+}
+
+impl pallet_transaction_payment::Config for Runtime {
+ type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;
+ type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
+ type OperationalFeeMultiplier = OperationalFeeMultiplier;
+ type WeightToFee = pallet_configuration::WeightToFee<Self, Balance>;
+ type FeeMultiplierUpdate = ();
+}
+
+parameter_types! {
+ pub const ProposalBond: Permill = Permill::from_percent(5);
+ pub const ProposalBondMinimum: Balance = 1 * UNIQUE;
+ pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;
+ pub const SpendPeriod: BlockNumber = 5 * MINUTES;
+ pub const Burn: Permill = Permill::from_percent(0);
+ pub const TipCountdown: BlockNumber = 1 * DAYS;
+ pub const TipFindersFee: Percent = Percent::from_percent(20);
+ pub const TipReportDepositBase: Balance = 1 * UNIQUE;
+ pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;
+ pub const BountyDepositBase: Balance = 1 * UNIQUE;
+ pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;
+ pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");
+ pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;
+ pub const MaximumReasonLength: u32 = 16384;
+ pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);
+ pub const BountyValueMinimum: Balance = 5 * UNIQUE;
+ pub const MaxApprovals: u32 = 100;
+}
+
+impl pallet_treasury::Config for Runtime {
+ type PalletId = TreasuryModuleId;
+ type Currency = Balances;
+ type ApproveOrigin = EnsureRoot<AccountId>;
+ type RejectOrigin = EnsureRoot<AccountId>;
+ type Event = Event;
+ type OnSlash = ();
+ type ProposalBond = ProposalBond;
+ type ProposalBondMinimum = ProposalBondMinimum;
+ type ProposalBondMaximum = ProposalBondMaximum;
+ type SpendPeriod = SpendPeriod;
+ type Burn = Burn;
+ type BurnDestination = ();
+ type SpendFunds = ();
+ type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;
+ type MaxApprovals = MaxApprovals;
+}
+
+impl pallet_sudo::Config for Runtime {
+ type Event = Event;
+ type Call = Call;
+}
+
+parameter_types! {
+ pub const MaxAuthorities: u32 = 100_000;
+}
+
+impl pallet_aura::Config for Runtime {
+ type AuthorityId = AuraId;
+ type DisabledValidators = ();
+ type MaxAuthorities = MaxAuthorities;
+}
runtime/common/config/xcm.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/config/xcm.rs
@@ -0,0 +1,302 @@
+// 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/>.
+
+use frame_support::{
+ traits::{
+ tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Get, Everything,
+ },
+ weights::{Weight, WeightToFeePolynomial, WeightToFee},
+ parameter_types, match_types,
+};
+use frame_system::EnsureRoot;
+use sp_runtime::{
+ traits::{Saturating, CheckedConversion, Zero},
+ SaturatedConversion,
+};
+use pallet_xcm::XcmPassthrough;
+use polkadot_parachain::primitives::Sibling;
+use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};
+use xcm::latest::{
+ AssetId::{Concrete},
+ Fungibility::Fungible as XcmFungible,
+ MultiAsset, Error as XcmError,
+};
+use xcm_executor::traits::{MatchesFungible, WeightTrader};
+use xcm_builder::{
+ AccountId32Aliases, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin,
+ FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser, RelayChainAsNative,
+ SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
+ SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, ParentIsPreset,
+};
+use xcm_executor::{Config, XcmExecutor, Assets};
+use sp_std::marker::PhantomData;
+use crate::{
+ Runtime, Call, Event, Origin, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, XcmpQueue,
+};
+use up_common::{
+ types::{AccountId, Balance},
+ constants::*,
+};
+
+parameter_types! {
+ pub const RelayLocation: MultiLocation = MultiLocation::parent();
+ pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
+ pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
+ pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
+}
+
+/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
+/// when determining ownership of accounts for asset transacting and when attempting to use XCM
+/// `Transact` in order to determine the dispatch Origin.
+pub type LocationToAccountId = (
+ // The parent (Relay-chain) origin converts to the default `AccountId`.
+ ParentIsPreset<AccountId>,
+ // Sibling parachain origins convert to AccountId via the `ParaId::into`.
+ SiblingParachainConvertsVia<Sibling, AccountId>,
+ // Straight up local `AccountId32` origins just alias directly to `AccountId`.
+ AccountId32Aliases<RelayNetwork, AccountId>,
+);
+
+pub struct OnlySelfCurrency;
+impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {
+ fn matches_fungible(a: &MultiAsset) -> Option<B> {
+ match (&a.id, &a.fun) {
+ (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),
+ _ => None,
+ }
+ }
+}
+
+/// Means for transacting assets on this chain.
+pub type LocalAssetTransactor = CurrencyAdapter<
+ // Use this currency:
+ Balances,
+ // Use this currency when it is a fungible asset matching the given location or name:
+ OnlySelfCurrency,
+ // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
+ LocationToAccountId,
+ // Our chain's account ID type (we can't get away without mentioning it explicitly):
+ AccountId,
+ // We don't track any teleports.
+ (),
+>;
+
+/// No local origins on this chain are allowed to dispatch XCM sends/executions.
+pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);
+
+/// The means for routing XCM messages which are not for local execution into the right message
+/// queues.
+pub type XcmRouter = (
+ // Two routers - use UMP to communicate with the relay chain:
+ cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,
+ // ..and XCMP to communicate with the sibling chains.
+ XcmpQueue,
+);
+
+/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
+/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
+/// biases the kind of local `Origin` it will become.
+pub type XcmOriginToTransactDispatchOrigin = (
+ // Sovereign account converter; this attempts to derive an `AccountId` from the origin location
+ // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
+ // foreign chains who want to have a local sovereign account on this chain which they control.
+ SovereignSignedViaLocation<LocationToAccountId, Origin>,
+ // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
+ // recognised.
+ RelayChainAsNative<RelayOrigin, Origin>,
+ // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
+ // recognised.
+ SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,
+ // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
+ // transaction from the Root origin.
+ ParentAsSuperuser<Origin>,
+ // Native signed account converter; this just converts an `AccountId32` origin into a normal
+ // `Origin::Signed` origin of the same 32-byte value.
+ SignedAccountId32AsNative<RelayNetwork, Origin>,
+ // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
+ XcmPassthrough<Origin>,
+);
+
+parameter_types! {
+ // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.
+ pub UnitWeightCost: Weight = 1_000_000;
+ // 1200 UNIQUEs buy 1 second of weight.
+ pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);
+ pub const MaxInstructions: u32 = 100;
+}
+
+match_types! {
+ pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {
+ MultiLocation { parents: 1, interior: Here } |
+ MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }
+ };
+}
+
+pub type Barrier = (
+ TakeWeightCredit,
+ AllowTopLevelPaidExecutionFrom<Everything>,
+ // ^^^ Parent & its unit plurality gets free execution
+);
+
+pub struct UsingOnlySelfCurrencyComponents<
+ WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
+ AssetId: Get<MultiLocation>,
+ AccountId,
+ Currency: CurrencyT<AccountId>,
+ OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
+>(
+ Weight,
+ Currency::Balance,
+ PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,
+);
+impl<
+ WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
+ AssetId: Get<MultiLocation>,
+ AccountId,
+ Currency: CurrencyT<AccountId>,
+ OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
+ > WeightTrader
+ for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
+{
+ fn new() -> Self {
+ Self(0, Zero::zero(), PhantomData)
+ }
+
+ fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {
+ let amount = WeightToFee::weight_to_fee(&weight);
+ let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;
+
+ // location to this parachain through relay chain
+ let option1: xcm::v1::AssetId = Concrete(MultiLocation {
+ parents: 1,
+ interior: X1(Parachain(ParachainInfo::parachain_id().into())),
+ });
+ // direct location
+ let option2: xcm::v1::AssetId = Concrete(MultiLocation {
+ parents: 0,
+ interior: Here,
+ });
+
+ let required = if payment.fungible.contains_key(&option1) {
+ (option1, u128_amount).into()
+ } else if payment.fungible.contains_key(&option2) {
+ (option2, u128_amount).into()
+ } else {
+ (Concrete(MultiLocation::default()), u128_amount).into()
+ };
+
+ let unused = payment
+ .checked_sub(required)
+ .map_err(|_| XcmError::TooExpensive)?;
+ self.0 = self.0.saturating_add(weight);
+ self.1 = self.1.saturating_add(amount);
+ Ok(unused)
+ }
+
+ fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {
+ let weight = weight.min(self.0);
+ let amount = WeightToFee::weight_to_fee(&weight);
+ self.0 -= weight;
+ self.1 = self.1.saturating_sub(amount);
+ let amount: u128 = amount.saturated_into();
+ if amount > 0 {
+ Some((AssetId::get(), amount).into())
+ } else {
+ None
+ }
+ }
+}
+impl<
+ WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
+ AssetId: Get<MultiLocation>,
+ AccountId,
+ Currency: CurrencyT<AccountId>,
+ OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
+ > Drop
+ for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
+{
+ fn drop(&mut self) {
+ OnUnbalanced::on_unbalanced(Currency::issue(self.1));
+ }
+}
+
+pub struct XcmConfig<T>(PhantomData<T>);
+impl<T> Config for XcmConfig<T>
+where
+ T: pallet_configuration::Config,
+{
+ type Call = Call;
+ type XcmSender = XcmRouter;
+ // How to withdraw and deposit an asset.
+ type AssetTransactor = LocalAssetTransactor;
+ type OriginConverter = XcmOriginToTransactDispatchOrigin;
+ type IsReserve = NativeAsset;
+ type IsTeleporter = (); // Teleportation is disabled
+ type LocationInverter = LocationInverter<Ancestry>;
+ type Barrier = Barrier;
+ type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
+ type Trader = UsingOnlySelfCurrencyComponents<
+ pallet_configuration::WeightToFee<T, Balance>,
+ RelayLocation,
+ AccountId,
+ Balances,
+ (),
+ >;
+ type ResponseHandler = (); // Don't handle responses for now.
+ type SubscriptionService = PolkadotXcm;
+
+ type AssetTrap = PolkadotXcm;
+ type AssetClaims = PolkadotXcm;
+}
+
+impl pallet_xcm::Config for Runtime {
+ type Event = Event;
+ type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
+ type XcmRouter = XcmRouter;
+ type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
+ type XcmExecuteFilter = Everything;
+ type XcmExecutor = XcmExecutor<XcmConfig<Self>>;
+ type XcmTeleportFilter = Everything;
+ type XcmReserveTransferFilter = Everything;
+ type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
+ type LocationInverter = LocationInverter<Ancestry>;
+ type Origin = Origin;
+ type Call = Call;
+ const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
+ type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
+}
+
+impl cumulus_pallet_xcm::Config for Runtime {
+ type Event = Event;
+ type XcmExecutor = XcmExecutor<XcmConfig<Self>>;
+}
+
+impl cumulus_pallet_xcmp_queue::Config for Runtime {
+ type WeightInfo = ();
+ type Event = Event;
+ type XcmExecutor = XcmExecutor<XcmConfig<Self>>;
+ type ChannelInfo = ParachainSystem;
+ type VersionWrapper = ();
+ type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
+ type ControllerOrigin = EnsureRoot<AccountId>;
+ type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
+}
+
+impl cumulus_pallet_dmp_queue::Config for Runtime {
+ type Event = Event;
+ type XcmExecutor = XcmExecutor<XcmConfig<Self>>;
+ type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
+}
runtime/common/construct_runtime/mod.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/construct_runtime/mod.rs
@@ -0,0 +1,90 @@
+// 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/>.
+
+mod util;
+
+#[macro_export]
+macro_rules! construct_runtime {
+ ($select_runtime:ident) => {
+ $crate::construct_runtime_impl! {
+ select_runtime($select_runtime);
+
+ pub enum Runtime where
+ Block = Block,
+ NodeBlock = opaque::Block,
+ UncheckedExtrinsic = UncheckedExtrinsic
+ {
+ ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,
+ ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,
+
+ Aura: pallet_aura::{Pallet, Config<T>} = 22,
+ AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,
+
+ Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,
+ RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,
+ Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,
+ TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,
+ Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,
+ Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,
+ System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,
+ Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,
+ // Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,
+ // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,
+
+ // XCM helpers.
+ XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
+ PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
+ CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,
+ DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
+
+ // Unique Pallets
+ Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,
+ Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,
+
+ #[runtimes(opal)]
+ Scheduler: pallet_unique_scheduler::{Pallet, Call, Storage, Event<T>} = 62,
+
+ Configuration: pallet_configuration::{Pallet, Call, Storage} = 63,
+
+ Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,
+ // ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,
+ Common: pallet_common::{Pallet, Storage, Event<T>} = 66,
+ Fungible: pallet_fungible::{Pallet, Storage} = 67,
+
+ #[runtimes(opal)]
+ Refungible: pallet_refungible::{Pallet, Storage} = 68,
+
+ Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,
+ Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,
+
+ #[runtimes(opal)]
+ RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,
+
+ #[runtimes(opal)]
+ RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,
+
+ // Frontier
+ EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,
+ Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,
+
+ EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,
+ EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,
+ EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,
+ EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,
+ }
+ }
+ }
+}
runtime/common/construct_runtime/util.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/construct_runtime/util.rs
@@ -0,0 +1,222 @@
+// 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/>.
+
+#[macro_export]
+macro_rules! construct_runtime_impl {
+ (
+ select_runtime($select_runtime:ident);
+
+ pub enum Runtime where
+ $($where_ident:ident = $where_ty:ty),* $(,)?
+ {
+ $(
+ $(#[runtimes($($pallet_runtimes:ident),+ $(,)?)])?
+ $pallet_name:ident: $pallet_mod:ident::{$($pallet_parts:ty),*} = $index:literal
+ ),*
+ $(,)?
+ }
+ ) => {
+ $crate::construct_runtime_helper! {
+ select_runtime($select_runtime),
+ selected_pallets(),
+
+ where_clause($($where_ident = $where_ty),*),
+ pallets(
+ $(
+ $(#[runtimes($($pallet_runtimes),+)])?
+ $pallet_name: $pallet_mod::{$($pallet_parts),*} = $index
+ ),*,
+ )
+ }
+ }
+}
+
+#[macro_export]
+macro_rules! construct_runtime_helper {
+ (
+ select_runtime($select_runtime:ident),
+ selected_pallets($($selected_pallets:tt)*),
+
+ where_clause($($where_clause:tt)*),
+ pallets(
+ #[runtimes($($pallet_runtimes:ident),+)]
+ $pallet_name:ident: $pallet_mod:ident::{$($pallet_parts:ty),*} = $index:literal,
+
+ $($pallets_tl:tt)*
+ )
+ ) => {
+ $crate::add_runtime_specific_pallets! {
+ select_runtime($select_runtime),
+ runtimes($($pallet_runtimes),+,),
+ selected_pallets($($selected_pallets)*),
+
+ where_clause($($where_clause)*),
+ pallets(
+ $pallet_name: $pallet_mod::{$($pallet_parts),*} = $index,
+ $($pallets_tl)*
+ )
+ }
+ };
+
+ (
+ select_runtime($select_runtime:ident),
+ selected_pallets($($selected_pallets:tt)*),
+
+ where_clause($($where_clause:tt)*),
+ pallets(
+ $pallet_name:ident: $pallet_mod:ident::{$($pallet_parts:ty),*} = $index:literal,
+
+ $($pallets_tl:tt)*
+ )
+ ) => {
+ $crate::construct_runtime_helper! {
+ select_runtime($select_runtime),
+ selected_pallets(
+ $($selected_pallets)*
+ $pallet_name: $pallet_mod::{$($pallet_parts),*} = $index,
+ ),
+
+ where_clause($($where_clause)*),
+ pallets($($pallets_tl)*)
+ }
+ };
+
+ (
+ select_runtime($select_runtime:ident),
+ selected_pallets($($selected_pallets:tt)*),
+
+ where_clause($($where_clause:tt)*),
+ pallets()
+ ) => {
+ frame_support::construct_runtime! {
+ pub enum Runtime where
+ $($where_clause)*
+ {
+ $($selected_pallets)*
+ }
+ }
+ };
+}
+
+#[macro_export]
+macro_rules! add_runtime_specific_pallets {
+ (
+ select_runtime(opal),
+ runtimes(opal, $($_runtime_tl:tt)*),
+ selected_pallets($($selected_pallets:tt)*),
+
+ where_clause($($where_clause:tt)*),
+ pallets(
+ $pallet_name:ident: $pallet_mod:ident::{$($pallet_parts:ty),*} = $index:literal,
+ $($pallets_tl:tt)*
+ )
+ ) => {
+ $crate::construct_runtime_helper! {
+ select_runtime(opal),
+ selected_pallets(
+ $($selected_pallets)*
+ $pallet_name: $pallet_mod::{$($pallet_parts),*} = $index,
+ ),
+
+ where_clause($($where_clause)*),
+ pallets($($pallets_tl)*)
+ }
+ };
+
+ (
+ select_runtime(quartz),
+ runtimes(quartz, $($_runtime_tl:tt)*),
+ selected_pallets($($selected_pallets:tt)*),
+
+ where_clause($($where_clause:tt)*),
+ pallets(
+ $pallet_name:ident: $pallet_mod:ident::{$($pallet_parts:ty),*} = $index:literal,
+ $($pallets_tl:tt)*
+ )
+ ) => {
+ $crate::construct_runtime_helper! {
+ select_runtime(quartz),
+ selected_pallets(
+ $($selected_pallets)*
+ $pallet_name: $pallet_mod::{$($pallet_parts),*} = $index,
+ ),
+
+ where_clause($($where_clause)*),
+ pallets($($pallets_tl)*)
+ }
+ };
+
+ (
+ select_runtime(unique),
+ runtimes(unique, $($_runtime_tl:tt)*),
+ selected_pallets($($selected_pallets:tt)*),
+
+ where_clause($($where_clause:tt)*),
+ pallets(
+ $pallet_name:ident: $pallet_mod:ident::{$($pallet_parts:ty),*} = $index:literal,
+ $($pallets_tl:tt)*
+ )
+ ) => {
+ $crate::construct_runtime_helper! {
+ select_runtime(unique),
+ selected_pallets(
+ $($selected_pallets)*
+ $pallet_name: $pallet_mod::{$($pallet_parts),*} = $index,
+ ),
+
+ where_clause($($where_clause)*),
+ pallets($($pallets_tl)*)
+ }
+ };
+
+ (
+ select_runtime($select_runtime:ident),
+ runtimes($_current_runtime:ident, $($runtime_tl:tt)*),
+ selected_pallets($($selected_pallets:tt)*),
+
+ where_clause($($where_clause:tt)*),
+ pallets($($pallets:tt)*)
+ ) => {
+ $crate::add_runtime_specific_pallets! {
+ select_runtime($select_runtime),
+ runtimes($($runtime_tl)*),
+ selected_pallets($($selected_pallets)*),
+
+ where_clause($($where_clause)*),
+ pallets($($pallets)*)
+ }
+ };
+
+ (
+ select_runtime($select_runtime:ident),
+ runtimes(),
+ selected_pallets($($selected_pallets:tt)*),
+
+ where_clause($($where_clause:tt)*),
+ pallets(
+ $_pallet_name:ident: $_pallet_mod:ident::{$($_pallet_parts:ty),*} = $_index:literal,
+ $($pallets_tl:tt)*
+ )
+ ) => {
+ $crate::construct_runtime_helper! {
+ select_runtime($select_runtime),
+ selected_pallets($($selected_pallets)*),
+
+ where_clause($($where_clause)*),
+ pallets($($pallets_tl)*)
+ }
+ };
+}
runtime/common/dispatch.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/dispatch.rs
@@ -0,0 +1,189 @@
+// 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/>.
+
+use frame_support::{dispatch::DispatchResult, ensure};
+use pallet_evm::{PrecompileHandle, PrecompileResult};
+use sp_core::H160;
+use sp_runtime::DispatchError;
+use sp_std::{borrow::ToOwned, vec::Vec};
+use pallet_common::{
+ CollectionById, CollectionHandle, CommonCollectionOperations, erc::CommonEvmHandler,
+ eth::map_eth_to_id,
+};
+pub use pallet_common::dispatch::CollectionDispatch;
+use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};
+use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};
+use pallet_refungible::{
+ Pallet as PalletRefungible, RefungibleHandle, erc_token::RefungibleTokenHandle,
+};
+use up_data_structs::{
+ CollectionMode, CreateCollectionData, MAX_DECIMAL_POINTS, mapping::TokenAddressMapping,
+ CollectionId,
+};
+
+#[cfg(not(feature = "refungible"))]
+use pallet_common::unsupported;
+
+pub enum CollectionDispatchT<T>
+where
+ T: pallet_fungible::Config + pallet_nonfungible::Config + pallet_refungible::Config,
+{
+ Fungible(FungibleHandle<T>),
+ Nonfungible(NonfungibleHandle<T>),
+ Refungible(RefungibleHandle<T>),
+}
+impl<T> CollectionDispatch<T> for CollectionDispatchT<T>
+where
+ T: pallet_common::Config
+ + pallet_unique::Config
+ + pallet_fungible::Config
+ + pallet_nonfungible::Config
+ + pallet_refungible::Config,
+{
+ fn create(
+ sender: T::CrossAccountId,
+ data: CreateCollectionData<T::AccountId>,
+ ) -> Result<CollectionId, DispatchError> {
+ let id = match data.mode {
+ CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, data, false)?,
+ CollectionMode::Fungible(decimal_points) => {
+ // check params
+ ensure!(
+ decimal_points <= MAX_DECIMAL_POINTS,
+ pallet_unique::Error::<T>::CollectionDecimalPointLimitExceeded
+ );
+ <PalletFungible<T>>::init_collection(sender, data)?
+ }
+
+ #[cfg(feature = "refungible")]
+ CollectionMode::ReFungible => <PalletRefungible<T>>::init_collection(sender, data)?,
+
+ #[cfg(not(feature = "refungible"))]
+ CollectionMode::ReFungible => return unsupported!(T),
+ };
+ Ok(id)
+ }
+
+ fn destroy(sender: T::CrossAccountId, collection: CollectionHandle<T>) -> DispatchResult {
+ match collection.mode {
+ CollectionMode::ReFungible => {
+ PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?
+ }
+ CollectionMode::Fungible(_) => {
+ PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?
+ }
+ CollectionMode::NFT => {
+ PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?
+ }
+ }
+ Ok(())
+ }
+
+ fn dispatch(handle: CollectionHandle<T>) -> Self {
+ match handle.mode {
+ CollectionMode::Fungible(_) => Self::Fungible(FungibleHandle::cast(handle)),
+ CollectionMode::NFT => Self::Nonfungible(NonfungibleHandle::cast(handle)),
+ CollectionMode::ReFungible => Self::Refungible(RefungibleHandle::cast(handle)),
+ }
+ }
+
+ fn into_inner(self) -> CollectionHandle<T> {
+ match self {
+ Self::Fungible(f) => f.into_inner(),
+ Self::Nonfungible(f) => f.into_inner(),
+ Self::Refungible(f) => f.into_inner(),
+ }
+ }
+
+ fn as_dyn(&self) -> &dyn CommonCollectionOperations<T> {
+ match self {
+ Self::Fungible(h) => h,
+ Self::Nonfungible(h) => h,
+ Self::Refungible(h) => h,
+ }
+ }
+}
+
+impl<T> pallet_evm::OnMethodCall<T> for CollectionDispatchT<T>
+where
+ T: pallet_common::Config
+ + pallet_unique::Config
+ + pallet_fungible::Config
+ + pallet_nonfungible::Config
+ + pallet_refungible::Config,
+ T::AccountId: From<[u8; 32]>,
+{
+ fn is_reserved(target: &H160) -> bool {
+ map_eth_to_id(target).is_some()
+ }
+ fn is_used(target: &H160) -> bool {
+ map_eth_to_id(target)
+ .map(<CollectionById<T>>::contains_key)
+ .unwrap_or(false)
+ }
+ fn get_code(target: &H160) -> Option<Vec<u8>> {
+ if let Some(collection_id) = map_eth_to_id(target) {
+ let collection = <CollectionById<T>>::get(collection_id)?;
+ Some(
+ match collection.mode {
+ CollectionMode::NFT => <NonfungibleHandle<T>>::CODE,
+ CollectionMode::Fungible(_) => <FungibleHandle<T>>::CODE,
+ CollectionMode::ReFungible => <RefungibleHandle<T>>::CODE,
+ }
+ .to_owned(),
+ )
+ } else if let Some((collection_id, _token_id)) =
+ <T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(target)
+ {
+ let collection = <CollectionById<T>>::get(collection_id)?;
+ if collection.mode != CollectionMode::ReFungible {
+ return None;
+ }
+ // TODO: check token existence
+ Some(<RefungibleTokenHandle<T>>::CODE.to_owned())
+ } else {
+ None
+ }
+ }
+ fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {
+ if let Some(collection_id) = map_eth_to_id(&handle.code_address()) {
+ let collection =
+ <CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;
+ let dispatched = Self::dispatch(collection);
+
+ match dispatched {
+ Self::Fungible(h) => h.call(handle),
+ Self::Nonfungible(h) => h.call(handle),
+ Self::Refungible(h) => h.call(handle),
+ }
+ } else if let Some((collection_id, token_id)) =
+ <T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(
+ &handle.code_address(),
+ ) {
+ let collection =
+ <CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;
+ if collection.mode != CollectionMode::ReFungible {
+ return None;
+ }
+
+ let h = RefungibleHandle::cast(collection);
+ // TODO: check token existence
+ RefungibleTokenHandle(h, token_id).call(handle)
+ } else {
+ None
+ }
+ }
+}
runtime/common/ethereum/mod.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/ethereum/mod.rs
@@ -0,0 +1,19 @@
+// 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/>.
+
+pub mod self_contained_call;
+pub mod sponsoring;
+pub mod transaction_converter;
runtime/common/ethereum/self_contained_call.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/ethereum/self_contained_call.rs
@@ -0,0 +1,74 @@
+// 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/>.
+
+use sp_core::H160;
+use sp_runtime::{
+ traits::{Dispatchable, DispatchInfoOf, PostDispatchInfoOf},
+ transaction_validity::{TransactionValidityError, TransactionValidity},
+};
+use crate::{Origin, Call};
+
+impl fp_self_contained::SelfContainedCall for Call {
+ type SignedInfo = H160;
+
+ fn is_self_contained(&self) -> bool {
+ match self {
+ Call::Ethereum(call) => call.is_self_contained(),
+ _ => false,
+ }
+ }
+
+ fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
+ match self {
+ Call::Ethereum(call) => call.check_self_contained(),
+ _ => None,
+ }
+ }
+
+ fn validate_self_contained(
+ &self,
+ info: &Self::SignedInfo,
+ dispatch_info: &DispatchInfoOf<Call>,
+ len: usize,
+ ) -> Option<TransactionValidity> {
+ match self {
+ Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),
+ _ => None,
+ }
+ }
+
+ fn pre_dispatch_self_contained(
+ &self,
+ info: &Self::SignedInfo,
+ ) -> Option<Result<(), TransactionValidityError>> {
+ match self {
+ Call::Ethereum(call) => call.pre_dispatch_self_contained(info),
+ _ => None,
+ }
+ }
+
+ fn apply_self_contained(
+ self,
+ info: Self::SignedInfo,
+ ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {
+ match self {
+ call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(
+ Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),
+ )),
+ _ => None,
+ }
+ }
+}
runtime/common/ethereum/sponsoring.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/ethereum/sponsoring.rs
@@ -0,0 +1,127 @@
+// 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/>.
+
+//! Implements EVM sponsoring logic via TransactionValidityHack
+
+use evm_coder::{Call, abi::AbiReader};
+use pallet_common::{CollectionHandle, eth::map_eth_to_id};
+use sp_core::H160;
+use sp_std::prelude::*;
+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>,
+);
+
+pub struct UniqueEthSponsorshipHandler<T: UniqueConfig>(PhantomData<*const T>);
+impl<T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig>
+ SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)> 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)?;
+ let collection = <CollectionHandle<T>>::new(collection_id)?;
+ let sponsor = collection.sponsorship.sponsor()?.clone();
+ let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;
+ Some(T::CrossAccountId::from_sub(match &collection.mode {
+ CollectionMode::NFT => {
+ let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;
+ match call {
+ UniqueNFTCall::TokenProperties(TokenPropertiesCall::SetProperty {
+ token_id,
+ key,
+ value,
+ ..
+ }) => {
+ let token_id: TokenId = token_id.try_into().ok()?;
+ withdraw_set_token_property::<T>(
+ &collection,
+ &who,
+ &token_id,
+ key.len() + value.len(),
+ )
+ .map(|()| sponsor)
+ }
+ UniqueNFTCall::ERC721UniqueExtensions(
+ ERC721UniqueExtensionsCall::Transfer { token_id, .. },
+ ) => {
+ let token_id: TokenId = token_id.try_into().ok()?;
+ withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)
+ }
+ UniqueNFTCall::ERC721Mintable(
+ ERC721MintableCall::Mint { token_id, .. }
+ | ERC721MintableCall::MintWithTokenUri { token_id, .. },
+ ) => {
+ let _token_id: TokenId = token_id.try_into().ok()?;
+ withdraw_create_item::<T>(
+ &collection,
+ &who,
+ &CreateItemData::NFT(CreateNftData::default()),
+ )
+ .map(|()| sponsor)
+ }
+ UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, from, .. }) => {
+ let token_id: TokenId = token_id.try_into().ok()?;
+ let from = T::CrossAccountId::from_eth(from);
+ withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)
+ }
+ UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {
+ let token_id: TokenId = token_id.try_into().ok()?;
+ withdraw_approve::<T>(&collection, who.as_sub(), &token_id)
+ .map(|()| sponsor)
+ }
+ _ => None,
+ }
+ }
+ CollectionMode::Fungible(_) => {
+ let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader).ok()??;
+ #[allow(clippy::single_match)]
+ match call {
+ UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {
+ withdraw_transfer::<T>(&collection, who, &TokenId::default())
+ .map(|()| sponsor)
+ }
+ UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {
+ let from = T::CrossAccountId::from_eth(from);
+ withdraw_transfer::<T>(&collection, &from, &TokenId::default())
+ .map(|()| sponsor)
+ }
+ UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {
+ withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())
+ .map(|()| sponsor)
+ }
+ _ => None,
+ }
+ }
+ _ => None,
+ }?))
+ }
+}
runtime/common/ethereum/transaction_converter.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/ethereum/transaction_converter.rs
@@ -0,0 +1,42 @@
+// 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/>.
+
+use codec::{Encode, Decode};
+use crate::{opaque, Runtime, UncheckedExtrinsic};
+
+pub struct TransactionConverter;
+
+impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {
+ fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {
+ UncheckedExtrinsic::new_unsigned(
+ pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
+ )
+ }
+}
+
+impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {
+ fn convert_transaction(
+ &self,
+ transaction: pallet_ethereum::Transaction,
+ ) -> opaque::UncheckedExtrinsic {
+ let extrinsic = UncheckedExtrinsic::new_unsigned(
+ pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
+ );
+ let encoded = extrinsic.encode();
+ opaque::UncheckedExtrinsic::decode(&mut &encoded[..])
+ .expect("Encoded extrinsic is always valid")
+ }
+}
runtime/common/instance.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/instance.rs
@@ -0,0 +1,16 @@
+use crate::{
+ runtime_common::{
+ config::ethereum::CrossAccountId, ethereum::transaction_converter::TransactionConverter,
+ },
+ Runtime,
+};
+use up_common::types::opaque::RuntimeInstance;
+
+impl RuntimeInstance for Runtime {
+ type CrossAccountId = CrossAccountId;
+ type TransactionConverter = TransactionConverter;
+
+ fn get_transaction_converter() -> TransactionConverter {
+ TransactionConverter
+ }
+}
runtime/common/mod.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/mod.rs
@@ -0,0 +1,167 @@
+// 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/>.
+
+pub mod config;
+pub mod construct_runtime;
+pub mod dispatch;
+pub mod ethereum;
+pub mod instance;
+pub mod runtime_apis;
+pub mod scheduler;
+pub mod sponsoring;
+pub mod weights;
+
+use sp_core::H160;
+use frame_support::traits::{Currency, OnUnbalanced, Imbalance};
+use sp_runtime::{
+ generic,
+ traits::{BlakeTwo256, BlockNumberProvider},
+ impl_opaque_keys,
+};
+use sp_std::vec::Vec;
+
+#[cfg(feature = "std")]
+use sp_version::NativeVersion;
+
+use crate::{
+ Runtime, Call, Balances, Treasury, Aura, Signature, AllPalletsReversedWithSystemFirst,
+ InherentDataExt,
+};
+use up_common::types::{AccountId, BlockNumber};
+
+#[macro_export]
+macro_rules! unsupported {
+ () => {
+ pallet_common::unsupported!($crate::Runtime)
+ };
+}
+
+/// The address format for describing accounts.
+pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
+/// Block header type as expected by this runtime.
+pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
+/// Block type as expected by this runtime.
+pub type Block = generic::Block<Header, UncheckedExtrinsic>;
+/// A Block signed with a Justification
+pub type SignedBlock = generic::SignedBlock<Block>;
+/// BlockId type as expected by this runtime.
+pub type BlockId = generic::BlockId<Block>;
+
+impl_opaque_keys! {
+ pub struct SessionKeys {
+ pub aura: Aura,
+ }
+}
+
+/// The version information used to identify this runtime when compiled natively.
+#[cfg(feature = "std")]
+pub fn native_version() -> NativeVersion {
+ NativeVersion {
+ runtime_version: crate::VERSION,
+ can_author_with: Default::default(),
+ }
+}
+
+pub type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;
+
+pub type SignedExtra = (
+ frame_system::CheckSpecVersion<Runtime>,
+ // system::CheckTxVersion<Runtime>,
+ frame_system::CheckGenesis<Runtime>,
+ frame_system::CheckEra<Runtime>,
+ frame_system::CheckNonce<Runtime>,
+ frame_system::CheckWeight<Runtime>,
+ ChargeTransactionPayment,
+ //pallet_contract_helpers::ContractHelpersExtension<Runtime>,
+ pallet_ethereum::FakeTransactionFinalizer<Runtime>,
+);
+
+/// Unchecked extrinsic type as expected by this runtime.
+pub type UncheckedExtrinsic =
+ fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
+
+/// Extrinsic type that has already been checked.
+pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;
+
+/// Executive: handles dispatch to the various modules.
+pub type Executive = frame_executive::Executive<
+ Runtime,
+ Block,
+ frame_system::ChainContext<Runtime>,
+ Runtime,
+ AllPalletsReversedWithSystemFirst,
+>;
+
+type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
+
+pub struct DealWithFees;
+impl OnUnbalanced<NegativeImbalance> for DealWithFees {
+ fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {
+ if let Some(fees) = fees_then_tips.next() {
+ // for fees, 100% to treasury
+ let mut split = fees.ration(100, 0);
+ if let Some(tips) = fees_then_tips.next() {
+ // for tips, if any, 100% to treasury
+ tips.ration_merge_into(100, 0, &mut split);
+ }
+ Treasury::on_unbalanced(split.0);
+ // Author::on_unbalanced(split.1);
+ }
+ }
+}
+
+pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);
+
+impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider
+ for RelayChainBlockNumberProvider<T>
+{
+ type BlockNumber = BlockNumber;
+
+ fn current_block_number() -> Self::BlockNumber {
+ cumulus_pallet_parachain_system::Pallet::<T>::validation_data()
+ .map(|d| d.relay_parent_number)
+ .unwrap_or_default()
+ }
+}
+
+pub(crate) struct CheckInherents;
+
+impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
+ fn check_inherents(
+ block: &Block,
+ relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
+ ) -> sp_inherents::CheckInherentsResult {
+ let relay_chain_slot = relay_state_proof
+ .read_slot()
+ .expect("Could not read the relay chain slot from the proof");
+
+ let inherent_data =
+ cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
+ relay_chain_slot,
+ sp_std::time::Duration::from_secs(6),
+ )
+ .create_inherent_data()
+ .expect("Could not create the timestamp inherent data");
+
+ inherent_data.check_extrinsics(block)
+ }
+}
+
+#[derive(codec::Encode, codec::Decode)]
+pub enum XCMPMessage<XAccountId, XBalance> {
+ /// Transfer tokens to the given account from the Parachain account.
+ TransferToken(XAccountId, XBalance),
+}
runtime/common/runtime_apis.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/runtime_apis.rs
@@ -0,0 +1,732 @@
+// 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/>.
+
+#[macro_export]
+macro_rules! dispatch_unique_runtime {
+ ($collection:ident.$method:ident($($name:ident),*)) => {{
+ let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);
+ let dispatch = collection.as_dyn();
+
+ Ok::<_, DispatchError>(dispatch.$method($($name),*))
+ }};
+}
+
+#[macro_export]
+macro_rules! impl_common_runtime_apis {
+ (
+ $(
+ #![custom_apis]
+
+ $($custom_apis:tt)+
+ )?
+ ) => {
+ use sp_std::prelude::*;
+ use sp_api::impl_runtime_apis;
+ use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};
+ use sp_runtime::{
+ Permill,
+ traits::Block as BlockT,
+ transaction_validity::{TransactionSource, TransactionValidity},
+ ApplyExtrinsicResult, DispatchError,
+ };
+ use fp_rpc::TransactionStatus;
+ use pallet_transaction_payment::{
+ FeeDetails, RuntimeDispatchInfo,
+ };
+ use pallet_evm::{
+ Runner, account::CrossAccountId as _,
+ Account as EVMAccount, FeeCalculator,
+ };
+ use runtime_common::{
+ sponsoring::{SponsorshipPredict, UniqueSponsorshipPredict},
+ dispatch::CollectionDispatch,
+ config::ethereum::CrossAccountId,
+ };
+ use up_data_structs::*;
+
+
+ impl_runtime_apis! {
+ $($($custom_apis)+)?
+
+ impl up_rpc::UniqueApi<Block, CrossAccountId, AccountId> for Runtime {
+ fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result<Vec<TokenId>, DispatchError> {
+ dispatch_unique_runtime!(collection.account_tokens(account))
+ }
+ fn collection_tokens(collection: CollectionId) -> Result<Vec<TokenId>, DispatchError> {
+ dispatch_unique_runtime!(collection.collection_tokens())
+ }
+ fn token_exists(collection: CollectionId, token: TokenId) -> Result<bool, DispatchError> {
+ dispatch_unique_runtime!(collection.token_exists(token))
+ }
+
+ fn token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {
+ dispatch_unique_runtime!(collection.token_owner(token))
+ }
+
+ fn token_owners(collection: CollectionId, token: TokenId) -> Result<Vec::<CrossAccountId>, DispatchError> {
+ dispatch_unique_runtime!(collection.token_owners(token))
+ }
+
+ fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {
+ let budget = up_data_structs::budget::Value::new(10);
+
+ Ok(Some(<pallet_structure::Pallet<Runtime>>::find_topmost_owner(collection, token, &budget)?))
+ }
+ fn token_children(collection: CollectionId, token: TokenId) -> Result<Vec<TokenChild>, DispatchError> {
+ Ok(<pallet_nonfungible::Pallet<Runtime>>::token_children_ids(collection, token))
+ }
+ fn collection_properties(
+ collection: CollectionId,
+ keys: Option<Vec<Vec<u8>>>
+ ) -> Result<Vec<Property>, DispatchError> {
+ let keys = keys.map(
+ |keys| Common::bytes_keys_to_property_keys(keys)
+ ).transpose()?;
+
+ Common::filter_collection_properties(collection, keys)
+ }
+
+ fn token_properties(
+ collection: CollectionId,
+ token_id: TokenId,
+ keys: Option<Vec<Vec<u8>>>
+ ) -> Result<Vec<Property>, DispatchError> {
+ let keys = keys.map(
+ |keys| Common::bytes_keys_to_property_keys(keys)
+ ).transpose()?;
+
+ dispatch_unique_runtime!(collection.token_properties(token_id, keys))
+ }
+
+ fn property_permissions(
+ collection: CollectionId,
+ keys: Option<Vec<Vec<u8>>>
+ ) -> Result<Vec<PropertyKeyPermission>, DispatchError> {
+ let keys = keys.map(
+ |keys| Common::bytes_keys_to_property_keys(keys)
+ ).transpose()?;
+
+ Common::filter_property_permissions(collection, keys)
+ }
+
+ fn token_data(
+ collection: CollectionId,
+ token_id: TokenId,
+ keys: Option<Vec<Vec<u8>>>
+ ) -> Result<TokenData<CrossAccountId>, DispatchError> {
+ let token_data = TokenData {
+ properties: Self::token_properties(collection, token_id, keys)?,
+ owner: Self::token_owner(collection, token_id)?,
+ pieces: Self::total_pieces(collection, token_id)?.unwrap_or(0),
+ };
+
+ Ok(token_data)
+ }
+
+ fn total_supply(collection: CollectionId) -> Result<u32, DispatchError> {
+ dispatch_unique_runtime!(collection.total_supply())
+ }
+ fn account_balance(collection: CollectionId, account: CrossAccountId) -> Result<u32, DispatchError> {
+ dispatch_unique_runtime!(collection.account_balance(account))
+ }
+ fn balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<u128, DispatchError> {
+ dispatch_unique_runtime!(collection.balance(account, token))
+ }
+ fn allowance(
+ collection: CollectionId,
+ sender: CrossAccountId,
+ spender: CrossAccountId,
+ token: TokenId,
+ ) -> Result<u128, DispatchError> {
+ dispatch_unique_runtime!(collection.allowance(sender, spender, token))
+ }
+
+ fn adminlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {
+ Ok(<pallet_common::Pallet<Runtime>>::adminlist(collection))
+ }
+ fn allowlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {
+ Ok(<pallet_common::Pallet<Runtime>>::allowlist(collection))
+ }
+ fn allowed(collection: CollectionId, user: CrossAccountId) -> Result<bool, DispatchError> {
+ Ok(<pallet_common::Pallet<Runtime>>::allowed(collection, user))
+ }
+ fn last_token_id(collection: CollectionId) -> Result<TokenId, DispatchError> {
+ dispatch_unique_runtime!(collection.last_token_id())
+ }
+ fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollection<AccountId>>, DispatchError> {
+ Ok(<pallet_common::Pallet<Runtime>>::rpc_collection(collection))
+ }
+ fn collection_stats() -> Result<CollectionStats, DispatchError> {
+ Ok(<pallet_common::Pallet<Runtime>>::collection_stats())
+ }
+ fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>, DispatchError> {
+ Ok(<UniqueSponsorshipPredict<Runtime> as SponsorshipPredict<Runtime>>::predict(
+ collection,
+ account,
+ token
+ ))
+ }
+
+ fn effective_collection_limits(collection: CollectionId) -> Result<Option<CollectionLimits>, DispatchError> {
+ Ok(<pallet_common::Pallet<Runtime>>::effective_collection_limits(collection))
+ }
+
+ fn total_pieces(collection: CollectionId, token_id: TokenId) -> Result<Option<u128>, DispatchError> {
+ dispatch_unique_runtime!(collection.total_pieces(token_id))
+ }
+ }
+
+ impl rmrk_rpc::RmrkApi<
+ Block,
+ AccountId,
+ RmrkCollectionInfo<AccountId>,
+ RmrkInstanceInfo<AccountId>,
+ RmrkResourceInfo,
+ RmrkPropertyInfo,
+ RmrkBaseInfo<AccountId>,
+ RmrkPartType,
+ RmrkTheme
+ > for Runtime {
+ fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_core::rpc::last_collection_idx::<Runtime>();
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+
+ #[allow(unused_variables)]
+ fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_core::rpc::collection_by_id::<Runtime>(collection_id);
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+
+ #[allow(unused_variables)]
+ fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_core::rpc::nft_by_id::<Runtime>(collection_id, nft_by_id);
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+
+ #[allow(unused_variables)]
+ fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_core::rpc::account_tokens::<Runtime>(account_id, collection_id);
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+
+ #[allow(unused_variables)]
+ fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_core::rpc::nft_children::<Runtime>(collection_id, nft_id);
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+
+ #[allow(unused_variables)]
+ fn collection_properties(
+ collection_id: RmrkCollectionId,
+ filter_keys: Option<Vec<RmrkPropertyKey>>
+ ) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_core::rpc::collection_properties::<Runtime>(collection_id, filter_keys);
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+
+ #[allow(unused_variables)]
+ fn nft_properties(
+ collection_id: RmrkCollectionId,
+ nft_id: RmrkNftId,
+ filter_keys: Option<Vec<RmrkPropertyKey>>
+ ) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_core::rpc::nft_properties::<Runtime>(collection_id, nft_id, filter_keys);
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+
+ #[allow(unused_variables)]
+ fn nft_resources(collection_id: RmrkCollectionId,nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_core::rpc::nft_resources::<Runtime>(collection_id, nft_id);
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+
+ #[allow(unused_variables)]
+ fn nft_resource_priority(
+ collection_id: RmrkCollectionId,
+ nft_id: RmrkNftId,
+ resource_id: RmrkResourceId
+ ) -> Result<Option<u32>, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_core::rpc::nft_resource_priority::<Runtime>(collection_id, nft_id, resource_id);
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+
+ #[allow(unused_variables)]
+ fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_equip::rpc::base::<Runtime>(base_id);
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+
+ #[allow(unused_variables)]
+ fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_equip::rpc::base_parts::<Runtime>(base_id);
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+
+ #[allow(unused_variables)]
+ fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_equip::rpc::theme_names::<Runtime>(base_id);
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+
+ #[allow(unused_variables)]
+ fn theme(
+ base_id: RmrkBaseId,
+ theme_name: RmrkThemeName,
+ filter_keys: Option<Vec<RmrkPropertyKey>>
+ ) -> Result<Option<RmrkTheme>, DispatchError> {
+ #[cfg(feature = "rmrk")]
+ return pallet_proxy_rmrk_equip::rpc::theme::<Runtime>(base_id, theme_name, filter_keys);
+
+ #[cfg(not(feature = "rmrk"))]
+ return unsupported!();
+ }
+ }
+
+ impl sp_api::Core<Block> for Runtime {
+ fn version() -> RuntimeVersion {
+ VERSION
+ }
+
+ fn execute_block(block: Block) {
+ Executive::execute_block(block)
+ }
+
+ fn initialize_block(header: &<Block as BlockT>::Header) {
+ Executive::initialize_block(header)
+ }
+ }
+
+ impl sp_api::Metadata<Block> for Runtime {
+ fn metadata() -> OpaqueMetadata {
+ OpaqueMetadata::new(Runtime::metadata().into())
+ }
+ }
+
+ impl sp_block_builder::BlockBuilder<Block> for Runtime {
+ fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
+ Executive::apply_extrinsic(extrinsic)
+ }
+
+ fn finalize_block() -> <Block as BlockT>::Header {
+ Executive::finalize_block()
+ }
+
+ fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
+ data.create_extrinsics()
+ }
+
+ fn check_inherents(
+ block: Block,
+ data: sp_inherents::InherentData,
+ ) -> sp_inherents::CheckInherentsResult {
+ data.check_extrinsics(&block)
+ }
+
+ // fn random_seed() -> <Block as BlockT>::Hash {
+ // RandomnessCollectiveFlip::random_seed().0
+ // }
+ }
+
+ impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
+ fn validate_transaction(
+ source: TransactionSource,
+ tx: <Block as BlockT>::Extrinsic,
+ hash: <Block as BlockT>::Hash,
+ ) -> TransactionValidity {
+ Executive::validate_transaction(source, tx, hash)
+ }
+ }
+
+ impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
+ fn offchain_worker(header: &<Block as BlockT>::Header) {
+ Executive::offchain_worker(header)
+ }
+ }
+
+ impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
+ fn chain_id() -> u64 {
+ <Runtime as pallet_evm::Config>::ChainId::get()
+ }
+
+ fn account_basic(address: H160) -> EVMAccount {
+ let (account, _) = EVM::account_basic(&address);
+ account
+ }
+
+ fn gas_price() -> U256 {
+ let (price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();
+ price
+ }
+
+ fn account_code_at(address: H160) -> Vec<u8> {
+ EVM::account_codes(address)
+ }
+
+ fn author() -> H160 {
+ <pallet_evm::Pallet<Runtime>>::find_author()
+ }
+
+ fn storage_at(address: H160, index: U256) -> H256 {
+ let mut tmp = [0u8; 32];
+ index.to_big_endian(&mut tmp);
+ EVM::account_storages(address, H256::from_slice(&tmp[..]))
+ }
+
+ #[allow(clippy::redundant_closure)]
+ fn call(
+ from: H160,
+ to: H160,
+ data: Vec<u8>,
+ value: U256,
+ gas_limit: U256,
+ max_fee_per_gas: Option<U256>,
+ max_priority_fee_per_gas: Option<U256>,
+ nonce: Option<U256>,
+ estimate: bool,
+ access_list: Option<Vec<(H160, Vec<H256>)>>,
+ ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
+ let config = if estimate {
+ let mut config = <Runtime as pallet_evm::Config>::config().clone();
+ config.estimate = true;
+ Some(config)
+ } else {
+ None
+ };
+
+ let is_transactional = false;
+ <Runtime as pallet_evm::Config>::Runner::call(
+ CrossAccountId::from_eth(from),
+ to,
+ data,
+ value,
+ gas_limit.low_u64(),
+ max_fee_per_gas,
+ max_priority_fee_per_gas,
+ nonce,
+ access_list.unwrap_or_default(),
+ is_transactional,
+ config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),
+ ).map_err(|err| err.error.into())
+ }
+
+ #[allow(clippy::redundant_closure)]
+ fn create(
+ from: H160,
+ data: Vec<u8>,
+ value: U256,
+ gas_limit: U256,
+ max_fee_per_gas: Option<U256>,
+ max_priority_fee_per_gas: Option<U256>,
+ nonce: Option<U256>,
+ estimate: bool,
+ access_list: Option<Vec<(H160, Vec<H256>)>>,
+ ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
+ let config = if estimate {
+ let mut config = <Runtime as pallet_evm::Config>::config().clone();
+ config.estimate = true;
+ Some(config)
+ } else {
+ None
+ };
+
+ let is_transactional = false;
+ <Runtime as pallet_evm::Config>::Runner::create(
+ CrossAccountId::from_eth(from),
+ data,
+ value,
+ gas_limit.low_u64(),
+ max_fee_per_gas,
+ max_priority_fee_per_gas,
+ nonce,
+ access_list.unwrap_or_default(),
+ is_transactional,
+ config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),
+ ).map_err(|err| err.error.into())
+ }
+
+ fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {
+ Ethereum::current_transaction_statuses()
+ }
+
+ fn current_block() -> Option<pallet_ethereum::Block> {
+ Ethereum::current_block()
+ }
+
+ fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {
+ Ethereum::current_receipts()
+ }
+
+ fn current_all() -> (
+ Option<pallet_ethereum::Block>,
+ Option<Vec<pallet_ethereum::Receipt>>,
+ Option<Vec<TransactionStatus>>
+ ) {
+ (
+ Ethereum::current_block(),
+ Ethereum::current_receipts(),
+ Ethereum::current_transaction_statuses()
+ )
+ }
+
+ fn extrinsic_filter(xts: Vec<<Block as sp_api::BlockT>::Extrinsic>) -> Vec<pallet_ethereum::Transaction> {
+ xts.into_iter().filter_map(|xt| match xt.0.function {
+ Call::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),
+ _ => None
+ }).collect()
+ }
+
+ fn elasticity() -> Option<Permill> {
+ None
+ }
+ }
+
+ impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {
+ fn convert_transaction(transaction: pallet_ethereum::Transaction) -> <Block as BlockT>::Extrinsic {
+ UncheckedExtrinsic::new_unsigned(
+ pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
+ )
+ }
+ }
+
+ impl sp_session::SessionKeys<Block> for Runtime {
+ fn decode_session_keys(
+ encoded: Vec<u8>,
+ ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
+ SessionKeys::decode_into_raw_public_keys(&encoded)
+ }
+
+ fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
+ SessionKeys::generate(seed)
+ }
+ }
+
+ impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
+ fn slot_duration() -> sp_consensus_aura::SlotDuration {
+ sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
+ }
+
+ fn authorities() -> Vec<AuraId> {
+ Aura::authorities().to_vec()
+ }
+ }
+
+ impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
+ fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
+ ParachainSystem::collect_collation_info(header)
+ }
+ }
+
+ impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
+ fn account_nonce(account: AccountId) -> Index {
+ System::account_nonce(account)
+ }
+ }
+
+ impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
+ fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {
+ TransactionPayment::query_info(uxt, len)
+ }
+ fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {
+ TransactionPayment::query_fee_details(uxt, len)
+ }
+ }
+
+ /*
+ impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>
+ for Runtime
+ {
+ fn call(
+ origin: AccountId,
+ dest: AccountId,
+ value: Balance,
+ gas_limit: u64,
+ input_data: Vec<u8>,
+ ) -> pallet_contracts_primitives::ContractExecResult {
+ Contracts::bare_call(origin, dest, value, gas_limit, input_data, false)
+ }
+
+ fn instantiate(
+ origin: AccountId,
+ endowment: Balance,
+ gas_limit: u64,
+ code: pallet_contracts_primitives::Code<Hash>,
+ data: Vec<u8>,
+ salt: Vec<u8>,
+ ) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, BlockNumber>
+ {
+ Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true, false)
+ }
+
+ fn get_storage(
+ address: AccountId,
+ key: [u8; 32],
+ ) -> pallet_contracts_primitives::GetStorageResult {
+ Contracts::get_storage(address, key)
+ }
+
+ fn rent_projection(
+ address: AccountId,
+ ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {
+ Contracts::rent_projection(address)
+ }
+ }
+ */
+
+ #[cfg(feature = "runtime-benchmarks")]
+ impl frame_benchmarking::Benchmark<Block> for Runtime {
+ fn benchmark_metadata(extra: bool) -> (
+ Vec<frame_benchmarking::BenchmarkList>,
+ Vec<frame_support::traits::StorageInfo>,
+ ) {
+ use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};
+ use frame_support::traits::StorageInfoTrait;
+
+ let mut list = Vec::<BenchmarkList>::new();
+
+ list_benchmark!(list, extra, pallet_evm_migration, EvmMigration);
+ list_benchmark!(list, extra, pallet_common, Common);
+ list_benchmark!(list, extra, pallet_unique, Unique);
+ list_benchmark!(list, extra, pallet_structure, Structure);
+ list_benchmark!(list, extra, pallet_inflation, Inflation);
+ list_benchmark!(list, extra, pallet_fungible, Fungible);
+ list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);
+
+ #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))]
+ list_benchmark!(list, extra, pallet_refungible, Refungible);
+
+ #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))]
+ list_benchmark!(list, extra, pallet_unique_scheduler, Scheduler);
+
+ #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))]
+ list_benchmark!(list, extra, pallet_proxy_rmrk_core, RmrkCore);
+
+ #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))]
+ list_benchmark!(list, extra, pallet_proxy_rmrk_equip, RmrkEquip);
+
+ // list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate);
+
+ let storage_info = AllPalletsReversedWithSystemFirst::storage_info();
+
+ return (list, storage_info)
+ }
+
+ fn dispatch_benchmark(
+ config: frame_benchmarking::BenchmarkConfig
+ ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {
+ use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};
+
+ let allowlist: Vec<TrackedStorageKey> = vec![
+ // Total Issuance
+ hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),
+
+ // Block Number
+ hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),
+ // Execution Phase
+ hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),
+ // Event Count
+ hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),
+ // System Events
+ hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),
+
+ // Evm CurrentLogs
+ hex_literal::hex!("1da53b775b270400e7e61ed5cbc5a146547f210cec367e9af919603343b9cb56").to_vec().into(),
+
+ // Transactional depth
+ hex_literal::hex!("3a7472616e73616374696f6e5f6c6576656c3a").to_vec().into(),
+ ];
+
+ let mut batches = Vec::<BenchmarkBatch>::new();
+ let params = (&config, &allowlist);
+
+ add_benchmark!(params, batches, pallet_evm_migration, EvmMigration);
+ add_benchmark!(params, batches, pallet_common, Common);
+ add_benchmark!(params, batches, pallet_unique, Unique);
+ add_benchmark!(params, batches, pallet_structure, Structure);
+ add_benchmark!(params, batches, pallet_inflation, Inflation);
+ add_benchmark!(params, batches, pallet_fungible, Fungible);
+ add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);
+
+ #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))]
+ add_benchmark!(params, batches, pallet_refungible, Refungible);
+
+ #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))]
+ add_benchmark!(params, batches, pallet_unique_scheduler, Scheduler);
+
+ #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))]
+ add_benchmark!(params, batches, pallet_proxy_rmrk_core, RmrkCore);
+
+ #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))]
+ add_benchmark!(params, batches, pallet_proxy_rmrk_equip, RmrkEquip);
+
+ // add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate);
+
+ if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
+ Ok(batches)
+ }
+ }
+
+ #[cfg(feature = "try-runtime")]
+ impl frame_try_runtime::TryRuntime<Block> for Runtime {
+ fn on_runtime_upgrade() -> (Weight, Weight) {
+ log::info!("try-runtime::on_runtime_upgrade unique-chain.");
+ let weight = Executive::try_runtime_upgrade().unwrap();
+ (weight, RuntimeBlockWeights::get().max_block)
+ }
+
+ fn execute_block_no_check(block: Block) -> Weight {
+ Executive::execute_block_no_check(block)
+ }
+ }
+ }
+ }
+}
runtime/common/scheduler.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/scheduler.rs
@@ -0,0 +1,141 @@
+// 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/>.
+
+use frame_support::{
+ traits::NamedReservableCurrency,
+ weights::{GetDispatchInfo, PostDispatchInfo, DispatchInfo},
+};
+use sp_runtime::{
+ traits::{Dispatchable, Applyable, Member},
+ generic::Era,
+ transaction_validity::TransactionValidityError,
+ DispatchErrorWithPostInfo, DispatchError,
+};
+use crate::{Runtime, Call, Origin, Balances, ChargeTransactionPayment};
+use up_common::types::{AccountId, Balance};
+use fp_self_contained::SelfContainedCall;
+use pallet_unique_scheduler::DispatchCall;
+
+/// The SignedExtension to the basic transaction logic.
+pub type SignedExtraScheduler = (
+ frame_system::CheckSpecVersion<Runtime>,
+ frame_system::CheckGenesis<Runtime>,
+ frame_system::CheckEra<Runtime>,
+ frame_system::CheckNonce<Runtime>,
+ frame_system::CheckWeight<Runtime>,
+);
+
+fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {
+ (
+ frame_system::CheckSpecVersion::<Runtime>::new(),
+ frame_system::CheckGenesis::<Runtime>::new(),
+ frame_system::CheckEra::<Runtime>::from(Era::Immortal),
+ frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(
+ from,
+ )),
+ frame_system::CheckWeight::<Runtime>::new(),
+ // sponsoring transaction logic
+ // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
+ )
+}
+
+pub struct SchedulerPaymentExecutor;
+
+impl<T: frame_system::Config + pallet_unique_scheduler::Config, SelfContainedSignedInfo>
+ DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor
+where
+ <T as frame_system::Config>::Call: Member
+ + Dispatchable<Origin = Origin, Info = DispatchInfo>
+ + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>
+ + GetDispatchInfo
+ + From<frame_system::Call<Runtime>>,
+ SelfContainedSignedInfo: Send + Sync + 'static,
+ Call: From<<T as frame_system::Config>::Call>
+ + From<<T as pallet_unique_scheduler::Config>::Call>
+ + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,
+ sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,
+{
+ fn dispatch_call(
+ signer: <T as frame_system::Config>::AccountId,
+ call: <T as pallet_unique_scheduler::Config>::Call,
+ ) -> Result<
+ Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,
+ TransactionValidityError,
+ > {
+ let dispatch_info = call.get_dispatch_info();
+ let extrinsic = fp_self_contained::CheckedExtrinsic::<
+ AccountId,
+ Call,
+ SignedExtraScheduler,
+ SelfContainedSignedInfo,
+ > {
+ signed: fp_self_contained::CheckedSignature::<
+ AccountId,
+ SignedExtraScheduler,
+ SelfContainedSignedInfo,
+ >::Signed(signer.clone().into(), get_signed_extras(signer.into())),
+ function: call.into(),
+ };
+
+ extrinsic.apply::<Runtime>(&dispatch_info, 0)
+ }
+
+ fn reserve_balance(
+ id: [u8; 16],
+ sponsor: <T as frame_system::Config>::AccountId,
+ call: <T as pallet_unique_scheduler::Config>::Call,
+ count: u32,
+ ) -> Result<(), DispatchError> {
+ let dispatch_info = call.get_dispatch_info();
+ let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)
+ .saturating_mul(count.into());
+
+ <Balances as NamedReservableCurrency<AccountId>>::reserve_named(
+ &id,
+ &(sponsor.into()),
+ weight,
+ )
+ }
+
+ fn pay_for_call(
+ id: [u8; 16],
+ sponsor: <T as frame_system::Config>::AccountId,
+ call: <T as pallet_unique_scheduler::Config>::Call,
+ ) -> Result<u128, DispatchError> {
+ let dispatch_info = call.get_dispatch_info();
+ let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);
+ Ok(
+ <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
+ &id,
+ &(sponsor.into()),
+ weight,
+ ),
+ )
+ }
+
+ fn cancel_reserve(
+ id: [u8; 16],
+ sponsor: <T as frame_system::Config>::AccountId,
+ ) -> Result<u128, DispatchError> {
+ Ok(
+ <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
+ &id,
+ &(sponsor.into()),
+ u128::MAX,
+ ),
+ )
+ }
+}
runtime/common/sponsoring.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/sponsoring.rs
@@ -0,0 +1,359 @@
+// 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/>.
+
+use core::marker::PhantomData;
+use up_sponsorship::SponsorshipHandler;
+use frame_support::{
+ traits::{IsSubType},
+ storage::{StorageMap, StorageDoubleMap, StorageNMap},
+};
+use up_data_structs::{
+ CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, NFT_SPONSOR_TRANSFER_TIMEOUT,
+ REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId, CollectionMode, CreateItemData,
+};
+use sp_runtime::traits::Saturating;
+use pallet_common::{CollectionHandle};
+use pallet_evm::account::CrossAccountId;
+use pallet_unique::{
+ Call as UniqueCall, Config as UniqueConfig, FungibleApproveBasket, RefungibleApproveBasket,
+ NftApproveBasket, CreateItemBasket, ReFungibleTransferBasket, FungibleTransferBasket,
+ NftTransferBasket, TokenPropertyBasket,
+};
+use pallet_fungible::Config as FungibleConfig;
+use pallet_nonfungible::Config as NonfungibleConfig;
+use pallet_refungible::Config as RefungibleConfig;
+
+pub trait Config: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig {}
+impl<T> Config for T where T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig {}
+
+// TODO: permission check?
+pub fn withdraw_set_token_property<T: Config>(
+ collection: &CollectionHandle<T>,
+ who: &T::CrossAccountId,
+ item_id: &TokenId,
+ data_size: usize,
+) -> Option<()> {
+ // preliminary sponsoring correctness check
+ match collection.mode {
+ CollectionMode::NFT => {
+ let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
+ if !owner.conv_eq(who) {
+ return None;
+ }
+ }
+ CollectionMode::Fungible(_) => {
+ // Fungible tokens have no properties
+ return None;
+ }
+ CollectionMode::ReFungible => {
+ if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
+ return None;
+ }
+ }
+ }
+
+ if data_size > collection.limits.sponsored_data_size() as usize {
+ return None;
+ }
+
+ let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+ let limit = collection.limits.sponsored_data_rate_limit()?;
+
+ if let Some(last_tx_block) = TokenPropertyBasket::<T>::get(collection.id, item_id) {
+ let timeout = last_tx_block + limit.into();
+ if block_number < timeout {
+ return None;
+ }
+ }
+
+ <TokenPropertyBasket<T>>::insert(collection.id, item_id, block_number);
+
+ Some(())
+}
+
+pub fn withdraw_transfer<T: Config>(
+ collection: &CollectionHandle<T>,
+ who: &T::CrossAccountId,
+ item_id: &TokenId,
+) -> Option<()> {
+ // preliminary sponsoring correctness check
+ match collection.mode {
+ CollectionMode::NFT => {
+ let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
+ if !owner.conv_eq(who) {
+ return None;
+ }
+ }
+ CollectionMode::Fungible(_) => {
+ if item_id != &TokenId::default() {
+ return None;
+ }
+ if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {
+ return None;
+ }
+ }
+ CollectionMode::ReFungible => {
+ if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
+ return None;
+ }
+ }
+ }
+
+ // sponsor timeout
+ let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+ let limit = collection
+ .limits
+ .sponsor_transfer_timeout(match collection.mode {
+ CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
+ CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+ CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+ });
+
+ let last_tx_block = match collection.mode {
+ CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, item_id),
+ CollectionMode::Fungible(_) => {
+ <FungibleTransferBasket<T>>::get(collection.id, who.as_sub())
+ }
+ CollectionMode::ReFungible => {
+ <ReFungibleTransferBasket<T>>::get((collection.id, item_id, who.as_sub()))
+ }
+ };
+
+ if let Some(last_tx_block) = last_tx_block {
+ let timeout = last_tx_block + limit.into();
+ if block_number < timeout {
+ return None;
+ }
+ }
+
+ match collection.mode {
+ CollectionMode::NFT => <NftTransferBasket<T>>::insert(collection.id, item_id, block_number),
+ CollectionMode::Fungible(_) => {
+ <FungibleTransferBasket<T>>::insert(collection.id, who.as_sub(), block_number)
+ }
+ CollectionMode::ReFungible => <ReFungibleTransferBasket<T>>::insert(
+ (collection.id, item_id, who.as_sub()),
+ block_number,
+ ),
+ };
+
+ Some(())
+}
+
+pub fn withdraw_create_item<T: Config>(
+ collection: &CollectionHandle<T>,
+ who: &T::CrossAccountId,
+ properties: &CreateItemData,
+) -> Option<()> {
+ // sponsor timeout
+ let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+ let limit = collection
+ .limits
+ .sponsor_transfer_timeout(match properties {
+ CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,
+ CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+ CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+ });
+
+ if let Some(last_tx_block) = <CreateItemBasket<T>>::get((collection.id, who.as_sub())) {
+ let timeout = last_tx_block + limit.into();
+ if block_number < timeout {
+ return None;
+ }
+ }
+
+ CreateItemBasket::<T>::insert((collection.id, who.as_sub()), block_number);
+
+ Some(())
+}
+
+pub fn withdraw_approve<T: Config>(
+ collection: &CollectionHandle<T>,
+ who: &T::AccountId,
+ item_id: &TokenId,
+) -> Option<()> {
+ // sponsor timeout
+ let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+ let limit = collection.limits.sponsor_approve_timeout();
+
+ let last_tx_block = match collection.mode {
+ CollectionMode::NFT => <NftApproveBasket<T>>::get(collection.id, item_id),
+ CollectionMode::Fungible(_) => <FungibleApproveBasket<T>>::get(collection.id, who),
+ CollectionMode::ReFungible => {
+ <RefungibleApproveBasket<T>>::get((collection.id, item_id, who))
+ }
+ };
+
+ if let Some(last_tx_block) = last_tx_block {
+ let timeout = last_tx_block + limit.into();
+ if block_number < timeout {
+ return None;
+ }
+ }
+
+ match collection.mode {
+ CollectionMode::NFT => <NftApproveBasket<T>>::insert(collection.id, item_id, block_number),
+ CollectionMode::Fungible(_) => {
+ <FungibleApproveBasket<T>>::insert(collection.id, who, block_number)
+ }
+ CollectionMode::ReFungible => {
+ <RefungibleApproveBasket<T>>::insert((collection.id, item_id, who), block_number)
+ }
+ };
+
+ Some(())
+}
+
+fn load<T: UniqueConfig>(id: CollectionId) -> Option<(T::AccountId, CollectionHandle<T>)> {
+ let collection = CollectionHandle::new(id)?;
+ let sponsor = collection.sponsorship.sponsor().cloned()?;
+ Some((sponsor, collection))
+}
+
+pub struct UniqueSponsorshipHandler<T>(PhantomData<T>);
+impl<T, C> SponsorshipHandler<T::AccountId, C> for UniqueSponsorshipHandler<T>
+where
+ T: Config,
+ C: IsSubType<UniqueCall<T>>,
+{
+ fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {
+ match IsSubType::<UniqueCall<T>>::is_sub_type(call)? {
+ UniqueCall::set_token_properties {
+ collection_id,
+ token_id,
+ properties,
+ ..
+ } => {
+ let (sponsor, collection) = load::<T>(*collection_id)?;
+ withdraw_set_token_property(
+ &collection,
+ &T::CrossAccountId::from_sub(who.clone()),
+ &token_id,
+ // No overflow may happen, as data larger than usize can't reach here
+ properties.iter().map(|p| p.key.len() + p.value.len()).sum(),
+ )
+ .map(|()| sponsor)
+ }
+ UniqueCall::create_item {
+ collection_id,
+ data,
+ ..
+ } => {
+ let (sponsor, collection) = load(*collection_id)?;
+ withdraw_create_item::<T>(
+ &collection,
+ &T::CrossAccountId::from_sub(who.clone()),
+ data,
+ )
+ .map(|()| sponsor)
+ }
+ UniqueCall::transfer {
+ collection_id,
+ item_id,
+ ..
+ } => {
+ let (sponsor, collection) = load(*collection_id)?;
+ withdraw_transfer::<T>(
+ &collection,
+ &T::CrossAccountId::from_sub(who.clone()),
+ item_id,
+ )
+ .map(|()| sponsor)
+ }
+ UniqueCall::transfer_from {
+ collection_id,
+ item_id,
+ from,
+ ..
+ } => {
+ let (sponsor, collection) = load(*collection_id)?;
+ withdraw_transfer::<T>(&collection, from, item_id).map(|()| sponsor)
+ }
+ UniqueCall::approve {
+ collection_id,
+ item_id,
+ ..
+ } => {
+ let (sponsor, collection) = load(*collection_id)?;
+ withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)
+ }
+ _ => None,
+ }
+ }
+}
+
+pub trait SponsorshipPredict<T: Config> {
+ fn predict(collection: CollectionId, account: T::CrossAccountId, token: TokenId) -> Option<u64>
+ where
+ u64: From<<T as frame_system::Config>::BlockNumber>;
+}
+
+pub struct UniqueSponsorshipPredict<T>(PhantomData<T>);
+
+impl<T: Config> SponsorshipPredict<T> for UniqueSponsorshipPredict<T> {
+ fn predict(collection_id: CollectionId, who: T::CrossAccountId, token: TokenId) -> Option<u64>
+ where
+ u64: From<<T as frame_system::Config>::BlockNumber>,
+ {
+ let collection = <CollectionHandle<T>>::try_get(collection_id).ok()?;
+ let _ = collection.sponsorship.sponsor()?;
+
+ // sponsor timeout
+ let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+ let limit = collection
+ .limits
+ .sponsor_transfer_timeout(match collection.mode {
+ CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
+ CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+ CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
+ });
+
+ let last_tx_block = match collection.mode {
+ CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, token),
+ CollectionMode::Fungible(_) => {
+ <FungibleTransferBasket<T>>::get(collection.id, who.as_sub())
+ }
+ CollectionMode::ReFungible => {
+ <ReFungibleTransferBasket<T>>::get((collection.id, token, who.as_sub()))
+ }
+ };
+
+ if let Some(last_tx_block) = last_tx_block {
+ return Some(
+ last_tx_block
+ .saturating_add(limit.into())
+ .saturating_sub(block_number)
+ .into(),
+ );
+ }
+
+ let token_exists = match collection.mode {
+ CollectionMode::NFT => {
+ <pallet_nonfungible::TokenData<T>>::contains_key((collection.id, token))
+ }
+ CollectionMode::Fungible(_) => token == TokenId::default(),
+ CollectionMode::ReFungible => {
+ <pallet_refungible::TotalSupply<T>>::contains_key((collection.id, token))
+ }
+ };
+
+ if token_exists {
+ Some(0)
+ } else {
+ None
+ }
+ }
+}
runtime/common/src/constants.rsdiffbeforeafterboth--- a/runtime/common/src/constants.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-// 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/>.
-
-use sp_runtime::Perbill;
-use frame_support::{
- parameter_types,
- weights::{Weight, constants::WEIGHT_PER_SECOND},
-};
-use crate::types::{BlockNumber, Balance};
-
-pub const MILLISECS_PER_BLOCK: u64 = 12000;
-
-pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
-
-// These time units are defined in number of blocks.
-pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
-pub const HOURS: BlockNumber = MINUTES * 60;
-pub const DAYS: BlockNumber = HOURS * 24;
-
-pub const MICROUNIQUE: Balance = 1_000_000_000_000;
-pub const MILLIUNIQUE: Balance = 1_000 * MICROUNIQUE;
-pub const CENTIUNIQUE: Balance = 10 * MILLIUNIQUE;
-pub const UNIQUE: Balance = 100 * CENTIUNIQUE;
-
-// Targeting 0.1 UNQ per transfer
-pub const WEIGHT_TO_FEE_COEFF: u32 = 207_890_902;
-
-// Targeting 0.15 UNQ per transfer via ETH
-pub const MIN_GAS_PRICE: u64 = 1_019_493_469_850;
-
-/// We assume that ~10% of the block weight is consumed by `on_initalize` handlers.
-/// This is used to limit the maximal weight of a single extrinsic.
-pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
-/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used
-/// by Operational extrinsics.
-pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
-/// We allow for 2 seconds of compute with a 6 second average block time.
-pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND / 2;
-
-parameter_types! {
- pub const DefaultSponsoringRateLimit: BlockNumber = 1 * DAYS;
-
- pub const TransactionByteFee: Balance = 501 * MICROUNIQUE;
-}
runtime/common/src/dispatch.rsdiffbeforeafterboth--- a/runtime/common/src/dispatch.rs
+++ /dev/null
@@ -1,181 +0,0 @@
-// 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/>.
-
-use frame_support::{dispatch::DispatchResult, ensure};
-use pallet_evm::{PrecompileHandle, PrecompileResult};
-use sp_core::H160;
-use sp_runtime::DispatchError;
-use sp_std::{borrow::ToOwned, vec::Vec};
-use pallet_common::{
- CollectionById, CollectionHandle, CommonCollectionOperations, erc::CommonEvmHandler,
- eth::map_eth_to_id,
-};
-pub use pallet_common::dispatch::CollectionDispatch;
-use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};
-use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};
-use pallet_refungible::{
- Pallet as PalletRefungible, RefungibleHandle, erc_token::RefungibleTokenHandle,
-};
-use up_data_structs::{
- CollectionMode, CreateCollectionData, MAX_DECIMAL_POINTS, mapping::TokenAddressMapping,
- CollectionId,
-};
-
-pub enum CollectionDispatchT<T>
-where
- T: pallet_fungible::Config + pallet_nonfungible::Config + pallet_refungible::Config,
-{
- Fungible(FungibleHandle<T>),
- Nonfungible(NonfungibleHandle<T>),
- Refungible(RefungibleHandle<T>),
-}
-impl<T> CollectionDispatch<T> for CollectionDispatchT<T>
-where
- T: pallet_common::Config
- + pallet_unique::Config
- + pallet_fungible::Config
- + pallet_nonfungible::Config
- + pallet_refungible::Config,
-{
- fn create(
- sender: T::CrossAccountId,
- data: CreateCollectionData<T::AccountId>,
- ) -> Result<CollectionId, DispatchError> {
- let id = match data.mode {
- CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, data, false)?,
- CollectionMode::Fungible(decimal_points) => {
- // check params
- ensure!(
- decimal_points <= MAX_DECIMAL_POINTS,
- pallet_unique::Error::<T>::CollectionDecimalPointLimitExceeded
- );
- <PalletFungible<T>>::init_collection(sender, data)?
- }
- CollectionMode::ReFungible => <PalletRefungible<T>>::init_collection(sender, data)?,
- };
- Ok(id)
- }
-
- fn destroy(sender: T::CrossAccountId, collection: CollectionHandle<T>) -> DispatchResult {
- match collection.mode {
- CollectionMode::ReFungible => {
- PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?
- }
- CollectionMode::Fungible(_) => {
- PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?
- }
- CollectionMode::NFT => {
- PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?
- }
- }
- Ok(())
- }
-
- fn dispatch(handle: CollectionHandle<T>) -> Self {
- match handle.mode {
- CollectionMode::Fungible(_) => Self::Fungible(FungibleHandle::cast(handle)),
- CollectionMode::NFT => Self::Nonfungible(NonfungibleHandle::cast(handle)),
- CollectionMode::ReFungible => Self::Refungible(RefungibleHandle::cast(handle)),
- }
- }
-
- fn into_inner(self) -> CollectionHandle<T> {
- match self {
- Self::Fungible(f) => f.into_inner(),
- Self::Nonfungible(f) => f.into_inner(),
- Self::Refungible(f) => f.into_inner(),
- }
- }
-
- fn as_dyn(&self) -> &dyn CommonCollectionOperations<T> {
- match self {
- Self::Fungible(h) => h,
- Self::Nonfungible(h) => h,
- Self::Refungible(h) => h,
- }
- }
-}
-
-impl<T> pallet_evm::OnMethodCall<T> for CollectionDispatchT<T>
-where
- T: pallet_common::Config
- + pallet_unique::Config
- + pallet_fungible::Config
- + pallet_nonfungible::Config
- + pallet_refungible::Config,
- T::AccountId: From<[u8; 32]>,
-{
- fn is_reserved(target: &H160) -> bool {
- map_eth_to_id(target).is_some()
- }
- fn is_used(target: &H160) -> bool {
- map_eth_to_id(target)
- .map(<CollectionById<T>>::contains_key)
- .unwrap_or(false)
- }
- fn get_code(target: &H160) -> Option<Vec<u8>> {
- if let Some(collection_id) = map_eth_to_id(target) {
- let collection = <CollectionById<T>>::get(collection_id)?;
- Some(
- match collection.mode {
- CollectionMode::NFT => <NonfungibleHandle<T>>::CODE,
- CollectionMode::Fungible(_) => <FungibleHandle<T>>::CODE,
- CollectionMode::ReFungible => <RefungibleHandle<T>>::CODE,
- }
- .to_owned(),
- )
- } else if let Some((collection_id, _token_id)) =
- <T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(target)
- {
- let collection = <CollectionById<T>>::get(collection_id)?;
- if collection.mode != CollectionMode::ReFungible {
- return None;
- }
- // TODO: check token existence
- Some(<RefungibleTokenHandle<T>>::CODE.to_owned())
- } else {
- None
- }
- }
- fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {
- if let Some(collection_id) = map_eth_to_id(&handle.code_address()) {
- let collection =
- <CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;
- let dispatched = Self::dispatch(collection);
-
- match dispatched {
- Self::Fungible(h) => h.call(handle),
- Self::Nonfungible(h) => h.call(handle),
- Self::Refungible(h) => h.call(handle),
- }
- } else if let Some((collection_id, token_id)) =
- <T as pallet_common::Config>::EvmTokenAddressMapping::address_to_token(
- &handle.code_address(),
- ) {
- let collection =
- <CollectionHandle<T>>::new_with_gas_limit(collection_id, handle.remaining_gas())?;
- if collection.mode != CollectionMode::ReFungible {
- return None;
- }
-
- let h = RefungibleHandle::cast(collection);
- // TODO: check token existence
- RefungibleTokenHandle(h, token_id).call(handle)
- } else {
- None
- }
- }
-}
runtime/common/src/eth_sponsoring.rsdiffbeforeafterboth--- a/runtime/common/src/eth_sponsoring.rs
+++ /dev/null
@@ -1,122 +0,0 @@
-// 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/>.
-
-//! Implements EVM sponsoring logic via TransactionValidityHack
-
-use evm_coder::{Call, abi::AbiReader};
-use pallet_common::{CollectionHandle, eth::map_eth_to_id};
-use sp_core::H160;
-use sp_std::prelude::*;
-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::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 struct UniqueEthSponsorshipHandler<T: UniqueConfig>(PhantomData<*const T>);
-impl<T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig>
- SponsorshipHandler<T::CrossAccountId, (H160, Vec<u8>)> 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)?;
- let collection = <CollectionHandle<T>>::new(collection_id)?;
- let sponsor = collection.sponsorship.sponsor()?.clone();
- let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;
- Some(T::CrossAccountId::from_sub(match &collection.mode {
- CollectionMode::NFT => {
- let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;
- match call {
- UniqueNFTCall::TokenProperties(TokenPropertiesCall::SetProperty {
- token_id,
- key,
- value,
- ..
- }) => {
- let token_id: TokenId = token_id.try_into().ok()?;
- withdraw_set_token_property::<T>(
- &collection,
- &who,
- &token_id,
- key.len() + value.len(),
- )
- .map(|()| sponsor)
- }
- UniqueNFTCall::ERC721UniqueExtensions(
- ERC721UniqueExtensionsCall::Transfer { token_id, .. },
- ) => {
- let token_id: TokenId = token_id.try_into().ok()?;
- withdraw_transfer::<T>(&collection, &who, &token_id).map(|()| sponsor)
- }
- UniqueNFTCall::ERC721Mintable(
- ERC721MintableCall::Mint { token_id, .. }
- | ERC721MintableCall::MintWithTokenUri { token_id, .. },
- ) => {
- let _token_id: TokenId = token_id.try_into().ok()?;
- withdraw_create_item::<T>(
- &collection,
- &who,
- &CreateItemData::NFT(CreateNftData::default()),
- )
- .map(|()| sponsor)
- }
- UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, from, .. }) => {
- let token_id: TokenId = token_id.try_into().ok()?;
- let from = T::CrossAccountId::from_eth(from);
- withdraw_transfer::<T>(&collection, &from, &token_id).map(|()| sponsor)
- }
- UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {
- let token_id: TokenId = token_id.try_into().ok()?;
- withdraw_approve::<T>(&collection, who.as_sub(), &token_id)
- .map(|()| sponsor)
- }
- _ => None,
- }
- }
- CollectionMode::Fungible(_) => {
- let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader).ok()??;
- #[allow(clippy::single_match)]
- match call {
- UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {
- withdraw_transfer::<T>(&collection, who, &TokenId::default())
- .map(|()| sponsor)
- }
- UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {
- let from = T::CrossAccountId::from_eth(from);
- withdraw_transfer::<T>(&collection, &from, &TokenId::default())
- .map(|()| sponsor)
- }
- UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {
- withdraw_approve::<T>(&collection, who.as_sub(), &TokenId::default())
- .map(|()| sponsor)
- }
- _ => None,
- }
- }
- _ => None,
- }?))
- }
-}
runtime/common/src/lib.rsdiffbeforeafterboth--- a/runtime/common/src/lib.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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/>.
-
-#![cfg_attr(not(feature = "std"), no_std)]
-
-pub mod constants;
-pub mod dispatch;
-pub mod eth_sponsoring;
-pub mod runtime_apis;
-pub mod sponsoring;
-pub mod types;
-pub mod weights;
runtime/common/src/runtime_apis.rsdiffbeforeafterboth--- a/runtime/common/src/runtime_apis.rs
+++ /dev/null
@@ -1,546 +0,0 @@
-// 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/>.
-
-#[macro_export]
-macro_rules! impl_common_runtime_apis {
- (
- $(
- #![custom_apis]
-
- $($custom_apis:tt)+
- )?
- ) => {
- impl_runtime_apis! {
- $($($custom_apis)+)?
-
- impl up_rpc::UniqueApi<Block, CrossAccountId, AccountId> for Runtime {
- fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result<Vec<TokenId>, DispatchError> {
- dispatch_unique_runtime!(collection.account_tokens(account))
- }
- fn collection_tokens(collection: CollectionId) -> Result<Vec<TokenId>, DispatchError> {
- dispatch_unique_runtime!(collection.collection_tokens())
- }
- fn token_exists(collection: CollectionId, token: TokenId) -> Result<bool, DispatchError> {
- dispatch_unique_runtime!(collection.token_exists(token))
- }
-
- fn token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {
- dispatch_unique_runtime!(collection.token_owner(token))
- }
-
- fn token_owners(collection: CollectionId, token: TokenId) -> Result<Vec::<CrossAccountId>, DispatchError> {
- dispatch_unique_runtime!(collection.token_owners(token))
- }
-
- fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {
- let budget = up_data_structs::budget::Value::new(10);
-
- Ok(Some(<pallet_structure::Pallet<Runtime>>::find_topmost_owner(collection, token, &budget)?))
- }
- fn token_children(collection: CollectionId, token: TokenId) -> Result<Vec<TokenChild>, DispatchError> {
- Ok(<pallet_nonfungible::Pallet<Runtime>>::token_children_ids(collection, token))
- }
- fn collection_properties(
- collection: CollectionId,
- keys: Option<Vec<Vec<u8>>>
- ) -> Result<Vec<Property>, DispatchError> {
- let keys = keys.map(
- |keys| Common::bytes_keys_to_property_keys(keys)
- ).transpose()?;
-
- Common::filter_collection_properties(collection, keys)
- }
-
- fn token_properties(
- collection: CollectionId,
- token_id: TokenId,
- keys: Option<Vec<Vec<u8>>>
- ) -> Result<Vec<Property>, DispatchError> {
- let keys = keys.map(
- |keys| Common::bytes_keys_to_property_keys(keys)
- ).transpose()?;
-
- dispatch_unique_runtime!(collection.token_properties(token_id, keys))
- }
-
- fn property_permissions(
- collection: CollectionId,
- keys: Option<Vec<Vec<u8>>>
- ) -> Result<Vec<PropertyKeyPermission>, DispatchError> {
- let keys = keys.map(
- |keys| Common::bytes_keys_to_property_keys(keys)
- ).transpose()?;
-
- Common::filter_property_permissions(collection, keys)
- }
-
- fn token_data(
- collection: CollectionId,
- token_id: TokenId,
- keys: Option<Vec<Vec<u8>>>
- ) -> Result<TokenData<CrossAccountId>, DispatchError> {
- let token_data = TokenData {
- properties: Self::token_properties(collection, token_id, keys)?,
- owner: Self::token_owner(collection, token_id)?,
- pieces: Self::total_pieces(collection, token_id)?.unwrap_or(0),
- };
-
- Ok(token_data)
- }
-
- fn total_supply(collection: CollectionId) -> Result<u32, DispatchError> {
- dispatch_unique_runtime!(collection.total_supply())
- }
- fn account_balance(collection: CollectionId, account: CrossAccountId) -> Result<u32, DispatchError> {
- dispatch_unique_runtime!(collection.account_balance(account))
- }
- fn balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<u128, DispatchError> {
- dispatch_unique_runtime!(collection.balance(account, token))
- }
- fn allowance(
- collection: CollectionId,
- sender: CrossAccountId,
- spender: CrossAccountId,
- token: TokenId,
- ) -> Result<u128, DispatchError> {
- dispatch_unique_runtime!(collection.allowance(sender, spender, token))
- }
-
- fn adminlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {
- Ok(<pallet_common::Pallet<Runtime>>::adminlist(collection))
- }
- fn allowlist(collection: CollectionId) -> Result<Vec<CrossAccountId>, DispatchError> {
- Ok(<pallet_common::Pallet<Runtime>>::allowlist(collection))
- }
- fn allowed(collection: CollectionId, user: CrossAccountId) -> Result<bool, DispatchError> {
- Ok(<pallet_common::Pallet<Runtime>>::allowed(collection, user))
- }
- fn last_token_id(collection: CollectionId) -> Result<TokenId, DispatchError> {
- dispatch_unique_runtime!(collection.last_token_id())
- }
- fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollection<AccountId>>, DispatchError> {
- Ok(<pallet_common::Pallet<Runtime>>::rpc_collection(collection))
- }
- fn collection_stats() -> Result<CollectionStats, DispatchError> {
- Ok(<pallet_common::Pallet<Runtime>>::collection_stats())
- }
- fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>, DispatchError> {
- Ok(<$crate::sponsoring::UniqueSponsorshipPredict<Runtime> as
- $crate::sponsoring::SponsorshipPredict<Runtime>>::predict(
- collection,
- account,
- token))
- }
-
- fn effective_collection_limits(collection: CollectionId) -> Result<Option<CollectionLimits>, DispatchError> {
- Ok(<pallet_common::Pallet<Runtime>>::effective_collection_limits(collection))
- }
-
- fn total_pieces(collection: CollectionId, token_id: TokenId) -> Result<Option<u128>, DispatchError> {
- dispatch_unique_runtime!(collection.total_pieces(token_id))
- }
- }
-
- impl sp_api::Core<Block> for Runtime {
- fn version() -> RuntimeVersion {
- VERSION
- }
-
- fn execute_block(block: Block) {
- Executive::execute_block(block)
- }
-
- fn initialize_block(header: &<Block as BlockT>::Header) {
- Executive::initialize_block(header)
- }
- }
-
- impl sp_api::Metadata<Block> for Runtime {
- fn metadata() -> OpaqueMetadata {
- OpaqueMetadata::new(Runtime::metadata().into())
- }
- }
-
- impl sp_block_builder::BlockBuilder<Block> for Runtime {
- fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
- Executive::apply_extrinsic(extrinsic)
- }
-
- fn finalize_block() -> <Block as BlockT>::Header {
- Executive::finalize_block()
- }
-
- fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
- data.create_extrinsics()
- }
-
- fn check_inherents(
- block: Block,
- data: sp_inherents::InherentData,
- ) -> sp_inherents::CheckInherentsResult {
- data.check_extrinsics(&block)
- }
-
- // fn random_seed() -> <Block as BlockT>::Hash {
- // RandomnessCollectiveFlip::random_seed().0
- // }
- }
-
- impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
- fn validate_transaction(
- source: TransactionSource,
- tx: <Block as BlockT>::Extrinsic,
- hash: <Block as BlockT>::Hash,
- ) -> TransactionValidity {
- Executive::validate_transaction(source, tx, hash)
- }
- }
-
- impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
- fn offchain_worker(header: &<Block as BlockT>::Header) {
- Executive::offchain_worker(header)
- }
- }
-
- impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
- fn chain_id() -> u64 {
- <Runtime as pallet_evm::Config>::ChainId::get()
- }
-
- fn account_basic(address: H160) -> EVMAccount {
- let (account, _) = EVM::account_basic(&address);
- account
- }
-
- fn gas_price() -> U256 {
- let (price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();
- price
- }
-
- fn account_code_at(address: H160) -> Vec<u8> {
- EVM::account_codes(address)
- }
-
- fn author() -> H160 {
- <pallet_evm::Pallet<Runtime>>::find_author()
- }
-
- fn storage_at(address: H160, index: U256) -> H256 {
- let mut tmp = [0u8; 32];
- index.to_big_endian(&mut tmp);
- EVM::account_storages(address, H256::from_slice(&tmp[..]))
- }
-
- #[allow(clippy::redundant_closure)]
- fn call(
- from: H160,
- to: H160,
- data: Vec<u8>,
- value: U256,
- gas_limit: U256,
- max_fee_per_gas: Option<U256>,
- max_priority_fee_per_gas: Option<U256>,
- nonce: Option<U256>,
- estimate: bool,
- access_list: Option<Vec<(H160, Vec<H256>)>>,
- ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
- let config = if estimate {
- let mut config = <Runtime as pallet_evm::Config>::config().clone();
- config.estimate = true;
- Some(config)
- } else {
- None
- };
-
- let is_transactional = false;
- <Runtime as pallet_evm::Config>::Runner::call(
- CrossAccountId::from_eth(from),
- to,
- data,
- value,
- gas_limit.low_u64(),
- max_fee_per_gas,
- max_priority_fee_per_gas,
- nonce,
- access_list.unwrap_or_default(),
- is_transactional,
- config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),
- ).map_err(|err| err.error.into())
- }
-
- #[allow(clippy::redundant_closure)]
- fn create(
- from: H160,
- data: Vec<u8>,
- value: U256,
- gas_limit: U256,
- max_fee_per_gas: Option<U256>,
- max_priority_fee_per_gas: Option<U256>,
- nonce: Option<U256>,
- estimate: bool,
- access_list: Option<Vec<(H160, Vec<H256>)>>,
- ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
- let config = if estimate {
- let mut config = <Runtime as pallet_evm::Config>::config().clone();
- config.estimate = true;
- Some(config)
- } else {
- None
- };
-
- let is_transactional = false;
- <Runtime as pallet_evm::Config>::Runner::create(
- CrossAccountId::from_eth(from),
- data,
- value,
- gas_limit.low_u64(),
- max_fee_per_gas,
- max_priority_fee_per_gas,
- nonce,
- access_list.unwrap_or_default(),
- is_transactional,
- config.as_ref().unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),
- ).map_err(|err| err.error.into())
- }
-
- fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {
- Ethereum::current_transaction_statuses()
- }
-
- fn current_block() -> Option<pallet_ethereum::Block> {
- Ethereum::current_block()
- }
-
- fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {
- Ethereum::current_receipts()
- }
-
- fn current_all() -> (
- Option<pallet_ethereum::Block>,
- Option<Vec<pallet_ethereum::Receipt>>,
- Option<Vec<TransactionStatus>>
- ) {
- (
- Ethereum::current_block(),
- Ethereum::current_receipts(),
- Ethereum::current_transaction_statuses()
- )
- }
-
- fn extrinsic_filter(xts: Vec<<Block as sp_api::BlockT>::Extrinsic>) -> Vec<pallet_ethereum::Transaction> {
- xts.into_iter().filter_map(|xt| match xt.0.function {
- Call::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),
- _ => None
- }).collect()
- }
-
- fn elasticity() -> Option<Permill> {
- None
- }
- }
-
- impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {
- fn convert_transaction(transaction: pallet_ethereum::Transaction) -> <Block as BlockT>::Extrinsic {
- UncheckedExtrinsic::new_unsigned(
- pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
- )
- }
- }
-
- impl sp_session::SessionKeys<Block> for Runtime {
- fn decode_session_keys(
- encoded: Vec<u8>,
- ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
- SessionKeys::decode_into_raw_public_keys(&encoded)
- }
-
- fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
- SessionKeys::generate(seed)
- }
- }
-
- impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
- fn slot_duration() -> sp_consensus_aura::SlotDuration {
- sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
- }
-
- fn authorities() -> Vec<AuraId> {
- Aura::authorities().to_vec()
- }
- }
-
- impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
- fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
- ParachainSystem::collect_collation_info(header)
- }
- }
-
- impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
- fn account_nonce(account: AccountId) -> Index {
- System::account_nonce(account)
- }
- }
-
- impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
- fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {
- TransactionPayment::query_info(uxt, len)
- }
- fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {
- TransactionPayment::query_fee_details(uxt, len)
- }
- }
-
- /*
- impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>
- for Runtime
- {
- fn call(
- origin: AccountId,
- dest: AccountId,
- value: Balance,
- gas_limit: u64,
- input_data: Vec<u8>,
- ) -> pallet_contracts_primitives::ContractExecResult {
- Contracts::bare_call(origin, dest, value, gas_limit, input_data, false)
- }
-
- fn instantiate(
- origin: AccountId,
- endowment: Balance,
- gas_limit: u64,
- code: pallet_contracts_primitives::Code<Hash>,
- data: Vec<u8>,
- salt: Vec<u8>,
- ) -> pallet_contracts_primitives::ContractInstantiateResult<AccountId, BlockNumber>
- {
- Contracts::bare_instantiate(origin, endowment, gas_limit, code, data, salt, true, false)
- }
-
- fn get_storage(
- address: AccountId,
- key: [u8; 32],
- ) -> pallet_contracts_primitives::GetStorageResult {
- Contracts::get_storage(address, key)
- }
-
- fn rent_projection(
- address: AccountId,
- ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {
- Contracts::rent_projection(address)
- }
- }
- */
-
- #[cfg(feature = "runtime-benchmarks")]
- impl frame_benchmarking::Benchmark<Block> for Runtime {
- fn benchmark_metadata(extra: bool) -> (
- Vec<frame_benchmarking::BenchmarkList>,
- Vec<frame_support::traits::StorageInfo>,
- ) {
- use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList};
- use frame_support::traits::StorageInfoTrait;
-
- let mut list = Vec::<BenchmarkList>::new();
-
- list_benchmark!(list, extra, pallet_evm_migration, EvmMigration);
- list_benchmark!(list, extra, pallet_common, Common);
- list_benchmark!(list, extra, pallet_unique, Unique);
- list_benchmark!(list, extra, pallet_structure, Structure);
- list_benchmark!(list, extra, pallet_inflation, Inflation);
- list_benchmark!(list, extra, pallet_fungible, Fungible);
- list_benchmark!(list, extra, pallet_refungible, Refungible);
- list_benchmark!(list, extra, pallet_nonfungible, Nonfungible);
- list_benchmark!(list, extra, pallet_unique_scheduler, Scheduler);
-
- #[cfg(not(feature = "unique-runtime"))]
- list_benchmark!(list, extra, pallet_proxy_rmrk_core, RmrkCore);
-
- #[cfg(not(feature = "unique-runtime"))]
- list_benchmark!(list, extra, pallet_proxy_rmrk_equip, RmrkEquip);
-
- // list_benchmark!(list, extra, pallet_evm_coder_substrate, EvmCoderSubstrate);
-
- let storage_info = AllPalletsReversedWithSystemFirst::storage_info();
-
- return (list, storage_info)
- }
-
- fn dispatch_benchmark(
- config: frame_benchmarking::BenchmarkConfig
- ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {
- use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};
-
- let allowlist: Vec<TrackedStorageKey> = vec![
- // Total Issuance
- hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),
-
- // Block Number
- hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),
- // Execution Phase
- hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),
- // Event Count
- hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),
- // System Events
- hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),
-
- // Evm CurrentLogs
- hex_literal::hex!("1da53b775b270400e7e61ed5cbc5a146547f210cec367e9af919603343b9cb56").to_vec().into(),
-
- // Transactional depth
- hex_literal::hex!("3a7472616e73616374696f6e5f6c6576656c3a").to_vec().into(),
- ];
-
- let mut batches = Vec::<BenchmarkBatch>::new();
- let params = (&config, &allowlist);
-
- add_benchmark!(params, batches, pallet_evm_migration, EvmMigration);
- add_benchmark!(params, batches, pallet_common, Common);
- add_benchmark!(params, batches, pallet_unique, Unique);
- add_benchmark!(params, batches, pallet_structure, Structure);
- add_benchmark!(params, batches, pallet_inflation, Inflation);
- add_benchmark!(params, batches, pallet_fungible, Fungible);
- add_benchmark!(params, batches, pallet_refungible, Refungible);
- add_benchmark!(params, batches, pallet_nonfungible, Nonfungible);
- add_benchmark!(params, batches, pallet_unique_scheduler, Scheduler);
-
- #[cfg(not(feature = "unique-runtime"))]
- add_benchmark!(params, batches, pallet_proxy_rmrk_core, RmrkCore);
-
- #[cfg(not(feature = "unique-runtime"))]
- add_benchmark!(params, batches, pallet_proxy_rmrk_equip, RmrkEquip);
-
- // add_benchmark!(params, batches, pallet_evm_coder_substrate, EvmCoderSubstrate);
-
- if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
- Ok(batches)
- }
- }
-
- #[cfg(feature = "try-runtime")]
- impl frame_try_runtime::TryRuntime<Block> for Runtime {
- fn on_runtime_upgrade() -> (Weight, Weight) {
- log::info!("try-runtime::on_runtime_upgrade unique-chain.");
- let weight = Executive::try_runtime_upgrade().unwrap();
- (weight, RuntimeBlockWeights::get().max_block)
- }
-
- fn execute_block_no_check(block: Block) -> Weight {
- Executive::execute_block_no_check(block)
- }
- }
- }
- }
-}
runtime/common/src/sponsoring.rsdiffbeforeafterboth--- a/runtime/common/src/sponsoring.rs
+++ /dev/null
@@ -1,359 +0,0 @@
-// 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/>.
-
-use core::marker::PhantomData;
-use up_sponsorship::SponsorshipHandler;
-use frame_support::{
- traits::{IsSubType},
- storage::{StorageMap, StorageDoubleMap, StorageNMap},
-};
-use up_data_structs::{
- CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, NFT_SPONSOR_TRANSFER_TIMEOUT,
- REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId, CollectionMode, CreateItemData,
-};
-use sp_runtime::traits::Saturating;
-use pallet_common::{CollectionHandle};
-use pallet_evm::account::CrossAccountId;
-use pallet_unique::{
- Call as UniqueCall, Config as UniqueConfig, FungibleApproveBasket, RefungibleApproveBasket,
- NftApproveBasket, CreateItemBasket, ReFungibleTransferBasket, FungibleTransferBasket,
- NftTransferBasket, TokenPropertyBasket,
-};
-use pallet_fungible::Config as FungibleConfig;
-use pallet_nonfungible::Config as NonfungibleConfig;
-use pallet_refungible::Config as RefungibleConfig;
-
-pub trait Config: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig {}
-impl<T> Config for T where T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig {}
-
-// TODO: permission check?
-pub fn withdraw_set_token_property<T: Config>(
- collection: &CollectionHandle<T>,
- who: &T::CrossAccountId,
- item_id: &TokenId,
- data_size: usize,
-) -> Option<()> {
- // preliminary sponsoring correctness check
- match collection.mode {
- CollectionMode::NFT => {
- let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
- if !owner.conv_eq(who) {
- return None;
- }
- }
- CollectionMode::Fungible(_) => {
- // Fungible tokens have no properties
- return None;
- }
- CollectionMode::ReFungible => {
- if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
- return None;
- }
- }
- }
-
- if data_size > collection.limits.sponsored_data_size() as usize {
- return None;
- }
-
- let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
- let limit = collection.limits.sponsored_data_rate_limit()?;
-
- if let Some(last_tx_block) = TokenPropertyBasket::<T>::get(collection.id, item_id) {
- let timeout = last_tx_block + limit.into();
- if block_number < timeout {
- return None;
- }
- }
-
- <TokenPropertyBasket<T>>::insert(collection.id, item_id, block_number);
-
- Some(())
-}
-
-pub fn withdraw_transfer<T: Config>(
- collection: &CollectionHandle<T>,
- who: &T::CrossAccountId,
- item_id: &TokenId,
-) -> Option<()> {
- // preliminary sponsoring correctness check
- match collection.mode {
- CollectionMode::NFT => {
- let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
- if !owner.conv_eq(who) {
- return None;
- }
- }
- CollectionMode::Fungible(_) => {
- if item_id != &TokenId::default() {
- return None;
- }
- if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {
- return None;
- }
- }
- CollectionMode::ReFungible => {
- if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
- return None;
- }
- }
- }
-
- // sponsor timeout
- let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
- let limit = collection
- .limits
- .sponsor_transfer_timeout(match collection.mode {
- CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
- CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
- CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
- });
-
- let last_tx_block = match collection.mode {
- CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, item_id),
- CollectionMode::Fungible(_) => {
- <FungibleTransferBasket<T>>::get(collection.id, who.as_sub())
- }
- CollectionMode::ReFungible => {
- <ReFungibleTransferBasket<T>>::get((collection.id, item_id, who.as_sub()))
- }
- };
-
- if let Some(last_tx_block) = last_tx_block {
- let timeout = last_tx_block + limit.into();
- if block_number < timeout {
- return None;
- }
- }
-
- match collection.mode {
- CollectionMode::NFT => <NftTransferBasket<T>>::insert(collection.id, item_id, block_number),
- CollectionMode::Fungible(_) => {
- <FungibleTransferBasket<T>>::insert(collection.id, who.as_sub(), block_number)
- }
- CollectionMode::ReFungible => <ReFungibleTransferBasket<T>>::insert(
- (collection.id, item_id, who.as_sub()),
- block_number,
- ),
- };
-
- Some(())
-}
-
-pub fn withdraw_create_item<T: Config>(
- collection: &CollectionHandle<T>,
- who: &T::CrossAccountId,
- properties: &CreateItemData,
-) -> Option<()> {
- // sponsor timeout
- let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
- let limit = collection
- .limits
- .sponsor_transfer_timeout(match properties {
- CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,
- CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
- CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
- });
-
- if let Some(last_tx_block) = <CreateItemBasket<T>>::get((collection.id, who.as_sub())) {
- let timeout = last_tx_block + limit.into();
- if block_number < timeout {
- return None;
- }
- }
-
- CreateItemBasket::<T>::insert((collection.id, who.as_sub()), block_number);
-
- Some(())
-}
-
-pub fn withdraw_approve<T: Config>(
- collection: &CollectionHandle<T>,
- who: &T::AccountId,
- item_id: &TokenId,
-) -> Option<()> {
- // sponsor timeout
- let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
- let limit = collection.limits.sponsor_approve_timeout();
-
- let last_tx_block = match collection.mode {
- CollectionMode::NFT => <NftApproveBasket<T>>::get(collection.id, item_id),
- CollectionMode::Fungible(_) => <FungibleApproveBasket<T>>::get(collection.id, who),
- CollectionMode::ReFungible => {
- <RefungibleApproveBasket<T>>::get((collection.id, item_id, who))
- }
- };
-
- if let Some(last_tx_block) = last_tx_block {
- let timeout = last_tx_block + limit.into();
- if block_number < timeout {
- return None;
- }
- }
-
- match collection.mode {
- CollectionMode::NFT => <NftApproveBasket<T>>::insert(collection.id, item_id, block_number),
- CollectionMode::Fungible(_) => {
- <FungibleApproveBasket<T>>::insert(collection.id, who, block_number)
- }
- CollectionMode::ReFungible => {
- <RefungibleApproveBasket<T>>::insert((collection.id, item_id, who), block_number)
- }
- };
-
- Some(())
-}
-
-fn load<T: UniqueConfig>(id: CollectionId) -> Option<(T::AccountId, CollectionHandle<T>)> {
- let collection = CollectionHandle::new(id)?;
- let sponsor = collection.sponsorship.sponsor().cloned()?;
- Some((sponsor, collection))
-}
-
-pub struct UniqueSponsorshipHandler<T>(PhantomData<T>);
-impl<T, C> SponsorshipHandler<T::AccountId, C> for UniqueSponsorshipHandler<T>
-where
- T: Config,
- C: IsSubType<UniqueCall<T>>,
-{
- fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {
- match IsSubType::<UniqueCall<T>>::is_sub_type(call)? {
- UniqueCall::set_token_properties {
- collection_id,
- token_id,
- properties,
- ..
- } => {
- let (sponsor, collection) = load::<T>(*collection_id)?;
- withdraw_set_token_property(
- &collection,
- &T::CrossAccountId::from_sub(who.clone()),
- &token_id,
- // No overflow may happen, as data larger than usize can't reach here
- properties.iter().map(|p| p.key.len() + p.value.len()).sum(),
- )
- .map(|()| sponsor)
- }
- UniqueCall::create_item {
- collection_id,
- data,
- ..
- } => {
- let (sponsor, collection) = load(*collection_id)?;
- withdraw_create_item::<T>(
- &collection,
- &T::CrossAccountId::from_sub(who.clone()),
- data,
- )
- .map(|()| sponsor)
- }
- UniqueCall::transfer {
- collection_id,
- item_id,
- ..
- } => {
- let (sponsor, collection) = load(*collection_id)?;
- withdraw_transfer::<T>(
- &collection,
- &T::CrossAccountId::from_sub(who.clone()),
- item_id,
- )
- .map(|()| sponsor)
- }
- UniqueCall::transfer_from {
- collection_id,
- item_id,
- from,
- ..
- } => {
- let (sponsor, collection) = load(*collection_id)?;
- withdraw_transfer::<T>(&collection, from, item_id).map(|()| sponsor)
- }
- UniqueCall::approve {
- collection_id,
- item_id,
- ..
- } => {
- let (sponsor, collection) = load(*collection_id)?;
- withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)
- }
- _ => None,
- }
- }
-}
-
-pub trait SponsorshipPredict<T: Config> {
- fn predict(collection: CollectionId, account: T::CrossAccountId, token: TokenId) -> Option<u64>
- where
- u64: From<<T as frame_system::Config>::BlockNumber>;
-}
-
-pub struct UniqueSponsorshipPredict<T>(PhantomData<T>);
-
-impl<T: Config> SponsorshipPredict<T> for UniqueSponsorshipPredict<T> {
- fn predict(collection_id: CollectionId, who: T::CrossAccountId, token: TokenId) -> Option<u64>
- where
- u64: From<<T as frame_system::Config>::BlockNumber>,
- {
- let collection = <CollectionHandle<T>>::try_get(collection_id).ok()?;
- let _ = collection.sponsorship.sponsor()?;
-
- // sponsor timeout
- let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
- let limit = collection
- .limits
- .sponsor_transfer_timeout(match collection.mode {
- CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
- CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
- CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
- });
-
- let last_tx_block = match collection.mode {
- CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, token),
- CollectionMode::Fungible(_) => {
- <FungibleTransferBasket<T>>::get(collection.id, who.as_sub())
- }
- CollectionMode::ReFungible => {
- <ReFungibleTransferBasket<T>>::get((collection.id, token, who.as_sub()))
- }
- };
-
- if let Some(last_tx_block) = last_tx_block {
- return Some(
- last_tx_block
- .saturating_add(limit.into())
- .saturating_sub(block_number)
- .into(),
- );
- }
-
- let token_exists = match collection.mode {
- CollectionMode::NFT => {
- <pallet_nonfungible::TokenData<T>>::contains_key((collection.id, token))
- }
- CollectionMode::Fungible(_) => token == TokenId::default(),
- CollectionMode::ReFungible => {
- <pallet_refungible::TotalSupply<T>>::contains_key((collection.id, token))
- }
- };
-
- if token_exists {
- Some(0)
- } else {
- None
- }
- }
-}
runtime/common/src/types.rsdiffbeforeafterboth--- a/runtime/common/src/types.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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/>.
-
-use sp_runtime::{
- traits::{Verify, IdentifyAccount, BlakeTwo256},
- generic, MultiSignature,
-};
-
-pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
-
-/// Opaque block header type.
-pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
-
-/// Opaque block type.
-pub type Block = generic::Block<Header, UncheckedExtrinsic>;
-
-pub type SessionHandlers = ();
-
-/// An index to a block.
-pub type BlockNumber = u32;
-
-/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
-pub type Signature = MultiSignature;
-
-/// Some way of identifying an account on the chain. We intentionally make it equivalent
-/// to the public key of our transaction signing scheme.
-pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
-
-/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
-/// never know...
-pub type AccountIndex = u32;
-
-/// Balance of an account.
-pub type Balance = u128;
-
-/// Index of a transaction in the chain.
-pub type Index = u32;
-
-/// A hash of some data used by the chain.
-pub type Hash = sp_core::H256;
-
-/// Digest item type.
-pub type DigestItem = generic::DigestItem;
-
-pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
-
-pub trait RuntimeInstance {
- type CrossAccountId: pallet_evm::account::CrossAccountId<sp_runtime::AccountId32>
- + Send
- + Sync
- + 'static;
-
- type TransactionConverter: fp_rpc::ConvertTransaction<UncheckedExtrinsic>
- + Send
- + Sync
- + 'static;
-
- fn get_transaction_converter() -> Self::TransactionConverter;
-}
runtime/common/src/weights.rsdiffbeforeafterboth--- a/runtime/common/src/weights.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-// 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/>.
-
-use core::marker::PhantomData;
-use frame_support::{weights::Weight};
-use pallet_common::{CommonWeightInfo, dispatch::dispatch_weight, RefungibleExtensionsWeightInfo};
-
-use pallet_fungible::{Config as FungibleConfig, common::CommonWeights as FungibleWeights};
-use pallet_nonfungible::{Config as NonfungibleConfig, common::CommonWeights as NonfungibleWeights};
-use pallet_refungible::{
- Config as RefungibleConfig, weights::WeightInfo, common::CommonWeights as RefungibleWeights,
-};
-use up_data_structs::{CreateItemExData, CreateItemData};
-
-macro_rules! max_weight_of {
- ($method:ident ( $($args:tt)* )) => {
- <FungibleWeights<T>>::$method($($args)*)
- .max(<NonfungibleWeights<T>>::$method($($args)*))
- .max(<RefungibleWeights<T>>::$method($($args)*))
- };
-}
-
-pub struct CommonWeights<T>(PhantomData<T>)
-where
- T: FungibleConfig + NonfungibleConfig + RefungibleConfig;
-impl<T> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T>
-where
- T: FungibleConfig + NonfungibleConfig + RefungibleConfig,
-{
- fn create_item() -> Weight {
- dispatch_weight::<T>() + max_weight_of!(create_item())
- }
-
- fn create_multiple_items(data: &[CreateItemData]) -> Weight {
- dispatch_weight::<T>() + max_weight_of!(create_multiple_items(data))
- }
-
- fn create_multiple_items_ex(data: &CreateItemExData<T::CrossAccountId>) -> Weight {
- dispatch_weight::<T>() + max_weight_of!(create_multiple_items_ex(data))
- }
-
- fn burn_item() -> Weight {
- dispatch_weight::<T>() + max_weight_of!(burn_item())
- }
-
- fn set_collection_properties(amount: u32) -> Weight {
- dispatch_weight::<T>() + max_weight_of!(set_collection_properties(amount))
- }
-
- fn delete_collection_properties(amount: u32) -> Weight {
- dispatch_weight::<T>() + max_weight_of!(delete_collection_properties(amount))
- }
-
- fn set_token_properties(amount: u32) -> Weight {
- dispatch_weight::<T>() + max_weight_of!(set_token_properties(amount))
- }
-
- fn delete_token_properties(amount: u32) -> Weight {
- dispatch_weight::<T>() + max_weight_of!(delete_token_properties(amount))
- }
-
- fn set_token_property_permissions(amount: u32) -> Weight {
- dispatch_weight::<T>() + max_weight_of!(set_token_property_permissions(amount))
- }
-
- fn transfer() -> Weight {
- dispatch_weight::<T>() + max_weight_of!(transfer())
- }
-
- fn approve() -> Weight {
- dispatch_weight::<T>() + max_weight_of!(approve())
- }
-
- fn transfer_from() -> Weight {
- dispatch_weight::<T>() + max_weight_of!(transfer_from())
- }
-
- fn burn_from() -> Weight {
- dispatch_weight::<T>() + max_weight_of!(burn_from())
- }
-
- fn burn_recursively_self_raw() -> Weight {
- max_weight_of!(burn_recursively_self_raw())
- }
-
- fn burn_recursively_breadth_raw(amount: u32) -> Weight {
- max_weight_of!(burn_recursively_breadth_raw(amount))
- }
-}
-
-impl<T> RefungibleExtensionsWeightInfo for CommonWeights<T>
-where
- T: FungibleConfig + NonfungibleConfig + RefungibleConfig,
-{
- fn repartition() -> Weight {
- dispatch_weight::<T>() + <<T as RefungibleConfig>::WeightInfo>::repartition_item()
- }
-}
runtime/common/weights.rsdiffbeforeafterboth--- /dev/null
+++ b/runtime/common/weights.rs
@@ -0,0 +1,143 @@
+// 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/>.
+
+use core::marker::PhantomData;
+use frame_support::{weights::Weight};
+use pallet_common::{CommonWeightInfo, dispatch::dispatch_weight, RefungibleExtensionsWeightInfo};
+
+use pallet_fungible::{Config as FungibleConfig, common::CommonWeights as FungibleWeights};
+use pallet_nonfungible::{Config as NonfungibleConfig, common::CommonWeights as NonfungibleWeights};
+
+#[cfg(feature = "refungible")]
+use pallet_refungible::{
+ Config as RefungibleConfig, weights::WeightInfo, common::CommonWeights as RefungibleWeights,
+};
+use up_data_structs::{CreateItemExData, CreateItemData};
+
+macro_rules! max_weight_of {
+ ($method:ident ( $($args:tt)* )) => {{
+ let max_weight = <FungibleWeights<T>>::$method($($args)*)
+ .max(<NonfungibleWeights<T>>::$method($($args)*));
+
+ #[cfg(feature = "refungible")]
+ let max_weight = max_weight.max(<RefungibleWeights<T>>::$method($($args)*));
+
+ max_weight
+ }};
+}
+
+#[cfg(not(feature = "refungible"))]
+pub trait CommonWeightConfigs: FungibleConfig + NonfungibleConfig {}
+
+#[cfg(not(feature = "refungible"))]
+impl<T: FungibleConfig + NonfungibleConfig> CommonWeightConfigs for T {}
+
+#[cfg(feature = "refungible")]
+pub trait CommonWeightConfigs: FungibleConfig + NonfungibleConfig + RefungibleConfig {}
+
+#[cfg(feature = "refungible")]
+impl<T: FungibleConfig + NonfungibleConfig + RefungibleConfig> CommonWeightConfigs for T {}
+
+pub struct CommonWeights<T>(PhantomData<T>);
+
+impl<T> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T>
+where
+ T: CommonWeightConfigs,
+{
+ fn create_item() -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(create_item())
+ }
+
+ fn create_multiple_items(data: &[CreateItemData]) -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(create_multiple_items(data))
+ }
+
+ fn create_multiple_items_ex(data: &CreateItemExData<T::CrossAccountId>) -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(create_multiple_items_ex(data))
+ }
+
+ fn burn_item() -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(burn_item())
+ }
+
+ fn set_collection_properties(amount: u32) -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(set_collection_properties(amount))
+ }
+
+ fn delete_collection_properties(amount: u32) -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(delete_collection_properties(amount))
+ }
+
+ fn set_token_properties(amount: u32) -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(set_token_properties(amount))
+ }
+
+ fn delete_token_properties(amount: u32) -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(delete_token_properties(amount))
+ }
+
+ fn set_token_property_permissions(amount: u32) -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(set_token_property_permissions(amount))
+ }
+
+ fn transfer() -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(transfer())
+ }
+
+ fn approve() -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(approve())
+ }
+
+ fn transfer_from() -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(transfer_from())
+ }
+
+ fn burn_from() -> Weight {
+ dispatch_weight::<T>() + max_weight_of!(burn_from())
+ }
+
+ fn burn_recursively_self_raw() -> Weight {
+ max_weight_of!(burn_recursively_self_raw())
+ }
+
+ fn burn_recursively_breadth_raw(amount: u32) -> Weight {
+ max_weight_of!(burn_recursively_breadth_raw(amount))
+ }
+
+ fn token_owner() -> Weight {
+ max_weight_of!(token_owner())
+ }
+}
+
+#[cfg(feature = "refungible")]
+impl<T> RefungibleExtensionsWeightInfo for CommonWeights<T>
+where
+ T: FungibleConfig + NonfungibleConfig + RefungibleConfig,
+{
+ fn repartition() -> Weight {
+ dispatch_weight::<T>() + <<T as RefungibleConfig>::WeightInfo>::repartition_item()
+ }
+}
+
+#[cfg(not(feature = "refungible"))]
+impl<T> RefungibleExtensionsWeightInfo for CommonWeights<T>
+where
+ T: FungibleConfig + NonfungibleConfig,
+{
+ fn repartition() -> Weight {
+ dispatch_weight::<T>()
+ }
+}
runtime/opal/CHANGELOG.mddiffbeforeafterboth--- /dev/null
+++ b/runtime/opal/CHANGELOG.md
@@ -0,0 +1,3 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
runtime/opal/Cargo.tomldiffbeforeafterboth--- a/runtime/opal/Cargo.toml
+++ b/runtime/opal/Cargo.toml
@@ -16,7 +16,7 @@
targets = ['x86_64-unknown-linux-gnu']
[features]
-default = ['std']
+default = ['std', 'opal-runtime']
runtime-benchmarks = [
'hex-literal',
'frame-benchmarking',
@@ -87,6 +87,7 @@
'parachain-info/std',
'serde',
'pallet-inflation/std',
+ 'pallet-configuration/std',
'pallet-common/std',
'pallet-structure/std',
'pallet-fungible/std',
@@ -113,13 +114,20 @@
'xcm/std',
'xcm-builder/std',
'xcm-executor/std',
- 'unique-runtime-common/std',
+ 'up-common/std',
'rmrk-rpc/std',
+ 'evm-coder/std',
+ 'up-sponsorship/std',
"orml-vesting/std",
]
limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
+opal-runtime = ['refungible', 'scheduler', 'rmrk']
+refungible = []
+scheduler = []
+rmrk = []
+
################################################################################
# Substrate Dependencies
@@ -396,7 +404,7 @@
[dependencies]
log = { version = "0.4.16", default-features = false }
-unique-runtime-common = { path = "../common", default-features = false }
+up-common = { path = "../../primitives/common", default-features = false }
scale-info = { version = "2.0.1", default-features = false, features = [
"derive",
] }
@@ -407,6 +415,7 @@
fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
pallet-inflation = { path = '../../pallets/inflation', default-features = false }
up-data-structs = { path = '../../primitives/data-structs', default-features = false }
+pallet-configuration = { default-features = false, path = "../../pallets/configuration" }
pallet-common = { default-features = false, path = "../../pallets/common" }
pallet-structure = { default-features = false, path = "../../pallets/structure" }
pallet-fungible = { default-features = false, path = "../../pallets/fungible" }
@@ -426,6 +435,8 @@
pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
+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.24' }
################################################################################
# Build Dependencies
runtime/opal/src/lib.rsdiffbeforeafterboth--- a/runtime/opal/src/lib.rs
+++ b/runtime/opal/src/lib.rs
@@ -25,168 +25,21 @@
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
-use sp_api::impl_runtime_apis;
-use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};
-use sp_runtime::DispatchError;
-use fp_self_contained::*;
-// #[cfg(any(feature = "std", test))]
-// pub use sp_runtime::BuildStorage;
-
-use sp_runtime::{
- Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,
- traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},
- transaction_validity::{TransactionSource, TransactionValidity},
- ApplyExtrinsicResult, RuntimeAppPublic,
-};
+use frame_support::parameter_types;
-use sp_std::prelude::*;
-
-#[cfg(feature = "std")]
-use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
-pub use pallet_transaction_payment::{
- Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,
-};
-// A few exports that help ease life for downstream crates.
-pub use pallet_balances::Call as BalancesCall;
-pub use pallet_evm::{
- EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,
- OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,
-};
-pub use frame_support::{
- construct_runtime, match_types,
- dispatch::DispatchResult,
- PalletId, parameter_types, StorageValue, ConsensusEngineId,
- traits::{
- tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,
- Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,
- OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,
- },
- weights::{
- constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
- DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
- WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,
- WeightToFee,
- },
-};
-use pallet_unique_scheduler::DispatchCall;
-use up_data_structs::{
- CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,
- CollectionStats, RpcCollection,
- mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},
- TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,
- RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, RmrkNftId,
- RmrkNftChild, RmrkPropertyKey, RmrkResourceId, RmrkBaseId,
-};
+use sp_runtime::create_runtime_str;
-// use pallet_contracts::weights::WeightInfo;
-// #[cfg(any(feature = "std", test))]
-use frame_system::{
- self as frame_system, EnsureRoot, EnsureSigned,
- limits::{BlockWeights, BlockLength},
-};
-use sp_arithmetic::{
- traits::{BaseArithmetic, Unsigned},
-};
-use smallvec::smallvec;
-// use scale_info::TypeInfo;
-use codec::{Encode, Decode};
-use fp_rpc::TransactionStatus;
-use sp_runtime::{
- traits::{
- Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,
- Saturating, CheckedConversion,
- },
- generic::Era,
- transaction_validity::TransactionValidityError,
- DispatchErrorWithPostInfo, SaturatedConversion,
-};
+use up_common::types::*;
-// pub use pallet_timestamp::Call as TimestampCall;
-pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
+#[path = "../../common/mod.rs"]
+mod runtime_common;
-// Polkadot imports
-use pallet_xcm::XcmPassthrough;
-use polkadot_parachain::primitives::Sibling;
-use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};
-use xcm_builder::{
- AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
- EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,
- RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
- SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
- ParentIsPreset,
-};
-use xcm_executor::{Config, XcmExecutor, Assets};
-use sp_std::{cmp::Ordering, marker::PhantomData};
-
-use xcm::latest::{
- // Xcm,
- AssetId::{Concrete},
- Fungibility::Fungible as XcmFungible,
- MultiAsset,
- Error as XcmError,
-};
-use xcm_executor::traits::{MatchesFungible, WeightTrader};
-//use xcm_executor::traits::MatchesFungible;
+pub use runtime_common::*;
-use unique_runtime_common::{
- impl_common_runtime_apis,
- types::*,
- constants::*,
- dispatch::{CollectionDispatchT, CollectionDispatch},
- sponsoring::UniqueSponsorshipHandler,
- eth_sponsoring::UniqueEthSponsorshipHandler,
- weights::CommonWeights,
-};
-
pub const RUNTIME_NAME: &str = "opal";
pub const TOKEN_SYMBOL: &str = "OPL";
-
-type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;
-impl RuntimeInstance for Runtime {
- type CrossAccountId = self::CrossAccountId;
- type TransactionConverter = self::TransactionConverter;
-
- fn get_transaction_converter() -> TransactionConverter {
- TransactionConverter
- }
-}
-
-/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
-/// never know...
-pub type AccountIndex = u32;
-
-/// Balance of an account.
-pub type Balance = u128;
-
-/// Index of a transaction in the chain.
-pub type Index = u32;
-
-/// A hash of some data used by the chain.
-pub type Hash = sp_core::H256;
-
-/// Digest item type.
-pub type DigestItem = generic::DigestItem;
-
-/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
-/// the specifics of the runtime. They can then be made to be agnostic over specific formats
-/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
-/// to even the core data structures.
-pub mod opaque {
- use sp_std::prelude::*;
- use sp_runtime::impl_opaque_keys;
- use super::Aura;
-
- pub use unique_runtime_common::types::*;
-
- impl_opaque_keys! {
- pub struct SessionKeys {
- pub aura: Aura,
- }
- }
-}
-
/// This runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!(RUNTIME_NAME),
@@ -199,1206 +52,15 @@
state_version: 0,
};
-#[derive(codec::Encode, codec::Decode)]
-pub enum XCMPMessage<XAccountId, XBalance> {
- /// Transfer tokens to the given account from the Parachain account.
- TransferToken(XAccountId, XBalance),
-}
-
-/// The version information used to identify this runtime when compiled natively.
-#[cfg(feature = "std")]
-pub fn native_version() -> NativeVersion {
- NativeVersion {
- runtime_version: VERSION,
- can_author_with: Default::default(),
- }
-}
-
-type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
-
-pub struct DealWithFees;
-impl OnUnbalanced<NegativeImbalance> for DealWithFees {
- fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {
- if let Some(fees) = fees_then_tips.next() {
- // for fees, 100% to treasury
- let mut split = fees.ration(100, 0);
- if let Some(tips) = fees_then_tips.next() {
- // for tips, if any, 100% to treasury
- tips.ration_merge_into(100, 0, &mut split);
- }
- Treasury::on_unbalanced(split.0);
- // Author::on_unbalanced(split.1);
- }
- }
-}
-
parameter_types! {
- pub const BlockHashCount: BlockNumber = 2400;
- pub RuntimeBlockLength: BlockLength =
- BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
- pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
- pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
- pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
- .base_block(BlockExecutionWeight::get())
- .for_class(DispatchClass::all(), |weights| {
- weights.base_extrinsic = ExtrinsicBaseWeight::get();
- })
- .for_class(DispatchClass::Normal, |weights| {
- weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
- })
- .for_class(DispatchClass::Operational, |weights| {
- weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
- // Operational transactions have some extra reserved space, so that they
- // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
- weights.reserved = Some(
- MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
- );
- })
- .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
- .build_or_panic();
pub const Version: RuntimeVersion = VERSION;
pub const SS58Prefix: u8 = 42;
-}
-
-parameter_types! {
pub const ChainId: u64 = 8882;
-}
-
-pub struct FixedFee;
-impl FeeCalculator for FixedFee {
- fn min_gas_price() -> (U256, u64) {
- (MIN_GAS_PRICE.into(), 0)
- }
-}
-
-// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case
-// (contract, which only writes a lot of data),
-// approximating on top of our real store write weight
-parameter_types! {
- pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;
- pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;
- pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();
}
-/// Limiting EVM execution to 50% of block for substrate users and management tasks
-/// EVM transaction consumes more weight than substrate's, so we can't rely on them being
-/// scheduled fairly
-const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);
-parameter_types! {
- pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());
-}
-
-pub enum FixedGasWeightMapping {}
-impl GasWeightMapping for FixedGasWeightMapping {
- fn gas_to_weight(gas: u64) -> Weight {
- gas.saturating_mul(WeightPerGas::get())
- }
- fn weight_to_gas(weight: Weight) -> u64 {
- weight / WeightPerGas::get()
- }
-}
-
-impl pallet_evm::account::Config for Runtime {
- type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;
- type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;
- type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;
-}
-
-impl pallet_evm::Config for Runtime {
- type BlockGasLimit = BlockGasLimit;
- type FeeCalculator = FixedFee;
- type GasWeightMapping = FixedGasWeightMapping;
- type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
- type CallOrigin = EnsureAddressTruncated<Self>;
- type WithdrawOrigin = EnsureAddressTruncated<Self>;
- type AddressMapping = HashedAddressMapping<Self::Hashing>;
- type PrecompilesType = ();
- type PrecompilesValue = ();
- type Currency = Balances;
- type Event = Event;
- type OnMethodCall = (
- pallet_evm_migration::OnMethodCall<Self>,
- pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,
- CollectionDispatchT<Self>,
- pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,
- );
- type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
- type ChainId = ChainId;
- type Runner = pallet_evm::runner::stack::Runner<Self>;
- type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;
- type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;
- type FindAuthor = EthereumFindAuthor<Aura>;
-}
-
-impl pallet_evm_migration::Config for Runtime {
- type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;
-}
-
-pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);
-impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {
- fn find_author<'a, I>(digests: I) -> Option<H160>
- where
- I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
- {
- if let Some(author_index) = F::find_author(digests) {
- let authority_id = Aura::authorities()[author_index as usize].clone();
- return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));
- }
- None
- }
-}
-
-impl pallet_ethereum::Config for Runtime {
- type Event = Event;
- type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;
-}
-
-impl pallet_randomness_collective_flip::Config for Runtime {}
-
-impl frame_system::Config for Runtime {
- /// The data to be stored in an account.
- type AccountData = pallet_balances::AccountData<Balance>;
- /// The identifier used to distinguish between accounts.
- type AccountId = AccountId;
- /// The basic call filter to use in dispatchable.
- type BaseCallFilter = Everything;
- /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
- type BlockHashCount = BlockHashCount;
- /// The maximum length of a block (in bytes).
- type BlockLength = RuntimeBlockLength;
- /// The index type for blocks.
- type BlockNumber = BlockNumber;
- /// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.
- type BlockWeights = RuntimeBlockWeights;
- /// The aggregated dispatch type that is available for extrinsics.
- type Call = Call;
- /// The weight of database operations that the runtime can invoke.
- type DbWeight = RocksDbWeight;
- /// The ubiquitous event type.
- type Event = Event;
- /// The type for hashing blocks and tries.
- type Hash = Hash;
- /// The hashing algorithm used.
- type Hashing = BlakeTwo256;
- /// The header type.
- type Header = generic::Header<BlockNumber, BlakeTwo256>;
- /// The index type for storing how many extrinsics an account has signed.
- type Index = Index;
- /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
- type Lookup = AccountIdLookup<AccountId, ()>;
- /// What to do if an account is fully reaped from the system.
- type OnKilledAccount = ();
- /// What to do if a new account is created.
- type OnNewAccount = ();
- type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
- /// The ubiquitous origin type.
- type Origin = Origin;
- /// This type is being generated by `construct_runtime!`.
- type PalletInfo = PalletInfo;
- /// This is used as an identifier of the chain. 42 is the generic substrate prefix.
- type SS58Prefix = SS58Prefix;
- /// Weight information for the extrinsics of this pallet.
- type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;
- /// Version of the runtime.
- type Version = Version;
- type MaxConsumers = ConstU32<16>;
-}
-
-parameter_types! {
- pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
-}
-
-impl pallet_timestamp::Config for Runtime {
- /// A timestamp: milliseconds since the unix epoch.
- type Moment = u64;
- type OnTimestampSet = ();
- type MinimumPeriod = MinimumPeriod;
- type WeightInfo = ();
-}
-
-parameter_types! {
- // pub const ExistentialDeposit: u128 = 500;
- pub const ExistentialDeposit: u128 = 0;
- pub const MaxLocks: u32 = 50;
- pub const MaxReserves: u32 = 50;
-}
-
-impl pallet_balances::Config for Runtime {
- type MaxLocks = MaxLocks;
- type MaxReserves = MaxReserves;
- type ReserveIdentifier = [u8; 16];
- /// The type for recording an account's balance.
- type Balance = Balance;
- /// The ubiquitous event type.
- type Event = Event;
- type DustRemoval = Treasury;
- type ExistentialDeposit = ExistentialDeposit;
- type AccountStore = System;
- type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;
-}
-
-pub const fn deposit(items: u32, bytes: u32) -> Balance {
- items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE
-}
-
-/*
-parameter_types! {
- pub TombstoneDeposit: Balance = deposit(
- 1,
- sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,
- );
- pub DepositPerContract: Balance = TombstoneDeposit::get();
- pub const DepositPerStorageByte: Balance = deposit(0, 1);
- pub const DepositPerStorageItem: Balance = deposit(1, 0);
- pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);
- pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;
- pub const SignedClaimHandicap: u32 = 2;
- pub const MaxDepth: u32 = 32;
- pub const MaxValueSize: u32 = 16 * 1024;
- pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb
- // The lazy deletion runs inside on_initialize.
- pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *
- RuntimeBlockWeights::get().max_block;
- // The weight needed for decoding the queue should be less or equal than a fifth
- // of the overall weight dedicated to the lazy deletion.
- pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (
- <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -
- <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)
- )) / 5) as u32;
- pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();
-}
-
-impl pallet_contracts::Config for Runtime {
- type Time = Timestamp;
- type Randomness = RandomnessCollectiveFlip;
- type Currency = Balances;
- type Event = Event;
- type RentPayment = ();
- type SignedClaimHandicap = SignedClaimHandicap;
- type TombstoneDeposit = TombstoneDeposit;
- type DepositPerContract = DepositPerContract;
- type DepositPerStorageByte = DepositPerStorageByte;
- type DepositPerStorageItem = DepositPerStorageItem;
- type RentFraction = RentFraction;
- type SurchargeReward = SurchargeReward;
- type WeightPrice = pallet_transaction_payment::Pallet<Self>;
- type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
- type ChainExtension = NFTExtension;
- type DeletionQueueDepth = DeletionQueueDepth;
- type DeletionWeightLimit = DeletionWeightLimit;
- type Schedule = Schedule;
- type CallStack = [pallet_contracts::Frame<Self>; 31];
-}
-*/
+construct_runtime!(opal);
-parameter_types! {
- /// This value increases the priority of `Operational` transactions by adding
- /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.
- pub const OperationalFeeMultiplier: u8 = 5;
-}
-
-/// Linear implementor of `WeightToFeePolynomial`
-pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);
-
-impl<T> WeightToFeePolynomial for LinearFee<T>
-where
- T: BaseArithmetic + From<u32> + Copy + Unsigned,
-{
- type Balance = T;
-
- fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
- smallvec!(WeightToFeeCoefficient {
- coeff_integer: WEIGHT_TO_FEE_COEFF.into(),
- coeff_frac: Perbill::zero(),
- negative: false,
- degree: 1,
- })
- }
-}
-
-impl pallet_transaction_payment::Config for Runtime {
- type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;
- type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
- type OperationalFeeMultiplier = OperationalFeeMultiplier;
- type WeightToFee = LinearFee<Balance>;
- type FeeMultiplierUpdate = ();
-}
-
-parameter_types! {
- pub const ProposalBond: Permill = Permill::from_percent(5);
- pub const ProposalBondMinimum: Balance = 1 * UNIQUE;
- pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;
- pub const SpendPeriod: BlockNumber = 5 * MINUTES;
- pub const Burn: Permill = Permill::from_percent(0);
- pub const TipCountdown: BlockNumber = 1 * DAYS;
- pub const TipFindersFee: Percent = Percent::from_percent(20);
- pub const TipReportDepositBase: Balance = 1 * UNIQUE;
- pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;
- pub const BountyDepositBase: Balance = 1 * UNIQUE;
- pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;
- pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");
- pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;
- pub const MaximumReasonLength: u32 = 16384;
- pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);
- pub const BountyValueMinimum: Balance = 5 * UNIQUE;
- pub const MaxApprovals: u32 = 100;
-}
-
-impl pallet_treasury::Config for Runtime {
- type PalletId = TreasuryModuleId;
- type Currency = Balances;
- type ApproveOrigin = EnsureRoot<AccountId>;
- type RejectOrigin = EnsureRoot<AccountId>;
- type Event = Event;
- type OnSlash = ();
- type ProposalBond = ProposalBond;
- type ProposalBondMinimum = ProposalBondMinimum;
- type ProposalBondMaximum = ProposalBondMaximum;
- type SpendPeriod = SpendPeriod;
- type Burn = Burn;
- type BurnDestination = ();
- type SpendFunds = ();
- type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;
- type MaxApprovals = MaxApprovals;
-}
-
-impl pallet_sudo::Config for Runtime {
- type Event = Event;
- type Call = Call;
-}
-
-pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);
-
-impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider
- for RelayChainBlockNumberProvider<T>
-{
- type BlockNumber = BlockNumber;
-
- fn current_block_number() -> Self::BlockNumber {
- cumulus_pallet_parachain_system::Pallet::<T>::validation_data()
- .map(|d| d.relay_parent_number)
- .unwrap_or_default()
- }
-}
-
-parameter_types! {
- pub const MinVestedTransfer: Balance = 10 * UNIQUE;
- pub const MaxVestingSchedules: u32 = 28;
-}
-
-impl orml_vesting::Config for Runtime {
- type Event = Event;
- type Currency = pallet_balances::Pallet<Runtime>;
- type MinVestedTransfer = MinVestedTransfer;
- type VestedTransferOrigin = EnsureSigned<AccountId>;
- type WeightInfo = ();
- type MaxVestingSchedules = MaxVestingSchedules;
- type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
-}
-
-parameter_types! {
- pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
- pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
-}
-
-impl cumulus_pallet_parachain_system::Config for Runtime {
- type Event = Event;
- type SelfParaId = parachain_info::Pallet<Self>;
- type OnSystemEvent = ();
- // type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<
- // MaxDownwardMessageWeight,
- // XcmExecutor<XcmConfig>,
- // Call,
- // >;
- type OutboundXcmpMessageSource = XcmpQueue;
- type DmpMessageHandler = DmpQueue;
- type ReservedDmpWeight = ReservedDmpWeight;
- type ReservedXcmpWeight = ReservedXcmpWeight;
- type XcmpMessageHandler = XcmpQueue;
-}
-
-impl parachain_info::Config for Runtime {}
-
-impl cumulus_pallet_aura_ext::Config for Runtime {}
-
-parameter_types! {
- pub const RelayLocation: MultiLocation = MultiLocation::parent();
- pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
- pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
- pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
-}
-
-/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
-/// when determining ownership of accounts for asset transacting and when attempting to use XCM
-/// `Transact` in order to determine the dispatch Origin.
-pub type LocationToAccountId = (
- // The parent (Relay-chain) origin converts to the default `AccountId`.
- ParentIsPreset<AccountId>,
- // Sibling parachain origins convert to AccountId via the `ParaId::into`.
- SiblingParachainConvertsVia<Sibling, AccountId>,
- // Straight up local `AccountId32` origins just alias directly to `AccountId`.
- AccountId32Aliases<RelayNetwork, AccountId>,
-);
-
-pub struct OnlySelfCurrency;
-impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {
- fn matches_fungible(a: &MultiAsset) -> Option<B> {
- match (&a.id, &a.fun) {
- (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),
- _ => None,
- }
- }
-}
-
-/// Means for transacting assets on this chain.
-pub type LocalAssetTransactor = CurrencyAdapter<
- // Use this currency:
- Balances,
- // Use this currency when it is a fungible asset matching the given location or name:
- OnlySelfCurrency,
- // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
- LocationToAccountId,
- // Our chain's account ID type (we can't get away without mentioning it explicitly):
- AccountId,
- // We don't track any teleports.
- (),
->;
-
-/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
-/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
-/// biases the kind of local `Origin` it will become.
-pub type XcmOriginToTransactDispatchOrigin = (
- // Sovereign account converter; this attempts to derive an `AccountId` from the origin location
- // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
- // foreign chains who want to have a local sovereign account on this chain which they control.
- SovereignSignedViaLocation<LocationToAccountId, Origin>,
- // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
- // recognised.
- RelayChainAsNative<RelayOrigin, Origin>,
- // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
- // recognised.
- SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,
- // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
- // transaction from the Root origin.
- ParentAsSuperuser<Origin>,
- // Native signed account converter; this just converts an `AccountId32` origin into a normal
- // `Origin::Signed` origin of the same 32-byte value.
- SignedAccountId32AsNative<RelayNetwork, Origin>,
- // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
- XcmPassthrough<Origin>,
-);
-
-parameter_types! {
- // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.
- pub UnitWeightCost: Weight = 1_000_000;
- // 1200 UNIQUEs buy 1 second of weight.
- pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);
- pub const MaxInstructions: u32 = 100;
- pub const MaxAuthorities: u32 = 100_000;
-}
-
-match_types! {
- pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {
- MultiLocation { parents: 1, interior: Here } |
- MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }
- };
-}
-
-pub type Barrier = (
- TakeWeightCredit,
- AllowTopLevelPaidExecutionFrom<Everything>,
- // ^^^ Parent & its unit plurality gets free execution
-);
-
-pub struct UsingOnlySelfCurrencyComponents<
- WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
- AssetId: Get<MultiLocation>,
- AccountId,
- Currency: CurrencyT<AccountId>,
- OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
->(
- Weight,
- Currency::Balance,
- PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,
-);
-impl<
- WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
- AssetId: Get<MultiLocation>,
- AccountId,
- Currency: CurrencyT<AccountId>,
- OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
- > WeightTrader
- for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
-{
- fn new() -> Self {
- Self(0, Zero::zero(), PhantomData)
- }
-
- fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {
- let amount = WeightToFee::weight_to_fee(&weight);
- let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;
-
- // location to this parachain through relay chain
- let option1: xcm::v1::AssetId = Concrete(MultiLocation {
- parents: 1,
- interior: X1(Parachain(ParachainInfo::parachain_id().into())),
- });
- // direct location
- let option2: xcm::v1::AssetId = Concrete(MultiLocation {
- parents: 0,
- interior: Here,
- });
-
- let required = if payment.fungible.contains_key(&option1) {
- (option1, u128_amount).into()
- } else if payment.fungible.contains_key(&option2) {
- (option2, u128_amount).into()
- } else {
- (Concrete(MultiLocation::default()), u128_amount).into()
- };
-
- let unused = payment
- .checked_sub(required)
- .map_err(|_| XcmError::TooExpensive)?;
- self.0 = self.0.saturating_add(weight);
- self.1 = self.1.saturating_add(amount);
- Ok(unused)
- }
-
- fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {
- let weight = weight.min(self.0);
- let amount = WeightToFee::weight_to_fee(&weight);
- self.0 -= weight;
- self.1 = self.1.saturating_sub(amount);
- let amount: u128 = amount.saturated_into();
- if amount > 0 {
- Some((AssetId::get(), amount).into())
- } else {
- None
- }
- }
-}
-impl<
- WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
- AssetId: Get<MultiLocation>,
- AccountId,
- Currency: CurrencyT<AccountId>,
- OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
- > Drop
- for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
-{
- fn drop(&mut self) {
- OnUnbalanced::on_unbalanced(Currency::issue(self.1));
- }
-}
-
-pub struct XcmConfig;
-impl Config for XcmConfig {
- type Call = Call;
- type XcmSender = XcmRouter;
- // How to withdraw and deposit an asset.
- type AssetTransactor = LocalAssetTransactor;
- type OriginConverter = XcmOriginToTransactDispatchOrigin;
- type IsReserve = NativeAsset;
- type IsTeleporter = (); // Teleportation is disabled
- type LocationInverter = LocationInverter<Ancestry>;
- type Barrier = Barrier;
- type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
- type Trader =
- UsingOnlySelfCurrencyComponents<LinearFee<Balance>, RelayLocation, AccountId, Balances, ()>;
- type ResponseHandler = (); // Don't handle responses for now.
- type SubscriptionService = PolkadotXcm;
-
- type AssetTrap = PolkadotXcm;
- type AssetClaims = PolkadotXcm;
-}
-
-// parameter_types! {
-// pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;
-// }
-
-/// No local origins on this chain are allowed to dispatch XCM sends/executions.
-pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);
-
-/// The means for routing XCM messages which are not for local execution into the right message
-/// queues.
-pub type XcmRouter = (
- // Two routers - use UMP to communicate with the relay chain:
- cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,
- // ..and XCMP to communicate with the sibling chains.
- XcmpQueue,
-);
-
-impl pallet_evm_coder_substrate::Config for Runtime {}
-
-impl pallet_xcm::Config for Runtime {
- type Event = Event;
- type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
- type XcmRouter = XcmRouter;
- type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
- type XcmExecuteFilter = Everything;
- type XcmExecutor = XcmExecutor<XcmConfig>;
- type XcmTeleportFilter = Everything;
- type XcmReserveTransferFilter = Everything;
- type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
- type LocationInverter = LocationInverter<Ancestry>;
- type Origin = Origin;
- type Call = Call;
- const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
- type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
-}
-
-impl cumulus_pallet_xcm::Config for Runtime {
- type Event = Event;
- type XcmExecutor = XcmExecutor<XcmConfig>;
-}
-
-impl cumulus_pallet_xcmp_queue::Config for Runtime {
- type WeightInfo = ();
- type Event = Event;
- type XcmExecutor = XcmExecutor<XcmConfig>;
- type ChannelInfo = ParachainSystem;
- type VersionWrapper = ();
- type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
- type ControllerOrigin = EnsureRoot<AccountId>;
- type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
-}
-
-impl cumulus_pallet_dmp_queue::Config for Runtime {
- type Event = Event;
- type XcmExecutor = XcmExecutor<XcmConfig>;
- type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
-}
-
-impl pallet_aura::Config for Runtime {
- type AuthorityId = AuraId;
- type DisabledValidators = ();
- type MaxAuthorities = MaxAuthorities;
-}
-
-parameter_types! {
- pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();
- pub const CollectionCreationPrice: Balance = 2 * UNIQUE;
-}
-
-impl pallet_common::Config for Runtime {
- type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;
- type Event = Event;
- type Currency = Balances;
- type CollectionCreationPrice = CollectionCreationPrice;
- type TreasuryAccountId = TreasuryAccountId;
- type CollectionDispatch = CollectionDispatchT<Self>;
-
- type EvmTokenAddressMapping = EvmTokenAddressMapping;
- type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
- type ContractAddress = EvmCollectionHelpersAddress;
-}
-
-impl pallet_structure::Config for Runtime {
- type Event = Event;
- type Call = Call;
- type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;
-}
-
-impl pallet_fungible::Config for Runtime {
- type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;
-}
-impl pallet_refungible::Config for Runtime {
- type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;
-}
-impl pallet_nonfungible::Config for Runtime {
- type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;
-}
-
-impl pallet_proxy_rmrk_core::Config for Runtime {
- type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
- type Event = Event;
-}
-
-impl pallet_proxy_rmrk_equip::Config for Runtime {
- type WeightInfo = pallet_proxy_rmrk_equip::weights::SubstrateWeight<Self>;
- type Event = Event;
-}
-
-impl pallet_unique::Config for Runtime {
- type Event = Event;
- type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
- type CommonWeightInfo = CommonWeights<Self>;
- type RefungibleExtensionsWeightInfo = CommonWeights<Self>;
-}
-
-parameter_types! {
- pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied
-}
-
-/// Used for the pallet inflation
-impl pallet_inflation::Config for Runtime {
- type Currency = Balances;
- type TreasuryAccountId = TreasuryAccountId;
- type InflationBlockInterval = InflationBlockInterval;
- type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
-}
-
-parameter_types! {
- pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *
- RuntimeBlockWeights::get().max_block;
- pub const MaxScheduledPerBlock: u32 = 50;
-}
-
-type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;
-use frame_support::traits::NamedReservableCurrency;
-
-fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {
- (
- frame_system::CheckSpecVersion::<Runtime>::new(),
- frame_system::CheckGenesis::<Runtime>::new(),
- frame_system::CheckEra::<Runtime>::from(Era::Immortal),
- frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(
- from,
- )),
- frame_system::CheckWeight::<Runtime>::new(),
- // sponsoring transaction logic
- // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
- )
-}
-
-pub struct SchedulerPaymentExecutor;
-impl<T: frame_system::Config + pallet_unique_scheduler::Config, SelfContainedSignedInfo>
- DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor
-where
- <T as frame_system::Config>::Call: Member
- + Dispatchable<Origin = Origin, Info = DispatchInfo>
- + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>
- + GetDispatchInfo
- + From<frame_system::Call<Runtime>>,
- SelfContainedSignedInfo: Send + Sync + 'static,
- Call: From<<T as frame_system::Config>::Call>
- + From<<T as pallet_unique_scheduler::Config>::Call>
- + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,
- sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,
-{
- fn dispatch_call(
- signer: <T as frame_system::Config>::AccountId,
- call: <T as pallet_unique_scheduler::Config>::Call,
- ) -> Result<
- Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,
- TransactionValidityError,
- > {
- let dispatch_info = call.get_dispatch_info();
- let extrinsic = fp_self_contained::CheckedExtrinsic::<
- AccountId,
- Call,
- SignedExtraScheduler,
- SelfContainedSignedInfo,
- > {
- signed:
- CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(
- signer.clone().into(),
- get_signed_extras(signer.into()),
- ),
- function: call.into(),
- };
-
- extrinsic.apply::<Runtime>(&dispatch_info, 0)
- }
-
- fn reserve_balance(
- id: [u8; 16],
- sponsor: <T as frame_system::Config>::AccountId,
- call: <T as pallet_unique_scheduler::Config>::Call,
- count: u32,
- ) -> Result<(), DispatchError> {
- let dispatch_info = call.get_dispatch_info();
- let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)
- .saturating_mul(count.into());
-
- <Balances as NamedReservableCurrency<AccountId>>::reserve_named(
- &id,
- &(sponsor.into()),
- weight,
- )
- }
-
- fn pay_for_call(
- id: [u8; 16],
- sponsor: <T as frame_system::Config>::AccountId,
- call: <T as pallet_unique_scheduler::Config>::Call,
- ) -> Result<u128, DispatchError> {
- let dispatch_info = call.get_dispatch_info();
- let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);
- Ok(
- <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
- &id,
- &(sponsor.into()),
- weight,
- ),
- )
- }
-
- fn cancel_reserve(
- id: [u8; 16],
- sponsor: <T as frame_system::Config>::AccountId,
- ) -> Result<u128, DispatchError> {
- Ok(
- <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
- &id,
- &(sponsor.into()),
- u128::MAX,
- ),
- )
- }
-}
-
-parameter_types! {
- pub const NoPreimagePostponement: Option<u32> = Some(10);
- pub const Preimage: Option<u32> = Some(10);
-}
-
-/// Used the compare the privilege of an origin inside the scheduler.
-pub struct OriginPrivilegeCmp;
-
-impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {
- fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {
- Some(Ordering::Equal)
- }
-}
-
-impl pallet_unique_scheduler::Config for Runtime {
- type Event = Event;
- type Origin = Origin;
- type Currency = Balances;
- type PalletsOrigin = OriginCaller;
- type Call = Call;
- type MaximumWeight = MaximumSchedulerWeight;
- type ScheduleOrigin = EnsureSigned<AccountId>;
- type MaxScheduledPerBlock = MaxScheduledPerBlock;
- type WeightInfo = ();
- type CallExecutor = SchedulerPaymentExecutor;
- type OriginPrivilegeCmp = OriginPrivilegeCmp;
- type PreimageProvider = ();
- type NoPreimagePostponement = NoPreimagePostponement;
-}
-
-type EvmSponsorshipHandler = (
- UniqueEthSponsorshipHandler<Runtime>,
- pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,
-);
-
-type SponsorshipHandler = (
- UniqueSponsorshipHandler<Runtime>,
- //pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,
- pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,
-);
-
-impl pallet_evm_transaction_payment::Config for Runtime {
- type EvmSponsorshipHandler = EvmSponsorshipHandler;
- type Currency = Balances;
-}
-
-impl pallet_charge_transaction::Config for Runtime {
- type SponsorshipHandler = SponsorshipHandler;
-}
-
-// impl pallet_contract_helpers::Config for Runtime {
-// type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
-// }
-
-parameter_types! {
- // 0x842899ECF380553E8a4de75bF534cdf6fBF64049
- pub const HelpersContractAddress: H160 = H160([
- 0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,
- ]);
-
- // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f
- pub const EvmCollectionHelpersAddress: H160 = H160([
- 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,
- ]);
-}
-
-impl pallet_evm_contract_helpers::Config for Runtime {
- type ContractAddress = HelpersContractAddress;
- type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
-}
-
-construct_runtime!(
- pub enum Runtime where
- Block = Block,
- NodeBlock = opaque::Block,
- UncheckedExtrinsic = UncheckedExtrinsic
- {
- ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,
- ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,
-
- Aura: pallet_aura::{Pallet, Config<T>} = 22,
- AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,
-
- Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,
- RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,
- Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,
- TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,
- Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,
- Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,
- System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,
- Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,
- // Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,
- // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,
-
- // XCM helpers.
- XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
- PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
- CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,
- DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
-
- // Unique Pallets
- Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,
- Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,
- Scheduler: pallet_unique_scheduler::{Pallet, Call, Storage, Event<T>} = 62,
- // free = 63
- Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,
- // ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,
- Common: pallet_common::{Pallet, Storage, Event<T>} = 66,
- Fungible: pallet_fungible::{Pallet, Storage} = 67,
- Refungible: pallet_refungible::{Pallet, Storage} = 68,
- Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,
- Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,
- RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,
- RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,
-
- // Frontier
- EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,
- Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,
-
- EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,
- EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,
- EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,
- EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,
- }
-);
-
-pub struct TransactionConverter;
-
-impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {
- fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {
- UncheckedExtrinsic::new_unsigned(
- pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
- )
- }
-}
-
-impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {
- fn convert_transaction(
- &self,
- transaction: pallet_ethereum::Transaction,
- ) -> opaque::UncheckedExtrinsic {
- let extrinsic = UncheckedExtrinsic::new_unsigned(
- pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
- );
- let encoded = extrinsic.encode();
- opaque::UncheckedExtrinsic::decode(&mut &encoded[..])
- .expect("Encoded extrinsic is always valid")
- }
-}
-
-/// The address format for describing accounts.
-pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
-/// Block header type as expected by this runtime.
-pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
-/// Block type as expected by this runtime.
-pub type Block = generic::Block<Header, UncheckedExtrinsic>;
-/// A Block signed with a Justification
-pub type SignedBlock = generic::SignedBlock<Block>;
-/// BlockId type as expected by this runtime.
-pub type BlockId = generic::BlockId<Block>;
-/// The SignedExtension to the basic transaction logic.
-pub type SignedExtra = (
- frame_system::CheckSpecVersion<Runtime>,
- // system::CheckTxVersion<Runtime>,
- frame_system::CheckGenesis<Runtime>,
- frame_system::CheckEra<Runtime>,
- frame_system::CheckNonce<Runtime>,
- frame_system::CheckWeight<Runtime>,
- ChargeTransactionPayment,
- //pallet_contract_helpers::ContractHelpersExtension<Runtime>,
- pallet_ethereum::FakeTransactionFinalizer<Runtime>,
-);
-pub type SignedExtraScheduler = (
- frame_system::CheckSpecVersion<Runtime>,
- frame_system::CheckGenesis<Runtime>,
- frame_system::CheckEra<Runtime>,
- frame_system::CheckNonce<Runtime>,
- frame_system::CheckWeight<Runtime>,
-);
-/// Unchecked extrinsic type as expected by this runtime.
-pub type UncheckedExtrinsic =
- fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
-/// Extrinsic type that has already been checked.
-pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;
-/// Executive: handles dispatch to the various modules.
-pub type Executive = frame_executive::Executive<
- Runtime,
- Block,
- frame_system::ChainContext<Runtime>,
- Runtime,
- AllPalletsReversedWithSystemFirst,
->;
-
-impl_opaque_keys! {
- pub struct SessionKeys {
- pub aura: Aura,
- }
-}
-
-impl fp_self_contained::SelfContainedCall for Call {
- type SignedInfo = H160;
-
- fn is_self_contained(&self) -> bool {
- match self {
- Call::Ethereum(call) => call.is_self_contained(),
- _ => false,
- }
- }
-
- fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
- match self {
- Call::Ethereum(call) => call.check_self_contained(),
- _ => None,
- }
- }
-
- fn validate_self_contained(
- &self,
- info: &Self::SignedInfo,
- dispatch_info: &DispatchInfoOf<Call>,
- len: usize,
- ) -> Option<TransactionValidity> {
- match self {
- Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),
- _ => None,
- }
- }
-
- fn pre_dispatch_self_contained(
- &self,
- info: &Self::SignedInfo,
- ) -> Option<Result<(), TransactionValidityError>> {
- match self {
- Call::Ethereum(call) => call.pre_dispatch_self_contained(info),
- _ => None,
- }
- }
-
- fn apply_self_contained(
- self,
- info: Self::SignedInfo,
- ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {
- match self {
- call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(
- Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),
- )),
- _ => None,
- }
- }
-}
-
-macro_rules! dispatch_unique_runtime {
- ($collection:ident.$method:ident($($name:ident),*)) => {{
- let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);
- let dispatch = collection.as_dyn();
-
- Ok::<_, DispatchError>(dispatch.$method($($name),*))
- }};
-}
-
-impl_common_runtime_apis! {
- #![custom_apis]
-
- impl rmrk_rpc::RmrkApi<
- Block,
- AccountId,
- RmrkCollectionInfo<AccountId>,
- RmrkInstanceInfo<AccountId>,
- RmrkResourceInfo,
- RmrkPropertyInfo,
- RmrkBaseInfo<AccountId>,
- RmrkPartType,
- RmrkTheme
- > for Runtime {
- fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {
- pallet_proxy_rmrk_core::rpc::last_collection_idx::<Runtime>()
- }
-
- fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::collection_by_id::<Runtime>(collection_id)
- }
-
- fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::nft_by_id::<Runtime>(collection_id, nft_by_id)
- }
-
- fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::account_tokens::<Runtime>(account_id, collection_id)
- }
-
- fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::nft_children::<Runtime>(collection_id, nft_id)
- }
-
- fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::collection_properties::<Runtime>(collection_id, filter_keys)
- }
-
- fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::nft_properties::<Runtime>(collection_id, nft_id, filter_keys)
- }
-
- fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::nft_resources::<Runtime>(collection_id, nft_id)
- }
-
- fn nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Result<Option<u32>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::nft_resource_priority::<Runtime>(collection_id, nft_id, resource_id)
- }
-
- fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {
- pallet_proxy_rmrk_equip::rpc::base::<Runtime>(base_id)
- }
-
- fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {
- pallet_proxy_rmrk_equip::rpc::base_parts::<Runtime>(base_id)
- }
-
- fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {
- pallet_proxy_rmrk_equip::rpc::theme_names::<Runtime>(base_id)
- }
-
- fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {
- pallet_proxy_rmrk_equip::rpc::theme::<Runtime>(base_id, theme_name, filter_keys)
- }
- }
-}
-
-struct CheckInherents;
-
-impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
- fn check_inherents(
- block: &Block,
- relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
- ) -> sp_inherents::CheckInherentsResult {
- let relay_chain_slot = relay_state_proof
- .read_slot()
- .expect("Could not read the relay chain slot from the proof");
-
- let inherent_data =
- cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
- relay_chain_slot,
- sp_std::time::Duration::from_secs(6),
- )
- .create_inherent_data()
- .expect("Could not create the timestamp inherent data");
-
- inherent_data.check_extrinsics(block)
- }
-}
+impl_common_runtime_apis!();
cumulus_pallet_parachain_system::register_validate_block!(
Runtime = Runtime,
runtime/quartz/CHANGELOG.mddiffbeforeafterboth--- /dev/null
+++ b/runtime/quartz/CHANGELOG.md
@@ -0,0 +1,3 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
runtime/quartz/Cargo.tomldiffbeforeafterboth--- a/runtime/quartz/Cargo.toml
+++ b/runtime/quartz/Cargo.toml
@@ -16,7 +16,7 @@
targets = ['x86_64-unknown-linux-gnu']
[features]
-default = ['std']
+default = ['std', 'quartz-runtime']
runtime-benchmarks = [
'hex-literal',
'frame-benchmarking',
@@ -87,6 +87,7 @@
'parachain-info/std',
'serde',
'pallet-inflation/std',
+ 'pallet-configuration/std',
'pallet-common/std',
'pallet-structure/std',
'pallet-fungible/std',
@@ -113,12 +114,17 @@
'xcm/std',
'xcm-builder/std',
'xcm-executor/std',
- 'unique-runtime-common/std',
+ 'up-common/std',
"orml-vesting/std",
]
limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
+quartz-runtime = []
+refungible = []
+scheduler = []
+rmrk = []
+
################################################################################
# Substrate Dependencies
@@ -403,7 +409,7 @@
[dependencies]
log = { version = "0.4.16", default-features = false }
-unique-runtime-common = { path = "../common", default-features = false }
+up-common = { path = "../../primitives/common", default-features = false }
scale-info = { version = "2.0.1", default-features = false, features = [
"derive",
] }
@@ -413,6 +419,7 @@
fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
pallet-inflation = { path = '../../pallets/inflation', default-features = false }
up-data-structs = { path = '../../primitives/data-structs', default-features = false }
+pallet-configuration = { default-features = false, path = "../../pallets/configuration" }
pallet-common = { default-features = false, path = "../../pallets/common" }
pallet-structure = { default-features = false, path = "../../pallets/structure" }
pallet-fungible = { default-features = false, path = "../../pallets/fungible" }
@@ -432,6 +439,8 @@
pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
+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.24' }
################################################################################
# Build Dependencies
runtime/quartz/src/lib.rsdiffbeforeafterboth--- a/runtime/quartz/src/lib.rs
+++ b/runtime/quartz/src/lib.rs
@@ -25,167 +25,21 @@
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
-use sp_api::impl_runtime_apis;
-use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};
-use sp_runtime::DispatchError;
-use fp_self_contained::*;
-// #[cfg(any(feature = "std", test))]
-// pub use sp_runtime::BuildStorage;
-
-use sp_runtime::{
- Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,
- traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},
- transaction_validity::{TransactionSource, TransactionValidity},
- ApplyExtrinsicResult, RuntimeAppPublic,
-};
+use frame_support::parameter_types;
-use sp_std::prelude::*;
-
-#[cfg(feature = "std")]
-use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
-pub use pallet_transaction_payment::{
- Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,
-};
-// A few exports that help ease life for downstream crates.
-pub use pallet_balances::Call as BalancesCall;
-pub use pallet_evm::{
- EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,
- OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,
-};
-pub use frame_support::{
- construct_runtime, match_types,
- dispatch::DispatchResult,
- PalletId, parameter_types, StorageValue, ConsensusEngineId,
- traits::{
- tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,
- Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,
- OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,
- },
- weights::{
- constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
- DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
- WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,
- WeightToFee,
- },
-};
-use pallet_unique_scheduler::DispatchCall;
-use up_data_structs::{
- CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,
- CollectionStats, RpcCollection,
- mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},
- TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,
- RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, RmrkNftId,
- RmrkNftChild, RmrkPropertyKey, RmrkResourceId, RmrkBaseId,
-};
+use sp_runtime::create_runtime_str;
-// use pallet_contracts::weights::WeightInfo;
-// #[cfg(any(feature = "std", test))]
-use frame_system::{
- self as frame_system, EnsureRoot, EnsureSigned,
- limits::{BlockWeights, BlockLength},
-};
-use sp_arithmetic::{
- traits::{BaseArithmetic, Unsigned},
-};
-use smallvec::smallvec;
-use codec::{Encode, Decode};
-use fp_rpc::TransactionStatus;
-use sp_runtime::{
- traits::{
- Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,
- Saturating, CheckedConversion,
- },
- generic::Era,
- transaction_validity::TransactionValidityError,
- DispatchErrorWithPostInfo, SaturatedConversion,
-};
+use up_common::types::*;
-// pub use pallet_timestamp::Call as TimestampCall;
-pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
+#[path = "../../common/mod.rs"]
+mod runtime_common;
-// Polkadot imports
-use pallet_xcm::XcmPassthrough;
-use polkadot_parachain::primitives::Sibling;
-use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};
-use xcm_builder::{
- AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
- EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,
- RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
- SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
- ParentIsPreset,
-};
-use xcm_executor::{Config, XcmExecutor, Assets};
-use sp_std::{cmp::Ordering, marker::PhantomData};
-
-use xcm::latest::{
- // Xcm,
- AssetId::{Concrete},
- Fungibility::Fungible as XcmFungible,
- MultiAsset,
- Error as XcmError,
-};
-use xcm_executor::traits::{MatchesFungible, WeightTrader};
+pub use runtime_common::*;
-use unique_runtime_common::{
- impl_common_runtime_apis,
- types::*,
- constants::*,
- dispatch::{CollectionDispatchT, CollectionDispatch},
- sponsoring::UniqueSponsorshipHandler,
- eth_sponsoring::UniqueEthSponsorshipHandler,
- weights::CommonWeights,
-};
-
pub const RUNTIME_NAME: &str = "quartz";
pub const TOKEN_SYMBOL: &str = "QTZ";
-
-type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;
-
-impl RuntimeInstance for Runtime {
- type CrossAccountId = self::CrossAccountId;
-
- type TransactionConverter = self::TransactionConverter;
-
- fn get_transaction_converter() -> TransactionConverter {
- TransactionConverter
- }
-}
-
-/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
-/// never know...
-pub type AccountIndex = u32;
-/// Balance of an account.
-pub type Balance = u128;
-
-/// Index of a transaction in the chain.
-pub type Index = u32;
-
-/// A hash of some data used by the chain.
-pub type Hash = sp_core::H256;
-
-/// Digest item type.
-pub type DigestItem = generic::DigestItem;
-
-/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
-/// the specifics of the runtime. They can then be made to be agnostic over specific formats
-/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
-/// to even the core data structures.
-pub mod opaque {
- use sp_std::prelude::*;
- use sp_runtime::impl_opaque_keys;
- use super::Aura;
-
- pub use unique_runtime_common::types::*;
-
- impl_opaque_keys! {
- pub struct SessionKeys {
- pub aura: Aura,
- }
- }
-}
-
/// This runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!(RUNTIME_NAME),
@@ -198,1207 +52,15 @@
state_version: 0,
};
-#[derive(codec::Encode, codec::Decode)]
-pub enum XCMPMessage<XAccountId, XBalance> {
- /// Transfer tokens to the given account from the Parachain account.
- TransferToken(XAccountId, XBalance),
-}
-
-/// The version information used to identify this runtime when compiled natively.
-#[cfg(feature = "std")]
-pub fn native_version() -> NativeVersion {
- NativeVersion {
- runtime_version: VERSION,
- can_author_with: Default::default(),
- }
-}
-
-type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
-
-pub struct DealWithFees;
-impl OnUnbalanced<NegativeImbalance> for DealWithFees {
- fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {
- if let Some(fees) = fees_then_tips.next() {
- // for fees, 100% to treasury
- let mut split = fees.ration(100, 0);
- if let Some(tips) = fees_then_tips.next() {
- // for tips, if any, 100% to treasury
- tips.ration_merge_into(100, 0, &mut split);
- }
- Treasury::on_unbalanced(split.0);
- // Author::on_unbalanced(split.1);
- }
- }
-}
-
parameter_types! {
- pub const BlockHashCount: BlockNumber = 2400;
- pub RuntimeBlockLength: BlockLength =
- BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
- pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
- pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
- pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
- .base_block(BlockExecutionWeight::get())
- .for_class(DispatchClass::all(), |weights| {
- weights.base_extrinsic = ExtrinsicBaseWeight::get();
- })
- .for_class(DispatchClass::Normal, |weights| {
- weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
- })
- .for_class(DispatchClass::Operational, |weights| {
- weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
- // Operational transactions have some extra reserved space, so that they
- // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
- weights.reserved = Some(
- MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
- );
- })
- .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
- .build_or_panic();
pub const Version: RuntimeVersion = VERSION;
pub const SS58Prefix: u8 = 255;
-}
-
-parameter_types! {
pub const ChainId: u64 = 8881;
-}
-
-pub struct FixedFee;
-impl FeeCalculator for FixedFee {
- fn min_gas_price() -> (U256, u64) {
- (MIN_GAS_PRICE.into(), 0)
- }
-}
-
-// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case
-// (contract, which only writes a lot of data),
-// approximating on top of our real store write weight
-parameter_types! {
- pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;
- pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;
- pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();
-}
-
-/// Limiting EVM execution to 50% of block for substrate users and management tasks
-/// EVM transaction consumes more weight than substrate's, so we can't rely on them being
-/// scheduled fairly
-const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);
-parameter_types! {
- pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());
}
-pub enum FixedGasWeightMapping {}
-impl GasWeightMapping for FixedGasWeightMapping {
- fn gas_to_weight(gas: u64) -> Weight {
- gas.saturating_mul(WeightPerGas::get())
- }
- fn weight_to_gas(weight: Weight) -> u64 {
- weight / WeightPerGas::get()
- }
-}
-
-impl pallet_evm::account::Config for Runtime {
- type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;
- type EvmAddressMapping = HashedAddressMapping<Self::Hashing>;
- type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;
-}
-
-impl pallet_evm::Config for Runtime {
- type BlockGasLimit = BlockGasLimit;
- type FeeCalculator = FixedFee;
- type GasWeightMapping = FixedGasWeightMapping;
- type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
- type CallOrigin = EnsureAddressTruncated<Self>;
- type WithdrawOrigin = EnsureAddressTruncated<Self>;
- type AddressMapping = HashedAddressMapping<Self::Hashing>;
- type PrecompilesType = ();
- type PrecompilesValue = ();
- type Currency = Balances;
- type Event = Event;
- type OnMethodCall = (
- pallet_evm_migration::OnMethodCall<Self>,
- pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,
- CollectionDispatchT<Self>,
- pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,
- );
- type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
- type ChainId = ChainId;
- type Runner = pallet_evm::runner::stack::Runner<Self>;
- type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;
- type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;
- type FindAuthor = EthereumFindAuthor<Aura>;
-}
-
-impl pallet_evm_migration::Config for Runtime {
- type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;
-}
-
-pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);
-impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {
- fn find_author<'a, I>(digests: I) -> Option<H160>
- where
- I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
- {
- if let Some(author_index) = F::find_author(digests) {
- let authority_id = Aura::authorities()[author_index as usize].clone();
- return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));
- }
- None
- }
-}
-
-impl pallet_ethereum::Config for Runtime {
- type Event = Event;
- type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;
-}
-
-impl pallet_randomness_collective_flip::Config for Runtime {}
-
-impl frame_system::Config for Runtime {
- /// The data to be stored in an account.
- type AccountData = pallet_balances::AccountData<Balance>;
- /// The identifier used to distinguish between accounts.
- type AccountId = AccountId;
- /// The basic call filter to use in dispatchable.
- type BaseCallFilter = Everything;
- /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
- type BlockHashCount = BlockHashCount;
- /// The maximum length of a block (in bytes).
- type BlockLength = RuntimeBlockLength;
- /// The index type for blocks.
- type BlockNumber = BlockNumber;
- /// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.
- type BlockWeights = RuntimeBlockWeights;
- /// The aggregated dispatch type that is available for extrinsics.
- type Call = Call;
- /// The weight of database operations that the runtime can invoke.
- type DbWeight = RocksDbWeight;
- /// The ubiquitous event type.
- type Event = Event;
- /// The type for hashing blocks and tries.
- type Hash = Hash;
- /// The hashing algorithm used.
- type Hashing = BlakeTwo256;
- /// The header type.
- type Header = generic::Header<BlockNumber, BlakeTwo256>;
- /// The index type for storing how many extrinsics an account has signed.
- type Index = Index;
- /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
- type Lookup = AccountIdLookup<AccountId, ()>;
- /// What to do if an account is fully reaped from the system.
- type OnKilledAccount = ();
- /// What to do if a new account is created.
- type OnNewAccount = ();
- type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
- /// The ubiquitous origin type.
- type Origin = Origin;
- /// This type is being generated by `construct_runtime!`.
- type PalletInfo = PalletInfo;
- /// This is used as an identifier of the chain. 42 is the generic substrate prefix.
- type SS58Prefix = SS58Prefix;
- /// Weight information for the extrinsics of this pallet.
- type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;
- /// Version of the runtime.
- type Version = Version;
- type MaxConsumers = ConstU32<16>;
-}
-
-parameter_types! {
- pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
-}
-
-impl pallet_timestamp::Config for Runtime {
- /// A timestamp: milliseconds since the unix epoch.
- type Moment = u64;
- type OnTimestampSet = ();
- type MinimumPeriod = MinimumPeriod;
- type WeightInfo = ();
-}
-
-parameter_types! {
- // pub const ExistentialDeposit: u128 = 500;
- pub const ExistentialDeposit: u128 = 0;
- pub const MaxLocks: u32 = 50;
- pub const MaxReserves: u32 = 50;
-}
-
-impl pallet_balances::Config for Runtime {
- type MaxLocks = MaxLocks;
- type MaxReserves = MaxReserves;
- type ReserveIdentifier = [u8; 16];
- /// The type for recording an account's balance.
- type Balance = Balance;
- /// The ubiquitous event type.
- type Event = Event;
- type DustRemoval = Treasury;
- type ExistentialDeposit = ExistentialDeposit;
- type AccountStore = System;
- type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;
-}
-
-pub const fn deposit(items: u32, bytes: u32) -> Balance {
- items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE
-}
-
-/*
-parameter_types! {
- pub TombstoneDeposit: Balance = deposit(
- 1,
- sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,
- );
- pub DepositPerContract: Balance = TombstoneDeposit::get();
- pub const DepositPerStorageByte: Balance = deposit(0, 1);
- pub const DepositPerStorageItem: Balance = deposit(1, 0);
- pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);
- pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;
- pub const SignedClaimHandicap: u32 = 2;
- pub const MaxDepth: u32 = 32;
- pub const MaxValueSize: u32 = 16 * 1024;
- pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb
- // The lazy deletion runs inside on_initialize.
- pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *
- RuntimeBlockWeights::get().max_block;
- // The weight needed for decoding the queue should be less or equal than a fifth
- // of the overall weight dedicated to the lazy deletion.
- pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (
- <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -
- <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)
- )) / 5) as u32;
- pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();
-}
-
-impl pallet_contracts::Config for Runtime {
- type Time = Timestamp;
- type Randomness = RandomnessCollectiveFlip;
- type Currency = Balances;
- type Event = Event;
- type RentPayment = ();
- type SignedClaimHandicap = SignedClaimHandicap;
- type TombstoneDeposit = TombstoneDeposit;
- type DepositPerContract = DepositPerContract;
- type DepositPerStorageByte = DepositPerStorageByte;
- type DepositPerStorageItem = DepositPerStorageItem;
- type RentFraction = RentFraction;
- type SurchargeReward = SurchargeReward;
- type WeightPrice = pallet_transaction_payment::Pallet<Self>;
- type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
- type ChainExtension = NFTExtension;
- type DeletionQueueDepth = DeletionQueueDepth;
- type DeletionWeightLimit = DeletionWeightLimit;
- type Schedule = Schedule;
- type CallStack = [pallet_contracts::Frame<Self>; 31];
-}
-*/
+construct_runtime!(quartz);
-parameter_types! {
- /// This value increases the priority of `Operational` transactions by adding
- /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.
- pub const OperationalFeeMultiplier: u8 = 5;
-}
-
-/// Linear implementor of `WeightToFeePolynomial`
-pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);
-
-impl<T> WeightToFeePolynomial for LinearFee<T>
-where
- T: BaseArithmetic + From<u32> + Copy + Unsigned,
-{
- type Balance = T;
-
- fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
- smallvec!(WeightToFeeCoefficient {
- coeff_integer: WEIGHT_TO_FEE_COEFF.into(),
- coeff_frac: Perbill::zero(),
- negative: false,
- degree: 1,
- })
- }
-}
-
-impl pallet_transaction_payment::Config for Runtime {
- type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;
- type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
- type OperationalFeeMultiplier = OperationalFeeMultiplier;
- type WeightToFee = LinearFee<Balance>;
- type FeeMultiplierUpdate = ();
-}
-
-parameter_types! {
- pub const ProposalBond: Permill = Permill::from_percent(5);
- pub const ProposalBondMinimum: Balance = 1 * UNIQUE;
- pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;
- pub const SpendPeriod: BlockNumber = 5 * MINUTES;
- pub const Burn: Permill = Permill::from_percent(0);
- pub const TipCountdown: BlockNumber = 1 * DAYS;
- pub const TipFindersFee: Percent = Percent::from_percent(20);
- pub const TipReportDepositBase: Balance = 1 * UNIQUE;
- pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;
- pub const BountyDepositBase: Balance = 1 * UNIQUE;
- pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;
- pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");
- pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;
- pub const MaximumReasonLength: u32 = 16384;
- pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);
- pub const BountyValueMinimum: Balance = 5 * UNIQUE;
- pub const MaxApprovals: u32 = 100;
-}
-
-impl pallet_treasury::Config for Runtime {
- type PalletId = TreasuryModuleId;
- type Currency = Balances;
- type ApproveOrigin = EnsureRoot<AccountId>;
- type RejectOrigin = EnsureRoot<AccountId>;
- type Event = Event;
- type OnSlash = ();
- type ProposalBond = ProposalBond;
- type ProposalBondMinimum = ProposalBondMinimum;
- type ProposalBondMaximum = ProposalBondMaximum;
- type SpendPeriod = SpendPeriod;
- type Burn = Burn;
- type BurnDestination = ();
- type SpendFunds = ();
- type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;
- type MaxApprovals = MaxApprovals;
-}
-
-impl pallet_sudo::Config for Runtime {
- type Event = Event;
- type Call = Call;
-}
-
-pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);
-
-impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider
- for RelayChainBlockNumberProvider<T>
-{
- type BlockNumber = BlockNumber;
-
- fn current_block_number() -> Self::BlockNumber {
- cumulus_pallet_parachain_system::Pallet::<T>::validation_data()
- .map(|d| d.relay_parent_number)
- .unwrap_or_default()
- }
-}
-
-parameter_types! {
- pub const MinVestedTransfer: Balance = 10 * UNIQUE;
- pub const MaxVestingSchedules: u32 = 28;
-}
-
-impl orml_vesting::Config for Runtime {
- type Event = Event;
- type Currency = pallet_balances::Pallet<Runtime>;
- type MinVestedTransfer = MinVestedTransfer;
- type VestedTransferOrigin = EnsureSigned<AccountId>;
- type WeightInfo = ();
- type MaxVestingSchedules = MaxVestingSchedules;
- type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
-}
-
-parameter_types! {
- pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
- pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
-}
-
-impl cumulus_pallet_parachain_system::Config for Runtime {
- type Event = Event;
- type SelfParaId = parachain_info::Pallet<Self>;
- type OnSystemEvent = ();
- // type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<
- // MaxDownwardMessageWeight,
- // XcmExecutor<XcmConfig>,
- // Call,
- // >;
- type OutboundXcmpMessageSource = XcmpQueue;
- type DmpMessageHandler = DmpQueue;
- type ReservedDmpWeight = ReservedDmpWeight;
- type ReservedXcmpWeight = ReservedXcmpWeight;
- type XcmpMessageHandler = XcmpQueue;
-}
-
-impl parachain_info::Config for Runtime {}
-
-impl cumulus_pallet_aura_ext::Config for Runtime {}
-
-parameter_types! {
- pub const RelayLocation: MultiLocation = MultiLocation::parent();
- pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
- pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
- pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
-}
-
-/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
-/// when determining ownership of accounts for asset transacting and when attempting to use XCM
-/// `Transact` in order to determine the dispatch Origin.
-pub type LocationToAccountId = (
- // The parent (Relay-chain) origin converts to the default `AccountId`.
- ParentIsPreset<AccountId>,
- // Sibling parachain origins convert to AccountId via the `ParaId::into`.
- SiblingParachainConvertsVia<Sibling, AccountId>,
- // Straight up local `AccountId32` origins just alias directly to `AccountId`.
- AccountId32Aliases<RelayNetwork, AccountId>,
-);
-
-pub struct OnlySelfCurrency;
-impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {
- fn matches_fungible(a: &MultiAsset) -> Option<B> {
- match (&a.id, &a.fun) {
- (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),
- _ => None,
- }
- }
-}
-
-/// Means for transacting assets on this chain.
-pub type LocalAssetTransactor = CurrencyAdapter<
- // Use this currency:
- Balances,
- // Use this currency when it is a fungible asset matching the given location or name:
- OnlySelfCurrency,
- // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
- LocationToAccountId,
- // Our chain's account ID type (we can't get away without mentioning it explicitly):
- AccountId,
- // We don't track any teleports.
- (),
->;
-
-/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
-/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
-/// biases the kind of local `Origin` it will become.
-pub type XcmOriginToTransactDispatchOrigin = (
- // Sovereign account converter; this attempts to derive an `AccountId` from the origin location
- // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
- // foreign chains who want to have a local sovereign account on this chain which they control.
- SovereignSignedViaLocation<LocationToAccountId, Origin>,
- // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
- // recognised.
- RelayChainAsNative<RelayOrigin, Origin>,
- // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
- // recognised.
- SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,
- // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
- // transaction from the Root origin.
- ParentAsSuperuser<Origin>,
- // Native signed account converter; this just converts an `AccountId32` origin into a normal
- // `Origin::Signed` origin of the same 32-byte value.
- SignedAccountId32AsNative<RelayNetwork, Origin>,
- // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
- XcmPassthrough<Origin>,
-);
-
-parameter_types! {
- // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.
- pub UnitWeightCost: Weight = 1_000_000;
- // 1200 UNIQUEs buy 1 second of weight.
- pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);
- pub const MaxInstructions: u32 = 100;
- pub const MaxAuthorities: u32 = 100_000;
-}
-
-match_types! {
- pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {
- MultiLocation { parents: 1, interior: Here } |
- MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }
- };
-}
-
-pub type Barrier = (
- TakeWeightCredit,
- AllowTopLevelPaidExecutionFrom<Everything>,
- // ^^^ Parent & its unit plurality gets free execution
-);
-
-pub struct UsingOnlySelfCurrencyComponents<
- WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
- AssetId: Get<MultiLocation>,
- AccountId,
- Currency: CurrencyT<AccountId>,
- OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
->(
- Weight,
- Currency::Balance,
- PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,
-);
-impl<
- WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
- AssetId: Get<MultiLocation>,
- AccountId,
- Currency: CurrencyT<AccountId>,
- OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
- > WeightTrader
- for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
-{
- fn new() -> Self {
- Self(0, Zero::zero(), PhantomData)
- }
-
- fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {
- let amount = WeightToFee::weight_to_fee(&weight);
- let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;
-
- // location to this parachain through relay chain
- let option1: xcm::v1::AssetId = Concrete(MultiLocation {
- parents: 1,
- interior: X1(Parachain(ParachainInfo::parachain_id().into())),
- });
- // direct location
- let option2: xcm::v1::AssetId = Concrete(MultiLocation {
- parents: 0,
- interior: Here,
- });
-
- let required = if payment.fungible.contains_key(&option1) {
- (option1, u128_amount).into()
- } else if payment.fungible.contains_key(&option2) {
- (option2, u128_amount).into()
- } else {
- (Concrete(MultiLocation::default()), u128_amount).into()
- };
-
- let unused = payment
- .checked_sub(required)
- .map_err(|_| XcmError::TooExpensive)?;
- self.0 = self.0.saturating_add(weight);
- self.1 = self.1.saturating_add(amount);
- Ok(unused)
- }
-
- fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {
- let weight = weight.min(self.0);
- let amount = WeightToFee::weight_to_fee(&weight);
- self.0 -= weight;
- self.1 = self.1.saturating_sub(amount);
- let amount: u128 = amount.saturated_into();
- if amount > 0 {
- Some((AssetId::get(), amount).into())
- } else {
- None
- }
- }
-}
-impl<
- WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
- AssetId: Get<MultiLocation>,
- AccountId,
- Currency: CurrencyT<AccountId>,
- OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
- > Drop
- for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
-{
- fn drop(&mut self) {
- OnUnbalanced::on_unbalanced(Currency::issue(self.1));
- }
-}
-
-pub struct XcmConfig;
-impl Config for XcmConfig {
- type Call = Call;
- type XcmSender = XcmRouter;
- // How to withdraw and deposit an asset.
- type AssetTransactor = LocalAssetTransactor;
- type OriginConverter = XcmOriginToTransactDispatchOrigin;
- type IsReserve = NativeAsset;
- type IsTeleporter = (); // Teleportation is disabled
- type LocationInverter = LocationInverter<Ancestry>;
- type Barrier = Barrier;
- type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
- type Trader =
- UsingOnlySelfCurrencyComponents<LinearFee<Balance>, RelayLocation, AccountId, Balances, ()>;
- type ResponseHandler = (); // Don't handle responses for now.
- type SubscriptionService = PolkadotXcm;
-
- type AssetTrap = PolkadotXcm;
- type AssetClaims = PolkadotXcm;
-}
-
-// parameter_types! {
-// pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;
-// }
-
-/// No local origins on this chain are allowed to dispatch XCM sends/executions.
-pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);
-
-/// The means for routing XCM messages which are not for local execution into the right message
-/// queues.
-pub type XcmRouter = (
- // Two routers - use UMP to communicate with the relay chain:
- cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,
- // ..and XCMP to communicate with the sibling chains.
- XcmpQueue,
-);
-
-impl pallet_evm_coder_substrate::Config for Runtime {}
-
-impl pallet_xcm::Config for Runtime {
- type Event = Event;
- type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
- type XcmRouter = XcmRouter;
- type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
- type XcmExecuteFilter = Everything;
- type XcmExecutor = XcmExecutor<XcmConfig>;
- type XcmTeleportFilter = Everything;
- type XcmReserveTransferFilter = Everything;
- type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
- type LocationInverter = LocationInverter<Ancestry>;
- type Origin = Origin;
- type Call = Call;
- const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
- type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
-}
-
-impl cumulus_pallet_xcm::Config for Runtime {
- type Event = Event;
- type XcmExecutor = XcmExecutor<XcmConfig>;
-}
-
-impl cumulus_pallet_xcmp_queue::Config for Runtime {
- type WeightInfo = ();
- type Event = Event;
- type XcmExecutor = XcmExecutor<XcmConfig>;
- type ChannelInfo = ParachainSystem;
- type VersionWrapper = ();
- type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
- type ControllerOrigin = EnsureRoot<AccountId>;
- type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
-}
-
-impl cumulus_pallet_dmp_queue::Config for Runtime {
- type Event = Event;
- type XcmExecutor = XcmExecutor<XcmConfig>;
- type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
-}
-
-impl pallet_aura::Config for Runtime {
- type AuthorityId = AuraId;
- type DisabledValidators = ();
- type MaxAuthorities = MaxAuthorities;
-}
-
-parameter_types! {
- pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();
- pub const CollectionCreationPrice: Balance = 2 * UNIQUE;
-}
-
-impl pallet_common::Config for Runtime {
- type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;
- type Event = Event;
- type Currency = Balances;
- type CollectionCreationPrice = CollectionCreationPrice;
- type TreasuryAccountId = TreasuryAccountId;
- type CollectionDispatch = CollectionDispatchT<Self>;
-
- type EvmTokenAddressMapping = EvmTokenAddressMapping;
- type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
- type ContractAddress = EvmCollectionHelpersAddress;
-}
-
-impl pallet_structure::Config for Runtime {
- type Event = Event;
- type Call = Call;
- type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;
-}
-
-impl pallet_fungible::Config for Runtime {
- type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;
-}
-impl pallet_refungible::Config for Runtime {
- type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;
-}
-impl pallet_nonfungible::Config for Runtime {
- type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;
-}
-
-impl pallet_proxy_rmrk_core::Config for Runtime {
- type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
- type Event = Event;
-}
-
-impl pallet_proxy_rmrk_equip::Config for Runtime {
- type WeightInfo = pallet_proxy_rmrk_equip::weights::SubstrateWeight<Self>;
- type Event = Event;
-}
-
-impl pallet_unique::Config for Runtime {
- type Event = Event;
- type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
- type CommonWeightInfo = CommonWeights<Self>;
- type RefungibleExtensionsWeightInfo = CommonWeights<Self>;
-}
-
-parameter_types! {
- pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied
-}
-
-/// Used for the pallet inflation
-impl pallet_inflation::Config for Runtime {
- type Currency = Balances;
- type TreasuryAccountId = TreasuryAccountId;
- type InflationBlockInterval = InflationBlockInterval;
- type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
-}
-
-parameter_types! {
- pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *
- RuntimeBlockWeights::get().max_block;
- pub const MaxScheduledPerBlock: u32 = 50;
-}
-
-type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;
-use frame_support::traits::NamedReservableCurrency;
-
-fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {
- (
- frame_system::CheckSpecVersion::<Runtime>::new(),
- frame_system::CheckGenesis::<Runtime>::new(),
- frame_system::CheckEra::<Runtime>::from(Era::Immortal),
- frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(
- from,
- )),
- frame_system::CheckWeight::<Runtime>::new(),
- // sponsoring transaction logic
- // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
- )
-}
-
-pub struct SchedulerPaymentExecutor;
-impl<T: frame_system::Config + pallet_unique_scheduler::Config, SelfContainedSignedInfo>
- DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor
-where
- <T as frame_system::Config>::Call: Member
- + Dispatchable<Origin = Origin, Info = DispatchInfo>
- + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>
- + GetDispatchInfo
- + From<frame_system::Call<Runtime>>,
- SelfContainedSignedInfo: Send + Sync + 'static,
- Call: From<<T as frame_system::Config>::Call>
- + From<<T as pallet_unique_scheduler::Config>::Call>
- + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,
- sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,
-{
- fn dispatch_call(
- signer: <T as frame_system::Config>::AccountId,
- call: <T as pallet_unique_scheduler::Config>::Call,
- ) -> Result<
- Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,
- TransactionValidityError,
- > {
- let dispatch_info = call.get_dispatch_info();
- let extrinsic = fp_self_contained::CheckedExtrinsic::<
- AccountId,
- Call,
- SignedExtraScheduler,
- SelfContainedSignedInfo,
- > {
- signed:
- CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(
- signer.clone().into(),
- get_signed_extras(signer.into()),
- ),
- function: call.into(),
- };
-
- extrinsic.apply::<Runtime>(&dispatch_info, 0)
- }
-
- fn reserve_balance(
- id: [u8; 16],
- sponsor: <T as frame_system::Config>::AccountId,
- call: <T as pallet_unique_scheduler::Config>::Call,
- count: u32,
- ) -> Result<(), DispatchError> {
- let dispatch_info = call.get_dispatch_info();
- let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)
- .saturating_mul(count.into());
-
- <Balances as NamedReservableCurrency<AccountId>>::reserve_named(
- &id,
- &(sponsor.into()),
- weight.into(),
- )
- }
-
- fn pay_for_call(
- id: [u8; 16],
- sponsor: <T as frame_system::Config>::AccountId,
- call: <T as pallet_unique_scheduler::Config>::Call,
- ) -> Result<u128, DispatchError> {
- let dispatch_info = call.get_dispatch_info();
- let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);
- Ok(
- <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
- &id,
- &(sponsor.into()),
- weight.into(),
- ),
- )
- }
-
- fn cancel_reserve(
- id: [u8; 16],
- sponsor: <T as frame_system::Config>::AccountId,
- ) -> Result<u128, DispatchError> {
- Ok(
- <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
- &id,
- &(sponsor.into()),
- u128::MAX,
- ),
- )
- }
-}
-
-parameter_types! {
- pub const NoPreimagePostponement: Option<u32> = Some(10);
- pub const Preimage: Option<u32> = Some(10);
-}
-
-/// Used the compare the privilege of an origin inside the scheduler.
-pub struct OriginPrivilegeCmp;
-
-impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {
- fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {
- Some(Ordering::Equal)
- }
-}
-
-impl pallet_unique_scheduler::Config for Runtime {
- type Event = Event;
- type Origin = Origin;
- type Currency = Balances;
- type PalletsOrigin = OriginCaller;
- type Call = Call;
- type MaximumWeight = MaximumSchedulerWeight;
- type ScheduleOrigin = EnsureSigned<AccountId>;
- type MaxScheduledPerBlock = MaxScheduledPerBlock;
- type WeightInfo = ();
- type CallExecutor = SchedulerPaymentExecutor;
- type OriginPrivilegeCmp = OriginPrivilegeCmp;
- type PreimageProvider = ();
- type NoPreimagePostponement = NoPreimagePostponement;
-}
-
-type EvmSponsorshipHandler = (
- UniqueEthSponsorshipHandler<Runtime>,
- pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,
-);
-type SponsorshipHandler = (
- UniqueSponsorshipHandler<Runtime>,
- //pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,
- pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,
-);
-
-impl pallet_evm_transaction_payment::Config for Runtime {
- type EvmSponsorshipHandler = EvmSponsorshipHandler;
- type Currency = Balances;
-}
-
-impl pallet_charge_transaction::Config for Runtime {
- type SponsorshipHandler = SponsorshipHandler;
-}
-
-// impl pallet_contract_helpers::Config for Runtime {
-// type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
-// }
-
-parameter_types! {
- // 0x842899ECF380553E8a4de75bF534cdf6fBF64049
- pub const HelpersContractAddress: H160 = H160([
- 0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,
- ]);
-
- // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f
- pub const EvmCollectionHelpersAddress: H160 = H160([
- 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,
- ]);
-}
-
-impl pallet_evm_contract_helpers::Config for Runtime {
- type ContractAddress = HelpersContractAddress;
- type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
-}
-
-construct_runtime!(
- pub enum Runtime where
- Block = Block,
- NodeBlock = opaque::Block,
- UncheckedExtrinsic = UncheckedExtrinsic
- {
- ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,
- ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,
-
- Aura: pallet_aura::{Pallet, Config<T>} = 22,
- AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,
-
- Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,
- RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,
- Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,
- TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,
- Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,
- Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,
- System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,
- Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,
- // Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,
- // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,
-
- // XCM helpers.
- XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
- PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
- CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,
- DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
-
- // Unique Pallets
- Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,
- Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,
- Scheduler: pallet_unique_scheduler::{Pallet, Call, Storage, Event<T>} = 62,
- // free = 63
- Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,
- // ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,
- Common: pallet_common::{Pallet, Storage, Event<T>} = 66,
- Fungible: pallet_fungible::{Pallet, Storage} = 67,
- Refungible: pallet_refungible::{Pallet, Storage} = 68,
- Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,
- Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,
- RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,
- RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,
-
- // Frontier
- EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,
- Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,
-
- EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,
- EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,
- EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,
- EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,
- }
-);
-
-pub struct TransactionConverter;
-
-impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {
- fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {
- UncheckedExtrinsic::new_unsigned(
- pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
- )
- }
-}
-
-impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {
- fn convert_transaction(
- &self,
- transaction: pallet_ethereum::Transaction,
- ) -> opaque::UncheckedExtrinsic {
- let extrinsic = UncheckedExtrinsic::new_unsigned(
- pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
- );
- let encoded = extrinsic.encode();
- opaque::UncheckedExtrinsic::decode(&mut &encoded[..])
- .expect("Encoded extrinsic is always valid")
- }
-}
-
-/// The address format for describing accounts.
-pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
-/// Block header type as expected by this runtime.
-pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
-/// Block type as expected by this runtime.
-pub type Block = generic::Block<Header, UncheckedExtrinsic>;
-/// A Block signed with a Justification
-pub type SignedBlock = generic::SignedBlock<Block>;
-/// BlockId type as expected by this runtime.
-pub type BlockId = generic::BlockId<Block>;
-/// The SignedExtension to the basic transaction logic.
-pub type SignedExtra = (
- frame_system::CheckSpecVersion<Runtime>,
- // system::CheckTxVersion<Runtime>,
- frame_system::CheckGenesis<Runtime>,
- frame_system::CheckEra<Runtime>,
- frame_system::CheckNonce<Runtime>,
- frame_system::CheckWeight<Runtime>,
- ChargeTransactionPayment,
- //pallet_contract_helpers::ContractHelpersExtension<Runtime>,
- pallet_ethereum::FakeTransactionFinalizer<Runtime>,
-);
-
-pub type SignedExtraScheduler = (
- frame_system::CheckSpecVersion<Runtime>,
- frame_system::CheckGenesis<Runtime>,
- frame_system::CheckEra<Runtime>,
- frame_system::CheckNonce<Runtime>,
- frame_system::CheckWeight<Runtime>,
- // pallet_charge_transaction::ChargeTransactionPayment<Runtime>,
-);
-/// Unchecked extrinsic type as expected by this runtime.
-pub type UncheckedExtrinsic =
- fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
-/// Extrinsic type that has already been checked.
-pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;
-/// Executive: handles dispatch to the various modules.
-pub type Executive = frame_executive::Executive<
- Runtime,
- Block,
- frame_system::ChainContext<Runtime>,
- Runtime,
- AllPalletsReversedWithSystemFirst,
->;
-
-impl_opaque_keys! {
- pub struct SessionKeys {
- pub aura: Aura,
- }
-}
-
-impl fp_self_contained::SelfContainedCall for Call {
- type SignedInfo = H160;
-
- fn is_self_contained(&self) -> bool {
- match self {
- Call::Ethereum(call) => call.is_self_contained(),
- _ => false,
- }
- }
-
- fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
- match self {
- Call::Ethereum(call) => call.check_self_contained(),
- _ => None,
- }
- }
-
- fn validate_self_contained(
- &self,
- info: &Self::SignedInfo,
- dispatch_info: &DispatchInfoOf<Call>,
- len: usize,
- ) -> Option<TransactionValidity> {
- match self {
- Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),
- _ => None,
- }
- }
-
- fn pre_dispatch_self_contained(
- &self,
- info: &Self::SignedInfo,
- ) -> Option<Result<(), TransactionValidityError>> {
- match self {
- Call::Ethereum(call) => call.pre_dispatch_self_contained(info),
- _ => None,
- }
- }
-
- fn apply_self_contained(
- self,
- info: Self::SignedInfo,
- ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {
- match self {
- call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(
- Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),
- )),
- _ => None,
- }
- }
-}
-
-macro_rules! dispatch_unique_runtime {
- ($collection:ident.$method:ident($($name:ident),*)) => {{
- let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);
- let dispatch = collection.as_dyn();
-
- Ok::<_, DispatchError>(dispatch.$method($($name),*))
- }};
-}
-
-impl_common_runtime_apis! {
- #![custom_apis]
-
- impl rmrk_rpc::RmrkApi<
- Block,
- AccountId,
- RmrkCollectionInfo<AccountId>,
- RmrkInstanceInfo<AccountId>,
- RmrkResourceInfo,
- RmrkPropertyInfo,
- RmrkBaseInfo<AccountId>,
- RmrkPartType,
- RmrkTheme
- > for Runtime {
- fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {
- pallet_proxy_rmrk_core::rpc::last_collection_idx::<Runtime>()
- }
-
- fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::collection_by_id::<Runtime>(collection_id)
- }
-
- fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::nft_by_id::<Runtime>(collection_id, nft_by_id)
- }
-
- fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::account_tokens::<Runtime>(account_id, collection_id)
- }
-
- fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::nft_children::<Runtime>(collection_id, nft_id)
- }
-
- fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::collection_properties::<Runtime>(collection_id, filter_keys)
- }
-
- fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::nft_properties::<Runtime>(collection_id, nft_id, filter_keys)
- }
-
- fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::nft_resources::<Runtime>(collection_id, nft_id)
- }
-
- fn nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Result<Option<u32>, DispatchError> {
- pallet_proxy_rmrk_core::rpc::nft_resource_priority::<Runtime>(collection_id, nft_id, resource_id)
- }
-
- fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {
- pallet_proxy_rmrk_equip::rpc::base::<Runtime>(base_id)
- }
-
- fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {
- pallet_proxy_rmrk_equip::rpc::base_parts::<Runtime>(base_id)
- }
-
- fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {
- pallet_proxy_rmrk_equip::rpc::theme_names::<Runtime>(base_id)
- }
-
- fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {
- pallet_proxy_rmrk_equip::rpc::theme::<Runtime>(base_id, theme_name, filter_keys)
- }
- }
-}
-
-struct CheckInherents;
-
-impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
- fn check_inherents(
- block: &Block,
- relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
- ) -> sp_inherents::CheckInherentsResult {
- let relay_chain_slot = relay_state_proof
- .read_slot()
- .expect("Could not read the relay chain slot from the proof");
-
- let inherent_data =
- cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
- relay_chain_slot,
- sp_std::time::Duration::from_secs(6),
- )
- .create_inherent_data()
- .expect("Could not create the timestamp inherent data");
-
- inherent_data.check_extrinsics(block)
- }
-}
+impl_common_runtime_apis!();
cumulus_pallet_parachain_system::register_validate_block!(
Runtime = Runtime,
runtime/tests/Cargo.tomldiffbeforeafterboth--- a/runtime/tests/Cargo.toml
+++ b/runtime/tests/Cargo.toml
@@ -3,8 +3,12 @@
version = "0.1.0"
edition = "2021"
+[features]
+default = ['refungible']
+
+refungible = []
+
[dependencies]
-unique-runtime-common = { path = '../common' }
up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
sp-core = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.24' }
@@ -37,3 +41,6 @@
"derive",
] }
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.24' }
runtime/tests/src/lib.rsdiffbeforeafterboth--- a/runtime/tests/src/lib.rs
+++ b/runtime/tests/src/lib.rs
@@ -35,9 +35,18 @@
use parity_scale_codec::{Encode, Decode, MaxEncodedLen};
use scale_info::TypeInfo;
-use unique_runtime_common::{dispatch::CollectionDispatchT, weights::CommonWeights};
use up_data_structs::mapping::{CrossTokenAddressMapping, EvmTokenAddressMapping};
+#[path = "../../common/dispatch.rs"]
+mod dispatch;
+
+use dispatch::CollectionDispatchT;
+
+#[path = "../../common/weights.rs"]
+mod weights;
+
+use weights::CommonWeights;
+
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
runtime/unique/CHANGELOG.mddiffbeforeafterboth--- /dev/null
+++ b/runtime/unique/CHANGELOG.md
@@ -0,0 +1,3 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
runtime/unique/Cargo.tomldiffbeforeafterboth--- a/runtime/unique/Cargo.toml
+++ b/runtime/unique/Cargo.toml
@@ -88,6 +88,7 @@
'parachain-info/std',
'serde',
'pallet-inflation/std',
+ 'pallet-configuration/std',
'pallet-common/std',
'pallet-structure/std',
'pallet-fungible/std',
@@ -114,13 +115,17 @@
'xcm/std',
'xcm-builder/std',
'xcm-executor/std',
- 'unique-runtime-common/std',
+ 'up-common/std',
"orml-vesting/std",
]
limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
unique-runtime = []
+refungible = []
+scheduler = []
+rmrk = []
+
################################################################################
# Substrate Dependencies
@@ -397,7 +402,7 @@
[dependencies]
log = { version = "0.4.16", default-features = false }
-unique-runtime-common = { path = "../common", default-features = false }
+up-common = { path = "../../primitives/common", default-features = false }
scale-info = { version = "2.0.1", default-features = false, features = [
"derive",
] }
@@ -407,6 +412,7 @@
rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false }
pallet-inflation = { path = '../../pallets/inflation', default-features = false }
up-data-structs = { path = '../../primitives/data-structs', default-features = false }
+pallet-configuration = { default-features = false, path = "../../pallets/configuration" }
pallet-common = { default-features = false, path = "../../pallets/common" }
pallet-structure = { default-features = false, path = "../../pallets/structure" }
pallet-fungible = { default-features = false, path = "../../pallets/fungible" }
@@ -427,6 +433,8 @@
fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
+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.24' }
################################################################################
# Build Dependencies
runtime/unique/src/lib.rsdiffbeforeafterboth--- a/runtime/unique/src/lib.rs
+++ b/runtime/unique/src/lib.rs
@@ -25,166 +25,21 @@
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
-use sp_api::impl_runtime_apis;
-use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};
-use sp_runtime::DispatchError;
-use fp_self_contained::*;
-// #[cfg(any(feature = "std", test))]
-// pub use sp_runtime::BuildStorage;
-
-use sp_runtime::{
- Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,
- traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},
- transaction_validity::{TransactionSource, TransactionValidity},
- ApplyExtrinsicResult, RuntimeAppPublic,
-};
-
-use sp_std::prelude::*;
+use frame_support::parameter_types;
-#[cfg(feature = "std")]
-use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
-pub use pallet_transaction_payment::{
- Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,
-};
-// A few exports that help ease life for downstream crates.
-pub use pallet_balances::Call as BalancesCall;
-pub use pallet_evm::{
- EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,
- OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,
-};
-pub use frame_support::{
- construct_runtime, match_types,
- dispatch::DispatchResult,
- PalletId, parameter_types, StorageValue, ConsensusEngineId,
- traits::{
- tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,
- Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,
- OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,
- },
- weights::{
- constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
- DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
- WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,
- WeightToFee,
- },
-};
-use pallet_unique_scheduler::DispatchCall;
-use up_data_structs::{
- CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,
- CollectionStats, RpcCollection,
- mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},
- TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,
- RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, RmrkNftId,
- RmrkNftChild, RmrkPropertyKey, RmrkResourceId, RmrkBaseId,
-};
+use sp_runtime::create_runtime_str;
-// use pallet_contracts::weights::WeightInfo;
-// #[cfg(any(feature = "std", test))]
-use frame_system::{
- self as frame_system, EnsureRoot, EnsureSigned,
- limits::{BlockWeights, BlockLength},
-};
-use sp_arithmetic::{
- traits::{BaseArithmetic, Unsigned},
-};
-use smallvec::smallvec;
-use codec::{Encode, Decode};
-use fp_rpc::TransactionStatus;
-use sp_runtime::{
- traits::{
- Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,
- Saturating, CheckedConversion,
- },
- generic::Era,
- transaction_validity::TransactionValidityError,
- DispatchErrorWithPostInfo, SaturatedConversion,
-};
+use up_common::types::*;
-// pub use pallet_timestamp::Call as TimestampCall;
-pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
+#[path = "../../common/mod.rs"]
+mod runtime_common;
-// Polkadot imports
-use pallet_xcm::XcmPassthrough;
-use polkadot_parachain::primitives::Sibling;
-use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};
-use xcm_builder::{
- AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
- EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,
- RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
- SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
- ParentIsPreset,
-};
-use xcm_executor::{Config, XcmExecutor, Assets};
-use sp_std::{cmp::Ordering, marker::PhantomData};
-
-use xcm::latest::{
- // Xcm,
- AssetId::{Concrete},
- Fungibility::Fungible as XcmFungible,
- MultiAsset,
- Error as XcmError,
-};
-use xcm_executor::traits::{MatchesFungible, WeightTrader};
-
-use unique_runtime_common::{
- impl_common_runtime_apis,
- types::*,
- constants::*,
- dispatch::{CollectionDispatchT, CollectionDispatch},
- sponsoring::UniqueSponsorshipHandler,
- eth_sponsoring::UniqueEthSponsorshipHandler,
- weights::CommonWeights,
-};
+pub use runtime_common::*;
pub const RUNTIME_NAME: &str = "unique";
pub const TOKEN_SYMBOL: &str = "UNQ";
-
-type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;
-
-impl RuntimeInstance for Runtime {
- type CrossAccountId = self::CrossAccountId;
- type TransactionConverter = self::TransactionConverter;
-
- fn get_transaction_converter() -> TransactionConverter {
- TransactionConverter
- }
-}
-
-/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
-/// never know...
-pub type AccountIndex = u32;
-
-/// Balance of an account.
-pub type Balance = u128;
-
-/// Index of a transaction in the chain.
-pub type Index = u32;
-
-/// A hash of some data used by the chain.
-pub type Hash = sp_core::H256;
-
-/// Digest item type.
-pub type DigestItem = generic::DigestItem;
-
-/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
-/// the specifics of the runtime. They can then be made to be agnostic over specific formats
-/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
-/// to even the core data structures.
-pub mod opaque {
- use sp_std::prelude::*;
- use sp_runtime::impl_opaque_keys;
- use super::Aura;
-
- pub use unique_runtime_common::types::*;
- impl_opaque_keys! {
- pub struct SessionKeys {
- pub aura: Aura,
- }
- }
-}
-
/// This runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!(RUNTIME_NAME),
@@ -197,1194 +52,15 @@
state_version: 0,
};
-#[derive(codec::Encode, codec::Decode)]
-pub enum XCMPMessage<XAccountId, XBalance> {
- /// Transfer tokens to the given account from the Parachain account.
- TransferToken(XAccountId, XBalance),
-}
-
-/// The version information used to identify this runtime when compiled natively.
-#[cfg(feature = "std")]
-pub fn native_version() -> NativeVersion {
- NativeVersion {
- runtime_version: VERSION,
- can_author_with: Default::default(),
- }
-}
-
-type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
-
-pub struct DealWithFees;
-impl OnUnbalanced<NegativeImbalance> for DealWithFees {
- fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {
- if let Some(fees) = fees_then_tips.next() {
- // for fees, 100% to treasury
- let mut split = fees.ration(100, 0);
- if let Some(tips) = fees_then_tips.next() {
- // for tips, if any, 100% to treasury
- tips.ration_merge_into(100, 0, &mut split);
- }
- Treasury::on_unbalanced(split.0);
- // Author::on_unbalanced(split.1);
- }
- }
-}
-
parameter_types! {
- pub const BlockHashCount: BlockNumber = 2400;
- pub RuntimeBlockLength: BlockLength =
- BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
- pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
- pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
- pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
- .base_block(BlockExecutionWeight::get())
- .for_class(DispatchClass::all(), |weights| {
- weights.base_extrinsic = ExtrinsicBaseWeight::get();
- })
- .for_class(DispatchClass::Normal, |weights| {
- weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
- })
- .for_class(DispatchClass::Operational, |weights| {
- weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
- // Operational transactions have some extra reserved space, so that they
- // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
- weights.reserved = Some(
- MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
- );
- })
- .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
- .build_or_panic();
pub const Version: RuntimeVersion = VERSION;
pub const SS58Prefix: u16 = 7391;
-}
-
-parameter_types! {
pub const ChainId: u64 = 8880;
-}
-
-pub struct FixedFee;
-impl FeeCalculator for FixedFee {
- fn min_gas_price() -> (U256, u64) {
- (MIN_GAS_PRICE.into(), 0)
- }
-}
-
-// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case
-// (contract, which only writes a lot of data),
-// approximating on top of our real store write weight
-parameter_types! {
- pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;
- pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;
- pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();
}
-/// Limiting EVM execution to 50% of block for substrate users and management tasks
-/// EVM transaction consumes more weight than substrate's, so we can't rely on them being
-/// scheduled fairly
-const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);
-parameter_types! {
- pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());
-}
-
-pub enum FixedGasWeightMapping {}
-impl GasWeightMapping for FixedGasWeightMapping {
- fn gas_to_weight(gas: u64) -> Weight {
- gas.saturating_mul(WeightPerGas::get())
- }
- fn weight_to_gas(weight: Weight) -> u64 {
- weight / WeightPerGas::get()
- }
-}
-
-impl pallet_evm::account::Config for Runtime {
- type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;
- type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;
- type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;
-}
-
-impl pallet_evm::Config for Runtime {
- type BlockGasLimit = BlockGasLimit;
- type FeeCalculator = FixedFee;
- type GasWeightMapping = FixedGasWeightMapping;
- type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
- type CallOrigin = EnsureAddressTruncated<Self>;
- type WithdrawOrigin = EnsureAddressTruncated<Self>;
- type AddressMapping = HashedAddressMapping<Self::Hashing>;
- type PrecompilesType = ();
- type PrecompilesValue = ();
- type Currency = Balances;
- type Event = Event;
- type OnMethodCall = (
- pallet_evm_migration::OnMethodCall<Self>,
- pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,
- CollectionDispatchT<Self>,
- pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,
- );
- type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
- type ChainId = ChainId;
- type Runner = pallet_evm::runner::stack::Runner<Self>;
- type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;
- type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;
- type FindAuthor = EthereumFindAuthor<Aura>;
-}
-
-impl pallet_evm_migration::Config for Runtime {
- type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;
-}
-
-pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);
-impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {
- fn find_author<'a, I>(digests: I) -> Option<H160>
- where
- I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
- {
- if let Some(author_index) = F::find_author(digests) {
- let authority_id = Aura::authorities()[author_index as usize].clone();
- return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));
- }
- None
- }
-}
-
-impl pallet_ethereum::Config for Runtime {
- type Event = Event;
- type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;
-}
-
-impl pallet_randomness_collective_flip::Config for Runtime {}
+construct_runtime!(unique);
-impl frame_system::Config for Runtime {
- /// The data to be stored in an account.
- type AccountData = pallet_balances::AccountData<Balance>;
- /// The identifier used to distinguish between accounts.
- type AccountId = AccountId;
- /// The basic call filter to use in dispatchable.
- type BaseCallFilter = Everything;
- /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
- type BlockHashCount = BlockHashCount;
- /// The maximum length of a block (in bytes).
- type BlockLength = RuntimeBlockLength;
- /// The index type for blocks.
- type BlockNumber = BlockNumber;
- /// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.
- type BlockWeights = RuntimeBlockWeights;
- /// The aggregated dispatch type that is available for extrinsics.
- type Call = Call;
- /// The weight of database operations that the runtime can invoke.
- type DbWeight = RocksDbWeight;
- /// The ubiquitous event type.
- type Event = Event;
- /// The type for hashing blocks and tries.
- type Hash = Hash;
- /// The hashing algorithm used.
- type Hashing = BlakeTwo256;
- /// The header type.
- type Header = generic::Header<BlockNumber, BlakeTwo256>;
- /// The index type for storing how many extrinsics an account has signed.
- type Index = Index;
- /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
- type Lookup = AccountIdLookup<AccountId, ()>;
- /// What to do if an account is fully reaped from the system.
- type OnKilledAccount = ();
- /// What to do if a new account is created.
- type OnNewAccount = ();
- type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
- /// The ubiquitous origin type.
- type Origin = Origin;
- /// This type is being generated by `construct_runtime!`.
- type PalletInfo = PalletInfo;
- /// This is used as an identifier of the chain. 42 is the generic substrate prefix.
- type SS58Prefix = SS58Prefix;
- /// Weight information for the extrinsics of this pallet.
- type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;
- /// Version of the runtime.
- type Version = Version;
- type MaxConsumers = ConstU32<16>;
-}
-
-parameter_types! {
- pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
-}
-
-impl pallet_timestamp::Config for Runtime {
- /// A timestamp: milliseconds since the unix epoch.
- type Moment = u64;
- type OnTimestampSet = ();
- type MinimumPeriod = MinimumPeriod;
- type WeightInfo = ();
-}
-
-parameter_types! {
- // pub const ExistentialDeposit: u128 = 500;
- pub const ExistentialDeposit: u128 = 0;
- pub const MaxLocks: u32 = 50;
- pub const MaxReserves: u32 = 50;
-}
-
-impl pallet_balances::Config for Runtime {
- type MaxLocks = MaxLocks;
- type MaxReserves = MaxReserves;
- type ReserveIdentifier = [u8; 16];
- /// The type for recording an account's balance.
- type Balance = Balance;
- /// The ubiquitous event type.
- type Event = Event;
- type DustRemoval = Treasury;
- type ExistentialDeposit = ExistentialDeposit;
- type AccountStore = System;
- type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;
-}
-
-pub const fn deposit(items: u32, bytes: u32) -> Balance {
- items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE
-}
-
-/*
-parameter_types! {
- pub TombstoneDeposit: Balance = deposit(
- 1,
- sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,
- );
- pub DepositPerContract: Balance = TombstoneDeposit::get();
- pub const DepositPerStorageByte: Balance = deposit(0, 1);
- pub const DepositPerStorageItem: Balance = deposit(1, 0);
- pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);
- pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;
- pub const SignedClaimHandicap: u32 = 2;
- pub const MaxDepth: u32 = 32;
- pub const MaxValueSize: u32 = 16 * 1024;
- pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb
- // The lazy deletion runs inside on_initialize.
- pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *
- RuntimeBlockWeights::get().max_block;
- // The weight needed for decoding the queue should be less or equal than a fifth
- // of the overall weight dedicated to the lazy deletion.
- pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (
- <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -
- <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)
- )) / 5) as u32;
- pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();
-}
-
-impl pallet_contracts::Config for Runtime {
- type Time = Timestamp;
- type Randomness = RandomnessCollectiveFlip;
- type Currency = Balances;
- type Event = Event;
- type RentPayment = ();
- type SignedClaimHandicap = SignedClaimHandicap;
- type TombstoneDeposit = TombstoneDeposit;
- type DepositPerContract = DepositPerContract;
- type DepositPerStorageByte = DepositPerStorageByte;
- type DepositPerStorageItem = DepositPerStorageItem;
- type RentFraction = RentFraction;
- type SurchargeReward = SurchargeReward;
- type WeightPrice = pallet_transaction_payment::Pallet<Self>;
- type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
- type ChainExtension = NFTExtension;
- type DeletionQueueDepth = DeletionQueueDepth;
- type DeletionWeightLimit = DeletionWeightLimit;
- type Schedule = Schedule;
- type CallStack = [pallet_contracts::Frame<Self>; 31];
-}
-*/
-
-parameter_types! {
- /// This value increases the priority of `Operational` transactions by adding
- /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.
- pub const OperationalFeeMultiplier: u8 = 5;
-}
-
-/// Linear implementor of `WeightToFeePolynomial`
-pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);
-
-impl<T> WeightToFeePolynomial for LinearFee<T>
-where
- T: BaseArithmetic + From<u32> + Copy + Unsigned,
-{
- type Balance = T;
-
- fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
- smallvec!(WeightToFeeCoefficient {
- coeff_integer: WEIGHT_TO_FEE_COEFF.into(),
- coeff_frac: Perbill::zero(),
- negative: false,
- degree: 1,
- })
- }
-}
-
-impl pallet_transaction_payment::Config for Runtime {
- type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;
- type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
- type OperationalFeeMultiplier = OperationalFeeMultiplier;
- type WeightToFee = LinearFee<Balance>;
- type FeeMultiplierUpdate = ();
-}
-
-parameter_types! {
- pub const ProposalBond: Permill = Permill::from_percent(5);
- pub const ProposalBondMinimum: Balance = 1 * UNIQUE;
- pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;
- pub const SpendPeriod: BlockNumber = 5 * MINUTES;
- pub const Burn: Permill = Permill::from_percent(0);
- pub const TipCountdown: BlockNumber = 1 * DAYS;
- pub const TipFindersFee: Percent = Percent::from_percent(20);
- pub const TipReportDepositBase: Balance = 1 * UNIQUE;
- pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;
- pub const BountyDepositBase: Balance = 1 * UNIQUE;
- pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;
- pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");
- pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;
- pub const MaximumReasonLength: u32 = 16384;
- pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);
- pub const BountyValueMinimum: Balance = 5 * UNIQUE;
- pub const MaxApprovals: u32 = 100;
-}
-
-impl pallet_treasury::Config for Runtime {
- type PalletId = TreasuryModuleId;
- type Currency = Balances;
- type ApproveOrigin = EnsureRoot<AccountId>;
- type RejectOrigin = EnsureRoot<AccountId>;
- type Event = Event;
- type OnSlash = ();
- type ProposalBond = ProposalBond;
- type ProposalBondMinimum = ProposalBondMinimum;
- type ProposalBondMaximum = ProposalBondMaximum;
- type SpendPeriod = SpendPeriod;
- type Burn = Burn;
- type BurnDestination = ();
- type SpendFunds = ();
- type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;
- type MaxApprovals = MaxApprovals;
-}
-
-impl pallet_sudo::Config for Runtime {
- type Event = Event;
- type Call = Call;
-}
-
-pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);
-
-impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider
- for RelayChainBlockNumberProvider<T>
-{
- type BlockNumber = BlockNumber;
-
- fn current_block_number() -> Self::BlockNumber {
- cumulus_pallet_parachain_system::Pallet::<T>::validation_data()
- .map(|d| d.relay_parent_number)
- .unwrap_or_default()
- }
-}
-
-parameter_types! {
- pub const MinVestedTransfer: Balance = 10 * UNIQUE;
- pub const MaxVestingSchedules: u32 = 28;
-}
-
-impl orml_vesting::Config for Runtime {
- type Event = Event;
- type Currency = pallet_balances::Pallet<Runtime>;
- type MinVestedTransfer = MinVestedTransfer;
- type VestedTransferOrigin = EnsureSigned<AccountId>;
- type WeightInfo = ();
- type MaxVestingSchedules = MaxVestingSchedules;
- type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
-}
-
-parameter_types! {
- pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
- pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
-}
-
-impl cumulus_pallet_parachain_system::Config for Runtime {
- type Event = Event;
- type SelfParaId = parachain_info::Pallet<Self>;
- type OnSystemEvent = ();
- // type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<
- // MaxDownwardMessageWeight,
- // XcmExecutor<XcmConfig>,
- // Call,
- // >;
- type OutboundXcmpMessageSource = XcmpQueue;
- type DmpMessageHandler = DmpQueue;
- type ReservedDmpWeight = ReservedDmpWeight;
- type ReservedXcmpWeight = ReservedXcmpWeight;
- type XcmpMessageHandler = XcmpQueue;
-}
-
-impl parachain_info::Config for Runtime {}
-
-impl cumulus_pallet_aura_ext::Config for Runtime {}
-
-parameter_types! {
- pub const RelayLocation: MultiLocation = MultiLocation::parent();
- pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
- pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
- pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
-}
-
-/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
-/// when determining ownership of accounts for asset transacting and when attempting to use XCM
-/// `Transact` in order to determine the dispatch Origin.
-pub type LocationToAccountId = (
- // The parent (Relay-chain) origin converts to the default `AccountId`.
- ParentIsPreset<AccountId>,
- // Sibling parachain origins convert to AccountId via the `ParaId::into`.
- SiblingParachainConvertsVia<Sibling, AccountId>,
- // Straight up local `AccountId32` origins just alias directly to `AccountId`.
- AccountId32Aliases<RelayNetwork, AccountId>,
-);
-
-pub struct OnlySelfCurrency;
-impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {
- fn matches_fungible(a: &MultiAsset) -> Option<B> {
- match (&a.id, &a.fun) {
- (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),
- _ => None,
- }
- }
-}
-
-/// Means for transacting assets on this chain.
-pub type LocalAssetTransactor = CurrencyAdapter<
- // Use this currency:
- Balances,
- // Use this currency when it is a fungible asset matching the given location or name:
- OnlySelfCurrency,
- // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
- LocationToAccountId,
- // Our chain's account ID type (we can't get away without mentioning it explicitly):
- AccountId,
- // We don't track any teleports.
- (),
->;
-
-/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
-/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
-/// biases the kind of local `Origin` it will become.
-pub type XcmOriginToTransactDispatchOrigin = (
- // Sovereign account converter; this attempts to derive an `AccountId` from the origin location
- // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
- // foreign chains who want to have a local sovereign account on this chain which they control.
- SovereignSignedViaLocation<LocationToAccountId, Origin>,
- // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
- // recognised.
- RelayChainAsNative<RelayOrigin, Origin>,
- // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
- // recognised.
- SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,
- // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
- // transaction from the Root origin.
- ParentAsSuperuser<Origin>,
- // Native signed account converter; this just converts an `AccountId32` origin into a normal
- // `Origin::Signed` origin of the same 32-byte value.
- SignedAccountId32AsNative<RelayNetwork, Origin>,
- // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
- XcmPassthrough<Origin>,
-);
-
-parameter_types! {
- // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.
- pub UnitWeightCost: Weight = 1_000_000;
- // 1200 UNIQUEs buy 1 second of weight.
- pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);
- pub const MaxInstructions: u32 = 100;
- pub const MaxAuthorities: u32 = 100_000;
-}
-
-match_types! {
- pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {
- MultiLocation { parents: 1, interior: Here } |
- MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }
- };
-}
-
-pub type Barrier = (
- TakeWeightCredit,
- AllowTopLevelPaidExecutionFrom<Everything>,
- // ^^^ Parent & its unit plurality gets free execution
-);
-
-pub struct UsingOnlySelfCurrencyComponents<
- WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
- AssetId: Get<MultiLocation>,
- AccountId,
- Currency: CurrencyT<AccountId>,
- OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
->(
- Weight,
- Currency::Balance,
- PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,
-);
-impl<
- WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
- AssetId: Get<MultiLocation>,
- AccountId,
- Currency: CurrencyT<AccountId>,
- OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
- > WeightTrader
- for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
-{
- fn new() -> Self {
- Self(0, Zero::zero(), PhantomData)
- }
-
- fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {
- let amount = WeightToFee::weight_to_fee(&weight);
- let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;
-
- // location to this parachain through relay chain
- let option1: xcm::v1::AssetId = Concrete(MultiLocation {
- parents: 1,
- interior: X1(Parachain(ParachainInfo::parachain_id().into())),
- });
- // direct location
- let option2: xcm::v1::AssetId = Concrete(MultiLocation {
- parents: 0,
- interior: Here,
- });
-
- let required = if payment.fungible.contains_key(&option1) {
- (option1, u128_amount).into()
- } else if payment.fungible.contains_key(&option2) {
- (option2, u128_amount).into()
- } else {
- (Concrete(MultiLocation::default()), u128_amount).into()
- };
-
- let unused = payment
- .checked_sub(required)
- .map_err(|_| XcmError::TooExpensive)?;
- self.0 = self.0.saturating_add(weight);
- self.1 = self.1.saturating_add(amount);
- Ok(unused)
- }
-
- fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {
- let weight = weight.min(self.0);
- let amount = WeightToFee::weight_to_fee(&weight);
- self.0 -= weight;
- self.1 = self.1.saturating_sub(amount);
- let amount: u128 = amount.saturated_into();
- if amount > 0 {
- Some((AssetId::get(), amount).into())
- } else {
- None
- }
- }
-}
-impl<
- WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
- AssetId: Get<MultiLocation>,
- AccountId,
- Currency: CurrencyT<AccountId>,
- OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
- > Drop
- for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
-{
- fn drop(&mut self) {
- OnUnbalanced::on_unbalanced(Currency::issue(self.1));
- }
-}
-
-pub struct XcmConfig;
-impl Config for XcmConfig {
- type Call = Call;
- type XcmSender = XcmRouter;
- // How to withdraw and deposit an asset.
- type AssetTransactor = LocalAssetTransactor;
- type OriginConverter = XcmOriginToTransactDispatchOrigin;
- type IsReserve = NativeAsset;
- type IsTeleporter = (); // Teleportation is disabled
- type LocationInverter = LocationInverter<Ancestry>;
- type Barrier = Barrier;
- type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
- type Trader =
- UsingOnlySelfCurrencyComponents<LinearFee<Balance>, RelayLocation, AccountId, Balances, ()>;
- type ResponseHandler = (); // Don't handle responses for now.
- type SubscriptionService = PolkadotXcm;
-
- type AssetTrap = PolkadotXcm;
- type AssetClaims = PolkadotXcm;
-}
-
-// parameter_types! {
-// pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;
-// }
-
-/// No local origins on this chain are allowed to dispatch XCM sends/executions.
-pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);
-
-/// The means for routing XCM messages which are not for local execution into the right message
-/// queues.
-pub type XcmRouter = (
- // Two routers - use UMP to communicate with the relay chain:
- cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,
- // ..and XCMP to communicate with the sibling chains.
- XcmpQueue,
-);
-
-impl pallet_evm_coder_substrate::Config for Runtime {}
-
-impl pallet_xcm::Config for Runtime {
- type Event = Event;
- type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
- type XcmRouter = XcmRouter;
- type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
- type XcmExecuteFilter = Everything;
- type XcmExecutor = XcmExecutor<XcmConfig>;
- type XcmTeleportFilter = Everything;
- type XcmReserveTransferFilter = Everything;
- type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
- type LocationInverter = LocationInverter<Ancestry>;
- type Origin = Origin;
- type Call = Call;
- const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
- type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
-}
-
-impl cumulus_pallet_xcm::Config for Runtime {
- type Event = Event;
- type XcmExecutor = XcmExecutor<XcmConfig>;
-}
-
-impl cumulus_pallet_xcmp_queue::Config for Runtime {
- type WeightInfo = ();
- type Event = Event;
- type XcmExecutor = XcmExecutor<XcmConfig>;
- type ChannelInfo = ParachainSystem;
- type VersionWrapper = ();
- type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
- type ControllerOrigin = EnsureRoot<AccountId>;
- type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
-}
-
-impl cumulus_pallet_dmp_queue::Config for Runtime {
- type Event = Event;
- type XcmExecutor = XcmExecutor<XcmConfig>;
- type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
-}
-
-impl pallet_aura::Config for Runtime {
- type AuthorityId = AuraId;
- type DisabledValidators = ();
- type MaxAuthorities = MaxAuthorities;
-}
-
-parameter_types! {
- pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();
- pub const CollectionCreationPrice: Balance = 2 * UNIQUE;
-}
-
-impl pallet_common::Config for Runtime {
- type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;
- type Event = Event;
- type Currency = Balances;
- type CollectionCreationPrice = CollectionCreationPrice;
- type TreasuryAccountId = TreasuryAccountId;
- type CollectionDispatch = CollectionDispatchT<Self>;
-
- type EvmTokenAddressMapping = EvmTokenAddressMapping;
- type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
- type ContractAddress = EvmCollectionHelpersAddress;
-}
-
-impl pallet_structure::Config for Runtime {
- type Event = Event;
- type Call = Call;
- type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;
-}
-
-impl pallet_fungible::Config for Runtime {
- type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;
-}
-impl pallet_refungible::Config for Runtime {
- type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;
-}
-impl pallet_nonfungible::Config for Runtime {
- type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;
-}
-
-impl pallet_unique::Config for Runtime {
- type Event = Event;
- type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
- type CommonWeightInfo = CommonWeights<Self>;
- type RefungibleExtensionsWeightInfo = CommonWeights<Self>;
-}
-
-parameter_types! {
- pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied
-}
-
-/// Used for the pallet inflation
-impl pallet_inflation::Config for Runtime {
- type Currency = Balances;
- type TreasuryAccountId = TreasuryAccountId;
- type InflationBlockInterval = InflationBlockInterval;
- type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
-}
-
-parameter_types! {
- pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *
- RuntimeBlockWeights::get().max_block;
- pub const MaxScheduledPerBlock: u32 = 50;
-}
-
-type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;
-use frame_support::traits::NamedReservableCurrency;
-
-fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {
- (
- frame_system::CheckSpecVersion::<Runtime>::new(),
- frame_system::CheckGenesis::<Runtime>::new(),
- frame_system::CheckEra::<Runtime>::from(Era::Immortal),
- frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(
- from,
- )),
- frame_system::CheckWeight::<Runtime>::new(),
- // sponsoring transaction logic
- // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
- )
-}
-
-pub struct SchedulerPaymentExecutor;
-impl<T: frame_system::Config + pallet_unique_scheduler::Config, SelfContainedSignedInfo>
- DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor
-where
- <T as frame_system::Config>::Call: Member
- + Dispatchable<Origin = Origin, Info = DispatchInfo>
- + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>
- + GetDispatchInfo
- + From<frame_system::Call<Runtime>>,
- SelfContainedSignedInfo: Send + Sync + 'static,
- Call: From<<T as frame_system::Config>::Call>
- + From<<T as pallet_unique_scheduler::Config>::Call>
- + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,
- sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,
-{
- fn dispatch_call(
- signer: <T as frame_system::Config>::AccountId,
- call: <T as pallet_unique_scheduler::Config>::Call,
- ) -> Result<
- Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,
- TransactionValidityError,
- > {
- let dispatch_info = call.get_dispatch_info();
- let extrinsic = fp_self_contained::CheckedExtrinsic::<
- AccountId,
- Call,
- SignedExtraScheduler,
- SelfContainedSignedInfo,
- > {
- signed:
- CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(
- signer.clone().into(),
- get_signed_extras(signer.into()),
- ),
- function: call.into(),
- };
-
- extrinsic.apply::<Runtime>(&dispatch_info, 0)
- }
-
- fn reserve_balance(
- id: [u8; 16],
- sponsor: <T as frame_system::Config>::AccountId,
- call: <T as pallet_unique_scheduler::Config>::Call,
- count: u32,
- ) -> Result<(), DispatchError> {
- let dispatch_info = call.get_dispatch_info();
- let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)
- .saturating_mul(count.into());
-
- <Balances as NamedReservableCurrency<AccountId>>::reserve_named(
- &id,
- &(sponsor.into()),
- weight,
- )
- }
-
- fn pay_for_call(
- id: [u8; 16],
- sponsor: <T as frame_system::Config>::AccountId,
- call: <T as pallet_unique_scheduler::Config>::Call,
- ) -> Result<u128, DispatchError> {
- let dispatch_info = call.get_dispatch_info();
- let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);
- Ok(
- <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
- &id,
- &(sponsor.into()),
- weight,
- ),
- )
- }
-
- fn cancel_reserve(
- id: [u8; 16],
- sponsor: <T as frame_system::Config>::AccountId,
- ) -> Result<u128, DispatchError> {
- Ok(
- <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
- &id,
- &(sponsor.into()),
- u128::MAX,
- ),
- )
- }
-}
-
-parameter_types! {
- pub const NoPreimagePostponement: Option<u32> = Some(10);
- pub const Preimage: Option<u32> = Some(10);
-}
-
-/// Used the compare the privilege of an origin inside the scheduler.
-pub struct OriginPrivilegeCmp;
-
-impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {
- fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {
- Some(Ordering::Equal)
- }
-}
-
-impl pallet_unique_scheduler::Config for Runtime {
- type Event = Event;
- type Origin = Origin;
- type Currency = Balances;
- type PalletsOrigin = OriginCaller;
- type Call = Call;
- type MaximumWeight = MaximumSchedulerWeight;
- type ScheduleOrigin = EnsureSigned<AccountId>;
- type MaxScheduledPerBlock = MaxScheduledPerBlock;
- type WeightInfo = ();
- type CallExecutor = SchedulerPaymentExecutor;
- type OriginPrivilegeCmp = OriginPrivilegeCmp;
- type PreimageProvider = ();
- type NoPreimagePostponement = NoPreimagePostponement;
-}
-
-type EvmSponsorshipHandler = (
- UniqueEthSponsorshipHandler<Runtime>,
- pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,
-);
-type SponsorshipHandler = (
- UniqueSponsorshipHandler<Runtime>,
- //pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,
- pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,
-);
-
-impl pallet_evm_transaction_payment::Config for Runtime {
- type EvmSponsorshipHandler = EvmSponsorshipHandler;
- type Currency = Balances;
-}
-
-impl pallet_charge_transaction::Config for Runtime {
- type SponsorshipHandler = SponsorshipHandler;
-}
-
-// impl pallet_contract_helpers::Config for Runtime {
-// type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
-// }
-
-parameter_types! {
- // 0x842899ECF380553E8a4de75bF534cdf6fBF64049
- pub const HelpersContractAddress: H160 = H160([
- 0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,
- ]);
-
- // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f
- pub const EvmCollectionHelpersAddress: H160 = H160([
- 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,
- ]);
-}
-
-impl pallet_evm_contract_helpers::Config for Runtime {
- type ContractAddress = HelpersContractAddress;
- type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
-}
-
-construct_runtime!(
- pub enum Runtime where
- Block = Block,
- NodeBlock = opaque::Block,
- UncheckedExtrinsic = UncheckedExtrinsic
- {
- ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,
- ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,
-
- Aura: pallet_aura::{Pallet, Config<T>} = 22,
- AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,
-
- Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,
- RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,
- Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,
- TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,
- Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,
- Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,
- System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,
- Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,
- // Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,
- // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,
-
- // XCM helpers.
- XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
- PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
- CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,
- DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
-
- // Unique Pallets
- Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,
- Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,
- Scheduler: pallet_unique_scheduler::{Pallet, Call, Storage, Event<T>} = 62,
- // free = 63
- Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,
- // ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,
- Common: pallet_common::{Pallet, Storage, Event<T>} = 66,
- Fungible: pallet_fungible::{Pallet, Storage} = 67,
- Refungible: pallet_refungible::{Pallet, Storage} = 68,
- Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,
- Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,
-
- // Frontier
- EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,
- Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,
-
- EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,
- EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,
- EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,
- EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,
- }
-);
-
-pub struct TransactionConverter;
-
-impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {
- fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {
- UncheckedExtrinsic::new_unsigned(
- pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
- )
- }
-}
-
-impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {
- fn convert_transaction(
- &self,
- transaction: pallet_ethereum::Transaction,
- ) -> opaque::UncheckedExtrinsic {
- let extrinsic = UncheckedExtrinsic::new_unsigned(
- pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
- );
- let encoded = extrinsic.encode();
- opaque::UncheckedExtrinsic::decode(&mut &encoded[..])
- .expect("Encoded extrinsic is always valid")
- }
-}
-
-/// The address format for describing accounts.
-pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
-/// Block header type as expected by this runtime.
-pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
-/// Block type as expected by this runtime.
-pub type Block = generic::Block<Header, UncheckedExtrinsic>;
-/// A Block signed with a Justification
-pub type SignedBlock = generic::SignedBlock<Block>;
-/// BlockId type as expected by this runtime.
-pub type BlockId = generic::BlockId<Block>;
-/// The SignedExtension to the basic transaction logic.
-pub type SignedExtra = (
- frame_system::CheckSpecVersion<Runtime>,
- // system::CheckTxVersion<Runtime>,
- frame_system::CheckGenesis<Runtime>,
- frame_system::CheckEra<Runtime>,
- frame_system::CheckNonce<Runtime>,
- frame_system::CheckWeight<Runtime>,
- pallet_charge_transaction::ChargeTransactionPayment<Runtime>,
- //pallet_contract_helpers::ContractHelpersExtension<Runtime>,
- pallet_ethereum::FakeTransactionFinalizer<Runtime>,
-);
-pub type SignedExtraScheduler = (
- frame_system::CheckSpecVersion<Runtime>,
- frame_system::CheckGenesis<Runtime>,
- frame_system::CheckEra<Runtime>,
- frame_system::CheckNonce<Runtime>,
- frame_system::CheckWeight<Runtime>,
- // pallet_charge_transaction::ChargeTransactionPayment<Runtime>,
-);
-/// Unchecked extrinsic type as expected by this runtime.
-pub type UncheckedExtrinsic =
- fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
-/// Extrinsic type that has already been checked.
-pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;
-/// Executive: handles dispatch to the various modules.
-pub type Executive = frame_executive::Executive<
- Runtime,
- Block,
- frame_system::ChainContext<Runtime>,
- Runtime,
- AllPalletsReversedWithSystemFirst,
->;
-
-impl_opaque_keys! {
- pub struct SessionKeys {
- pub aura: Aura,
- }
-}
-
-impl fp_self_contained::SelfContainedCall for Call {
- type SignedInfo = H160;
-
- fn is_self_contained(&self) -> bool {
- match self {
- Call::Ethereum(call) => call.is_self_contained(),
- _ => false,
- }
- }
-
- fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
- match self {
- Call::Ethereum(call) => call.check_self_contained(),
- _ => None,
- }
- }
-
- fn validate_self_contained(
- &self,
- info: &Self::SignedInfo,
- dispatch_info: &DispatchInfoOf<Call>,
- len: usize,
- ) -> Option<TransactionValidity> {
- match self {
- Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),
- _ => None,
- }
- }
-
- fn pre_dispatch_self_contained(
- &self,
- info: &Self::SignedInfo,
- ) -> Option<Result<(), TransactionValidityError>> {
- match self {
- Call::Ethereum(call) => call.pre_dispatch_self_contained(info),
- _ => None,
- }
- }
-
- fn apply_self_contained(
- self,
- info: Self::SignedInfo,
- ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {
- match self {
- call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(
- Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),
- )),
- _ => None,
- }
- }
-}
-
-macro_rules! dispatch_unique_runtime {
- ($collection:ident.$method:ident($($name:ident),*)) => {{
- let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);
- let dispatch = collection.as_dyn();
-
- Ok::<_, DispatchError>(dispatch.$method($($name),*))
- }};
-}
-
-impl_common_runtime_apis! {
- #![custom_apis]
-
- impl rmrk_rpc::RmrkApi<
- Block,
- AccountId,
- RmrkCollectionInfo<AccountId>,
- RmrkInstanceInfo<AccountId>,
- RmrkResourceInfo,
- RmrkPropertyInfo,
- RmrkBaseInfo<AccountId>,
- RmrkPartType,
- RmrkTheme
- > for Runtime {
- fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {
- Ok(Default::default())
- }
-
- fn collection_by_id(_collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {
- Ok(Default::default())
- }
-
- fn nft_by_id(_collection_id: RmrkCollectionId, _nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {
- Ok(Default::default())
- }
-
- fn account_tokens(_account_id: AccountId, _collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {
- Ok(Default::default())
- }
-
- fn nft_children(_collection_id: RmrkCollectionId, _nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {
- Ok(Default::default())
- }
-
- fn collection_properties(_collection_id: RmrkCollectionId, _filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
- Ok(Default::default())
- }
-
- fn nft_properties(_collection_id: RmrkCollectionId, _nft_id: RmrkNftId, _filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
- Ok(Default::default())
- }
-
- fn nft_resources(_collection_id: RmrkCollectionId, _nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
- Ok(Default::default())
- }
-
- fn nft_resource_priority(_collection_id: RmrkCollectionId, _nft_id: RmrkNftId, _resource_id: RmrkResourceId) -> Result<Option<u32>, DispatchError> {
- Ok(Default::default())
- }
-
- fn base(_base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {
- Ok(Default::default())
- }
-
- fn base_parts(_base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {
- Ok(Default::default())
- }
-
- fn theme_names(_base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {
- Ok(Default::default())
- }
-
- fn theme(_base_id: RmrkBaseId, _theme_name: RmrkThemeName, _filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {
- Ok(Default::default())
- }
- }
-}
-
-struct CheckInherents;
-
-impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
- fn check_inherents(
- block: &Block,
- relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
- ) -> sp_inherents::CheckInherentsResult {
- let relay_chain_slot = relay_state_proof
- .read_slot()
- .expect("Could not read the relay chain slot from the proof");
-
- let inherent_data =
- cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
- relay_chain_slot,
- sp_std::time::Duration::from_secs(6),
- )
- .create_inherent_data()
- .expect("Could not create the timestamp inherent data");
-
- inherent_data.check_extrinsics(block)
- }
-}
+impl_common_runtime_apis!();
cumulus_pallet_parachain_system::register_validate_block!(
Runtime = Runtime,
tests/.eslintrc.jsondiffbeforeafterboth--- a/tests/.eslintrc.json
+++ b/tests/.eslintrc.json
@@ -55,7 +55,13 @@
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-explicit-any": "off",
- "@typescript-eslint/no-unused-vars": "warn",
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
+ {
+ "varsIgnorePattern": "_.+",
+ "argsIgnorePattern": "_.+"
+ }
+ ],
"no-async-promise-executor": "warn",
"@typescript-eslint/no-empty-interface": "off",
"prefer-const": [
tests/CHANGELOG.mddiffbeforeafterboth--- a/tests/CHANGELOG.md
+++ b/tests/CHANGELOG.md
@@ -2,10 +2,15 @@
All notable changes to this project will be documented in this file.
+## 2022-08-12
+
+### Added
+
+- In integration tests for `RFT` added check of work with the maximum allowable number of pieces (MAX_REFUNGIBLE_PIECES).
+
## 2022-07-14
### Added
- - Integrintegration tests of RPC method `token_owners`.
- - Integrintegration tests of Fungible Pallet.
-
-
\ No newline at end of file
+
+- Integrintegration tests of RPC method `token_owners`.
+- Integrintegration tests of Fungible Pallet.
tests/package.jsondiffbeforeafterboth--- a/tests/package.json
+++ b/tests/package.json
@@ -8,6 +8,7 @@
"@polkadot/typegen": "8.7.2-15",
"@types/chai": "^4.3.1",
"@types/chai-as-promised": "^7.1.5",
+ "@types/chai-like": "^1.1.1",
"@types/mocha": "^9.1.1",
"@types/node": "^17.0.35",
"@typescript-eslint/eslint-plugin": "^5.26.0",
@@ -96,6 +97,7 @@
"@polkadot/util-crypto": "9.4.1",
"bignumber.js": "^9.0.2",
"chai-as-promised": "^7.1.1",
+ "chai-like": "^1.1.1",
"find-process": "^1.4.7",
"solc": "0.8.14-fixed",
"web3": "^1.7.3"
tests/src/approve.test.tsdiffbeforeafterboth--- a/tests/src/approve.test.ts
+++ b/tests/src/approve.test.ts
@@ -32,6 +32,8 @@
getCreatedCollectionCount,
transferFromExpectSuccess,
transferFromExpectFail,
+ requirePallets,
+ Pallets,
} from './util/helpers';
chai.use(chaiAsPromised);
@@ -49,34 +51,44 @@
});
});
- it('Execute the extrinsic and check approvedList', async () => {
+ it('[nft] Execute the extrinsic and check approvedList', async () => {
const nftCollectionId = await createCollectionExpectSuccess();
- // nft
const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
- // fungible
+ });
+
+ it('[fungible] Execute the extrinsic and check approvedList', async () => {
const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
- // reFungible
+ });
+
+ it('[refungible] Execute the extrinsic and check approvedList', 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);
});
- it('Remove approval by using 0 amount', async () => {
+ it('[nft] Remove approval by using 0 amount', async () => {
const nftCollectionId = await createCollectionExpectSuccess();
- // nft
const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 1);
await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 0);
- // fungible
+ });
+
+ it('[fungible] Remove approval by using 0 amount', async () => {
const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 1);
await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 0);
- // reFungible
+ });
+
+ it('[refungible] Remove approval by using 0 amount', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const reFungibleCollectionId =
await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
@@ -117,7 +129,9 @@
await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
});
- it('ReFungible up to an approved amount', async () => {
+ it('ReFungible up to an approved amount', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);
await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
@@ -151,7 +165,9 @@
await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'Fungible');
});
- it('ReFungible up to an approved amount', async () => {
+ it('ReFungible up to an approved amount', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);
await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
@@ -188,7 +204,9 @@
await transferFromExpectFail(collectionId, itemId, charlie, bob, alice, 1);
});
- it('ReFungible up to an approved amount', async () => {
+ it('ReFungible up to an approved amount', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);
await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
@@ -250,7 +268,9 @@
await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, bob, charlie, 1);
});
- it('ReFungible', async () => {
+ it('ReFungible', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const reFungibleCollectionId =
await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
@@ -285,7 +305,9 @@
await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, charlie, 11);
});
- it('ReFungible', async () => {
+ it('ReFungible', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, charlie, 101);
@@ -325,7 +347,9 @@
await transferFromExpectSuccess(collectionId, itemId, bob, dave, alice, 1, 'Fungible');
});
- it('ReFungible up to an approved amount', async () => {
+ it('ReFungible up to an approved amount', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', charlie.address);
@@ -422,63 +446,87 @@
});
});
- it('Approve for a collection that does not exist', async () => {
+ it('[nft] Approve for a collection that does not exist', async () => {
await usingApi(async (api: ApiPromise) => {
- // nft
const nftCollectionCount = await getCreatedCollectionCount(api);
await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);
- // fungible
+ });
+ });
+
+ it('[fungible] Approve 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);
- // reFungible
+ });
+ });
+
+ it('[refungible] Approve for a collection that does not exist', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
+ await usingApi(async (api: ApiPromise) => {
const reFungibleCollectionCount = await getCreatedCollectionCount(api);
await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);
});
});
- it('Approve for a collection that was destroyed', async () => {
- // nft
+ it('[nft] Approve for a collection that was destroyed', async () => {
const nftCollectionId = await createCollectionExpectSuccess();
await destroyCollectionExpectSuccess(nftCollectionId);
await approveExpectFail(nftCollectionId, 1, alice, bob);
- // fungible
+ });
+
+ it('Approve for a collection that was destroyed', async () => {
const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
await destroyCollectionExpectSuccess(fungibleCollectionId);
await approveExpectFail(fungibleCollectionId, 0, alice, bob);
- // reFungible
+ });
+
+ it('[refungible] Approve for a collection that was destroyed', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const reFungibleCollectionId =
await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await destroyCollectionExpectSuccess(reFungibleCollectionId);
await approveExpectFail(reFungibleCollectionId, 1, alice, bob);
});
- it('Approve transfer of a token that does not exist', async () => {
- // nft
+ it('[nft] Approve transfer of a token that does not exist', async () => {
const nftCollectionId = await createCollectionExpectSuccess();
await approveExpectFail(nftCollectionId, 2, alice, bob);
- // reFungible
+ });
+
+ it('[refungible] Approve transfer of a token that does not exist', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const reFungibleCollectionId =
await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await approveExpectFail(reFungibleCollectionId, 2, alice, bob);
});
- it('Approve using the address that does not own the approved token', async () => {
+ it('[nft] Approve using the address that does not own the approved token', async () => {
const nftCollectionId = await createCollectionExpectSuccess();
- // nft
const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
await approveExpectFail(nftCollectionId, newNftTokenId, bob, alice);
- // fungible
+ });
+
+ it('[fungible] Approve using the address that does not own the approved token', async () => {
const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice);
- // reFungible
+ });
+
+ it('[refungible] Approve using the address that does not own the approved token', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const reFungibleCollectionId =
await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, alice);
});
- it('should fail if approved more ReFungibles than owned', async () => {
+ it('should fail if approved more ReFungibles than owned', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const nftCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'ReFungible');
await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 100, 'ReFungible');
tests/src/burnItem.test.tsdiffbeforeafterboth--- a/tests/src/burnItem.test.ts
+++ b/tests/src/burnItem.test.ts
@@ -25,6 +25,8 @@
getBalance,
setCollectionLimitsExpectSuccess,
isTokenExists,
+ requirePallets,
+ Pallets,
} from './util/helpers';
import chai from 'chai';
@@ -80,7 +82,9 @@
});
});
- it('Burn item in ReFungible collection', async () => {
+ it('Burn item in ReFungible collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const createMode = 'ReFungible';
const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
@@ -99,7 +103,9 @@
});
});
- it('Burn owned portion of item in ReFungible collection', async () => {
+ it('Burn owned portion of item in ReFungible collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const createMode = 'ReFungible';
const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
@@ -189,7 +195,9 @@
});
// TODO: burnFrom
- it('Burn item in ReFungible collection', async () => {
+ it('Burn item in ReFungible collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const createMode = 'ReFungible';
const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
tests/src/calibrate.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/calibrate.ts
@@ -0,0 +1,182 @@
+import {ApiPromise} from '@polkadot/api';
+import {IKeyringPair} from '@polkadot/types/types';
+import Web3 from 'web3';
+import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, recordEthFee, usingWeb3} from './eth/util/helpers';
+import usingApi, {executeTransaction} from './substrate/substrate-api';
+import {createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, UNIQUE, waitNewBlocks} from './util/helpers';
+import nonFungibleAbi from './eth/nonFungibleAbi.json';
+
+function linearRegression(points: { x: bigint, y: bigint }[]) {
+ let sumxy = 0n;
+ let sumx = 0n;
+ let sumy = 0n;
+ let sumx2 = 0n;
+ const n = points.length;
+ for (let i = 0; i < n; i++) {
+ const p = points[i];
+ sumxy += p.x * p.y;
+ sumx += p.x;
+ sumy += p.y;
+ sumx2 += p.x * p.x;
+ }
+
+ const nb = BigInt(n);
+
+ const a = (nb * sumxy - sumx * sumy) / (nb * sumx2 - sumx * sumx);
+ const b = (sumy - a * sumx) / nb;
+
+ return {a, b};
+}
+
+// JS has no builtin function to calculate sqrt of bigint
+// https://stackoverflow.com/a/53684036/6190169
+function sqrt(value: bigint) {
+ if (value < 0n) {
+ throw 'square root of negative numbers is not supported';
+ }
+
+ if (value < 2n) {
+ return value;
+ }
+
+ function newtonIteration(n: bigint, x0: bigint): bigint {
+ const x1 = ((n / x0) + x0) >> 1n;
+ if (x0 === x1 || x0 === (x1 - 1n)) {
+ return x0;
+ }
+ return newtonIteration(n, x1);
+ }
+
+ return newtonIteration(value, 1n);
+}
+
+function _error(points: { x: bigint, y: bigint }[], hypothesis: (a: bigint) => bigint) {
+ return sqrt(points.map(p => {
+ const v = hypothesis(p.x);
+ const vv = p.y;
+
+ return (v - vv) ** 2n;
+ }).reduce((a, b) => a + b, 0n) / BigInt(points.length));
+}
+
+async function calibrateWeightToFee(api: ApiPromise, privateKey: (account: string) => IKeyringPair) {
+ const alice = privateKey('//Alice');
+ const bob = privateKey('//Bob');
+ const dataPoints = [];
+
+ {
+ const collectionId = await createCollectionExpectSuccess();
+ const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');
+ const aliceBalanceBefore = (await api.query.system.account(alice.address)).data.free.toBigInt();
+ await transferExpectSuccess(collectionId, tokenId, alice, bob, 1, 'NFT');
+ const aliceBalanceAfter = (await api.query.system.account(alice.address)).data.free.toBigInt();
+
+ console.log(`Original price: ${Number(aliceBalanceBefore - aliceBalanceAfter) / Number(UNIQUE)} UNQ`);
+ }
+
+ const defaultCoeff = (api.consts.configuration.defaultWeightToFeeCoefficient as any).toBigInt();
+ for (let i = -5; i < 5; i++) {
+ await executeTransaction(api, alice, api.tx.sudo.sudo(api.tx.configuration.setWeightToFeeCoefficientOverride(defaultCoeff + defaultCoeff / 1000n * BigInt(i))));
+
+ const coefficient = (await api.query.configuration.weightToFeeCoefficientOverride() as any).toBigInt();
+ const collectionId = await createCollectionExpectSuccess();
+ const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');
+
+ const aliceBalanceBefore = (await api.query.system.account(alice.address)).data.free.toBigInt();
+ await transferExpectSuccess(collectionId, tokenId, alice, bob, 1, 'NFT');
+ const aliceBalanceAfter = (await api.query.system.account(alice.address)).data.free.toBigInt();
+
+ const transferPrice = aliceBalanceBefore - aliceBalanceAfter;
+
+ dataPoints.push({x: transferPrice, y: coefficient});
+ }
+ const {a, b} = linearRegression(dataPoints);
+
+ // console.log(`Error: ${error(dataPoints, x => a*x+b)}`);
+
+ const perfectValue = a * UNIQUE / 10n + b;
+ await executeTransaction(api, alice, api.tx.sudo.sudo(api.tx.configuration.setWeightToFeeCoefficientOverride(perfectValue.toString())));
+
+ {
+ const collectionId = await createCollectionExpectSuccess();
+ const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');
+ const aliceBalanceBefore = (await api.query.system.account(alice.address)).data.free.toBigInt();
+ await transferExpectSuccess(collectionId, tokenId, alice, bob, 1, 'NFT');
+ const aliceBalanceAfter = (await api.query.system.account(alice.address)).data.free.toBigInt();
+
+ console.log(`Calibrated price: ${Number(aliceBalanceBefore - aliceBalanceAfter) / Number(UNIQUE)} UNQ`);
+ }
+}
+
+async function calibrateMinGasPrice(api: ApiPromise, web3: Web3, privateKey: (account: string) => IKeyringPair) {
+ const alice = privateKey('//Alice');
+ const caller = await createEthAccountWithBalance(api, web3, privateKey);
+ const receiver = createEthAccount(web3);
+ const dataPoints = [];
+
+ {
+ const collectionId = await createCollectionExpectSuccess();
+ const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', {Ethereum: caller});
+
+ const address = collectionIdToAddress(collectionId);
+ const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+
+ const cost = await recordEthFee(api, caller, () => contract.methods.transfer(receiver, tokenId).send(caller));
+
+ console.log(`Original price: ${Number(cost) / Number(UNIQUE)} UNQ`);
+ }
+
+ const defaultCoeff = (api.consts.configuration.defaultMinGasPrice as any).toBigInt();
+ for (let i = -8; i < 8; i++) {
+ const gasPrice = defaultCoeff + defaultCoeff / 100000n * BigInt(i);
+ const gasPriceStr = '0x' + gasPrice.toString(16);
+ await executeTransaction(api, alice, api.tx.sudo.sudo(api.tx.configuration.setMinGasPriceOverride(gasPrice)));
+
+ const coefficient = (await api.query.configuration.minGasPriceOverride() as any).toBigInt();
+ const collectionId = await createCollectionExpectSuccess();
+ const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', {Ethereum: caller});
+
+ const address = collectionIdToAddress(collectionId);
+ const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, gasPrice: gasPriceStr, ...GAS_ARGS});
+
+ const transferPrice = await recordEthFee(api, caller, () => contract.methods.transfer(receiver, tokenId).send(caller));
+
+ dataPoints.push({x: transferPrice, y: coefficient});
+ }
+
+ const {a, b} = linearRegression(dataPoints);
+
+ // console.log(`Error: ${error(dataPoints, x => a*x+b)}`);
+
+ // * 0.15 = * 10000 / 66666
+ const perfectValue = a * UNIQUE * 1000000n / 6666666n + b;
+ await executeTransaction(api, alice, api.tx.sudo.sudo(api.tx.configuration.setMinGasPriceOverride(perfectValue.toString())));
+
+ {
+ const collectionId = await createCollectionExpectSuccess();
+ const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', {Ethereum: caller});
+
+ const address = collectionIdToAddress(collectionId);
+ const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+
+ const cost = await recordEthFee(api, caller, () => contract.methods.transfer(receiver, tokenId).send(caller));
+
+ console.log(`Calibrated price: ${Number(cost) / Number(UNIQUE)} UNQ`);
+ }
+}
+
+(async () => {
+ await usingApi(async (api, privateKey) => {
+ // Second run slightly reduces error sometimes, as price line is not actually straight, this is a curve
+
+ await calibrateWeightToFee(api, privateKey);
+ await calibrateWeightToFee(api, privateKey);
+
+ await usingWeb3(async web3 => {
+ await calibrateMinGasPrice(api, web3, privateKey);
+ await calibrateMinGasPrice(api, web3, privateKey);
+ });
+
+ await api.disconnect();
+ });
+})();
tests/src/calibrateApply.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/calibrateApply.ts
@@ -0,0 +1,38 @@
+import {readFile, writeFile} from 'fs/promises';
+import path from 'path';
+import usingApi from './substrate/substrate-api';
+
+const formatNumber = (num: string): string => num.split('').reverse().join('').replace(/([0-9]{3})/g, '$1_').split('').reverse().join('').replace(/^_/, '');
+
+(async () => {
+ let weightToFeeCoefficientOverride: string;
+ let minGasPriceOverride: string;
+ await usingApi(async (api, _privateKey) => {
+ weightToFeeCoefficientOverride = (await api.query.configuration.weightToFeeCoefficientOverride() as any).toBigInt().toString();
+ minGasPriceOverride = (await api.query.configuration.minGasPriceOverride() as any).toBigInt().toString();
+ });
+ const constantsFile = path.resolve(__dirname, '../../primitives/common/src/constants.rs');
+ let constants = (await readFile(constantsFile)).toString();
+
+ let weight2feeFound = false;
+ constants = constants.replace(/(\/\*<weight2fee>\*\/)[0-9_]+(\/\*<\/weight2fee>\*\/)/, (_f, p, s) => {
+ weight2feeFound = true;
+ return p+formatNumber(weightToFeeCoefficientOverride)+s;
+ });
+ if (!weight2feeFound) {
+ throw new Error('failed to find weight2fee marker in source code');
+ }
+
+ let minGasPriceFound = false;
+ constants = constants.replace(/(\/\*<mingasprice>\*\/)[0-9_]+(\/\*<\/mingasprice>\*\/)/, (_f, p, s) => {
+ minGasPriceFound = true;
+ return p+formatNumber(minGasPriceOverride)+s;
+ });
+ if (!minGasPriceFound) {
+ throw new Error('failed to find mingasprice marker in source code');
+ }
+
+ await writeFile(constantsFile, constants);
+})().catch(e => {
+ console.log(e.stack);
+});
tests/src/confirmSponsorship.test.tsdiffbeforeafterboth--- a/tests/src/confirmSponsorship.test.ts
+++ b/tests/src/confirmSponsorship.test.ts
@@ -33,6 +33,8 @@
addCollectionAdminExpectSuccess,
getCreatedCollectionCount,
UNIQUE,
+ requirePallets,
+ Pallets,
} from './util/helpers';
import {IKeyringPair} from '@polkadot/types/types';
@@ -124,7 +126,9 @@
});
});
- it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async () => {
+ it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
@@ -252,7 +256,9 @@
});
});
- it('ReFungible: Sponsoring is rate limited', async () => {
+ it('ReFungible: Sponsoring is rate limited', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
await confirmSponsorshipExpectSuccess(collectionId, '//Bob');
tests/src/createCollection.test.tsdiffbeforeafterboth--- a/tests/src/createCollection.test.ts
+++ b/tests/src/createCollection.test.ts
@@ -16,7 +16,7 @@
import {expect} from 'chai';
import usingApi, {executeTransaction, submitTransactionAsync} from './substrate/substrate-api';
-import {createCollectionWithPropsExpectFailure, createCollectionExpectFailure, createCollectionExpectSuccess, getCreateCollectionResult, getDetailedCollectionInfo, createCollectionWithPropsExpectSuccess} from './util/helpers';
+import {createCollectionWithPropsExpectFailure, createCollectionExpectFailure, createCollectionExpectSuccess, getCreateCollectionResult, getDetailedCollectionInfo, createCollectionWithPropsExpectSuccess, requirePallets, Pallets} from './util/helpers';
describe('integration test: ext. createCollection():', () => {
it('Create new NFT collection', async () => {
@@ -34,7 +34,9 @@
it('Create new Fungible collection', async () => {
await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
});
- it('Create new ReFungible collection', async () => {
+ it('Create new ReFungible collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
});
tests/src/createItem.test.tsdiffbeforeafterboth--- a/tests/src/createItem.test.ts
+++ b/tests/src/createItem.test.ts
@@ -29,6 +29,8 @@
itApi,
normalizeAccountId,
getCreateItemResult,
+ requirePallets,
+ Pallets,
} from './util/helpers';
const expect = chai.expect;
@@ -79,7 +81,9 @@
}
});
- it('Create new item in ReFungible collection', async () => {
+ it('Create new item in ReFungible collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const createMode = 'ReFungible';
const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
await createItemExpectSuccess(alice, newCollectionID, createMode);
@@ -96,7 +100,9 @@
await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);
await createItemExpectSuccess(bob, newCollectionID, createMode);
});
- it('Create new item in ReFungible collection with collection admin permissions', async () => {
+ it('Create new item in ReFungible collection with collection admin permissions', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const createMode = 'ReFungible';
const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);
@@ -175,7 +181,9 @@
});
});
- it('Check total pieces of ReFungible token', async () => {
+ it('Check total pieces of ReFungible token', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async api => {
const createMode = 'ReFungible';
const createCollectionResult = await createCollection(api, alice, {mode: {type: createMode}});
@@ -219,7 +227,9 @@
const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});
await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;
});
- it('Regular user cannot create new item in ReFungible collection', async () => {
+ it('Regular user cannot create new item in ReFungible collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const createMode = 'ReFungible';
const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;
@@ -296,7 +306,9 @@
});
});
- it('Check total pieces for invalid Refungible token', async () => {
+ it('Check total pieces for invalid Refungible token', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async api => {
const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});
const collectionId = createCollectionResult.collectionId;
tests/src/createMultipleItems.test.tsdiffbeforeafterboth--- a/tests/src/createMultipleItems.test.ts
+++ b/tests/src/createMultipleItems.test.ts
@@ -33,6 +33,9 @@
createCollectionWithPropsExpectSuccess,
createMultipleItemsWithPropsExpectSuccess,
getTokenProperties,
+ requirePallets,
+ Pallets,
+ checkPalletsPresence,
} from './util/helpers';
chai.use(chaiAsPromised);
@@ -91,7 +94,9 @@
});
});
- it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {
+ it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async (api, privateKeyWrapper) => {
const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const itemsListIndexBefore = await getLastTokenId(api, collectionId);
@@ -272,7 +277,9 @@
});
});
- it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {
+ it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async (api: ApiPromise) => {
const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const itemsListIndexBefore = await getLastTokenId(api, collectionId);
@@ -335,7 +342,9 @@
});
});
- it('Regular user cannot create items in active ReFungible collection', async () => {
+ it('Regular user cannot create items in active ReFungible collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async (api: ApiPromise) => {
const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const itemsListIndexBefore = await getLastTokenId(api, collectionId);
@@ -358,9 +367,8 @@
});
});
- it('Create NFT and Re-fungible tokens that has reached the maximum data limit', async () => {
+ it('Create NFTs that has reached the maximum data limit', async function() {
await usingApi(async (api, privateKeyWrapper) => {
- // NFT
const collectionId = await createCollectionWithPropsExpectSuccess({
propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],
});
@@ -372,8 +380,13 @@
];
const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
+ });
+ });
- // ReFungible
+ it('Create Refungible tokens that has reached the maximum data limit', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
+ await usingApi(async api => {
const collectionIdReFungible =
await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
{
@@ -402,8 +415,15 @@
it('Create tokens with different types', async () => {
await usingApi(async (api: ApiPromise) => {
const collectionId = await createCollectionExpectSuccess();
+
+ const types = ['NFT', 'Fungible'];
+
+ if (await checkPalletsPresence([Pallets.ReFungible])) {
+ types.push('ReFungible');
+ }
+
const createMultipleItemsTx = api.tx.unique
- .createMultipleItems(collectionId, normalizeAccountId(alice.address), ['NFT', 'Fungible', 'ReFungible']);
+ .createMultipleItems(collectionId, normalizeAccountId(alice.address), types);
await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/nonfungible\.NotNonfungibleDataUsedToMintFungibleCollectionToken/);
// garbage collection :-D // lol
await destroyCollectionExpectSuccess(collectionId);
tests/src/createMultipleItemsEx.test.tsdiffbeforeafterboth--- a/tests/src/createMultipleItemsEx.test.ts
+++ b/tests/src/createMultipleItemsEx.test.ts
@@ -16,9 +16,9 @@
import {expect} from 'chai';
import usingApi, {executeTransaction} from './substrate/substrate-api';
-import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess, createCollectionWithPropsExpectSuccess, getBalance, getLastTokenId, getTokenProperties} from './util/helpers';
+import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess, createCollectionWithPropsExpectSuccess, getBalance, getLastTokenId, getTokenProperties, requirePallets, Pallets} from './util/helpers';
-describe.only('Integration Test: createMultipleItemsEx', () => {
+describe('Integration Test: createMultipleItemsEx', () => {
it('can initialize multiple NFT with different owners', async () => {
const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await usingApi(async (api, privateKeyWrapper) => {
@@ -146,7 +146,9 @@
});
});
- it('can initialize an RFT with multiple owners', async () => {
+ it('can initialize an RFT with multiple owners', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async (api, privateKeyWrapper) => {
const alice = privateKeyWrapper('//Alice');
const bob = privateKeyWrapper('//Bob');
@@ -178,7 +180,9 @@
});
});
- it('can initialize multiple RFTs with the same owner', async () => {
+ it('can initialize multiple RFTs with the same owner', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async (api, privateKeyWrapper) => {
const alice = privateKeyWrapper('//Alice');
const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
@@ -386,27 +390,6 @@
const tokens = await api.query.nonfungible.tokenData.entries(collection);
const json = tokens.map(([, token]) => token.toJSON());
expect(json).to.be.deep.equal(data);
- });
- });
-
- it('fails when trying to set multiple owners when creating multiple refungibles', async () => {
- const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
-
- await usingApi(async (api, privateKeyWrapper) => {
- const alice = privateKeyWrapper('//Alice');
- const bob = privateKeyWrapper('//Bob');
- // Polkadot requires map, and yet requires keys to be JSON encoded
- const users = new Map();
- users.set(JSON.stringify({substrate: alice.address}), 1);
- users.set(JSON.stringify({substrate: bob.address}), 1);
-
- // TODO: better error message?
- await expect(executeTransaction(api, alice, api.tx.unique.createMultipleItemsEx(collection, {
- RefungibleMultipleItems: [
- {users},
- {users},
- ],
- }))).to.be.rejectedWith(/^refungible\.NotRefungibleDataUsedToMintFungibleCollectionToken$/);
});
});
});
tests/src/destroyCollection.test.tsdiffbeforeafterboth--- a/tests/src/destroyCollection.test.ts
+++ b/tests/src/destroyCollection.test.ts
@@ -25,6 +25,8 @@
addCollectionAdminExpectSuccess,
getCreatedCollectionCount,
createItemExpectSuccess,
+ requirePallets,
+ Pallets,
} from './util/helpers';
chai.use(chaiAsPromised);
@@ -38,7 +40,9 @@
const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
await destroyCollectionExpectSuccess(collectionId);
});
- it('ReFungible collection can be destroyed', async () => {
+ it('ReFungible collection can be destroyed', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await destroyCollectionExpectSuccess(collectionId);
});
tests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth--- a/tests/src/eth/api/CollectionHelpers.sol
+++ b/tests/src/eth/api/CollectionHelpers.sol
@@ -48,7 +48,7 @@
string memory name,
string memory description,
string memory tokenPrefix
- ) external view returns (address);
+ ) external returns (address);
// Selector: createERC721MetadataCompatibleRFTCollection(string,string,string,string) a5596388
function createERC721MetadataCompatibleRFTCollection(
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -22,13 +22,7 @@
);
}
-// Selector: 79cc6790
-interface ERC20UniqueExtensions is Dummy, ERC165 {
- // Selector: burnFrom(address,uint256) 79cc6790
- function burnFrom(address from, uint256 amount) external returns (bool);
-}
-
-// Selector: 7d9262e6
+// Selector: 6cf113cd
interface Collection is Dummy, ERC165 {
// Set collection property.
//
@@ -174,6 +168,27 @@
//
// Selector: setCollectionMintMode(bool) 00018e84
function setCollectionMintMode(bool mode) external;
+
+ // Check that account is the owner or admin of the collection
+ //
+ // @param user account to verify
+ // @return "true" if account is the owner or admin
+ //
+ // Selector: verifyOwnerOrAdmin(address) c2282493
+ function verifyOwnerOrAdmin(address user) external view returns (bool);
+
+ // Returns collection type
+ //
+ // @return `Fungible` or `NFT` or `ReFungible`
+ //
+ // Selector: uniqueCollectionType() d34b55b8
+ function uniqueCollectionType() external returns (string memory);
+}
+
+// Selector: 79cc6790
+interface ERC20UniqueExtensions is Dummy, ERC165 {
+ // Selector: burnFrom(address,uint256) 79cc6790
+ function burnFrom(address from, uint256 amount) external returns (bool);
}
// Selector: 942e8b22
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -250,33 +250,7 @@
function finishMinting() external returns (bool);
}
-// Selector: 780e9d63
-interface ERC721Enumerable is Dummy, ERC165 {
- // @notice Enumerate valid NFTs
- // @param index A counter less than `totalSupply()`
- // @return The token identifier for the `index`th NFT,
- // (sort order not specified)
- //
- // Selector: tokenByIndex(uint256) 4f6ccce7
- function tokenByIndex(uint256 index) external view returns (uint256);
-
- // @dev Not implemented
- //
- // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
- function tokenOfOwnerByIndex(address owner, uint256 index)
- external
- view
- returns (uint256);
-
- // @notice Count NFTs tracked by this contract
- // @return A count of valid NFTs tracked by this contract, where each one of
- // them has an assigned and queryable owner not equal to the zero address
- //
- // Selector: totalSupply() 18160ddd
- function totalSupply() external view returns (uint256);
-}
-
-// Selector: 7d9262e6
+// Selector: 6cf113cd
interface Collection is Dummy, ERC165 {
// Set collection property.
//
@@ -422,6 +396,47 @@
//
// Selector: setCollectionMintMode(bool) 00018e84
function setCollectionMintMode(bool mode) external;
+
+ // Check that account is the owner or admin of the collection
+ //
+ // @param user account to verify
+ // @return "true" if account is the owner or admin
+ //
+ // Selector: verifyOwnerOrAdmin(address) c2282493
+ function verifyOwnerOrAdmin(address user) external view returns (bool);
+
+ // Returns collection type
+ //
+ // @return `Fungible` or `NFT` or `ReFungible`
+ //
+ // Selector: uniqueCollectionType() d34b55b8
+ function uniqueCollectionType() external returns (string memory);
+}
+
+// Selector: 780e9d63
+interface ERC721Enumerable is Dummy, ERC165 {
+ // @notice Enumerate valid NFTs
+ // @param index A counter less than `totalSupply()`
+ // @return The token identifier for the `index`th NFT,
+ // (sort order not specified)
+ //
+ // Selector: tokenByIndex(uint256) 4f6ccce7
+ function tokenByIndex(uint256 index) external view returns (uint256);
+
+ // @dev Not implemented
+ //
+ // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
+ function tokenOfOwnerByIndex(address owner, uint256 index)
+ external
+ view
+ returns (uint256);
+
+ // @notice Count NFTs tracked by this contract
+ // @return A count of valid NFTs tracked by this contract, where each one of
+ // them has an assigned and queryable owner not equal to the zero address
+ //
+ // Selector: totalSupply() 18160ddd
+ function totalSupply() external view returns (uint256);
}
// Selector: d74d154f
tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -248,33 +248,7 @@
function finishMinting() external returns (bool);
}
-// Selector: 780e9d63
-interface ERC721Enumerable is Dummy, ERC165 {
- // @notice Enumerate valid RFTs
- // @param index A counter less than `totalSupply()`
- // @return The token identifier for the `index`th NFT,
- // (sort order not specified)
- //
- // Selector: tokenByIndex(uint256) 4f6ccce7
- function tokenByIndex(uint256 index) external view returns (uint256);
-
- // Not implemented
- //
- // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
- function tokenOfOwnerByIndex(address owner, uint256 index)
- external
- view
- returns (uint256);
-
- // @notice Count RFTs tracked by this contract
- // @return A count of valid RFTs tracked by this contract, where each one of
- // them has an assigned and queryable owner not equal to the zero address
- //
- // Selector: totalSupply() 18160ddd
- function totalSupply() external view returns (uint256);
-}
-
-// Selector: 7d9262e6
+// Selector: 6cf113cd
interface Collection is Dummy, ERC165 {
// Set collection property.
//
@@ -420,9 +394,50 @@
//
// Selector: setCollectionMintMode(bool) 00018e84
function setCollectionMintMode(bool mode) external;
+
+ // Check that account is the owner or admin of the collection
+ //
+ // @param user account to verify
+ // @return "true" if account is the owner or admin
+ //
+ // Selector: verifyOwnerOrAdmin(address) c2282493
+ function verifyOwnerOrAdmin(address user) external view returns (bool);
+
+ // Returns collection type
+ //
+ // @return `Fungible` or `NFT` or `ReFungible`
+ //
+ // Selector: uniqueCollectionType() d34b55b8
+ function uniqueCollectionType() external returns (string memory);
+}
+
+// Selector: 780e9d63
+interface ERC721Enumerable is Dummy, ERC165 {
+ // @notice Enumerate valid RFTs
+ // @param index A counter less than `totalSupply()`
+ // @return The token identifier for the `index`th NFT,
+ // (sort order not specified)
+ //
+ // Selector: tokenByIndex(uint256) 4f6ccce7
+ function tokenByIndex(uint256 index) external view returns (uint256);
+
+ // Not implemented
+ //
+ // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
+ function tokenOfOwnerByIndex(address owner, uint256 index)
+ external
+ view
+ returns (uint256);
+
+ // @notice Count RFTs tracked by this contract
+ // @return A count of valid RFTs tracked by this contract, where each one of
+ // them has an assigned and queryable owner not equal to the zero address
+ //
+ // Selector: totalSupply() 18160ddd
+ function totalSupply() external view returns (uint256);
}
-// Selector: d74d154f
+// Selector: 7c3bef89
interface ERC721UniqueExtensions is Dummy, ERC165 {
// @notice Transfer ownership of an RFT
// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
@@ -473,6 +488,16 @@
function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)
external
returns (bool);
+
+ // Returns EVM address for refungible token
+ //
+ // @param token ID of the token
+ //
+ // Selector: tokenContractAddress(uint256) ab76fac6
+ function tokenContractAddress(uint256 token)
+ external
+ view
+ returns (address);
}
interface UniqueRefungible is
tests/src/eth/api/UniqueRefungibleToken.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungibleToken.sol
+++ b/tests/src/eth/api/UniqueRefungibleToken.sol
@@ -22,6 +22,23 @@
);
}
+// Selector: 042f1106
+interface ERC1633UniqueExtensions is Dummy, ERC165 {
+ // Selector: setParentNFT(address,uint256) 042f1106
+ function setParentNFT(address collection, uint256 nftId)
+ external
+ returns (bool);
+}
+
+// Selector: 5755c3f2
+interface ERC1633 is Dummy, ERC165 {
+ // Selector: parentToken() 80a54001
+ function parentToken() external view returns (address);
+
+ // Selector: parentTokenId() d7f083f3
+ function parentTokenId() external view returns (uint256);
+}
+
// Selector: 942e8b22
interface ERC20 is Dummy, ERC165, ERC20Events {
// @return the name of the token.
@@ -115,5 +132,7 @@
Dummy,
ERC165,
ERC20,
- ERC20UniqueExtensions
+ ERC20UniqueExtensions,
+ ERC1633,
+ ERC1633UniqueExtensions
{}
tests/src/eth/base.test.tsdiffbeforeafterboth--- a/tests/src/eth/base.test.ts
+++ b/tests/src/eth/base.test.ts
@@ -15,14 +15,14 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
import {
- collectionIdToAddress,
- createEthAccount,
- createEthAccountWithBalance,
- deployFlipper,
- ethBalanceViaSub,
- GAS_ARGS,
- itWeb3,
- recordEthFee,
+ collectionIdToAddress,
+ createEthAccount,
+ createEthAccountWithBalance,
+ deployFlipper,
+ ethBalanceViaSub,
+ GAS_ARGS,
+ itWeb3,
+ recordEthFee,
usingWeb3,
} from './util/helpers';
import {expect} from 'chai';
@@ -66,7 +66,7 @@
const fee = Number(cost) / Number(UNIQUE);
const expectedFee = 0.15;
- const tolerance = 0.00002;
+ const tolerance = 0.001;
expect(Math.abs(fee - expectedFee)).to.be.lessThan(tolerance);
});
tests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/eth/collectionAdmin.test.ts
+++ b/tests/src/eth/collectionAdmin.test.ts
@@ -59,6 +59,22 @@
expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())
.to.be.eq(newAdmin.address.toLocaleLowerCase());
});
+
+ itWeb3('Verify owner or admin', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
+
+ const newAdmin = createEthAccount(web3);
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+ expect(await collectionEvm.methods.verifyOwnerOrAdmin(newAdmin).call()).to.be.false;
+ await collectionEvm.methods.addCollectionAdmin(newAdmin).send();
+ expect(await collectionEvm.methods.verifyOwnerOrAdmin(newAdmin).call()).to.be.true;
+ });
itWeb3('(!negative tests!) Add admin by ADMIN is not allowed', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
tests/src/eth/collectionHelpersAbi.jsondiffbeforeafterboth--- a/tests/src/eth/collectionHelpersAbi.json
+++ b/tests/src/eth/collectionHelpersAbi.json
@@ -61,7 +61,7 @@
],
"name": "createRefungibleCollection",
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
- "stateMutability": "view",
+ "stateMutability": "nonpayable",
"type": "function"
},
{
tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createRFTCollection.test.ts
+++ b/tests/src/eth/createRFTCollection.test.ts
@@ -16,7 +16,7 @@
import {evmToAddress} from '@polkadot/util-crypto';
import {expect} from 'chai';
-import {getCreatedCollectionCount, getDetailedCollectionInfo} from '../util/helpers';
+import {getCreatedCollectionCount, getDetailedCollectionInfo, requirePallets, Pallets} from '../util/helpers';
import {
evmCollectionHelpers,
collectionIdToAddress,
@@ -28,6 +28,10 @@
} from './util/helpers';
describe('Create RFT collection from EVM', () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+ });
+
itWeb3('Create collection', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const collectionHelper = evmCollectionHelpers(web3, owner);
@@ -146,6 +150,10 @@
});
describe('(!negative tests!) Create RFT collection from EVM', () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+ });
+
itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, owner);
@@ -228,4 +236,4 @@
.setCollectionLimit('badLimit', 'true')
.call()).to.be.rejectedWith('unknown boolean limit "badLimit"');
});
-});
\ No newline at end of file
+});
tests/src/eth/fractionalizer/Fractionalizer.bindiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/fractionalizer/Fractionalizer.bin
@@ -0,0 +1 @@
+60c0604052600a60805269526546756e6769626c6560b01b60a0527fcdb72fd4e1d0d6d4eebd7ab142113ec2b4b06ddb24324db5c287ef01ab484d6b60055534801561004a57600080fd5b50600480546001600160a01b0319163317905561137a8061006c6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063115091401461005c5780631b191ea214610071578063d470e60f14610084578063dbc38ad214610097578063eb292412146100aa575b600080fd5b61006f61006a366004610f85565b6100bd565b005b61006f61007f366004610ff2565b61035b565b61006f61009236600461108c565b6104c0565b61006f6100a53660046110b8565b61089d565b61006f6100b8366004611114565b610ee0565b6004546001600160a01b031633146100f05760405162461bcd60e51b81526004016100e79061114d565b60405180910390fd5b6000546001600160a01b0316156101495760405162461bcd60e51b815260206004820152601d60248201527f52465420636f6c6c656374696f6e20697320616c72656164792073657400000060448201526064016100e7565b60008190506000816001600160a01b031663d34b55b86040518163ffffffff1660e01b81526004016000604051808303816000875af1158015610190573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101b8919081019061118b565b905060055481805190602001201461022f5760405162461bcd60e51b815260206004820152603460248201527f57726f6e6720636f6c6c656374696f6e20747970652e20436f6c6c656374696f604482015273371034b9903737ba103932b33ab733b4b136329760611b60648201526084016100e7565b816001600160a01b03166304a460536040518163ffffffff1660e01b81526004016020604051808303816000875af115801561026f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610293919061125b565b6103055760405162461bcd60e51b815260206004820152603c60248201527f4672616374696f6e616c697a657220636f6e74726163742073686f756c64206260448201527f6520616e2061646d696e206f662074686520636f6c6c656374696f6e0000000060648201526084016100e7565b600080546001600160a01b0319166001600160a01b0385169081179091556040519081527f7186a599bf2297b1f4c8957d30b0965291eee0021a5f9a0aeb54dcbd1ffdceef9060200160405180910390a1505050565b6004546001600160a01b031633146103855760405162461bcd60e51b81526004016100e79061114d565b6000546001600160a01b0316156103de5760405162461bcd60e51b815260206004820152601d60248201527f52465420636f6c6c656374696f6e20697320616c72656164792073657400000060448201526064016100e7565b6040516344a68ad560e01b8152736c4e9fe1ae37a41e93cee429e8e1881abdcbb54f9081906344a68ad590610421908a908a908a908a908a908a906004016112a1565b6020604051808303816000875af1158015610440573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061046491906112ea565b600080546001600160a01b0319166001600160a01b039290921691821790556040519081527f7186a599bf2297b1f4c8957d30b0965291eee0021a5f9a0aeb54dcbd1ffdceef906020015b60405180910390a150505050505050565b6000546001600160a01b03166105145760405162461bcd60e51b81526020600482015260196024820152781491950818dbdb1b1958dd1a5bdb881a5cc81b9bdd081cd95d603a1b60448201526064016100e7565b6000546001600160a01b038381169116146105685760405162461bcd60e51b81526020600482015260146024820152732bb937b7339029232a1031b7b63632b1ba34b7b760611b60448201526064016100e7565b600080546040516355bb7d6360e11b8152600481018490526001600160a01b039091169190829063ab76fac690602401602060405180830381865afa1580156105b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d991906112ea565b6001600160a01b03808216600090815260036020908152604091829020825180840190935280549093168083526001909301549082015291925061065f5760405162461bcd60e51b815260206004820181905260248201527f4e6f20636f72726573706f6e64696e67204e465420746f6b656e20666f756e6460448201526064016100e7565b6000829050806001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c69190611307565b6040516370a0823160e01b81523360048201526001600160a01b038316906370a0823190602401602060405180830381865afa15801561070a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072e9190611307565b1461078a5760405162461bcd60e51b815260206004820152602660248201527f4e6f7420616c6c2070696563657320617265206f776e6564206279207468652060448201526531b0b63632b960d11b60648201526084016100e7565b6040516323b872dd60e01b81526001600160a01b038516906323b872dd906107ba90339030908a90600401611320565b600060405180830381600087803b1580156107d457600080fd5b505af11580156107e8573d6000803e3d6000fd5b5050835160208501516040516323b872dd60e01b81526001600160a01b0390921693506323b872dd92506108229130913391600401611320565b600060405180830381600087803b15801561083c57600080fd5b505af1158015610850573d6000803e3d6000fd5b5050835160208501516040517fe9e9808d24ff79ccc3b1ecf48be7b2d11591adccc452150d0d7947cb48eb0d53945061088d935087929190611320565b60405180910390a1505050505050565b6000546001600160a01b03166108f15760405162461bcd60e51b81526020600482015260196024820152781491950818dbdb1b1958dd1a5bdb881a5cc81b9bdd081cd95d603a1b60448201526064016100e7565b600080546001600160a01b0385811683526001602081905260409093205491169160ff90911615151461098c5760405162461bcd60e51b815260206004820152603c60248201527f4672616374696f6e616c697a6174696f6e206f66207468697320636f6c6c656360448201527f74696f6e206973206e6f7420616c6c6f7765642062792061646d696e0000000060648201526084016100e7565b6040516331a9108f60e11b81526004810184905233906001600160a01b03861690636352211e90602401602060405180830381865afa1580156109d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f791906112ea565b6001600160a01b031614610a5d5760405162461bcd60e51b815260206004820152602760248201527f4f6e6c7920746f6b656e206f776e657220636f756c64206672616374696f6e616044820152661b1a5e99481a5d60ca1b60648201526084016100e7565b6040516323b872dd60e01b81526001600160a01b038516906323b872dd90610a8d90339030908890600401611320565b600060405180830381600087803b158015610aa757600080fd5b505af1158015610abb573d6000803e3d6000fd5b505050506001600160a01b0384166000908152600260209081526040808320868452909152812054819081908103610d0757836001600160a01b03166375794a3c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4f9190611307565b6040516340c10f1960e01b8152306004820152602481018290529093506001600160a01b038516906340c10f19906044016020604051808303816000875af1158015610b9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc3919061125b565b506040516355bb7d6360e11b8152600481018490526001600160a01b0385169063ab76fac690602401602060405180830381865afa158015610c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2d91906112ea565b6001600160a01b0388811660008181526002602090815260408083208c84528252808320899055805180820182528481528083018d8152878716808652600390945293829020905181546001600160a01b0319169616959095178555915160019094019390935551630217888360e11b81526004810191909152602481018990529193508392509063042f1106906044016020604051808303816000875af1158015610cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d01919061125b565b50610d98565b6001600160a01b0387811660009081526002602090815260408083208a8452909152908190205490516355bb7d6360e11b8152600481018290529094509085169063ab76fac690602401602060405180830381865afa158015610d6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9291906112ea565b91508190505b60405163d2418ca760e01b81526001600160801b03861660048201526001600160a01b0382169063d2418ca7906024016020604051808303816000875af1158015610de7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e0b919061125b565b5060405163a9059cbb60e01b81523360048201526001600160801b03861660248201526001600160a01b0382169063a9059cbb906044016020604051808303816000875af1158015610e61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e85919061125b565b50604080516001600160a01b03808a168252602082018990528416918101919091526001600160801b03861660608201527f29f372538523984f33874da1b50e596ce0f180a6eb04d7ff22bb2ce80e1576b6906080016104af565b6004546001600160a01b03163314610f0a5760405162461bcd60e51b81526004016100e79061114d565b6001600160a01b038216600081815260016020908152604091829020805460ff19168515159081179091558251938452908301527f6dad0aed33f4b7f07095619b668698e17943fd9f4c83e7cfcc7f6dd880a11588910160405180910390a15050565b6001600160a01b0381168114610f8257600080fd5b50565b600060208284031215610f9757600080fd5b8135610fa281610f6d565b9392505050565b60008083601f840112610fbb57600080fd5b50813567ffffffffffffffff811115610fd357600080fd5b602083019150836020828501011115610feb57600080fd5b9250929050565b6000806000806000806060878903121561100b57600080fd5b863567ffffffffffffffff8082111561102357600080fd5b61102f8a838b01610fa9565b9098509650602089013591508082111561104857600080fd5b6110548a838b01610fa9565b9096509450604089013591508082111561106d57600080fd5b5061107a89828a01610fa9565b979a9699509497509295939492505050565b6000806040838503121561109f57600080fd5b82356110aa81610f6d565b946020939093013593505050565b6000806000606084860312156110cd57600080fd5b83356110d881610f6d565b92506020840135915060408401356001600160801b03811681146110fb57600080fd5b809150509250925092565b8015158114610f8257600080fd5b6000806040838503121561112757600080fd5b823561113281610f6d565b9150602083013561114281611106565b809150509250929050565b6020808252600e908201526d27b7363c9037bbb732b91031b0b760911b604082015260600190565b634e487b7160e01b600052604160045260246000fd5b6000602080838503121561119e57600080fd5b825167ffffffffffffffff808211156111b657600080fd5b818501915085601f8301126111ca57600080fd5b8151818111156111dc576111dc611175565b604051601f8201601f19908116603f0116810190838211818310171561120457611204611175565b81604052828152888684870101111561121c57600080fd5b600093505b8284101561123e5784840186015181850187015292850192611221565b8284111561124f5760008684830101525b98975050505050505050565b60006020828403121561126d57600080fd5b8151610fa281611106565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006112b560608301888a611278565b82810360208401526112c8818789611278565b905082810360408401526112dd818587611278565b9998505050505050505050565b6000602082840312156112fc57600080fd5b8151610fa281610f6d565b60006020828403121561131957600080fd5b5051919050565b6001600160a01b03938416815291909216602082015260408101919091526060019056fea2646970667358221220a118fe8c3b83b3933baa7bfe084ed165a014ec509367252e5c99e1a3332d000364736f6c634300080f0033
\ No newline at end of file
tests/src/eth/fractionalizer/Fractionalizer.soldiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/fractionalizer/Fractionalizer.sol
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: Apache License
+pragma solidity >=0.8.0;
+import {CollectionHelpers} from "../api/CollectionHelpers.sol";
+import {ContractHelpers} from "../api/ContractHelpers.sol";
+import {UniqueRefungibleToken} from "../api/UniqueRefungibleToken.sol";
+import {UniqueRefungible} from "../api/UniqueRefungible.sol";
+import {UniqueNFT} from "../api/UniqueNFT.sol";
+
+/// @dev Fractionalization contract. It stores mappings between NFT and RFT tokens,
+/// 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)) nft2rftMapping;
+ mapping(address => Token) rft2nftMapping;
+ bytes32 refungibleCollectionType = keccak256(bytes("ReFungible"));
+
+ 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 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 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);
+
+ /// 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.verifyOwnerOrAdmin(address(this)),
+ "Fractionalizer contract should be an admin of the collection"
+ );
+ rftCollection = _collection;
+ emit RFTCollectionSet(rftCollection);
+ }
+
+ /// 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);
+ }
+
+ /// 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);
+ }
+
+ /// 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);
+
+ rftTokenContract = UniqueRefungibleToken(rftTokenAddress);
+ rftTokenContract.setParentNFT(_collection, _token);
+ } 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);
+ }
+}
\ No newline at end of file
tests/src/eth/fractionalizer/FractionalizerAbi.jsondiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/fractionalizer/FractionalizerAbi.json
@@ -0,0 +1,142 @@
+[
+ { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "_collection",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "_status",
+ "type": "bool"
+ }
+ ],
+ "name": "AllowListSet",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "_rftToken",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "_nftCollection",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "_nftTokenId",
+ "type": "uint256"
+ }
+ ],
+ "name": "Defractionalized",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "_collection",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "_tokenId",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "_rftToken",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint128",
+ "name": "_amount",
+ "type": "uint128"
+ }
+ ],
+ "name": "Fractionalized",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "_collection",
+ "type": "address"
+ }
+ ],
+ "name": "RFTCollectionSet",
+ "type": "event"
+ },
+ {
+ "inputs": [
+ { "internalType": "string", "name": "_name", "type": "string" },
+ { "internalType": "string", "name": "_description", "type": "string" },
+ { "internalType": "string", "name": "_tokenPrefix", "type": "string" }
+ ],
+ "name": "createAndSetRFTCollection",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "_collection", "type": "address" },
+ { "internalType": "uint256", "name": "_token", "type": "uint256" },
+ { "internalType": "uint128", "name": "_pieces", "type": "uint128" }
+ ],
+ "name": "nft2rft",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "_collection", "type": "address" },
+ { "internalType": "uint256", "name": "_token", "type": "uint256" }
+ ],
+ "name": "rft2nft",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "collection", "type": "address" },
+ { "internalType": "bool", "name": "status", "type": "bool" }
+ ],
+ "name": "setNftCollectionIsAllowed",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "_collection", "type": "address" }
+ ],
+ "name": "setRFTCollection",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+]
tests/src/eth/fractionalizer/fractionalizer.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/fractionalizer/fractionalizer.test.ts
@@ -0,0 +1,470 @@
+// 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/>.
+
+
+import Web3 from 'web3';
+import {ApiPromise} from '@polkadot/api';
+import {evmToAddress} from '@polkadot/util-crypto';
+import {readFile} from 'fs/promises';
+import {executeTransaction, submitTransactionAsync} from '../../substrate/substrate-api';
+import {getCreateCollectionResult, getCreateItemResult, UNIQUE} from '../../util/helpers';
+import {collectionIdToAddress, CompiledContract, createEthAccountWithBalance, createNonfungibleCollection, createRefungibleCollection, GAS_ARGS, itWeb3, tokenIdFromAddress, uniqueNFT, uniqueRefungible, uniqueRefungibleToken} from '../util/helpers';
+import {Contract} from 'web3-eth-contract';
+import * as solc from 'solc';
+
+import chai from 'chai';
+import chaiLike from 'chai-like';
+import {IKeyringPair} from '@polkadot/types/types';
+chai.use(chaiLike);
+const expect = chai.expect;
+let fractionalizer: CompiledContract;
+
+async function compileFractionalizer() {
+ if (!fractionalizer) {
+ const input = {
+ language: 'Solidity',
+ sources: {
+ ['Fractionalizer.sol']: {
+ content: (await readFile(`${__dirname}/Fractionalizer.sol`)).toString(),
+ },
+ },
+ settings: {
+ outputSelection: {
+ '*': {
+ '*': ['*'],
+ },
+ },
+ },
+ };
+ const json = JSON.parse(solc.compile(JSON.stringify(input), {import: await findImports()}));
+ const out = json.contracts['Fractionalizer.sol']['Fractionalizer'];
+
+ fractionalizer = {
+ abi: out.abi,
+ object: '0x' + out.evm.bytecode.object,
+ };
+ }
+ return fractionalizer;
+}
+
+async function findImports() {
+ const collectionHelpers = (await readFile(`${__dirname}/../api/CollectionHelpers.sol`)).toString();
+ const contractHelpers = (await readFile(`${__dirname}/../api/ContractHelpers.sol`)).toString();
+ const uniqueRefungibleToken = (await readFile(`${__dirname}/../api/UniqueRefungibleToken.sol`)).toString();
+ const uniqueRefungible = (await readFile(`${__dirname}/../api/UniqueRefungible.sol`)).toString();
+ const uniqueNFT = (await readFile(`${__dirname}/../api/UniqueNFT.sol`)).toString();
+
+ return function(path: string) {
+ switch (path) {
+ case 'api/CollectionHelpers.sol': return {contents: `${collectionHelpers}`};
+ case 'api/ContractHelpers.sol': return {contents: `${contractHelpers}`};
+ case 'api/UniqueRefungibleToken.sol': return {contents: `${uniqueRefungibleToken}`};
+ case 'api/UniqueRefungible.sol': return {contents: `${uniqueRefungible}`};
+ case 'api/UniqueNFT.sol': return {contents: `${uniqueNFT}`};
+ default: return {error: 'File not found'};
+ }
+ };
+}
+
+async function deployFractionalizer(web3: Web3, owner: string) {
+ const compiled = await compileFractionalizer();
+ const fractionalizerContract = new web3.eth.Contract(compiled.abi, undefined, {
+ data: compiled.object,
+ from: owner,
+ ...GAS_ARGS,
+ });
+ return await fractionalizerContract.deploy({data: compiled.object}).send({from: owner});
+}
+
+async function initFractionalizer(api: ApiPromise, web3: Web3, privateKeyWrapper: (account: string) => IKeyringPair, owner: string) {
+ const fractionalizer = await deployFractionalizer(web3, owner);
+ const amount = 10n * UNIQUE;
+ await web3.eth.sendTransaction({from: owner, to: fractionalizer.options.address, value: `${amount}`, ...GAS_ARGS});
+ const result = await fractionalizer.methods.createAndSetRFTCollection('A', 'B', 'C').send();
+ const rftCollectionAddress = result.events.RFTCollectionSet.returnValues._collection;
+ return {fractionalizer, rftCollectionAddress};
+}
+
+async function createRFTToken(api: ApiPromise, web3: Web3, owner: string, fractionalizer: Contract, amount: bigint) {
+ const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);
+ const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);
+ const nftTokenId = await nftContract.methods.nextTokenId().call();
+ await nftContract.methods.mint(owner, nftTokenId).send();
+
+ await fractionalizer.methods.setNftCollectionIsAllowed(nftCollectionAddress, true).send();
+ await nftContract.methods.approve(fractionalizer.options.address, nftTokenId).send();
+ const result = await fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, amount).send();
+ const {_collection, _tokenId, _rftToken} = result.events.Fractionalized.returnValues;
+ return {
+ nftCollectionAddress: _collection,
+ nftTokenId: _tokenId,
+ rftTokenAddress: _rftToken,
+ };
+}
+
+describe('Fractionalizer contract usage', () => {
+ 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 refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);
+ await refungibleContract.methods.addCollectionAdmin(fractionalizer.options.address).send();
+ const result = await fractionalizer.methods.setRFTCollection(collectionIdAddress).send();
+ expect(result.events).to.be.like({
+ RFTCollectionSet: {
+ returnValues: {
+ _collection: collectionIdAddress,
+ },
+ },
+ });
+ });
+
+ itWeb3('Mint RFT collection', async ({api, web3, privateKeyWrapper}) => {
+ const alice = privateKeyWrapper('//Alice');
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const fractionalizer = await deployFractionalizer(web3, owner);
+ const tx = api.tx.balances.transfer(evmToAddress(fractionalizer.options.address), 10n * UNIQUE);
+ await submitTransactionAsync(alice, tx);
+
+ const result = await fractionalizer.methods.createAndSetRFTCollection('A', 'B', 'C').send({from: owner});
+ expect(result.events).to.be.like({
+ RFTCollectionSet: {},
+ });
+ expect(result.events.RFTCollectionSet.returnValues._collection).to.be.ok;
+ });
+
+ itWeb3('Set Allowlist', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);
+ const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);
+ const result1 = await fractionalizer.methods.setNftCollectionIsAllowed(nftCollectionAddress, true).send({from: owner});
+ expect(result1.events).to.be.like({
+ AllowListSet: {
+ returnValues: {
+ _collection: nftCollectionAddress,
+ _status: true,
+ },
+ },
+ });
+ const result2 = await fractionalizer.methods.setNftCollectionIsAllowed(nftCollectionAddress, false).send({from: owner});
+ expect(result2.events).to.be.like({
+ AllowListSet: {
+ returnValues: {
+ _collection: nftCollectionAddress,
+ _status: false,
+ },
+ },
+ });
+ });
+
+ itWeb3('NFT to RFT', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);
+ const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);
+ const nftTokenId = await nftContract.methods.nextTokenId().call();
+ await nftContract.methods.mint(owner, nftTokenId).send();
+
+ const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);
+
+ await fractionalizer.methods.setNftCollectionIsAllowed(nftCollectionAddress, true).send();
+ await nftContract.methods.approve(fractionalizer.options.address, nftTokenId).send();
+ const result = await fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, 100).send();
+ expect(result.events).to.be.like({
+ Fractionalized: {
+ returnValues: {
+ _collection: nftCollectionAddress,
+ _tokenId: nftTokenId,
+ _amount: '100',
+ },
+ },
+ });
+ const rftTokenAddress = result.events.Fractionalized.returnValues._rftToken;
+ const rftTokenContract = uniqueRefungibleToken(web3, rftTokenAddress, owner);
+ expect(await rftTokenContract.methods.balanceOf(owner).call()).to.equal('100');
+ });
+
+ itWeb3('RFT to NFT', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const {fractionalizer, rftCollectionAddress} = await initFractionalizer(api, web3, privateKeyWrapper, owner);
+ const {rftTokenAddress, nftCollectionAddress, nftTokenId} = await createRFTToken(api, web3, owner, fractionalizer, 100n);
+
+ const {collectionId, tokenId} = tokenIdFromAddress(rftTokenAddress);
+ const refungibleAddress = collectionIdToAddress(collectionId);
+ expect(rftCollectionAddress).to.be.equal(refungibleAddress);
+ const refungibleTokenContract = uniqueRefungibleToken(web3, rftTokenAddress, owner);
+ await refungibleTokenContract.methods.approve(fractionalizer.options.address, 100).send();
+ const result = await fractionalizer.methods.rft2nft(refungibleAddress, tokenId).send();
+ expect(result.events).to.be.like({
+ Defractionalized: {
+ returnValues: {
+ _rftToken: rftTokenAddress,
+ _nftCollection: nftCollectionAddress,
+ _nftTokenId: nftTokenId,
+ },
+ },
+ });
+ });
+});
+
+
+
+describe('Negative Integration Tests for fractionalizer', () => {
+ itWeb3('call setRFTCollection twice', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const {collectionIdAddress} = await createRefungibleCollection(api, web3, owner);
+ const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);
+
+ const fractionalizer = await deployFractionalizer(web3, owner);
+ await refungibleContract.methods.addCollectionAdmin(fractionalizer.options.address).send();
+ await fractionalizer.methods.setRFTCollection(collectionIdAddress).send();
+
+ await expect(fractionalizer.methods.setRFTCollection(collectionIdAddress).call())
+ .to.be.rejectedWith(/RFT collection is already set$/g);
+ });
+
+ itWeb3('call setRFTCollection with NFT collection', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const {collectionIdAddress} = await createNonfungibleCollection(api, web3, owner);
+ const nftContract = uniqueNFT(web3, collectionIdAddress, owner);
+
+ const fractionalizer = await deployFractionalizer(web3, owner);
+ await nftContract.methods.addCollectionAdmin(fractionalizer.options.address).send();
+
+ await expect(fractionalizer.methods.setRFTCollection(collectionIdAddress).call())
+ .to.be.rejectedWith(/Wrong collection type. Collection is not refungible.$/g);
+ });
+
+ 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);
+
+ await expect(fractionalizer.methods.setRFTCollection(collectionIdAddress).call())
+ .to.be.rejectedWith(/Fractionalizer contract should be an admin of the collection$/g);
+ });
+
+ itWeb3('call setRFTCollection after createAndSetRFTCollection', async ({api, web3, privateKeyWrapper}) => {
+ const alice = privateKeyWrapper('//Alice');
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const fractionalizer = await deployFractionalizer(web3, owner);
+ const tx = api.tx.balances.transfer(evmToAddress(fractionalizer.options.address), 10n * UNIQUE);
+ await submitTransactionAsync(alice, tx);
+
+ const result = await fractionalizer.methods.createAndSetRFTCollection('A', 'B', 'C').send({from: owner});
+ const collectionIdAddress = result.events.RFTCollectionSet.returnValues._collection;
+
+ await expect(fractionalizer.methods.setRFTCollection(collectionIdAddress).call())
+ .to.be.rejectedWith(/RFT collection is already set$/g);
+ });
+
+ itWeb3('call nft2rft without setting RFT collection for contract', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);
+ const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);
+ const nftTokenId = await nftContract.methods.nextTokenId().call();
+ await nftContract.methods.mint(owner, nftTokenId).send();
+
+ const fractionalizer = await deployFractionalizer(web3, owner);
+
+ await expect(fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, 100).call())
+ .to.be.rejectedWith(/RFT collection is not set$/g);
+ });
+
+ itWeb3('call nft2rft while not owner of NFT token', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const nftOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);
+ const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);
+ const nftTokenId = await nftContract.methods.nextTokenId().call();
+ await nftContract.methods.mint(owner, nftTokenId).send();
+ await nftContract.methods.transfer(nftOwner, 1).send();
+
+
+ const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);
+ await fractionalizer.methods.setNftCollectionIsAllowed(nftCollectionAddress, true).send();
+
+ await expect(fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, 100).call())
+ .to.be.rejectedWith(/Only token owner could fractionalize it$/g);
+ });
+
+ itWeb3('call nft2rft while not in list of allowed accounts', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);
+ const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);
+ const nftTokenId = await nftContract.methods.nextTokenId().call();
+ await nftContract.methods.mint(owner, nftTokenId).send();
+
+ const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);
+
+ await nftContract.methods.approve(fractionalizer.options.address, nftTokenId).send();
+ await expect(fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, 100).call())
+ .to.be.rejectedWith(/Fractionalization of this collection is not allowed by admin$/g);
+ });
+
+ itWeb3('call nft2rft while fractionalizer doesnt have approval for nft token', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);
+ const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);
+ const nftTokenId = await nftContract.methods.nextTokenId().call();
+ await nftContract.methods.mint(owner, nftTokenId).send();
+
+ const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);
+
+ await fractionalizer.methods.setNftCollectionIsAllowed(nftCollectionAddress, true).send();
+ await expect(fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, 100).call())
+ .to.be.rejectedWith(/ApprovedValueTooLow$/g);
+ });
+
+ itWeb3('call rft2nft without setting RFT collection for contract', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const fractionalizer = await deployFractionalizer(web3, owner);
+ const {collectionIdAddress: rftCollectionAddress} = await createRefungibleCollection(api, web3, owner);
+ const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);
+ const rftTokenId = await refungibleContract.methods.nextTokenId().call();
+ await refungibleContract.methods.mint(owner, rftTokenId).send();
+
+ await expect(fractionalizer.methods.rft2nft(rftCollectionAddress, rftTokenId).call())
+ .to.be.rejectedWith(/RFT collection is not set$/g);
+ });
+
+ itWeb3('call rft2nft for RFT token that is not from configured RFT collection', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);
+ const {collectionIdAddress: rftCollectionAddress} = await createRefungibleCollection(api, web3, owner);
+ const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);
+ const rftTokenId = await refungibleContract.methods.nextTokenId().call();
+ await refungibleContract.methods.mint(owner, rftTokenId).send();
+
+ await expect(fractionalizer.methods.rft2nft(rftCollectionAddress, rftTokenId).call())
+ .to.be.rejectedWith(/Wrong RFT collection$/g);
+ });
+
+ 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 fractionalizer = await deployFractionalizer(web3, owner);
+ const refungibleContract = uniqueRefungible(web3, rftCollectionAddress, owner);
+
+ await refungibleContract.methods.addCollectionAdmin(fractionalizer.options.address).send();
+ await fractionalizer.methods.setRFTCollection(rftCollectionAddress).send();
+
+ const rftTokenId = await refungibleContract.methods.nextTokenId().call();
+ await refungibleContract.methods.mint(owner, rftTokenId).send();
+
+ await expect(fractionalizer.methods.rft2nft(rftCollectionAddress, rftTokenId).call())
+ .to.be.rejectedWith(/No corresponding NFT token found$/g);
+ });
+
+ itWeb3('call rft2nft without owning all RFT pieces', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const receiver = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const {fractionalizer, rftCollectionAddress} = await initFractionalizer(api, web3, privateKeyWrapper, owner);
+ const {rftTokenAddress} = await createRFTToken(api, web3, owner, fractionalizer, 100n);
+
+ const {tokenId} = tokenIdFromAddress(rftTokenAddress);
+ const refungibleTokenContract = uniqueRefungibleToken(web3, rftTokenAddress, owner);
+ await refungibleTokenContract.methods.transfer(receiver, 50).send();
+ await refungibleTokenContract.methods.approve(fractionalizer.options.address, 50).send();
+ await expect(fractionalizer.methods.rft2nft(rftCollectionAddress, tokenId).call())
+ .to.be.rejectedWith(/Not all pieces are owned by the caller$/g);
+ });
+
+ itWeb3('send QTZ/UNQ to contract from non owner', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const payer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const fractionalizer = await deployFractionalizer(web3, owner);
+ const amount = 10n * UNIQUE;
+ await expect(web3.eth.sendTransaction({from: payer, to: fractionalizer.options.address, value: `${amount}`, ...GAS_ARGS})).to.be.rejected;
+ });
+
+ itWeb3('fractionalize NFT with NFT transfers disallowed', async ({api, web3, privateKeyWrapper}) => {
+ const alice = privateKeyWrapper('//Alice');
+ let collectionId;
+ {
+ const tx = api.tx.unique.createCollectionEx({name: 'A', description: 'B', tokenPrefix: 'C', mode: 'NFT'});
+ const events = await submitTransactionAsync(alice, tx);
+ const result = getCreateCollectionResult(events);
+ collectionId = result.collectionId;
+ }
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ let nftTokenId;
+ {
+ const createData = {nft: {}};
+ const tx = api.tx.unique.createItem(collectionId, {Ethereum: owner}, createData as any);
+ const events = await executeTransaction(api, alice, tx);
+ const result = getCreateItemResult(events);
+ nftTokenId = result.itemId;
+ }
+ {
+ const tx = api.tx.unique.setTransfersEnabledFlag(collectionId, false);
+ await executeTransaction(api, alice, tx);
+ }
+ const nftCollectionAddress = collectionIdToAddress(collectionId);
+ const {fractionalizer} = await initFractionalizer(api, web3, privateKeyWrapper, owner);
+ await fractionalizer.methods.setNftCollectionIsAllowed(nftCollectionAddress, true).send();
+
+ const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);
+ await nftContract.methods.approve(fractionalizer.options.address, nftTokenId).send();
+ await expect(fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, 100).call())
+ .to.be.rejectedWith(/TransferNotAllowed$/g);
+ });
+
+ itWeb3('fractionalize NFT with RFT transfers disallowed', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const alice = privateKeyWrapper('//Alice');
+
+ let collectionId;
+ {
+ const tx = api.tx.unique.createCollectionEx({name: 'A', description: 'B', tokenPrefix: 'C', mode: 'ReFungible'});
+ const events = await submitTransactionAsync(alice, tx);
+ const result = getCreateCollectionResult(events);
+ collectionId = result.collectionId;
+ }
+ const rftCollectionAddress = collectionIdToAddress(collectionId);
+ const fractionalizer = await deployFractionalizer(web3, owner);
+ {
+ const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, {Ethereum: fractionalizer.options.address});
+ await submitTransactionAsync(alice, changeAdminTx);
+ }
+ await fractionalizer.methods.setRFTCollection(rftCollectionAddress).send();
+ {
+ const tx = api.tx.unique.setTransfersEnabledFlag(collectionId, false);
+ await executeTransaction(api, alice, tx);
+ }
+
+ const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);
+ const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);
+ const nftTokenId = await nftContract.methods.nextTokenId().call();
+ await nftContract.methods.mint(owner, nftTokenId).send();
+
+ await fractionalizer.methods.setNftCollectionIsAllowed(nftCollectionAddress, true).send();
+ await nftContract.methods.approve(fractionalizer.options.address, nftTokenId).send();
+
+ await expect(fractionalizer.methods.nft2rft(nftCollectionAddress, nftTokenId, 100n).call())
+ .to.be.rejectedWith(/TransferNotAllowed$/g);
+ });
+});
\ No newline at end of file
tests/src/eth/fungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/fungibleAbi.json
+++ b/tests/src/eth/fungibleAbi.json
@@ -301,5 +301,21 @@
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
"stateMutability": "nonpayable",
"type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "uniqueCollectionType",
+ "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "user", "type": "address" }
+ ],
+ "name": "verifyOwnerOrAdmin",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "view",
+ "type": "function"
}
]
tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -526,5 +526,21 @@
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "uniqueCollectionType",
+ "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "user", "type": "address" }
+ ],
+ "name": "verifyOwnerOrAdmin",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "view",
+ "type": "function"
}
]
tests/src/eth/reFungible.test.tsdiffbeforeafterboth--- a/tests/src/eth/reFungible.test.ts
+++ b/tests/src/eth/reFungible.test.ts
@@ -14,12 +14,15 @@
// 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 {createCollectionExpectSuccess, UNIQUE} from '../util/helpers';
-import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, tokenIdToAddress} from './util/helpers';
-import reFungibleTokenAbi from './reFungibleTokenAbi.json';
+import {createCollectionExpectSuccess, UNIQUE, requirePallets, Pallets} from '../util/helpers';
+import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, tokenIdToAddress, uniqueRefungibleToken} from './util/helpers';
import {expect} from 'chai';
describe('Refungible: Information getting', () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+ });
+
itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {
const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, caller);
@@ -84,7 +87,7 @@
await contract.methods.mint(caller, tokenId).send();
const tokenAddress = tokenIdToAddress(collectionId, tokenId);
- const tokenContract = new web3.eth.Contract(reFungibleTokenAbi as any, tokenAddress, {from: caller, ...GAS_ARGS});
+ const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller);
await tokenContract.methods.repartition(2).send();
await tokenContract.methods.transfer(receiver, 1).send();
@@ -108,7 +111,7 @@
await contract.methods.mint(caller, tokenId).send();
const tokenAddress = tokenIdToAddress(collectionId, tokenId);
- const tokenContract = new web3.eth.Contract(reFungibleTokenAbi as any, tokenAddress, {from: caller, ...GAS_ARGS});
+ const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller);
await tokenContract.methods.repartition(2).send();
await tokenContract.methods.transfer(receiver, 1).send();
@@ -120,6 +123,10 @@
});
describe('Refungible: Plain calls', () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+ });
+
itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, owner);
@@ -250,7 +257,7 @@
await contract.methods.mint(caller, tokenId).send();
const address = tokenIdToAddress(collectionId, tokenId);
- const tokenContract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});
+ const tokenContract = uniqueRefungibleToken(web3, address, caller);
await tokenContract.methods.repartition(15).send();
{
@@ -269,7 +276,7 @@
},
]);
});
-
+
expect(erc20Events).to.include.deep.members([
{
address,
@@ -345,12 +352,12 @@
await contract.methods.mint(caller, tokenId).send();
const tokenAddress = tokenIdToAddress(collectionId, tokenId);
- const tokenContract = new web3.eth.Contract(reFungibleTokenAbi as any, tokenAddress, {from: caller, ...GAS_ARGS});
+ const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller);
await tokenContract.methods.repartition(2).send();
await tokenContract.methods.transfer(receiver, 1).send();
- const events = await recordEvents(contract, async () =>
+ const events = await recordEvents(contract, async () =>
await tokenContract.methods.transfer(receiver, 1).send());
expect(events).to.deep.equal([
{
@@ -377,13 +384,13 @@
await contract.methods.mint(caller, tokenId).send();
const tokenAddress = tokenIdToAddress(collectionId, tokenId);
- const tokenContract = new web3.eth.Contract(reFungibleTokenAbi as any, tokenAddress, {from: caller, ...GAS_ARGS});
+ const tokenContract = uniqueRefungibleToken(web3, tokenAddress, caller);
await tokenContract.methods.repartition(2).send();
-
- const events = await recordEvents(contract, async () =>
+
+ const events = await recordEvents(contract, async () =>
await tokenContract.methods.transfer(receiver, 1).send());
-
+
expect(events).to.deep.equal([
{
address: collectionIdAddress,
@@ -399,6 +406,10 @@
});
describe('RFT: Fees', () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+ });
+
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);
@@ -435,6 +446,10 @@
});
describe('Common metadata', () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+ });
+
itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => {
const collection = await createCollectionExpectSuccess({
name: 'token name',
@@ -462,4 +477,4 @@
expect(symbol).to.equal('TOK');
});
-});
\ No newline at end of file
+});
tests/src/eth/reFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/reFungibleAbi.json
+++ b/tests/src/eth/reFungibleAbi.json
@@ -482,6 +482,15 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "token", "type": "uint256" }
+ ],
+ "name": "tokenContractAddress",
+ "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "owner", "type": "address" },
{ "internalType": "uint256", "name": "index", "type": "uint256" }
],
@@ -526,5 +535,21 @@
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "uniqueCollectionType",
+ "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ { "internalType": "address", "name": "user", "type": "address" }
+ ],
+ "name": "verifyOwnerOrAdmin",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "view",
+ "type": "function"
}
]
tests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth--- a/tests/src/eth/reFungibleToken.test.ts
+++ b/tests/src/eth/reFungibleToken.test.ts
@@ -14,9 +14,8 @@
// 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 {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE} from '../util/helpers';
-import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth} from './util/helpers';
-import reFungibleTokenAbi from './reFungibleTokenAbi.json';
+import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE, requirePallets, Pallets} from '../util/helpers';
+import {collectionIdFromAddress, collectionIdToAddress, createEthAccount, createEthAccountWithBalance, createNonfungibleCollection, createRefungibleCollection, evmCollection, evmCollectionHelpers, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth, uniqueNFT, uniqueRefungible, uniqueRefungibleToken} from './util/helpers';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
@@ -24,6 +23,10 @@
const expect = chai.expect;
describe('Refungible token: Information getting', () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+ });
+
itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
@@ -34,7 +37,7 @@
const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});
+ const contract = uniqueRefungibleToken(web3, address, caller);
const totalSupply = await contract.methods.totalSupply().call();
expect(totalSupply).to.equal('200');
@@ -50,7 +53,7 @@
const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});
+ const contract = uniqueRefungibleToken(web3, address, caller);
const balance = await contract.methods.balanceOf(caller).call();
expect(balance).to.equal('200');
@@ -66,7 +69,7 @@
const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: caller})).itemId;
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});
+ const contract = uniqueRefungibleToken(web3, address, caller);
const decimals = await contract.methods.decimals().call();
expect(decimals).to.equal('0');
@@ -75,6 +78,10 @@
// FIXME: Need erc721 for ReFubgible.
describe('Check ERC721 token URI for ReFungible', () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+ });
+
itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => {
const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const helper = evmCollectionHelpers(web3, owner);
@@ -82,7 +89,7 @@
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const receiver = createEthAccount(web3);
const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
-
+
const nextTokenId = await contract.methods.nextTokenId().call();
expect(nextTokenId).to.be.equal('1');
result = await contract.methods.mint(
@@ -115,17 +122,17 @@
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const receiver = createEthAccount(web3);
const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
-
+
const nextTokenId = await contract.methods.nextTokenId().call();
expect(nextTokenId).to.be.equal('1');
result = await contract.methods.mint(
receiver,
nextTokenId,
).send();
-
+
// Set URL
await contract.methods.setProperty(nextTokenId, 'url', Buffer.from('Token URI')).send();
-
+
const events = normalizeEvents(result.events);
const address = collectionIdToAddress(collectionId);
@@ -151,14 +158,14 @@
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const receiver = createEthAccount(web3);
const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
-
+
const nextTokenId = await contract.methods.nextTokenId().call();
expect(nextTokenId).to.be.equal('1');
result = await contract.methods.mint(
receiver,
nextTokenId,
).send();
-
+
const events = normalizeEvents(result.events);
const address = collectionIdToAddress(collectionId);
@@ -184,14 +191,14 @@
const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
const receiver = createEthAccount(web3);
const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
-
+
const nextTokenId = await contract.methods.nextTokenId().call();
expect(nextTokenId).to.be.equal('1');
result = await contract.methods.mint(
receiver,
nextTokenId,
).send();
-
+
// Set suffix
const suffix = '/some/suffix';
await contract.methods.setProperty(nextTokenId, 'suffix', Buffer.from(suffix)).send();
@@ -216,6 +223,10 @@
});
describe('Refungible: Plain calls', () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+ });
+
itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
@@ -229,7 +240,7 @@
const spender = createEthAccount(web3);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});
+ const contract = uniqueRefungibleToken(web3, address, owner);
{
const result = await contract.methods.approve(spender, 100).send({from: owner});
@@ -270,7 +281,7 @@
const receiver = createEthAccount(web3);
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});
+ const contract = uniqueRefungibleToken(web3, address, owner);
await contract.methods.approve(spender, 100).send();
@@ -324,7 +335,7 @@
await transferBalanceToEth(api, alice, receiver);
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});
+ const contract = uniqueRefungibleToken(web3, address, owner);
{
const result = await contract.methods.transfer(receiver, 50).send({from: owner});
@@ -367,14 +378,14 @@
const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});
+ const contract = uniqueRefungibleToken(web3, address, owner);
await contract.methods.repartition(200).send({from: owner});
expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(200);
await contract.methods.transfer(receiver, 110).send({from: owner});
expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(90);
expect(+await contract.methods.balanceOf(receiver).call()).to.be.equal(110);
-
+
await expect(contract.methods.repartition(80).send({from: owner})).to.eventually.be.rejected;
await contract.methods.transfer(receiver, 90).send({from: owner});
@@ -397,7 +408,7 @@
const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});
+ const contract = uniqueRefungibleToken(web3, address, owner);
const result = await contract.methods.repartition(200).send();
const events = normalizeEvents(result.events);
@@ -426,7 +437,7 @@
const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n, {Ethereum: owner})).itemId;
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});
+ const contract = uniqueRefungibleToken(web3, address, owner);
const result = await contract.methods.repartition(50).send();
const events = normalizeEvents(result.events);
@@ -456,11 +467,11 @@
const address = tokenIdToAddress(collectionId, tokenId);
- const tokenContract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: caller, ...GAS_ARGS});
+ const tokenContract = uniqueRefungibleToken(web3, address, caller);
await tokenContract.methods.repartition(2).send();
await tokenContract.methods.transfer(receiver, 1).send();
- const events = await recordEvents(contract, async () =>
+ const events = await recordEvents(contract, async () =>
await tokenContract.methods.burnFrom(caller, 1).send());
expect(events).to.deep.equal([
{
@@ -477,6 +488,10 @@
});
describe('Refungible: Fees', () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+ });
+
itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
@@ -488,7 +503,7 @@
const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});
+ const contract = uniqueRefungibleToken(web3, address, owner);
const cost = await recordEthFee(api, owner, () => contract.methods.approve(spender, 100).send({from: owner}));
expect(cost < BigInt(0.2 * Number(UNIQUE)));
@@ -505,7 +520,7 @@
const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});
+ const contract = uniqueRefungibleToken(web3, address, owner);
await contract.methods.approve(spender, 100).send({from: owner});
@@ -524,7 +539,7 @@
const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n, {Ethereum: owner})).itemId;
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address, {from: owner, ...GAS_ARGS});
+ const contract = uniqueRefungibleToken(web3, address, owner);
const cost = await recordEthFee(api, owner, () => contract.methods.transfer(receiver, 100).send({from: owner}));
expect(cost < BigInt(0.2 * Number(UNIQUE)));
@@ -532,6 +547,10 @@
});
describe('Refungible: Substrate calls', () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+ });
+
itWeb3('Events emitted for approve()', async ({web3, api, privateKeyWrapper}) => {
const alice = privateKeyWrapper('//Alice');
@@ -542,7 +561,7 @@
const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId;
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address);
+ const contract = uniqueRefungibleToken(web3, address);
const events = await recordEvents(contract, async () => {
expect(await approve(api, collectionId, tokenId, alice, {Ethereum: receiver}, 100n)).to.be.true;
@@ -573,7 +592,7 @@
expect(await approve(api, collectionId, tokenId, alice, bob.address, 100n)).to.be.true;
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address);
+ const contract = uniqueRefungibleToken(web3, address);
const events = await recordEvents(contract, async () => {
expect(await transferFrom(api, collectionId, tokenId, bob, alice, {Ethereum: receiver}, 51n)).to.be.true;
@@ -611,7 +630,7 @@
const tokenId = (await createRefungibleToken(api, alice, collectionId, 200n)).itemId;
const address = tokenIdToAddress(collectionId, tokenId);
- const contract = new web3.eth.Contract(reFungibleTokenAbi as any, address);
+ const contract = uniqueRefungibleToken(web3, address);
const events = await recordEvents(contract, async () => {
expect(await transfer(api, collectionId, tokenId, alice, {Ethereum: receiver}, 51n)).to.be.true;
@@ -630,3 +649,47 @@
]);
});
});
+
+describe('ERC 1633 implementation', () => {
+ itWeb3('Parent NFT token address and id', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ const {collectionIdAddress: nftCollectionAddress} = await createNonfungibleCollection(api, web3, owner);
+ const nftContract = uniqueNFT(web3, nftCollectionAddress, owner);
+ const nftTokenId = await nftContract.methods.nextTokenId().call();
+ await nftContract.methods.mint(owner, nftTokenId).send();
+ const nftCollectionId = collectionIdFromAddress(nftCollectionAddress);
+
+ const {collectionIdAddress, collectionId} = await createRefungibleCollection(api, web3, owner);
+ const refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);
+ const refungibleTokenId = await refungibleContract.methods.nextTokenId().call();
+ await refungibleContract.methods.mint(owner, refungibleTokenId).send();
+
+ const rftTokenAddress = tokenIdToAddress(collectionId, refungibleTokenId);
+ const refungibleTokenContract = uniqueRefungibleToken(web3, rftTokenAddress, owner);
+ await refungibleTokenContract.methods.setParentNFT(nftCollectionAddress, nftTokenId).send();
+
+ const tokenAddress = await refungibleTokenContract.methods.parentToken().call();
+ const tokenId = await refungibleTokenContract.methods.parentTokenId().call();
+ const nftTokenAddress = tokenIdToAddress(nftCollectionId, nftTokenId);
+ expect(tokenAddress).to.be.equal(nftTokenAddress);
+ expect(tokenId).to.be.equal(nftTokenId);
+ });
+
+ 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 refungibleContract = uniqueRefungible(web3, collectionIdAddress, owner);
+ const refungibleTokenId = await refungibleContract.methods.nextTokenId().call();
+ await refungibleContract.methods.mint(owner, refungibleTokenId).send();
+
+ const rftTokenAddress = tokenIdToAddress(collectionId, refungibleTokenId);
+ const refungibleTokenContract = uniqueRefungibleToken(web3, rftTokenAddress, owner);
+
+ const tokenAddress = await refungibleTokenContract.methods.parentToken().call();
+ const tokenId = await refungibleTokenContract.methods.parentTokenId().call();
+ expect(tokenAddress).to.be.equal(rftTokenAddress);
+ expect(tokenId).to.be.equal(refungibleTokenId);
+ });
+});
tests/src/eth/reFungibleTokenAbi.jsondiffbeforeafterboth--- a/tests/src/eth/reFungibleTokenAbi.json
+++ b/tests/src/eth/reFungibleTokenAbi.json
@@ -103,6 +103,20 @@
"type": "function"
},
{
+ "inputs": [],
+ "name": "parentToken",
+ "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "parentTokenId",
+ "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
"inputs": [
{ "internalType": "uint256", "name": "amount", "type": "uint256" }
],
@@ -113,6 +127,16 @@
},
{
"inputs": [
+ { "internalType": "address", "name": "collection", "type": "address" },
+ { "internalType": "uint256", "name": "nftId", "type": "uint256" }
+ ],
+ "name": "setParentNFT",
+ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }
],
"name": "supportsInterface",
tests/src/eth/scheduling.test.tsdiffbeforeafterboth--- a/tests/src/eth/scheduling.test.ts
+++ b/tests/src/eth/scheduling.test.ts
@@ -16,9 +16,13 @@
import {expect} from 'chai';
import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';
-import {scheduleExpectSuccess, waitNewBlocks} from '../util/helpers';
+import {scheduleExpectSuccess, waitNewBlocks, requirePallets, Pallets} from '../util/helpers';
describe('Scheduing EVM smart contracts', () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.Scheduler]);
+ });
+
itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3, privateKeyWrapper}) => {
const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const flipper = await deployFlipper(web3, deployer);
@@ -51,4 +55,4 @@
expect(await flipper.methods.getValue().call()).to.be.equal(initialValue);
}
});
-});
\ No newline at end of file
+});
tests/src/eth/util/helpers.tsdiffbeforeafterboth--- a/tests/src/eth/util/helpers.ts
+++ b/tests/src/eth/util/helpers.ts
@@ -32,6 +32,7 @@
import fungibleAbi from '../fungibleAbi.json';
import nonFungibleAbi from '../nonFungibleAbi.json';
import refungibleAbi from '../reFungibleAbi.json';
+import refungibleTokenAbi from '../reFungibleTokenAbi.json';
import contractHelpersAbi from './contractHelpersAbi.json';
export const GAS_ARGS = {gas: 2500000};
@@ -101,6 +102,18 @@
]);
return Web3.utils.toChecksumAddress('0x' + buf.toString('hex'));
}
+
+export function tokenIdFromAddress(address: string) {
+ if (!address.startsWith('0x'))
+ throw 'address not starts with "0x"';
+ if (address.length > 42)
+ throw 'address length is more than 20 bytes';
+ return {
+ collectionId: Number('0x' + address.substring(address.length - 16, address.length - 8)),
+ tokenId: Number('0x' + address.substring(address.length - 8)),
+ };
+}
+
export function tokenIdToCross(collection: number, token: number): CrossAccountId {
return {
Ethereum: tokenIdToAddress(collection, token),
@@ -128,6 +141,44 @@
expect(result.success).to.be.true;
}
+export async function createRefungibleCollection(api: ApiPromise, web3: Web3, owner: string) {
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+ const result = await collectionHelper.methods
+ .createRefungibleCollection('A', 'B', 'C')
+ .send();
+ return await getCollectionAddressFromResult(api, result);
+}
+
+
+export async function createNonfungibleCollection(api: ApiPromise, web3: Web3, owner: string) {
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ return await getCollectionAddressFromResult(api, result);
+}
+
+export function uniqueNFT(web3: Web3, address: string, owner: string) {
+ return new web3.eth.Contract(nonFungibleAbi as any, address, {
+ from: owner,
+ ...GAS_ARGS,
+ });
+}
+
+export function uniqueRefungible(web3: Web3, collectionAddress: string, owner: string) {
+ return new web3.eth.Contract(refungibleAbi as any, collectionAddress, {
+ from: owner,
+ ...GAS_ARGS,
+ });
+}
+
+export function uniqueRefungibleToken(web3: Web3, tokenAddress: string, owner: string | undefined = undefined) {
+ return new web3.eth.Contract(refungibleTokenAbi as any, tokenAddress, {
+ from: owner,
+ ...GAS_ARGS,
+ });
+}
+
export async function itWeb3(name: string, cb: (apis: { web3: Web3, api: ApiPromise, privateKeyWrapper: (account: string) => IKeyringPair }) => any, opts: { only?: boolean, skip?: boolean } = {}) {
let i: any = it;
if (opts.only) i = i.only;
@@ -199,7 +250,12 @@
return Web3.utils.toChecksumAddress(subToEthLowercase(eth));
}
-export function compileContract(name: string, src: string) {
+export interface CompiledContract {
+ abi: any,
+ object: string,
+}
+
+export function compileContract(name: string, src: string) : CompiledContract {
const out = JSON.parse(solc.compile(JSON.stringify({
language: 'Solidity',
sources: {
tests/src/evmCoder.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/evmCoder.test.ts
@@ -0,0 +1,117 @@
+// 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/>.
+
+import Web3 from 'web3';
+import {createEthAccountWithBalance, createRefungibleCollection, GAS_ARGS, itWeb3} from './eth/util/helpers';
+import * as solc from 'solc';
+
+import chai from 'chai';
+const expect = chai.expect;
+
+async function compileTestContract(collectionAddress: string, contractAddress: string) {
+ const input = {
+ language: 'Solidity',
+ sources: {
+ ['Test.sol']: {
+ content:
+ `
+ // SPDX-License-Identifier: MIT
+ pragma solidity ^0.8.0;
+ interface ITest {
+ function ztestzzzzzzz() external returns (uint256 n);
+ }
+ contract Test {
+ event Result(bool, uint256);
+ function test1() public {
+ try
+ ITest(${collectionAddress}).ztestzzzzzzz()
+ returns (uint256 n) {
+ // enters
+ emit Result(true, n); // => [true, BigNumber { value: "43648854190028290368124427828690944273759144372138548774646036134290060795932" }]
+ } catch {
+ emit Result(false, 0);
+ }
+ }
+ function test2() public {
+ try
+ ITest(${contractAddress}).ztestzzzzzzz()
+ returns (uint256 n) {
+ emit Result(true, n);
+ } catch {
+ // enters
+ emit Result(false, 0); // => [ false, BigNumber { value: "0" } ]
+ }
+ }
+ function test3() public {
+ ITest(${collectionAddress}).ztestzzzzzzz();
+ }
+ }
+ `,
+ },
+ },
+ settings: {
+ outputSelection: {
+ '*': {
+ '*': ['*'],
+ },
+ },
+ },
+ };
+ const json = JSON.parse(solc.compile(JSON.stringify(input)));
+ const out = json.contracts['Test.sol']['Test'];
+
+ return {
+ abi: out.abi,
+ object: '0x' + out.evm.bytecode.object,
+ };
+}
+
+async function deployTestContract(web3: Web3, owner: string, collectionAddress: string, contractAddress: string) {
+ const compiled = await compileTestContract(collectionAddress, contractAddress);
+ const fractionalizerContract = new web3.eth.Contract(compiled.abi, undefined, {
+ data: compiled.object,
+ from: owner,
+ ...GAS_ARGS,
+ });
+ return await fractionalizerContract.deploy({data: compiled.object}).send({from: owner});
+}
+
+describe('Evm Coder tests', () => {
+ itWeb3('Call non-existing function', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const {collectionIdAddress} = await createRefungibleCollection(api, web3, owner);
+ const contract = await deployTestContract(web3, owner, collectionIdAddress, '0x1bfed5D614b886b9Ab2eA4CBAc22A96B7EC29c9c');
+ const testContract = await deployTestContract(web3, owner, collectionIdAddress, contract.options.address);
+ {
+ const result = await testContract.methods.test1().send();
+ expect(result.events.Result.returnValues).to.deep.equal({
+ '0': false,
+ '1': '0',
+ });
+ }
+ {
+ const result = await testContract.methods.test2().send();
+ expect(result.events.Result.returnValues).to.deep.equal({
+ '0': false,
+ '1': '0',
+ });
+ }
+ {
+ await expect(testContract.methods.test3().call())
+ .to.be.rejectedWith(/unrecognized selector: 0xd9f02b36$/g);
+ }
+ });
+});
\ No newline at end of file
tests/src/fungible.test.tsdiffbeforeafterboth--- a/tests/src/fungible.test.ts
+++ b/tests/src/fungible.test.ts
@@ -14,25 +14,10 @@
// 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 {default as usingApi} from './substrate/substrate-api';
import {IKeyringPair} from '@polkadot/types/types';
-import {
- getBalance,
- createMultipleItemsExpectSuccess,
- isTokenExists,
- getLastTokenId,
- getAllowance,
- approve,
- transferFrom,
- createCollection,
- transfer,
- burnItem,
- normalizeAccountId,
- CrossAccountId,
- createFungibleItemExpectSuccess,
- U128_MAX,
- burnFromExpectSuccess,
-} from './util/helpers';
+import {U128_MAX} from './util/helpers';
+
+import {usingPlaygrounds} from './util/playgrounds';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
@@ -44,141 +29,137 @@
describe('integration test: Fungible functionality:', () => {
before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
+ await usingPlaygrounds(async (helper, privateKey) => {
+ alice = privateKey('//Alice');
+ bob = privateKey('//Bob');
});
});
it('Create fungible collection and token', async () => {
- await usingApi(async api => {
- const createCollectionResult = await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}});
- expect(createCollectionResult.success).to.be.true;
- const collectionId = createCollectionResult.collectionId;
- const defaultTokenId = await getLastTokenId(api, collectionId);
- const aliceTokenId = await createFungibleItemExpectSuccess(alice, collectionId, {Value: U128_MAX}, alice.address);
- const aliceBalance = await getBalance(api, collectionId, alice, aliceTokenId);
- const itemCountAfter = await getLastTokenId(api, collectionId);
-
- // What to expect
- // tslint:disable-next-line:no-unused-expression
+ 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);
+
+ await collection.mint(alice, {Substrate: alice.address}, 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);
});
});
it('RPC method tokenOnewrs for fungible collection and token', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
- const facelessCrowd = Array.from(Array(7).keys()).map(i => normalizeAccountId(privateKeyWrapper(i.toString())));
+ 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'});
+
+ await collection.mint(alice, {Substrate: alice.address}, U128_MAX);
+
+ await collection.transfer(alice, {Substrate: bob.address}, 1000n);
+ await collection.transfer(alice, ethAcc, 900n);
- 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);
+ await collection.transfer(alice, facelessCrowd[i], 1n);
}
-
- 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);
+ const owners = await collection.getTop10Owners();
+
// 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;
+ expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]);
+ expect(owners.length).to.be.equal(10);
- 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);
+ 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 usingApi(async api => {
+ await usingPlaygrounds(async helper => {
const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};
- const collectionId = (await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}})).collectionId;
- const tokenId = await createFungibleItemExpectSuccess(alice, collectionId, {Value: 500n}, alice.address);
+ const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+ await collection.mint(alice, {Substrate: alice.address}, 500n);
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(500n);
- expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;
- expect(await transfer(api, collectionId, tokenId, 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 getBalance(api, collectionId, alice, tokenId)).to.be.equal(300n);
- expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);
- expect(await getBalance(api, collectionId, ethAcc, tokenId)).to.be.equal(140n);
- await expect(transfer(api, collectionId, tokenId, alice, bob, 350n)).to.eventually.be.rejected;
+ 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;
});
});
it('Tokens multiple creation', async () => {
- await usingApi(async api => {
- const collectionId = (await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}})).collectionId;
-
- const args = [
- {Fungible: {Value: 500n}},
- {Fungible: {Value: 400n}},
- {Fungible: {Value: 300n}},
- ];
-
- await createMultipleItemsExpectSuccess(alice, collectionId, args);
- expect(await getBalance(api, collectionId, alice, 0)).to.be.equal(1200n);
- });
+ await usingPlaygrounds(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},
+ ]);
+
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1200n);
+ });
});
it('Burn some tokens ', async () => {
- await usingApi(async api => {
- const collectionId = (await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}})).collectionId;
- const tokenId = (await createFungibleItemExpectSuccess(alice, collectionId, {Value: 500n}, alice.address));
- expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(500n);
- expect(await burnItem(api, alice, collectionId, tokenId, 499n)).to.be.true;
- expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(1n);
+ 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);
+
+ 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 usingApi(async api => {
- const collectionId = (await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}})).collectionId;
- const tokenId = (await createFungibleItemExpectSuccess(alice, collectionId, {Value: 500n}, alice.address));
- expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;
- expect(await burnItem(api, alice, collectionId, tokenId, 500n)).to.be.true;
- expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;
-
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);
- expect((await api.rpc.unique.totalPieces(collectionId, tokenId)).value.toBigInt()).to.be.equal(0n);
+ 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);
+
+ 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);
});
});
it('Set allowance for token', async () => {
- await usingApi(async api => {
- const collectionId = (await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}})).collectionId;
+ 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);
+
+ expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(100n);
- const tokenId = (await createFungibleItemExpectSuccess(alice, collectionId, {Value: 100n}, alice.address));
- expect(await getBalance(api, collectionId, alice, tokenId)).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 approve(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;
- expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(60n);
- expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(0n);
-
- expect(await transferFrom(api, collectionId, tokenId, bob, alice, bob, 20n)).to.be.true;
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(80n);
- expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(20n);
- expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(40n);
-
- await burnFromExpectSuccess(bob, alice, collectionId, tokenId, 10n);
-
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(70n);
- expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(30n);
- expect(await transferFrom(api, collectionId, tokenId, bob, alice, ethAcc, 10n)).to.be.true;
- expect(await getBalance(api, collectionId, ethAcc, tokenId)).to.be.equal(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);
});
});
});
tests/src/interfaces/augment-api-consts.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-api-consts.ts
+++ b/tests/src/interfaces/augment-api-consts.ts
@@ -42,6 +42,14 @@
**/
[key: string]: Codec;
};
+ configuration: {
+ defaultMinGasPrice: u64 & AugmentedConst<ApiType>;
+ defaultWeightToFeeCoefficient: u32 & AugmentedConst<ApiType>;
+ /**
+ * Generic const
+ **/
+ [key: string]: Codec;
+ };
inflation: {
/**
* Number of blocks that pass between treasury balance updates due to inflation
tests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-api-errors.ts
+++ b/tests/src/interfaces/augment-api-errors.ts
@@ -173,7 +173,7 @@
**/
TransferNotAllowed: AugmentedError<ApiType>;
/**
- * Target collection doesn't support this operation
+ * The operation is not supported
**/
UnsupportedOperation: AugmentedError<ApiType>;
/**
tests/src/interfaces/augment-api-query.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-api-query.ts
+++ b/tests/src/interfaces/augment-api-query.ts
@@ -110,6 +110,14 @@
**/
[key: string]: QueryableStorageEntry<ApiType>;
};
+ configuration: {
+ minGasPriceOverride: AugmentedQuery<ApiType, () => Observable<u64>, []> & QueryableStorageEntry<ApiType, []>;
+ weightToFeeCoefficientOverride: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;
+ /**
+ * Generic query
+ **/
+ [key: string]: QueryableStorageEntry<ApiType>;
+ };
dmpQueue: {
/**
* The configuration.
@@ -266,7 +274,7 @@
*
* Currently used to store RMRK data.
**/
- tokenAuxProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: UpDataStructsPropertyScope | 'None' | 'Rmrk' | number | Uint8Array, arg4: Bytes | string | Uint8Array) => Observable<Option<Bytes>>, [u32, u32, UpDataStructsPropertyScope, Bytes]> & QueryableStorageEntry<ApiType, [u32, u32, UpDataStructsPropertyScope, Bytes]>;
+ tokenAuxProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: UpDataStructsPropertyScope | 'None' | 'Rmrk' | 'Eth' | number | Uint8Array, arg4: Bytes | string | Uint8Array) => Observable<Option<Bytes>>, [u32, u32, UpDataStructsPropertyScope, Bytes]> & QueryableStorageEntry<ApiType, [u32, u32, UpDataStructsPropertyScope, Bytes]>;
/**
* Used to enumerate token's children.
**/
tests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-api-tx.ts
+++ b/tests/src/interfaces/augment-api-tx.ts
@@ -104,6 +104,14 @@
**/
[key: string]: SubmittableExtrinsicFunction<ApiType>;
};
+ configuration: {
+ setMinGasPriceOverride: AugmentedSubmittable<(coeff: Option<u64> | null | object | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Option<u64>]>;
+ setWeightToFeeCoefficientOverride: AugmentedSubmittable<(coeff: Option<u32> | null | object | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Option<u32>]>;
+ /**
+ * Generic tx
+ **/
+ [key: string]: SubmittableExtrinsicFunction<ApiType>;
+ };
cumulusXcm: {
/**
* Generic tx
tests/src/interfaces/augment-types.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-types.ts
+++ b/tests/src/interfaces/augment-types.ts
@@ -1,7 +1,7 @@
// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
/* eslint-disable */
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default';
+import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default';
import type { Data, StorageKey } from '@polkadot/types';
import type { BitVec, Bool, Bytes, I128, I16, I256, I32, I64, I8, Json, Null, OptionBool, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec';
import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets';
@@ -763,6 +763,7 @@
PalletCallMetadataV14: PalletCallMetadataV14;
PalletCommonError: PalletCommonError;
PalletCommonEvent: PalletCommonEvent;
+ PalletConfigurationCall: PalletConfigurationCall;
PalletConstantMetadataLatest: PalletConstantMetadataLatest;
PalletConstantMetadataV14: PalletConstantMetadataV14;
PalletErrorMetadataLatest: PalletErrorMetadataLatest;
tests/src/interfaces/default/types.tsdiffbeforeafterboth--- a/tests/src/interfaces/default/types.ts
+++ b/tests/src/interfaces/default/types.ts
@@ -994,6 +994,19 @@
readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet';
}
+/** @name PalletConfigurationCall */
+export interface PalletConfigurationCall extends Enum {
+ readonly isSetWeightToFeeCoefficientOverride: boolean;
+ readonly asSetWeightToFeeCoefficientOverride: {
+ readonly coeff: Option<u32>;
+ } & Struct;
+ readonly isSetMinGasPriceOverride: boolean;
+ readonly asSetMinGasPriceOverride: {
+ readonly coeff: Option<u64>;
+ } & Struct;
+ readonly type: 'SetWeightToFeeCoefficientOverride' | 'SetMinGasPriceOverride';
+}
+
/** @name PalletEthereumCall */
export interface PalletEthereumCall extends Enum {
readonly isTransact: boolean;
@@ -2521,7 +2534,8 @@
export interface UpDataStructsPropertyScope extends Enum {
readonly isNone: boolean;
readonly isRmrk: boolean;
- readonly type: 'None' | 'Rmrk';
+ readonly isEth: boolean;
+ readonly type: 'None' | 'Rmrk' | 'Eth';
}
/** @name UpDataStructsRpcCollection */
tests/src/interfaces/lookup.tsdiffbeforeafterboth1// Auto-generated via `yarn polkadot-types-from-defs`, do not edit2/* eslint-disable */34/* eslint-disable sort-keys */56export default {7 /**8 * Lookup2: polkadot_primitives::v2::PersistedValidationData<primitive_types::H256, N>9 **/10 PolkadotPrimitivesV2PersistedValidationData: {11 parentHead: 'Bytes',12 relayParentNumber: 'u32',13 relayParentStorageRoot: 'H256',14 maxPovSize: 'u32'15 },16 /**17 * Lookup9: polkadot_primitives::v2::UpgradeRestriction18 **/19 PolkadotPrimitivesV2UpgradeRestriction: {20 _enum: ['Present']21 },22 /**23 * Lookup10: sp_trie::storage_proof::StorageProof24 **/25 SpTrieStorageProof: {26 trieNodes: 'BTreeSet<Bytes>'27 },28 /**29 * Lookup13: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot30 **/31 CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: {32 dmqMqcHead: 'H256',33 relayDispatchQueueSize: '(u32,u32)',34 ingressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>',35 egressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>'36 },37 /**38 * Lookup18: polkadot_primitives::v2::AbridgedHrmpChannel39 **/40 PolkadotPrimitivesV2AbridgedHrmpChannel: {41 maxCapacity: 'u32',42 maxTotalSize: 'u32',43 maxMessageSize: 'u32',44 msgCount: 'u32',45 totalSize: 'u32',46 mqcHead: 'Option<H256>'47 },48 /**49 * Lookup20: polkadot_primitives::v2::AbridgedHostConfiguration50 **/51 PolkadotPrimitivesV2AbridgedHostConfiguration: {52 maxCodeSize: 'u32',53 maxHeadDataSize: 'u32',54 maxUpwardQueueCount: 'u32',55 maxUpwardQueueSize: 'u32',56 maxUpwardMessageSize: 'u32',57 maxUpwardMessageNumPerCandidate: 'u32',58 hrmpMaxMessageNumPerCandidate: 'u32',59 validationUpgradeCooldown: 'u32',60 validationUpgradeDelay: 'u32'61 },62 /**63 * Lookup26: polkadot_core_primitives::OutboundHrmpMessage<polkadot_parachain::primitives::Id>64 **/65 PolkadotCorePrimitivesOutboundHrmpMessage: {66 recipient: 'u32',67 data: 'Bytes'68 },69 /**70 * Lookup28: cumulus_pallet_parachain_system::pallet::Call<T>71 **/72 CumulusPalletParachainSystemCall: {73 _enum: {74 set_validation_data: {75 data: 'CumulusPrimitivesParachainInherentParachainInherentData',76 },77 sudo_send_upward_message: {78 message: 'Bytes',79 },80 authorize_upgrade: {81 codeHash: 'H256',82 },83 enact_authorized_upgrade: {84 code: 'Bytes'85 }86 }87 },88 /**89 * Lookup29: cumulus_primitives_parachain_inherent::ParachainInherentData90 **/91 CumulusPrimitivesParachainInherentParachainInherentData: {92 validationData: 'PolkadotPrimitivesV2PersistedValidationData',93 relayChainState: 'SpTrieStorageProof',94 downwardMessages: 'Vec<PolkadotCorePrimitivesInboundDownwardMessage>',95 horizontalMessages: 'BTreeMap<u32, Vec<PolkadotCorePrimitivesInboundHrmpMessage>>'96 },97 /**98 * Lookup31: polkadot_core_primitives::InboundDownwardMessage<BlockNumber>99 **/100 PolkadotCorePrimitivesInboundDownwardMessage: {101 sentAt: 'u32',102 msg: 'Bytes'103 },104 /**105 * Lookup34: polkadot_core_primitives::InboundHrmpMessage<BlockNumber>106 **/107 PolkadotCorePrimitivesInboundHrmpMessage: {108 sentAt: 'u32',109 data: 'Bytes'110 },111 /**112 * Lookup37: cumulus_pallet_parachain_system::pallet::Event<T>113 **/114 CumulusPalletParachainSystemEvent: {115 _enum: {116 ValidationFunctionStored: 'Null',117 ValidationFunctionApplied: {118 relayChainBlockNum: 'u32',119 },120 ValidationFunctionDiscarded: 'Null',121 UpgradeAuthorized: {122 codeHash: 'H256',123 },124 DownwardMessagesReceived: {125 count: 'u32',126 },127 DownwardMessagesProcessed: {128 weightUsed: 'u64',129 dmqHead: 'H256'130 }131 }132 },133 /**134 * Lookup38: cumulus_pallet_parachain_system::pallet::Error<T>135 **/136 CumulusPalletParachainSystemError: {137 _enum: ['OverlappingUpgrades', 'ProhibitedByPolkadot', 'TooBig', 'ValidationDataNotAvailable', 'HostConfigurationNotAvailable', 'NotScheduled', 'NothingAuthorized', 'Unauthorized']138 },139 /**140 * Lookup41: pallet_balances::AccountData<Balance>141 **/142 PalletBalancesAccountData: {143 free: 'u128',144 reserved: 'u128',145 miscFrozen: 'u128',146 feeFrozen: 'u128'147 },148 /**149 * Lookup43: pallet_balances::BalanceLock<Balance>150 **/151 PalletBalancesBalanceLock: {152 id: '[u8;8]',153 amount: 'u128',154 reasons: 'PalletBalancesReasons'155 },156 /**157 * Lookup45: pallet_balances::Reasons158 **/159 PalletBalancesReasons: {160 _enum: ['Fee', 'Misc', 'All']161 },162 /**163 * Lookup48: pallet_balances::ReserveData<ReserveIdentifier, Balance>164 **/165 PalletBalancesReserveData: {166 id: '[u8;16]',167 amount: 'u128'168 },169 /**170 * Lookup51: pallet_balances::Releases171 **/172 PalletBalancesReleases: {173 _enum: ['V1_0_0', 'V2_0_0']174 },175 /**176 * Lookup52: pallet_balances::pallet::Call<T, I>177 **/178 PalletBalancesCall: {179 _enum: {180 transfer: {181 dest: 'MultiAddress',182 value: 'Compact<u128>',183 },184 set_balance: {185 who: 'MultiAddress',186 newFree: 'Compact<u128>',187 newReserved: 'Compact<u128>',188 },189 force_transfer: {190 source: 'MultiAddress',191 dest: 'MultiAddress',192 value: 'Compact<u128>',193 },194 transfer_keep_alive: {195 dest: 'MultiAddress',196 value: 'Compact<u128>',197 },198 transfer_all: {199 dest: 'MultiAddress',200 keepAlive: 'bool',201 },202 force_unreserve: {203 who: 'MultiAddress',204 amount: 'u128'205 }206 }207 },208 /**209 * Lookup58: pallet_balances::pallet::Event<T, I>210 **/211 PalletBalancesEvent: {212 _enum: {213 Endowed: {214 account: 'AccountId32',215 freeBalance: 'u128',216 },217 DustLost: {218 account: 'AccountId32',219 amount: 'u128',220 },221 Transfer: {222 from: 'AccountId32',223 to: 'AccountId32',224 amount: 'u128',225 },226 BalanceSet: {227 who: 'AccountId32',228 free: 'u128',229 reserved: 'u128',230 },231 Reserved: {232 who: 'AccountId32',233 amount: 'u128',234 },235 Unreserved: {236 who: 'AccountId32',237 amount: 'u128',238 },239 ReserveRepatriated: {240 from: 'AccountId32',241 to: 'AccountId32',242 amount: 'u128',243 destinationStatus: 'FrameSupportTokensMiscBalanceStatus',244 },245 Deposit: {246 who: 'AccountId32',247 amount: 'u128',248 },249 Withdraw: {250 who: 'AccountId32',251 amount: 'u128',252 },253 Slashed: {254 who: 'AccountId32',255 amount: 'u128'256 }257 }258 },259 /**260 * Lookup59: frame_support::traits::tokens::misc::BalanceStatus261 **/262 FrameSupportTokensMiscBalanceStatus: {263 _enum: ['Free', 'Reserved']264 },265 /**266 * Lookup60: pallet_balances::pallet::Error<T, I>267 **/268 PalletBalancesError: {269 _enum: ['VestingBalance', 'LiquidityRestrictions', 'InsufficientBalance', 'ExistentialDeposit', 'KeepAlive', 'ExistingVestingSchedule', 'DeadAccount', 'TooManyReserves']270 },271 /**272 * Lookup63: pallet_timestamp::pallet::Call<T>273 **/274 PalletTimestampCall: {275 _enum: {276 set: {277 now: 'Compact<u64>'278 }279 }280 },281 /**282 * Lookup66: pallet_transaction_payment::Releases283 **/284 PalletTransactionPaymentReleases: {285 _enum: ['V1Ancient', 'V2']286 },287 /**288 * Lookup67: pallet_treasury::Proposal<sp_core::crypto::AccountId32, Balance>289 **/290 PalletTreasuryProposal: {291 proposer: 'AccountId32',292 value: 'u128',293 beneficiary: 'AccountId32',294 bond: 'u128'295 },296 /**297 * Lookup70: pallet_treasury::pallet::Call<T, I>298 **/299 PalletTreasuryCall: {300 _enum: {301 propose_spend: {302 value: 'Compact<u128>',303 beneficiary: 'MultiAddress',304 },305 reject_proposal: {306 proposalId: 'Compact<u32>',307 },308 approve_proposal: {309 proposalId: 'Compact<u32>',310 },311 remove_approval: {312 proposalId: 'Compact<u32>'313 }314 }315 },316 /**317 * Lookup72: pallet_treasury::pallet::Event<T, I>318 **/319 PalletTreasuryEvent: {320 _enum: {321 Proposed: {322 proposalIndex: 'u32',323 },324 Spending: {325 budgetRemaining: 'u128',326 },327 Awarded: {328 proposalIndex: 'u32',329 award: 'u128',330 account: 'AccountId32',331 },332 Rejected: {333 proposalIndex: 'u32',334 slashed: 'u128',335 },336 Burnt: {337 burntFunds: 'u128',338 },339 Rollover: {340 rolloverBalance: 'u128',341 },342 Deposit: {343 value: 'u128'344 }345 }346 },347 /**348 * Lookup75: frame_support::PalletId349 **/350 FrameSupportPalletId: '[u8;8]',351 /**352 * Lookup76: pallet_treasury::pallet::Error<T, I>353 **/354 PalletTreasuryError: {355 _enum: ['InsufficientProposersBalance', 'InvalidIndex', 'TooManyApprovals', 'ProposalNotApproved']356 },357 /**358 * Lookup77: pallet_sudo::pallet::Call<T>359 **/360 PalletSudoCall: {361 _enum: {362 sudo: {363 call: 'Call',364 },365 sudo_unchecked_weight: {366 call: 'Call',367 weight: 'u64',368 },369 set_key: {370 _alias: {371 new_: 'new',372 },373 new_: 'MultiAddress',374 },375 sudo_as: {376 who: 'MultiAddress',377 call: 'Call'378 }379 }380 },381 /**382 * Lookup79: frame_system::pallet::Call<T>383 **/384 FrameSystemCall: {385 _enum: {386 fill_block: {387 ratio: 'Perbill',388 },389 remark: {390 remark: 'Bytes',391 },392 set_heap_pages: {393 pages: 'u64',394 },395 set_code: {396 code: 'Bytes',397 },398 set_code_without_checks: {399 code: 'Bytes',400 },401 set_storage: {402 items: 'Vec<(Bytes,Bytes)>',403 },404 kill_storage: {405 _alias: {406 keys_: 'keys',407 },408 keys_: 'Vec<Bytes>',409 },410 kill_prefix: {411 prefix: 'Bytes',412 subkeys: 'u32',413 },414 remark_with_event: {415 remark: 'Bytes'416 }417 }418 },419 /**420 * Lookup83: orml_vesting::module::Call<T>421 **/422 OrmlVestingModuleCall: {423 _enum: {424 claim: 'Null',425 vested_transfer: {426 dest: 'MultiAddress',427 schedule: 'OrmlVestingVestingSchedule',428 },429 update_vesting_schedules: {430 who: 'MultiAddress',431 vestingSchedules: 'Vec<OrmlVestingVestingSchedule>',432 },433 claim_for: {434 dest: 'MultiAddress'435 }436 }437 },438 /**439 * Lookup84: orml_vesting::VestingSchedule<BlockNumber, Balance>440 **/441 OrmlVestingVestingSchedule: {442 start: 'u32',443 period: 'u32',444 periodCount: 'u32',445 perPeriod: 'Compact<u128>'446 },447 /**448 * Lookup86: cumulus_pallet_xcmp_queue::pallet::Call<T>449 **/450 CumulusPalletXcmpQueueCall: {451 _enum: {452 service_overweight: {453 index: 'u64',454 weightLimit: 'u64',455 },456 suspend_xcm_execution: 'Null',457 resume_xcm_execution: 'Null',458 update_suspend_threshold: {459 _alias: {460 new_: 'new',461 },462 new_: 'u32',463 },464 update_drop_threshold: {465 _alias: {466 new_: 'new',467 },468 new_: 'u32',469 },470 update_resume_threshold: {471 _alias: {472 new_: 'new',473 },474 new_: 'u32',475 },476 update_threshold_weight: {477 _alias: {478 new_: 'new',479 },480 new_: 'u64',481 },482 update_weight_restrict_decay: {483 _alias: {484 new_: 'new',485 },486 new_: 'u64',487 },488 update_xcmp_max_individual_weight: {489 _alias: {490 new_: 'new',491 },492 new_: 'u64'493 }494 }495 },496 /**497 * Lookup87: pallet_xcm::pallet::Call<T>498 **/499 PalletXcmCall: {500 _enum: {501 send: {502 dest: 'XcmVersionedMultiLocation',503 message: 'XcmVersionedXcm',504 },505 teleport_assets: {506 dest: 'XcmVersionedMultiLocation',507 beneficiary: 'XcmVersionedMultiLocation',508 assets: 'XcmVersionedMultiAssets',509 feeAssetItem: 'u32',510 },511 reserve_transfer_assets: {512 dest: 'XcmVersionedMultiLocation',513 beneficiary: 'XcmVersionedMultiLocation',514 assets: 'XcmVersionedMultiAssets',515 feeAssetItem: 'u32',516 },517 execute: {518 message: 'XcmVersionedXcm',519 maxWeight: 'u64',520 },521 force_xcm_version: {522 location: 'XcmV1MultiLocation',523 xcmVersion: 'u32',524 },525 force_default_xcm_version: {526 maybeXcmVersion: 'Option<u32>',527 },528 force_subscribe_version_notify: {529 location: 'XcmVersionedMultiLocation',530 },531 force_unsubscribe_version_notify: {532 location: 'XcmVersionedMultiLocation',533 },534 limited_reserve_transfer_assets: {535 dest: 'XcmVersionedMultiLocation',536 beneficiary: 'XcmVersionedMultiLocation',537 assets: 'XcmVersionedMultiAssets',538 feeAssetItem: 'u32',539 weightLimit: 'XcmV2WeightLimit',540 },541 limited_teleport_assets: {542 dest: 'XcmVersionedMultiLocation',543 beneficiary: 'XcmVersionedMultiLocation',544 assets: 'XcmVersionedMultiAssets',545 feeAssetItem: 'u32',546 weightLimit: 'XcmV2WeightLimit'547 }548 }549 },550 /**551 * Lookup88: xcm::VersionedMultiLocation552 **/553 XcmVersionedMultiLocation: {554 _enum: {555 V0: 'XcmV0MultiLocation',556 V1: 'XcmV1MultiLocation'557 }558 },559 /**560 * Lookup89: xcm::v0::multi_location::MultiLocation561 **/562 XcmV0MultiLocation: {563 _enum: {564 Null: 'Null',565 X1: 'XcmV0Junction',566 X2: '(XcmV0Junction,XcmV0Junction)',567 X3: '(XcmV0Junction,XcmV0Junction,XcmV0Junction)',568 X4: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',569 X5: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',570 X6: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',571 X7: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',572 X8: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)'573 }574 },575 /**576 * Lookup90: xcm::v0::junction::Junction577 **/578 XcmV0Junction: {579 _enum: {580 Parent: 'Null',581 Parachain: 'Compact<u32>',582 AccountId32: {583 network: 'XcmV0JunctionNetworkId',584 id: '[u8;32]',585 },586 AccountIndex64: {587 network: 'XcmV0JunctionNetworkId',588 index: 'Compact<u64>',589 },590 AccountKey20: {591 network: 'XcmV0JunctionNetworkId',592 key: '[u8;20]',593 },594 PalletInstance: 'u8',595 GeneralIndex: 'Compact<u128>',596 GeneralKey: 'Bytes',597 OnlyChild: 'Null',598 Plurality: {599 id: 'XcmV0JunctionBodyId',600 part: 'XcmV0JunctionBodyPart'601 }602 }603 },604 /**605 * Lookup91: xcm::v0::junction::NetworkId606 **/607 XcmV0JunctionNetworkId: {608 _enum: {609 Any: 'Null',610 Named: 'Bytes',611 Polkadot: 'Null',612 Kusama: 'Null'613 }614 },615 /**616 * Lookup92: xcm::v0::junction::BodyId617 **/618 XcmV0JunctionBodyId: {619 _enum: {620 Unit: 'Null',621 Named: 'Bytes',622 Index: 'Compact<u32>',623 Executive: 'Null',624 Technical: 'Null',625 Legislative: 'Null',626 Judicial: 'Null'627 }628 },629 /**630 * Lookup93: xcm::v0::junction::BodyPart631 **/632 XcmV0JunctionBodyPart: {633 _enum: {634 Voice: 'Null',635 Members: {636 count: 'Compact<u32>',637 },638 Fraction: {639 nom: 'Compact<u32>',640 denom: 'Compact<u32>',641 },642 AtLeastProportion: {643 nom: 'Compact<u32>',644 denom: 'Compact<u32>',645 },646 MoreThanProportion: {647 nom: 'Compact<u32>',648 denom: 'Compact<u32>'649 }650 }651 },652 /**653 * Lookup94: xcm::v1::multilocation::MultiLocation654 **/655 XcmV1MultiLocation: {656 parents: 'u8',657 interior: 'XcmV1MultilocationJunctions'658 },659 /**660 * Lookup95: xcm::v1::multilocation::Junctions661 **/662 XcmV1MultilocationJunctions: {663 _enum: {664 Here: 'Null',665 X1: 'XcmV1Junction',666 X2: '(XcmV1Junction,XcmV1Junction)',667 X3: '(XcmV1Junction,XcmV1Junction,XcmV1Junction)',668 X4: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',669 X5: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',670 X6: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',671 X7: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',672 X8: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)'673 }674 },675 /**676 * Lookup96: xcm::v1::junction::Junction677 **/678 XcmV1Junction: {679 _enum: {680 Parachain: 'Compact<u32>',681 AccountId32: {682 network: 'XcmV0JunctionNetworkId',683 id: '[u8;32]',684 },685 AccountIndex64: {686 network: 'XcmV0JunctionNetworkId',687 index: 'Compact<u64>',688 },689 AccountKey20: {690 network: 'XcmV0JunctionNetworkId',691 key: '[u8;20]',692 },693 PalletInstance: 'u8',694 GeneralIndex: 'Compact<u128>',695 GeneralKey: 'Bytes',696 OnlyChild: 'Null',697 Plurality: {698 id: 'XcmV0JunctionBodyId',699 part: 'XcmV0JunctionBodyPart'700 }701 }702 },703 /**704 * Lookup97: xcm::VersionedXcm<Call>705 **/706 XcmVersionedXcm: {707 _enum: {708 V0: 'XcmV0Xcm',709 V1: 'XcmV1Xcm',710 V2: 'XcmV2Xcm'711 }712 },713 /**714 * Lookup98: xcm::v0::Xcm<Call>715 **/716 XcmV0Xcm: {717 _enum: {718 WithdrawAsset: {719 assets: 'Vec<XcmV0MultiAsset>',720 effects: 'Vec<XcmV0Order>',721 },722 ReserveAssetDeposit: {723 assets: 'Vec<XcmV0MultiAsset>',724 effects: 'Vec<XcmV0Order>',725 },726 TeleportAsset: {727 assets: 'Vec<XcmV0MultiAsset>',728 effects: 'Vec<XcmV0Order>',729 },730 QueryResponse: {731 queryId: 'Compact<u64>',732 response: 'XcmV0Response',733 },734 TransferAsset: {735 assets: 'Vec<XcmV0MultiAsset>',736 dest: 'XcmV0MultiLocation',737 },738 TransferReserveAsset: {739 assets: 'Vec<XcmV0MultiAsset>',740 dest: 'XcmV0MultiLocation',741 effects: 'Vec<XcmV0Order>',742 },743 Transact: {744 originType: 'XcmV0OriginKind',745 requireWeightAtMost: 'u64',746 call: 'XcmDoubleEncoded',747 },748 HrmpNewChannelOpenRequest: {749 sender: 'Compact<u32>',750 maxMessageSize: 'Compact<u32>',751 maxCapacity: 'Compact<u32>',752 },753 HrmpChannelAccepted: {754 recipient: 'Compact<u32>',755 },756 HrmpChannelClosing: {757 initiator: 'Compact<u32>',758 sender: 'Compact<u32>',759 recipient: 'Compact<u32>',760 },761 RelayedFrom: {762 who: 'XcmV0MultiLocation',763 message: 'XcmV0Xcm'764 }765 }766 },767 /**768 * Lookup100: xcm::v0::multi_asset::MultiAsset769 **/770 XcmV0MultiAsset: {771 _enum: {772 None: 'Null',773 All: 'Null',774 AllFungible: 'Null',775 AllNonFungible: 'Null',776 AllAbstractFungible: {777 id: 'Bytes',778 },779 AllAbstractNonFungible: {780 class: 'Bytes',781 },782 AllConcreteFungible: {783 id: 'XcmV0MultiLocation',784 },785 AllConcreteNonFungible: {786 class: 'XcmV0MultiLocation',787 },788 AbstractFungible: {789 id: 'Bytes',790 amount: 'Compact<u128>',791 },792 AbstractNonFungible: {793 class: 'Bytes',794 instance: 'XcmV1MultiassetAssetInstance',795 },796 ConcreteFungible: {797 id: 'XcmV0MultiLocation',798 amount: 'Compact<u128>',799 },800 ConcreteNonFungible: {801 class: 'XcmV0MultiLocation',802 instance: 'XcmV1MultiassetAssetInstance'803 }804 }805 },806 /**807 * Lookup101: xcm::v1::multiasset::AssetInstance808 **/809 XcmV1MultiassetAssetInstance: {810 _enum: {811 Undefined: 'Null',812 Index: 'Compact<u128>',813 Array4: '[u8;4]',814 Array8: '[u8;8]',815 Array16: '[u8;16]',816 Array32: '[u8;32]',817 Blob: 'Bytes'818 }819 },820 /**821 * Lookup104: xcm::v0::order::Order<Call>822 **/823 XcmV0Order: {824 _enum: {825 Null: 'Null',826 DepositAsset: {827 assets: 'Vec<XcmV0MultiAsset>',828 dest: 'XcmV0MultiLocation',829 },830 DepositReserveAsset: {831 assets: 'Vec<XcmV0MultiAsset>',832 dest: 'XcmV0MultiLocation',833 effects: 'Vec<XcmV0Order>',834 },835 ExchangeAsset: {836 give: 'Vec<XcmV0MultiAsset>',837 receive: 'Vec<XcmV0MultiAsset>',838 },839 InitiateReserveWithdraw: {840 assets: 'Vec<XcmV0MultiAsset>',841 reserve: 'XcmV0MultiLocation',842 effects: 'Vec<XcmV0Order>',843 },844 InitiateTeleport: {845 assets: 'Vec<XcmV0MultiAsset>',846 dest: 'XcmV0MultiLocation',847 effects: 'Vec<XcmV0Order>',848 },849 QueryHolding: {850 queryId: 'Compact<u64>',851 dest: 'XcmV0MultiLocation',852 assets: 'Vec<XcmV0MultiAsset>',853 },854 BuyExecution: {855 fees: 'XcmV0MultiAsset',856 weight: 'u64',857 debt: 'u64',858 haltOnError: 'bool',859 xcm: 'Vec<XcmV0Xcm>'860 }861 }862 },863 /**864 * Lookup106: xcm::v0::Response865 **/866 XcmV0Response: {867 _enum: {868 Assets: 'Vec<XcmV0MultiAsset>'869 }870 },871 /**872 * Lookup107: xcm::v0::OriginKind873 **/874 XcmV0OriginKind: {875 _enum: ['Native', 'SovereignAccount', 'Superuser', 'Xcm']876 },877 /**878 * Lookup108: xcm::double_encoded::DoubleEncoded<T>879 **/880 XcmDoubleEncoded: {881 encoded: 'Bytes'882 },883 /**884 * Lookup109: xcm::v1::Xcm<Call>885 **/886 XcmV1Xcm: {887 _enum: {888 WithdrawAsset: {889 assets: 'XcmV1MultiassetMultiAssets',890 effects: 'Vec<XcmV1Order>',891 },892 ReserveAssetDeposited: {893 assets: 'XcmV1MultiassetMultiAssets',894 effects: 'Vec<XcmV1Order>',895 },896 ReceiveTeleportedAsset: {897 assets: 'XcmV1MultiassetMultiAssets',898 effects: 'Vec<XcmV1Order>',899 },900 QueryResponse: {901 queryId: 'Compact<u64>',902 response: 'XcmV1Response',903 },904 TransferAsset: {905 assets: 'XcmV1MultiassetMultiAssets',906 beneficiary: 'XcmV1MultiLocation',907 },908 TransferReserveAsset: {909 assets: 'XcmV1MultiassetMultiAssets',910 dest: 'XcmV1MultiLocation',911 effects: 'Vec<XcmV1Order>',912 },913 Transact: {914 originType: 'XcmV0OriginKind',915 requireWeightAtMost: 'u64',916 call: 'XcmDoubleEncoded',917 },918 HrmpNewChannelOpenRequest: {919 sender: 'Compact<u32>',920 maxMessageSize: 'Compact<u32>',921 maxCapacity: 'Compact<u32>',922 },923 HrmpChannelAccepted: {924 recipient: 'Compact<u32>',925 },926 HrmpChannelClosing: {927 initiator: 'Compact<u32>',928 sender: 'Compact<u32>',929 recipient: 'Compact<u32>',930 },931 RelayedFrom: {932 who: 'XcmV1MultilocationJunctions',933 message: 'XcmV1Xcm',934 },935 SubscribeVersion: {936 queryId: 'Compact<u64>',937 maxResponseWeight: 'Compact<u64>',938 },939 UnsubscribeVersion: 'Null'940 }941 },942 /**943 * Lookup110: xcm::v1::multiasset::MultiAssets944 **/945 XcmV1MultiassetMultiAssets: 'Vec<XcmV1MultiAsset>',946 /**947 * Lookup112: xcm::v1::multiasset::MultiAsset948 **/949 XcmV1MultiAsset: {950 id: 'XcmV1MultiassetAssetId',951 fun: 'XcmV1MultiassetFungibility'952 },953 /**954 * Lookup113: xcm::v1::multiasset::AssetId955 **/956 XcmV1MultiassetAssetId: {957 _enum: {958 Concrete: 'XcmV1MultiLocation',959 Abstract: 'Bytes'960 }961 },962 /**963 * Lookup114: xcm::v1::multiasset::Fungibility964 **/965 XcmV1MultiassetFungibility: {966 _enum: {967 Fungible: 'Compact<u128>',968 NonFungible: 'XcmV1MultiassetAssetInstance'969 }970 },971 /**972 * Lookup116: xcm::v1::order::Order<Call>973 **/974 XcmV1Order: {975 _enum: {976 Noop: 'Null',977 DepositAsset: {978 assets: 'XcmV1MultiassetMultiAssetFilter',979 maxAssets: 'u32',980 beneficiary: 'XcmV1MultiLocation',981 },982 DepositReserveAsset: {983 assets: 'XcmV1MultiassetMultiAssetFilter',984 maxAssets: 'u32',985 dest: 'XcmV1MultiLocation',986 effects: 'Vec<XcmV1Order>',987 },988 ExchangeAsset: {989 give: 'XcmV1MultiassetMultiAssetFilter',990 receive: 'XcmV1MultiassetMultiAssets',991 },992 InitiateReserveWithdraw: {993 assets: 'XcmV1MultiassetMultiAssetFilter',994 reserve: 'XcmV1MultiLocation',995 effects: 'Vec<XcmV1Order>',996 },997 InitiateTeleport: {998 assets: 'XcmV1MultiassetMultiAssetFilter',999 dest: 'XcmV1MultiLocation',1000 effects: 'Vec<XcmV1Order>',1001 },1002 QueryHolding: {1003 queryId: 'Compact<u64>',1004 dest: 'XcmV1MultiLocation',1005 assets: 'XcmV1MultiassetMultiAssetFilter',1006 },1007 BuyExecution: {1008 fees: 'XcmV1MultiAsset',1009 weight: 'u64',1010 debt: 'u64',1011 haltOnError: 'bool',1012 instructions: 'Vec<XcmV1Xcm>'1013 }1014 }1015 },1016 /**1017 * Lookup117: xcm::v1::multiasset::MultiAssetFilter1018 **/1019 XcmV1MultiassetMultiAssetFilter: {1020 _enum: {1021 Definite: 'XcmV1MultiassetMultiAssets',1022 Wild: 'XcmV1MultiassetWildMultiAsset'1023 }1024 },1025 /**1026 * Lookup118: xcm::v1::multiasset::WildMultiAsset1027 **/1028 XcmV1MultiassetWildMultiAsset: {1029 _enum: {1030 All: 'Null',1031 AllOf: {1032 id: 'XcmV1MultiassetAssetId',1033 fun: 'XcmV1MultiassetWildFungibility'1034 }1035 }1036 },1037 /**1038 * Lookup119: xcm::v1::multiasset::WildFungibility1039 **/1040 XcmV1MultiassetWildFungibility: {1041 _enum: ['Fungible', 'NonFungible']1042 },1043 /**1044 * Lookup121: xcm::v1::Response1045 **/1046 XcmV1Response: {1047 _enum: {1048 Assets: 'XcmV1MultiassetMultiAssets',1049 Version: 'u32'1050 }1051 },1052 /**1053 * Lookup122: xcm::v2::Xcm<Call>1054 **/1055 XcmV2Xcm: 'Vec<XcmV2Instruction>',1056 /**1057 * Lookup124: xcm::v2::Instruction<Call>1058 **/1059 XcmV2Instruction: {1060 _enum: {1061 WithdrawAsset: 'XcmV1MultiassetMultiAssets',1062 ReserveAssetDeposited: 'XcmV1MultiassetMultiAssets',1063 ReceiveTeleportedAsset: 'XcmV1MultiassetMultiAssets',1064 QueryResponse: {1065 queryId: 'Compact<u64>',1066 response: 'XcmV2Response',1067 maxWeight: 'Compact<u64>',1068 },1069 TransferAsset: {1070 assets: 'XcmV1MultiassetMultiAssets',1071 beneficiary: 'XcmV1MultiLocation',1072 },1073 TransferReserveAsset: {1074 assets: 'XcmV1MultiassetMultiAssets',1075 dest: 'XcmV1MultiLocation',1076 xcm: 'XcmV2Xcm',1077 },1078 Transact: {1079 originType: 'XcmV0OriginKind',1080 requireWeightAtMost: 'Compact<u64>',1081 call: 'XcmDoubleEncoded',1082 },1083 HrmpNewChannelOpenRequest: {1084 sender: 'Compact<u32>',1085 maxMessageSize: 'Compact<u32>',1086 maxCapacity: 'Compact<u32>',1087 },1088 HrmpChannelAccepted: {1089 recipient: 'Compact<u32>',1090 },1091 HrmpChannelClosing: {1092 initiator: 'Compact<u32>',1093 sender: 'Compact<u32>',1094 recipient: 'Compact<u32>',1095 },1096 ClearOrigin: 'Null',1097 DescendOrigin: 'XcmV1MultilocationJunctions',1098 ReportError: {1099 queryId: 'Compact<u64>',1100 dest: 'XcmV1MultiLocation',1101 maxResponseWeight: 'Compact<u64>',1102 },1103 DepositAsset: {1104 assets: 'XcmV1MultiassetMultiAssetFilter',1105 maxAssets: 'Compact<u32>',1106 beneficiary: 'XcmV1MultiLocation',1107 },1108 DepositReserveAsset: {1109 assets: 'XcmV1MultiassetMultiAssetFilter',1110 maxAssets: 'Compact<u32>',1111 dest: 'XcmV1MultiLocation',1112 xcm: 'XcmV2Xcm',1113 },1114 ExchangeAsset: {1115 give: 'XcmV1MultiassetMultiAssetFilter',1116 receive: 'XcmV1MultiassetMultiAssets',1117 },1118 InitiateReserveWithdraw: {1119 assets: 'XcmV1MultiassetMultiAssetFilter',1120 reserve: 'XcmV1MultiLocation',1121 xcm: 'XcmV2Xcm',1122 },1123 InitiateTeleport: {1124 assets: 'XcmV1MultiassetMultiAssetFilter',1125 dest: 'XcmV1MultiLocation',1126 xcm: 'XcmV2Xcm',1127 },1128 QueryHolding: {1129 queryId: 'Compact<u64>',1130 dest: 'XcmV1MultiLocation',1131 assets: 'XcmV1MultiassetMultiAssetFilter',1132 maxResponseWeight: 'Compact<u64>',1133 },1134 BuyExecution: {1135 fees: 'XcmV1MultiAsset',1136 weightLimit: 'XcmV2WeightLimit',1137 },1138 RefundSurplus: 'Null',1139 SetErrorHandler: 'XcmV2Xcm',1140 SetAppendix: 'XcmV2Xcm',1141 ClearError: 'Null',1142 ClaimAsset: {1143 assets: 'XcmV1MultiassetMultiAssets',1144 ticket: 'XcmV1MultiLocation',1145 },1146 Trap: 'Compact<u64>',1147 SubscribeVersion: {1148 queryId: 'Compact<u64>',1149 maxResponseWeight: 'Compact<u64>',1150 },1151 UnsubscribeVersion: 'Null'1152 }1153 },1154 /**1155 * Lookup125: xcm::v2::Response1156 **/1157 XcmV2Response: {1158 _enum: {1159 Null: 'Null',1160 Assets: 'XcmV1MultiassetMultiAssets',1161 ExecutionResult: 'Option<(u32,XcmV2TraitsError)>',1162 Version: 'u32'1163 }1164 },1165 /**1166 * Lookup128: xcm::v2::traits::Error1167 **/1168 XcmV2TraitsError: {1169 _enum: {1170 Overflow: 'Null',1171 Unimplemented: 'Null',1172 UntrustedReserveLocation: 'Null',1173 UntrustedTeleportLocation: 'Null',1174 MultiLocationFull: 'Null',1175 MultiLocationNotInvertible: 'Null',1176 BadOrigin: 'Null',1177 InvalidLocation: 'Null',1178 AssetNotFound: 'Null',1179 FailedToTransactAsset: 'Null',1180 NotWithdrawable: 'Null',1181 LocationCannotHold: 'Null',1182 ExceedsMaxMessageSize: 'Null',1183 DestinationUnsupported: 'Null',1184 Transport: 'Null',1185 Unroutable: 'Null',1186 UnknownClaim: 'Null',1187 FailedToDecode: 'Null',1188 MaxWeightInvalid: 'Null',1189 NotHoldingFees: 'Null',1190 TooExpensive: 'Null',1191 Trap: 'u64',1192 UnhandledXcmVersion: 'Null',1193 WeightLimitReached: 'u64',1194 Barrier: 'Null',1195 WeightNotComputable: 'Null'1196 }1197 },1198 /**1199 * Lookup129: xcm::v2::WeightLimit1200 **/1201 XcmV2WeightLimit: {1202 _enum: {1203 Unlimited: 'Null',1204 Limited: 'Compact<u64>'1205 }1206 },1207 /**1208 * Lookup130: xcm::VersionedMultiAssets1209 **/1210 XcmVersionedMultiAssets: {1211 _enum: {1212 V0: 'Vec<XcmV0MultiAsset>',1213 V1: 'XcmV1MultiassetMultiAssets'1214 }1215 },1216 /**1217 * Lookup145: cumulus_pallet_xcm::pallet::Call<T>1218 **/1219 CumulusPalletXcmCall: 'Null',1220 /**1221 * Lookup146: cumulus_pallet_dmp_queue::pallet::Call<T>1222 **/1223 CumulusPalletDmpQueueCall: {1224 _enum: {1225 service_overweight: {1226 index: 'u64',1227 weightLimit: 'u64'1228 }1229 }1230 },1231 /**1232 * Lookup147: pallet_inflation::pallet::Call<T>1233 **/1234 PalletInflationCall: {1235 _enum: {1236 start_inflation: {1237 inflationStartRelayBlock: 'u32'1238 }1239 }1240 },1241 /**1242 * Lookup148: pallet_unique::Call<T>1243 **/1244 PalletUniqueCall: {1245 _enum: {1246 create_collection: {1247 collectionName: 'Vec<u16>',1248 collectionDescription: 'Vec<u16>',1249 tokenPrefix: 'Bytes',1250 mode: 'UpDataStructsCollectionMode',1251 },1252 create_collection_ex: {1253 data: 'UpDataStructsCreateCollectionData',1254 },1255 destroy_collection: {1256 collectionId: 'u32',1257 },1258 add_to_allow_list: {1259 collectionId: 'u32',1260 address: 'PalletEvmAccountBasicCrossAccountIdRepr',1261 },1262 remove_from_allow_list: {1263 collectionId: 'u32',1264 address: 'PalletEvmAccountBasicCrossAccountIdRepr',1265 },1266 change_collection_owner: {1267 collectionId: 'u32',1268 newOwner: 'AccountId32',1269 },1270 add_collection_admin: {1271 collectionId: 'u32',1272 newAdmin: 'PalletEvmAccountBasicCrossAccountIdRepr',1273 },1274 remove_collection_admin: {1275 collectionId: 'u32',1276 accountId: 'PalletEvmAccountBasicCrossAccountIdRepr',1277 },1278 set_collection_sponsor: {1279 collectionId: 'u32',1280 newSponsor: 'AccountId32',1281 },1282 confirm_sponsorship: {1283 collectionId: 'u32',1284 },1285 remove_collection_sponsor: {1286 collectionId: 'u32',1287 },1288 create_item: {1289 collectionId: 'u32',1290 owner: 'PalletEvmAccountBasicCrossAccountIdRepr',1291 data: 'UpDataStructsCreateItemData',1292 },1293 create_multiple_items: {1294 collectionId: 'u32',1295 owner: 'PalletEvmAccountBasicCrossAccountIdRepr',1296 itemsData: 'Vec<UpDataStructsCreateItemData>',1297 },1298 set_collection_properties: {1299 collectionId: 'u32',1300 properties: 'Vec<UpDataStructsProperty>',1301 },1302 delete_collection_properties: {1303 collectionId: 'u32',1304 propertyKeys: 'Vec<Bytes>',1305 },1306 set_token_properties: {1307 collectionId: 'u32',1308 tokenId: 'u32',1309 properties: 'Vec<UpDataStructsProperty>',1310 },1311 delete_token_properties: {1312 collectionId: 'u32',1313 tokenId: 'u32',1314 propertyKeys: 'Vec<Bytes>',1315 },1316 set_token_property_permissions: {1317 collectionId: 'u32',1318 propertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',1319 },1320 create_multiple_items_ex: {1321 collectionId: 'u32',1322 data: 'UpDataStructsCreateItemExData',1323 },1324 set_transfers_enabled_flag: {1325 collectionId: 'u32',1326 value: 'bool',1327 },1328 burn_item: {1329 collectionId: 'u32',1330 itemId: 'u32',1331 value: 'u128',1332 },1333 burn_from: {1334 collectionId: 'u32',1335 from: 'PalletEvmAccountBasicCrossAccountIdRepr',1336 itemId: 'u32',1337 value: 'u128',1338 },1339 transfer: {1340 recipient: 'PalletEvmAccountBasicCrossAccountIdRepr',1341 collectionId: 'u32',1342 itemId: 'u32',1343 value: 'u128',1344 },1345 approve: {1346 spender: 'PalletEvmAccountBasicCrossAccountIdRepr',1347 collectionId: 'u32',1348 itemId: 'u32',1349 amount: 'u128',1350 },1351 transfer_from: {1352 from: 'PalletEvmAccountBasicCrossAccountIdRepr',1353 recipient: 'PalletEvmAccountBasicCrossAccountIdRepr',1354 collectionId: 'u32',1355 itemId: 'u32',1356 value: 'u128',1357 },1358 set_collection_limits: {1359 collectionId: 'u32',1360 newLimit: 'UpDataStructsCollectionLimits',1361 },1362 set_collection_permissions: {1363 collectionId: 'u32',1364 newPermission: 'UpDataStructsCollectionPermissions',1365 },1366 repartition: {1367 collectionId: 'u32',1368 tokenId: 'u32',1369 amount: 'u128'1370 }1371 }1372 },1373 /**1374 * Lookup154: up_data_structs::CollectionMode1375 **/1376 UpDataStructsCollectionMode: {1377 _enum: {1378 NFT: 'Null',1379 Fungible: 'u8',1380 ReFungible: 'Null'1381 }1382 },1383 /**1384 * Lookup155: up_data_structs::CreateCollectionData<sp_core::crypto::AccountId32>1385 **/1386 UpDataStructsCreateCollectionData: {1387 mode: 'UpDataStructsCollectionMode',1388 access: 'Option<UpDataStructsAccessMode>',1389 name: 'Vec<u16>',1390 description: 'Vec<u16>',1391 tokenPrefix: 'Bytes',1392 pendingSponsor: 'Option<AccountId32>',1393 limits: 'Option<UpDataStructsCollectionLimits>',1394 permissions: 'Option<UpDataStructsCollectionPermissions>',1395 tokenPropertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',1396 properties: 'Vec<UpDataStructsProperty>'1397 },1398 /**1399 * Lookup157: up_data_structs::AccessMode1400 **/1401 UpDataStructsAccessMode: {1402 _enum: ['Normal', 'AllowList']1403 },1404 /**1405 * Lookup160: up_data_structs::CollectionLimits1406 **/1407 UpDataStructsCollectionLimits: {1408 accountTokenOwnershipLimit: 'Option<u32>',1409 sponsoredDataSize: 'Option<u32>',1410 sponsoredDataRateLimit: 'Option<UpDataStructsSponsoringRateLimit>',1411 tokenLimit: 'Option<u32>',1412 sponsorTransferTimeout: 'Option<u32>',1413 sponsorApproveTimeout: 'Option<u32>',1414 ownerCanTransfer: 'Option<bool>',1415 ownerCanDestroy: 'Option<bool>',1416 transfersEnabled: 'Option<bool>'1417 },1418 /**1419 * Lookup162: up_data_structs::SponsoringRateLimit1420 **/1421 UpDataStructsSponsoringRateLimit: {1422 _enum: {1423 SponsoringDisabled: 'Null',1424 Blocks: 'u32'1425 }1426 },1427 /**1428 * Lookup165: up_data_structs::CollectionPermissions1429 **/1430 UpDataStructsCollectionPermissions: {1431 access: 'Option<UpDataStructsAccessMode>',1432 mintMode: 'Option<bool>',1433 nesting: 'Option<UpDataStructsNestingPermissions>'1434 },1435 /**1436 * Lookup167: up_data_structs::NestingPermissions1437 **/1438 UpDataStructsNestingPermissions: {1439 tokenOwner: 'bool',1440 collectionAdmin: 'bool',1441 restricted: 'Option<UpDataStructsOwnerRestrictedSet>'1442 },1443 /**1444 * Lookup169: up_data_structs::OwnerRestrictedSet1445 **/1446 UpDataStructsOwnerRestrictedSet: 'BTreeSet<u32>',1447 /**1448 * Lookup175: up_data_structs::PropertyKeyPermission1449 **/1450 UpDataStructsPropertyKeyPermission: {1451 key: 'Bytes',1452 permission: 'UpDataStructsPropertyPermission'1453 },1454 /**1455 * Lookup177: up_data_structs::PropertyPermission1456 **/1457 UpDataStructsPropertyPermission: {1458 mutable: 'bool',1459 collectionAdmin: 'bool',1460 tokenOwner: 'bool'1461 },1462 /**1463 * Lookup180: up_data_structs::Property1464 **/1465 UpDataStructsProperty: {1466 key: 'Bytes',1467 value: 'Bytes'1468 },1469 /**1470 * Lookup183: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>1471 **/1472 PalletEvmAccountBasicCrossAccountIdRepr: {1473 _enum: {1474 Substrate: 'AccountId32',1475 Ethereum: 'H160'1476 }1477 },1478 /**1479 * Lookup185: up_data_structs::CreateItemData1480 **/1481 UpDataStructsCreateItemData: {1482 _enum: {1483 NFT: 'UpDataStructsCreateNftData',1484 Fungible: 'UpDataStructsCreateFungibleData',1485 ReFungible: 'UpDataStructsCreateReFungibleData'1486 }1487 },1488 /**1489 * Lookup186: up_data_structs::CreateNftData1490 **/1491 UpDataStructsCreateNftData: {1492 properties: 'Vec<UpDataStructsProperty>'1493 },1494 /**1495 * Lookup187: up_data_structs::CreateFungibleData1496 **/1497 UpDataStructsCreateFungibleData: {1498 value: 'u128'1499 },1500 /**1501 * Lookup188: up_data_structs::CreateReFungibleData1502 **/1503 UpDataStructsCreateReFungibleData: {1504 pieces: 'u128',1505 properties: 'Vec<UpDataStructsProperty>'1506 },1507 /**1508 * Lookup192: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>1509 **/1510 UpDataStructsCreateItemExData: {1511 _enum: {1512 NFT: 'Vec<UpDataStructsCreateNftExData>',1513 Fungible: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',1514 RefungibleMultipleItems: 'Vec<UpDataStructsCreateRefungibleExSingleOwner>',1515 RefungibleMultipleOwners: 'UpDataStructsCreateRefungibleExMultipleOwners'1516 }1517 },1518 /**1519 * Lookup194: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>1520 **/1521 UpDataStructsCreateNftExData: {1522 properties: 'Vec<UpDataStructsProperty>',1523 owner: 'PalletEvmAccountBasicCrossAccountIdRepr'1524 },1525 /**1526 * Lookup201: up_data_structs::CreateRefungibleExSingleOwner<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>1527 **/1528 UpDataStructsCreateRefungibleExSingleOwner: {1529 user: 'PalletEvmAccountBasicCrossAccountIdRepr',1530 pieces: 'u128',1531 properties: 'Vec<UpDataStructsProperty>'1532 },1533 /**1534 * Lookup203: up_data_structs::CreateRefungibleExMultipleOwners<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>1535 **/1536 UpDataStructsCreateRefungibleExMultipleOwners: {1537 users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',1538 properties: 'Vec<UpDataStructsProperty>'1539 },1540 /**1541 * Lookup204: pallet_unique_scheduler::pallet::Call<T>1542 **/1543 PalletUniqueSchedulerCall: {1544 _enum: {1545 schedule_named: {1546 id: '[u8;16]',1547 when: 'u32',1548 maybePeriodic: 'Option<(u32,u32)>',1549 priority: 'u8',1550 call: 'FrameSupportScheduleMaybeHashed',1551 },1552 cancel_named: {1553 id: '[u8;16]',1554 },1555 schedule_named_after: {1556 id: '[u8;16]',1557 after: 'u32',1558 maybePeriodic: 'Option<(u32,u32)>',1559 priority: 'u8',1560 call: 'FrameSupportScheduleMaybeHashed'1561 }1562 }1563 },1564 /**1565 * Lookup206: frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>1566 **/1567 FrameSupportScheduleMaybeHashed: {1568 _enum: {1569 Value: 'Call',1570 Hash: 'H256'1571 }1572 },1573 /**1574 * Lookup207: pallet_template_transaction_payment::Call<T>1575 **/1576 PalletTemplateTransactionPaymentCall: 'Null',1577 /**1578 * Lookup208: pallet_structure::pallet::Call<T>1579 **/1580 PalletStructureCall: 'Null',1581 /**1582 * Lookup209: pallet_rmrk_core::pallet::Call<T>1583 **/1584 PalletRmrkCoreCall: {1585 _enum: {1586 create_collection: {1587 metadata: 'Bytes',1588 max: 'Option<u32>',1589 symbol: 'Bytes',1590 },1591 destroy_collection: {1592 collectionId: 'u32',1593 },1594 change_collection_issuer: {1595 collectionId: 'u32',1596 newIssuer: 'MultiAddress',1597 },1598 lock_collection: {1599 collectionId: 'u32',1600 },1601 mint_nft: {1602 owner: 'Option<AccountId32>',1603 collectionId: 'u32',1604 recipient: 'Option<AccountId32>',1605 royaltyAmount: 'Option<Permill>',1606 metadata: 'Bytes',1607 transferable: 'bool',1608 resources: 'Option<Vec<RmrkTraitsResourceResourceTypes>>',1609 },1610 burn_nft: {1611 collectionId: 'u32',1612 nftId: 'u32',1613 maxBurns: 'u32',1614 },1615 send: {1616 rmrkCollectionId: 'u32',1617 rmrkNftId: 'u32',1618 newOwner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',1619 },1620 accept_nft: {1621 rmrkCollectionId: 'u32',1622 rmrkNftId: 'u32',1623 newOwner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',1624 },1625 reject_nft: {1626 rmrkCollectionId: 'u32',1627 rmrkNftId: 'u32',1628 },1629 accept_resource: {1630 rmrkCollectionId: 'u32',1631 rmrkNftId: 'u32',1632 resourceId: 'u32',1633 },1634 accept_resource_removal: {1635 rmrkCollectionId: 'u32',1636 rmrkNftId: 'u32',1637 resourceId: 'u32',1638 },1639 set_property: {1640 rmrkCollectionId: 'Compact<u32>',1641 maybeNftId: 'Option<u32>',1642 key: 'Bytes',1643 value: 'Bytes',1644 },1645 set_priority: {1646 rmrkCollectionId: 'u32',1647 rmrkNftId: 'u32',1648 priorities: 'Vec<u32>',1649 },1650 add_basic_resource: {1651 rmrkCollectionId: 'u32',1652 nftId: 'u32',1653 resource: 'RmrkTraitsResourceBasicResource',1654 },1655 add_composable_resource: {1656 rmrkCollectionId: 'u32',1657 nftId: 'u32',1658 resource: 'RmrkTraitsResourceComposableResource',1659 },1660 add_slot_resource: {1661 rmrkCollectionId: 'u32',1662 nftId: 'u32',1663 resource: 'RmrkTraitsResourceSlotResource',1664 },1665 remove_resource: {1666 rmrkCollectionId: 'u32',1667 nftId: 'u32',1668 resourceId: 'u32'1669 }1670 }1671 },1672 /**1673 * Lookup215: rmrk_traits::resource::ResourceTypes<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>1674 **/1675 RmrkTraitsResourceResourceTypes: {1676 _enum: {1677 Basic: 'RmrkTraitsResourceBasicResource',1678 Composable: 'RmrkTraitsResourceComposableResource',1679 Slot: 'RmrkTraitsResourceSlotResource'1680 }1681 },1682 /**1683 * Lookup217: rmrk_traits::resource::BasicResource<frame_support::storage::bounded_vec::BoundedVec<T, S>>1684 **/1685 RmrkTraitsResourceBasicResource: {1686 src: 'Option<Bytes>',1687 metadata: 'Option<Bytes>',1688 license: 'Option<Bytes>',1689 thumb: 'Option<Bytes>'1690 },1691 /**1692 * Lookup219: rmrk_traits::resource::ComposableResource<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>1693 **/1694 RmrkTraitsResourceComposableResource: {1695 parts: 'Vec<u32>',1696 base: 'u32',1697 src: 'Option<Bytes>',1698 metadata: 'Option<Bytes>',1699 license: 'Option<Bytes>',1700 thumb: 'Option<Bytes>'1701 },1702 /**1703 * Lookup220: rmrk_traits::resource::SlotResource<frame_support::storage::bounded_vec::BoundedVec<T, S>>1704 **/1705 RmrkTraitsResourceSlotResource: {1706 base: 'u32',1707 src: 'Option<Bytes>',1708 metadata: 'Option<Bytes>',1709 slot: 'u32',1710 license: 'Option<Bytes>',1711 thumb: 'Option<Bytes>'1712 },1713 /**1714 * Lookup222: rmrk_traits::nft::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>1715 **/1716 RmrkTraitsNftAccountIdOrCollectionNftTuple: {1717 _enum: {1718 AccountId: 'AccountId32',1719 CollectionAndNftTuple: '(u32,u32)'1720 }1721 },1722 /**1723 * Lookup226: pallet_rmrk_equip::pallet::Call<T>1724 **/1725 PalletRmrkEquipCall: {1726 _enum: {1727 create_base: {1728 baseType: 'Bytes',1729 symbol: 'Bytes',1730 parts: 'Vec<RmrkTraitsPartPartType>',1731 },1732 theme_add: {1733 baseId: 'u32',1734 theme: 'RmrkTraitsTheme',1735 },1736 equippable: {1737 baseId: 'u32',1738 slotId: 'u32',1739 equippables: 'RmrkTraitsPartEquippableList'1740 }1741 }1742 },1743 /**1744 * Lookup229: rmrk_traits::part::PartType<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>1745 **/1746 RmrkTraitsPartPartType: {1747 _enum: {1748 FixedPart: 'RmrkTraitsPartFixedPart',1749 SlotPart: 'RmrkTraitsPartSlotPart'1750 }1751 },1752 /**1753 * Lookup231: rmrk_traits::part::FixedPart<frame_support::storage::bounded_vec::BoundedVec<T, S>>1754 **/1755 RmrkTraitsPartFixedPart: {1756 id: 'u32',1757 z: 'u32',1758 src: 'Bytes'1759 },1760 /**1761 * Lookup232: rmrk_traits::part::SlotPart<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>1762 **/1763 RmrkTraitsPartSlotPart: {1764 id: 'u32',1765 equippable: 'RmrkTraitsPartEquippableList',1766 src: 'Bytes',1767 z: 'u32'1768 },1769 /**1770 * Lookup233: rmrk_traits::part::EquippableList<frame_support::storage::bounded_vec::BoundedVec<T, S>>1771 **/1772 RmrkTraitsPartEquippableList: {1773 _enum: {1774 All: 'Null',1775 Empty: 'Null',1776 Custom: 'Vec<u32>'1777 }1778 },1779 /**1780 * Lookup235: rmrk_traits::theme::Theme<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<rmrk_traits::theme::ThemeProperty<frame_support::storage::bounded_vec::BoundedVec<T, S>>, S>>1781 **/1782 RmrkTraitsTheme: {1783 name: 'Bytes',1784 properties: 'Vec<RmrkTraitsThemeThemeProperty>',1785 inherit: 'bool'1786 },1787 /**1788 * Lookup237: rmrk_traits::theme::ThemeProperty<frame_support::storage::bounded_vec::BoundedVec<T, S>>1789 **/1790 RmrkTraitsThemeThemeProperty: {1791 key: 'Bytes',1792 value: 'Bytes'1793 },1794 /**1795 * Lookup239: pallet_evm::pallet::Call<T>1796 **/1797 PalletEvmCall: {1798 _enum: {1799 withdraw: {1800 address: 'H160',1801 value: 'u128',1802 },1803 call: {1804 source: 'H160',1805 target: 'H160',1806 input: 'Bytes',1807 value: 'U256',1808 gasLimit: 'u64',1809 maxFeePerGas: 'U256',1810 maxPriorityFeePerGas: 'Option<U256>',1811 nonce: 'Option<U256>',1812 accessList: 'Vec<(H160,Vec<H256>)>',1813 },1814 create: {1815 source: 'H160',1816 init: 'Bytes',1817 value: 'U256',1818 gasLimit: 'u64',1819 maxFeePerGas: 'U256',1820 maxPriorityFeePerGas: 'Option<U256>',1821 nonce: 'Option<U256>',1822 accessList: 'Vec<(H160,Vec<H256>)>',1823 },1824 create2: {1825 source: 'H160',1826 init: 'Bytes',1827 salt: 'H256',1828 value: 'U256',1829 gasLimit: 'u64',1830 maxFeePerGas: 'U256',1831 maxPriorityFeePerGas: 'Option<U256>',1832 nonce: 'Option<U256>',1833 accessList: 'Vec<(H160,Vec<H256>)>'1834 }1835 }1836 },1837 /**1838 * Lookup245: pallet_ethereum::pallet::Call<T>1839 **/1840 PalletEthereumCall: {1841 _enum: {1842 transact: {1843 transaction: 'EthereumTransactionTransactionV2'1844 }1845 }1846 },1847 /**1848 * Lookup246: ethereum::transaction::TransactionV21849 **/1850 EthereumTransactionTransactionV2: {1851 _enum: {1852 Legacy: 'EthereumTransactionLegacyTransaction',1853 EIP2930: 'EthereumTransactionEip2930Transaction',1854 EIP1559: 'EthereumTransactionEip1559Transaction'1855 }1856 },1857 /**1858 * Lookup247: ethereum::transaction::LegacyTransaction1859 **/1860 EthereumTransactionLegacyTransaction: {1861 nonce: 'U256',1862 gasPrice: 'U256',1863 gasLimit: 'U256',1864 action: 'EthereumTransactionTransactionAction',1865 value: 'U256',1866 input: 'Bytes',1867 signature: 'EthereumTransactionTransactionSignature'1868 },1869 /**1870 * Lookup248: ethereum::transaction::TransactionAction1871 **/1872 EthereumTransactionTransactionAction: {1873 _enum: {1874 Call: 'H160',1875 Create: 'Null'1876 }1877 },1878 /**1879 * Lookup249: ethereum::transaction::TransactionSignature1880 **/1881 EthereumTransactionTransactionSignature: {1882 v: 'u64',1883 r: 'H256',1884 s: 'H256'1885 },1886 /**1887 * Lookup251: ethereum::transaction::EIP2930Transaction1888 **/1889 EthereumTransactionEip2930Transaction: {1890 chainId: 'u64',1891 nonce: 'U256',1892 gasPrice: 'U256',1893 gasLimit: 'U256',1894 action: 'EthereumTransactionTransactionAction',1895 value: 'U256',1896 input: 'Bytes',1897 accessList: 'Vec<EthereumTransactionAccessListItem>',1898 oddYParity: 'bool',1899 r: 'H256',1900 s: 'H256'1901 },1902 /**1903 * Lookup253: ethereum::transaction::AccessListItem1904 **/1905 EthereumTransactionAccessListItem: {1906 address: 'H160',1907 storageKeys: 'Vec<H256>'1908 },1909 /**1910 * Lookup254: ethereum::transaction::EIP1559Transaction1911 **/1912 EthereumTransactionEip1559Transaction: {1913 chainId: 'u64',1914 nonce: 'U256',1915 maxPriorityFeePerGas: 'U256',1916 maxFeePerGas: 'U256',1917 gasLimit: 'U256',1918 action: 'EthereumTransactionTransactionAction',1919 value: 'U256',1920 input: 'Bytes',1921 accessList: 'Vec<EthereumTransactionAccessListItem>',1922 oddYParity: 'bool',1923 r: 'H256',1924 s: 'H256'1925 },1926 /**1927 * Lookup255: pallet_evm_migration::pallet::Call<T>1928 **/1929 PalletEvmMigrationCall: {1930 _enum: {1931 begin: {1932 address: 'H160',1933 },1934 set_data: {1935 address: 'H160',1936 data: 'Vec<(H256,H256)>',1937 },1938 finish: {1939 address: 'H160',1940 code: 'Bytes'1941 }1942 }1943 },1944 /**1945 * Lookup258: pallet_sudo::pallet::Event<T>1946 **/1947 PalletSudoEvent: {1948 _enum: {1949 Sudid: {1950 sudoResult: 'Result<Null, SpRuntimeDispatchError>',1951 },1952 KeyChanged: {1953 oldSudoer: 'Option<AccountId32>',1954 },1955 SudoAsDone: {1956 sudoResult: 'Result<Null, SpRuntimeDispatchError>'1957 }1958 }1959 },1960 /**1961 * Lookup260: sp_runtime::DispatchError1962 **/1963 SpRuntimeDispatchError: {1964 _enum: {1965 Other: 'Null',1966 CannotLookup: 'Null',1967 BadOrigin: 'Null',1968 Module: 'SpRuntimeModuleError',1969 ConsumerRemaining: 'Null',1970 NoProviders: 'Null',1971 TooManyConsumers: 'Null',1972 Token: 'SpRuntimeTokenError',1973 Arithmetic: 'SpRuntimeArithmeticError',1974 Transactional: 'SpRuntimeTransactionalError'1975 }1976 },1977 /**1978 * Lookup261: sp_runtime::ModuleError1979 **/1980 SpRuntimeModuleError: {1981 index: 'u8',1982 error: '[u8;4]'1983 },1984 /**1985 * Lookup262: sp_runtime::TokenError1986 **/1987 SpRuntimeTokenError: {1988 _enum: ['NoFunds', 'WouldDie', 'BelowMinimum', 'CannotCreate', 'UnknownAsset', 'Frozen', 'Unsupported']1989 },1990 /**1991 * Lookup263: sp_runtime::ArithmeticError1992 **/1993 SpRuntimeArithmeticError: {1994 _enum: ['Underflow', 'Overflow', 'DivisionByZero']1995 },1996 /**1997 * Lookup264: sp_runtime::TransactionalError1998 **/1999 SpRuntimeTransactionalError: {2000 _enum: ['LimitReached', 'NoLayer']2001 },2002 /**2003 * Lookup265: pallet_sudo::pallet::Error<T>2004 **/2005 PalletSudoError: {2006 _enum: ['RequireSudo']2007 },2008 /**2009 * Lookup266: frame_system::AccountInfo<Index, pallet_balances::AccountData<Balance>>2010 **/2011 FrameSystemAccountInfo: {2012 nonce: 'u32',2013 consumers: 'u32',2014 providers: 'u32',2015 sufficients: 'u32',2016 data: 'PalletBalancesAccountData'2017 },2018 /**2019 * Lookup267: frame_support::weights::PerDispatchClass<T>2020 **/2021 FrameSupportWeightsPerDispatchClassU64: {2022 normal: 'u64',2023 operational: 'u64',2024 mandatory: 'u64'2025 },2026 /**2027 * Lookup268: sp_runtime::generic::digest::Digest2028 **/2029 SpRuntimeDigest: {2030 logs: 'Vec<SpRuntimeDigestDigestItem>'2031 },2032 /**2033 * Lookup270: sp_runtime::generic::digest::DigestItem2034 **/2035 SpRuntimeDigestDigestItem: {2036 _enum: {2037 Other: 'Bytes',2038 __Unused1: 'Null',2039 __Unused2: 'Null',2040 __Unused3: 'Null',2041 Consensus: '([u8;4],Bytes)',2042 Seal: '([u8;4],Bytes)',2043 PreRuntime: '([u8;4],Bytes)',2044 __Unused7: 'Null',2045 RuntimeEnvironmentUpdated: 'Null'2046 }2047 },2048 /**2049 * Lookup272: frame_system::EventRecord<opal_runtime::Event, primitive_types::H256>2050 **/2051 FrameSystemEventRecord: {2052 phase: 'FrameSystemPhase',2053 event: 'Event',2054 topics: 'Vec<H256>'2055 },2056 /**2057 * Lookup274: frame_system::pallet::Event<T>2058 **/2059 FrameSystemEvent: {2060 _enum: {2061 ExtrinsicSuccess: {2062 dispatchInfo: 'FrameSupportWeightsDispatchInfo',2063 },2064 ExtrinsicFailed: {2065 dispatchError: 'SpRuntimeDispatchError',2066 dispatchInfo: 'FrameSupportWeightsDispatchInfo',2067 },2068 CodeUpdated: 'Null',2069 NewAccount: {2070 account: 'AccountId32',2071 },2072 KilledAccount: {2073 account: 'AccountId32',2074 },2075 Remarked: {2076 _alias: {2077 hash_: 'hash',2078 },2079 sender: 'AccountId32',2080 hash_: 'H256'2081 }2082 }2083 },2084 /**2085 * Lookup275: frame_support::weights::DispatchInfo2086 **/2087 FrameSupportWeightsDispatchInfo: {2088 weight: 'u64',2089 class: 'FrameSupportWeightsDispatchClass',2090 paysFee: 'FrameSupportWeightsPays'2091 },2092 /**2093 * Lookup276: frame_support::weights::DispatchClass2094 **/2095 FrameSupportWeightsDispatchClass: {2096 _enum: ['Normal', 'Operational', 'Mandatory']2097 },2098 /**2099 * Lookup277: frame_support::weights::Pays2100 **/2101 FrameSupportWeightsPays: {2102 _enum: ['Yes', 'No']2103 },2104 /**2105 * Lookup278: orml_vesting::module::Event<T>2106 **/2107 OrmlVestingModuleEvent: {2108 _enum: {2109 VestingScheduleAdded: {2110 from: 'AccountId32',2111 to: 'AccountId32',2112 vestingSchedule: 'OrmlVestingVestingSchedule',2113 },2114 Claimed: {2115 who: 'AccountId32',2116 amount: 'u128',2117 },2118 VestingSchedulesUpdated: {2119 who: 'AccountId32'2120 }2121 }2122 },2123 /**2124 * Lookup279: cumulus_pallet_xcmp_queue::pallet::Event<T>2125 **/2126 CumulusPalletXcmpQueueEvent: {2127 _enum: {2128 Success: 'Option<H256>',2129 Fail: '(Option<H256>,XcmV2TraitsError)',2130 BadVersion: 'Option<H256>',2131 BadFormat: 'Option<H256>',2132 UpwardMessageSent: 'Option<H256>',2133 XcmpMessageSent: 'Option<H256>',2134 OverweightEnqueued: '(u32,u32,u64,u64)',2135 OverweightServiced: '(u64,u64)'2136 }2137 },2138 /**2139 * Lookup280: pallet_xcm::pallet::Event<T>2140 **/2141 PalletXcmEvent: {2142 _enum: {2143 Attempted: 'XcmV2TraitsOutcome',2144 Sent: '(XcmV1MultiLocation,XcmV1MultiLocation,XcmV2Xcm)',2145 UnexpectedResponse: '(XcmV1MultiLocation,u64)',2146 ResponseReady: '(u64,XcmV2Response)',2147 Notified: '(u64,u8,u8)',2148 NotifyOverweight: '(u64,u8,u8,u64,u64)',2149 NotifyDispatchError: '(u64,u8,u8)',2150 NotifyDecodeFailed: '(u64,u8,u8)',2151 InvalidResponder: '(XcmV1MultiLocation,u64,Option<XcmV1MultiLocation>)',2152 InvalidResponderVersion: '(XcmV1MultiLocation,u64)',2153 ResponseTaken: 'u64',2154 AssetsTrapped: '(H256,XcmV1MultiLocation,XcmVersionedMultiAssets)',2155 VersionChangeNotified: '(XcmV1MultiLocation,u32)',2156 SupportedVersionChanged: '(XcmV1MultiLocation,u32)',2157 NotifyTargetSendFail: '(XcmV1MultiLocation,u64,XcmV2TraitsError)',2158 NotifyTargetMigrationFail: '(XcmVersionedMultiLocation,u64)'2159 }2160 },2161 /**2162 * Lookup281: xcm::v2::traits::Outcome2163 **/2164 XcmV2TraitsOutcome: {2165 _enum: {2166 Complete: 'u64',2167 Incomplete: '(u64,XcmV2TraitsError)',2168 Error: 'XcmV2TraitsError'2169 }2170 },2171 /**2172 * Lookup283: cumulus_pallet_xcm::pallet::Event<T>2173 **/2174 CumulusPalletXcmEvent: {2175 _enum: {2176 InvalidFormat: '[u8;8]',2177 UnsupportedVersion: '[u8;8]',2178 ExecutedDownward: '([u8;8],XcmV2TraitsOutcome)'2179 }2180 },2181 /**2182 * Lookup284: cumulus_pallet_dmp_queue::pallet::Event<T>2183 **/2184 CumulusPalletDmpQueueEvent: {2185 _enum: {2186 InvalidFormat: {2187 messageId: '[u8;32]',2188 },2189 UnsupportedVersion: {2190 messageId: '[u8;32]',2191 },2192 ExecutedDownward: {2193 messageId: '[u8;32]',2194 outcome: 'XcmV2TraitsOutcome',2195 },2196 WeightExhausted: {2197 messageId: '[u8;32]',2198 remainingWeight: 'u64',2199 requiredWeight: 'u64',2200 },2201 OverweightEnqueued: {2202 messageId: '[u8;32]',2203 overweightIndex: 'u64',2204 requiredWeight: 'u64',2205 },2206 OverweightServiced: {2207 overweightIndex: 'u64',2208 weightUsed: 'u64'2209 }2210 }2211 },2212 /**2213 * Lookup285: pallet_unique::RawEvent<sp_core::crypto::AccountId32, pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2214 **/2215 PalletUniqueRawEvent: {2216 _enum: {2217 CollectionSponsorRemoved: 'u32',2218 CollectionAdminAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',2219 CollectionOwnedChanged: '(u32,AccountId32)',2220 CollectionSponsorSet: '(u32,AccountId32)',2221 SponsorshipConfirmed: '(u32,AccountId32)',2222 CollectionAdminRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',2223 AllowListAddressRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',2224 AllowListAddressAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',2225 CollectionLimitSet: 'u32',2226 CollectionPermissionSet: 'u32'2227 }2228 },2229 /**2230 * Lookup286: pallet_unique_scheduler::pallet::Event<T>2231 **/2232 PalletUniqueSchedulerEvent: {2233 _enum: {2234 Scheduled: {2235 when: 'u32',2236 index: 'u32',2237 },2238 Canceled: {2239 when: 'u32',2240 index: 'u32',2241 },2242 Dispatched: {2243 task: '(u32,u32)',2244 id: 'Option<[u8;16]>',2245 result: 'Result<Null, SpRuntimeDispatchError>',2246 },2247 CallLookupFailed: {2248 task: '(u32,u32)',2249 id: 'Option<[u8;16]>',2250 error: 'FrameSupportScheduleLookupError'2251 }2252 }2253 },2254 /**2255 * Lookup288: frame_support::traits::schedule::LookupError2256 **/2257 FrameSupportScheduleLookupError: {2258 _enum: ['Unknown', 'BadFormat']2259 },2260 /**2261 * Lookup289: pallet_common::pallet::Event<T>2262 **/2263 PalletCommonEvent: {2264 _enum: {2265 CollectionCreated: '(u32,u8,AccountId32)',2266 CollectionDestroyed: 'u32',2267 ItemCreated: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,u128)',2268 ItemDestroyed: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,u128)',2269 Transfer: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,u128)',2270 Approved: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,u128)',2271 CollectionPropertySet: '(u32,Bytes)',2272 CollectionPropertyDeleted: '(u32,Bytes)',2273 TokenPropertySet: '(u32,u32,Bytes)',2274 TokenPropertyDeleted: '(u32,u32,Bytes)',2275 PropertyPermissionSet: '(u32,Bytes)'2276 }2277 },2278 /**2279 * Lookup290: pallet_structure::pallet::Event<T>2280 **/2281 PalletStructureEvent: {2282 _enum: {2283 Executed: 'Result<Null, SpRuntimeDispatchError>'2284 }2285 },2286 /**2287 * Lookup291: pallet_rmrk_core::pallet::Event<T>2288 **/2289 PalletRmrkCoreEvent: {2290 _enum: {2291 CollectionCreated: {2292 issuer: 'AccountId32',2293 collectionId: 'u32',2294 },2295 CollectionDestroyed: {2296 issuer: 'AccountId32',2297 collectionId: 'u32',2298 },2299 IssuerChanged: {2300 oldIssuer: 'AccountId32',2301 newIssuer: 'AccountId32',2302 collectionId: 'u32',2303 },2304 CollectionLocked: {2305 issuer: 'AccountId32',2306 collectionId: 'u32',2307 },2308 NftMinted: {2309 owner: 'AccountId32',2310 collectionId: 'u32',2311 nftId: 'u32',2312 },2313 NFTBurned: {2314 owner: 'AccountId32',2315 nftId: 'u32',2316 },2317 NFTSent: {2318 sender: 'AccountId32',2319 recipient: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2320 collectionId: 'u32',2321 nftId: 'u32',2322 approvalRequired: 'bool',2323 },2324 NFTAccepted: {2325 sender: 'AccountId32',2326 recipient: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2327 collectionId: 'u32',2328 nftId: 'u32',2329 },2330 NFTRejected: {2331 sender: 'AccountId32',2332 collectionId: 'u32',2333 nftId: 'u32',2334 },2335 PropertySet: {2336 collectionId: 'u32',2337 maybeNftId: 'Option<u32>',2338 key: 'Bytes',2339 value: 'Bytes',2340 },2341 ResourceAdded: {2342 nftId: 'u32',2343 resourceId: 'u32',2344 },2345 ResourceRemoval: {2346 nftId: 'u32',2347 resourceId: 'u32',2348 },2349 ResourceAccepted: {2350 nftId: 'u32',2351 resourceId: 'u32',2352 },2353 ResourceRemovalAccepted: {2354 nftId: 'u32',2355 resourceId: 'u32',2356 },2357 PrioritySet: {2358 collectionId: 'u32',2359 nftId: 'u32'2360 }2361 }2362 },2363 /**2364 * Lookup292: pallet_rmrk_equip::pallet::Event<T>2365 **/2366 PalletRmrkEquipEvent: {2367 _enum: {2368 BaseCreated: {2369 issuer: 'AccountId32',2370 baseId: 'u32',2371 },2372 EquippablesUpdated: {2373 baseId: 'u32',2374 slotId: 'u32'2375 }2376 }2377 },2378 /**2379 * Lookup293: pallet_evm::pallet::Event<T>2380 **/2381 PalletEvmEvent: {2382 _enum: {2383 Log: 'EthereumLog',2384 Created: 'H160',2385 CreatedFailed: 'H160',2386 Executed: 'H160',2387 ExecutedFailed: 'H160',2388 BalanceDeposit: '(AccountId32,H160,U256)',2389 BalanceWithdraw: '(AccountId32,H160,U256)'2390 }2391 },2392 /**2393 * Lookup294: ethereum::log::Log2394 **/2395 EthereumLog: {2396 address: 'H160',2397 topics: 'Vec<H256>',2398 data: 'Bytes'2399 },2400 /**2401 * Lookup295: pallet_ethereum::pallet::Event2402 **/2403 PalletEthereumEvent: {2404 _enum: {2405 Executed: '(H160,H160,H256,EvmCoreErrorExitReason)'2406 }2407 },2408 /**2409 * Lookup296: evm_core::error::ExitReason2410 **/2411 EvmCoreErrorExitReason: {2412 _enum: {2413 Succeed: 'EvmCoreErrorExitSucceed',2414 Error: 'EvmCoreErrorExitError',2415 Revert: 'EvmCoreErrorExitRevert',2416 Fatal: 'EvmCoreErrorExitFatal'2417 }2418 },2419 /**2420 * Lookup297: evm_core::error::ExitSucceed2421 **/2422 EvmCoreErrorExitSucceed: {2423 _enum: ['Stopped', 'Returned', 'Suicided']2424 },2425 /**2426 * Lookup298: evm_core::error::ExitError2427 **/2428 EvmCoreErrorExitError: {2429 _enum: {2430 StackUnderflow: 'Null',2431 StackOverflow: 'Null',2432 InvalidJump: 'Null',2433 InvalidRange: 'Null',2434 DesignatedInvalid: 'Null',2435 CallTooDeep: 'Null',2436 CreateCollision: 'Null',2437 CreateContractLimit: 'Null',2438 OutOfOffset: 'Null',2439 OutOfGas: 'Null',2440 OutOfFund: 'Null',2441 PCUnderflow: 'Null',2442 CreateEmpty: 'Null',2443 Other: 'Text',2444 InvalidCode: 'Null'2445 }2446 },2447 /**2448 * Lookup301: evm_core::error::ExitRevert2449 **/2450 EvmCoreErrorExitRevert: {2451 _enum: ['Reverted']2452 },2453 /**2454 * Lookup302: evm_core::error::ExitFatal2455 **/2456 EvmCoreErrorExitFatal: {2457 _enum: {2458 NotSupported: 'Null',2459 UnhandledInterrupt: 'Null',2460 CallErrorAsFatal: 'EvmCoreErrorExitError',2461 Other: 'Text'2462 }2463 },2464 /**2465 * Lookup303: frame_system::Phase2466 **/2467 FrameSystemPhase: {2468 _enum: {2469 ApplyExtrinsic: 'u32',2470 Finalization: 'Null',2471 Initialization: 'Null'2472 }2473 },2474 /**2475 * Lookup305: frame_system::LastRuntimeUpgradeInfo2476 **/2477 FrameSystemLastRuntimeUpgradeInfo: {2478 specVersion: 'Compact<u32>',2479 specName: 'Text'2480 },2481 /**2482 * Lookup306: frame_system::limits::BlockWeights2483 **/2484 FrameSystemLimitsBlockWeights: {2485 baseBlock: 'u64',2486 maxBlock: 'u64',2487 perClass: 'FrameSupportWeightsPerDispatchClassWeightsPerClass'2488 },2489 /**2490 * Lookup307: frame_support::weights::PerDispatchClass<frame_system::limits::WeightsPerClass>2491 **/2492 FrameSupportWeightsPerDispatchClassWeightsPerClass: {2493 normal: 'FrameSystemLimitsWeightsPerClass',2494 operational: 'FrameSystemLimitsWeightsPerClass',2495 mandatory: 'FrameSystemLimitsWeightsPerClass'2496 },2497 /**2498 * Lookup308: frame_system::limits::WeightsPerClass2499 **/2500 FrameSystemLimitsWeightsPerClass: {2501 baseExtrinsic: 'u64',2502 maxExtrinsic: 'Option<u64>',2503 maxTotal: 'Option<u64>',2504 reserved: 'Option<u64>'2505 },2506 /**2507 * Lookup310: frame_system::limits::BlockLength2508 **/2509 FrameSystemLimitsBlockLength: {2510 max: 'FrameSupportWeightsPerDispatchClassU32'2511 },2512 /**2513 * Lookup311: frame_support::weights::PerDispatchClass<T>2514 **/2515 FrameSupportWeightsPerDispatchClassU32: {2516 normal: 'u32',2517 operational: 'u32',2518 mandatory: 'u32'2519 },2520 /**2521 * Lookup312: frame_support::weights::RuntimeDbWeight2522 **/2523 FrameSupportWeightsRuntimeDbWeight: {2524 read: 'u64',2525 write: 'u64'2526 },2527 /**2528 * Lookup313: sp_version::RuntimeVersion2529 **/2530 SpVersionRuntimeVersion: {2531 specName: 'Text',2532 implName: 'Text',2533 authoringVersion: 'u32',2534 specVersion: 'u32',2535 implVersion: 'u32',2536 apis: 'Vec<([u8;8],u32)>',2537 transactionVersion: 'u32',2538 stateVersion: 'u8'2539 },2540 /**2541 * Lookup317: frame_system::pallet::Error<T>2542 **/2543 FrameSystemError: {2544 _enum: ['InvalidSpecName', 'SpecVersionNeedsToIncrease', 'FailedToExtractRuntimeVersion', 'NonDefaultComposite', 'NonZeroRefCount', 'CallFiltered']2545 },2546 /**2547 * Lookup319: orml_vesting::module::Error<T>2548 **/2549 OrmlVestingModuleError: {2550 _enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded']2551 },2552 /**2553 * Lookup321: cumulus_pallet_xcmp_queue::InboundChannelDetails2554 **/2555 CumulusPalletXcmpQueueInboundChannelDetails: {2556 sender: 'u32',2557 state: 'CumulusPalletXcmpQueueInboundState',2558 messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>'2559 },2560 /**2561 * Lookup322: cumulus_pallet_xcmp_queue::InboundState2562 **/2563 CumulusPalletXcmpQueueInboundState: {2564 _enum: ['Ok', 'Suspended']2565 },2566 /**2567 * Lookup325: polkadot_parachain::primitives::XcmpMessageFormat2568 **/2569 PolkadotParachainPrimitivesXcmpMessageFormat: {2570 _enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals']2571 },2572 /**2573 * Lookup328: cumulus_pallet_xcmp_queue::OutboundChannelDetails2574 **/2575 CumulusPalletXcmpQueueOutboundChannelDetails: {2576 recipient: 'u32',2577 state: 'CumulusPalletXcmpQueueOutboundState',2578 signalsExist: 'bool',2579 firstIndex: 'u16',2580 lastIndex: 'u16'2581 },2582 /**2583 * Lookup329: cumulus_pallet_xcmp_queue::OutboundState2584 **/2585 CumulusPalletXcmpQueueOutboundState: {2586 _enum: ['Ok', 'Suspended']2587 },2588 /**2589 * Lookup331: cumulus_pallet_xcmp_queue::QueueConfigData2590 **/2591 CumulusPalletXcmpQueueQueueConfigData: {2592 suspendThreshold: 'u32',2593 dropThreshold: 'u32',2594 resumeThreshold: 'u32',2595 thresholdWeight: 'u64',2596 weightRestrictDecay: 'u64',2597 xcmpMaxIndividualWeight: 'u64'2598 },2599 /**2600 * Lookup333: cumulus_pallet_xcmp_queue::pallet::Error<T>2601 **/2602 CumulusPalletXcmpQueueError: {2603 _enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit']2604 },2605 /**2606 * Lookup334: pallet_xcm::pallet::Error<T>2607 **/2608 PalletXcmError: {2609 _enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed']2610 },2611 /**2612 * Lookup335: cumulus_pallet_xcm::pallet::Error<T>2613 **/2614 CumulusPalletXcmError: 'Null',2615 /**2616 * Lookup336: cumulus_pallet_dmp_queue::ConfigData2617 **/2618 CumulusPalletDmpQueueConfigData: {2619 maxIndividual: 'u64'2620 },2621 /**2622 * Lookup337: cumulus_pallet_dmp_queue::PageIndexData2623 **/2624 CumulusPalletDmpQueuePageIndexData: {2625 beginUsed: 'u32',2626 endUsed: 'u32',2627 overweightCount: 'u64'2628 },2629 /**2630 * Lookup340: cumulus_pallet_dmp_queue::pallet::Error<T>2631 **/2632 CumulusPalletDmpQueueError: {2633 _enum: ['Unknown', 'OverLimit']2634 },2635 /**2636 * Lookup344: pallet_unique::Error<T>2637 **/2638 PalletUniqueError: {2639 _enum: ['CollectionDecimalPointLimitExceeded', 'ConfirmUnsetSponsorFail', 'EmptyArgument', 'RepartitionCalledOnNonRefungibleCollection']2640 },2641 /**2642 * Lookup347: pallet_unique_scheduler::ScheduledV3<frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32>2643 **/2644 PalletUniqueSchedulerScheduledV3: {2645 maybeId: 'Option<[u8;16]>',2646 priority: 'u8',2647 call: 'FrameSupportScheduleMaybeHashed',2648 maybePeriodic: 'Option<(u32,u32)>',2649 origin: 'OpalRuntimeOriginCaller'2650 },2651 /**2652 * Lookup348: opal_runtime::OriginCaller2653 **/2654 OpalRuntimeOriginCaller: {2655 _enum: {2656 __Unused0: 'Null',2657 __Unused1: 'Null',2658 __Unused2: 'Null',2659 __Unused3: 'Null',2660 Void: 'SpCoreVoid',2661 __Unused5: 'Null',2662 __Unused6: 'Null',2663 __Unused7: 'Null',2664 __Unused8: 'Null',2665 __Unused9: 'Null',2666 __Unused10: 'Null',2667 __Unused11: 'Null',2668 __Unused12: 'Null',2669 __Unused13: 'Null',2670 __Unused14: 'Null',2671 __Unused15: 'Null',2672 __Unused16: 'Null',2673 __Unused17: 'Null',2674 __Unused18: 'Null',2675 __Unused19: 'Null',2676 __Unused20: 'Null',2677 __Unused21: 'Null',2678 __Unused22: 'Null',2679 __Unused23: 'Null',2680 __Unused24: 'Null',2681 __Unused25: 'Null',2682 __Unused26: 'Null',2683 __Unused27: 'Null',2684 __Unused28: 'Null',2685 __Unused29: 'Null',2686 __Unused30: 'Null',2687 __Unused31: 'Null',2688 __Unused32: 'Null',2689 __Unused33: 'Null',2690 __Unused34: 'Null',2691 __Unused35: 'Null',2692 system: 'FrameSupportDispatchRawOrigin',2693 __Unused37: 'Null',2694 __Unused38: 'Null',2695 __Unused39: 'Null',2696 __Unused40: 'Null',2697 __Unused41: 'Null',2698 __Unused42: 'Null',2699 __Unused43: 'Null',2700 __Unused44: 'Null',2701 __Unused45: 'Null',2702 __Unused46: 'Null',2703 __Unused47: 'Null',2704 __Unused48: 'Null',2705 __Unused49: 'Null',2706 __Unused50: 'Null',2707 PolkadotXcm: 'PalletXcmOrigin',2708 CumulusXcm: 'CumulusPalletXcmOrigin',2709 __Unused53: 'Null',2710 __Unused54: 'Null',2711 __Unused55: 'Null',2712 __Unused56: 'Null',2713 __Unused57: 'Null',2714 __Unused58: 'Null',2715 __Unused59: 'Null',2716 __Unused60: 'Null',2717 __Unused61: 'Null',2718 __Unused62: 'Null',2719 __Unused63: 'Null',2720 __Unused64: 'Null',2721 __Unused65: 'Null',2722 __Unused66: 'Null',2723 __Unused67: 'Null',2724 __Unused68: 'Null',2725 __Unused69: 'Null',2726 __Unused70: 'Null',2727 __Unused71: 'Null',2728 __Unused72: 'Null',2729 __Unused73: 'Null',2730 __Unused74: 'Null',2731 __Unused75: 'Null',2732 __Unused76: 'Null',2733 __Unused77: 'Null',2734 __Unused78: 'Null',2735 __Unused79: 'Null',2736 __Unused80: 'Null',2737 __Unused81: 'Null',2738 __Unused82: 'Null',2739 __Unused83: 'Null',2740 __Unused84: 'Null',2741 __Unused85: 'Null',2742 __Unused86: 'Null',2743 __Unused87: 'Null',2744 __Unused88: 'Null',2745 __Unused89: 'Null',2746 __Unused90: 'Null',2747 __Unused91: 'Null',2748 __Unused92: 'Null',2749 __Unused93: 'Null',2750 __Unused94: 'Null',2751 __Unused95: 'Null',2752 __Unused96: 'Null',2753 __Unused97: 'Null',2754 __Unused98: 'Null',2755 __Unused99: 'Null',2756 __Unused100: 'Null',2757 Ethereum: 'PalletEthereumRawOrigin'2758 }2759 },2760 /**2761 * Lookup349: frame_support::dispatch::RawOrigin<sp_core::crypto::AccountId32>2762 **/2763 FrameSupportDispatchRawOrigin: {2764 _enum: {2765 Root: 'Null',2766 Signed: 'AccountId32',2767 None: 'Null'2768 }2769 },2770 /**2771 * Lookup350: pallet_xcm::pallet::Origin2772 **/2773 PalletXcmOrigin: {2774 _enum: {2775 Xcm: 'XcmV1MultiLocation',2776 Response: 'XcmV1MultiLocation'2777 }2778 },2779 /**2780 * Lookup351: cumulus_pallet_xcm::pallet::Origin2781 **/2782 CumulusPalletXcmOrigin: {2783 _enum: {2784 Relay: 'Null',2785 SiblingParachain: 'u32'2786 }2787 },2788 /**2789 * Lookup352: pallet_ethereum::RawOrigin2790 **/2791 PalletEthereumRawOrigin: {2792 _enum: {2793 EthereumTransaction: 'H160'2794 }2795 },2796 /**2797 * Lookup353: sp_core::Void2798 **/2799 SpCoreVoid: 'Null',2800 /**2801 * Lookup354: pallet_unique_scheduler::pallet::Error<T>2802 **/2803 PalletUniqueSchedulerError: {2804 _enum: ['FailedToSchedule', 'NotFound', 'TargetBlockNumberInPast', 'RescheduleNoChange']2805 },2806 /**2807 * Lookup355: up_data_structs::Collection<sp_core::crypto::AccountId32>2808 **/2809 UpDataStructsCollection: {2810 owner: 'AccountId32',2811 mode: 'UpDataStructsCollectionMode',2812 name: 'Vec<u16>',2813 description: 'Vec<u16>',2814 tokenPrefix: 'Bytes',2815 sponsorship: 'UpDataStructsSponsorshipState',2816 limits: 'UpDataStructsCollectionLimits',2817 permissions: 'UpDataStructsCollectionPermissions',2818 externalCollection: 'bool'2819 },2820 /**2821 * Lookup356: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>2822 **/2823 UpDataStructsSponsorshipState: {2824 _enum: {2825 Disabled: 'Null',2826 Unconfirmed: 'AccountId32',2827 Confirmed: 'AccountId32'2828 }2829 },2830 /**2831 * Lookup357: up_data_structs::Properties2832 **/2833 UpDataStructsProperties: {2834 map: 'UpDataStructsPropertiesMapBoundedVec',2835 consumedSpace: 'u32',2836 spaceLimit: 'u32'2837 },2838 /**2839 * Lookup358: up_data_structs::PropertiesMap<frame_support::storage::bounded_vec::BoundedVec<T, S>>2840 **/2841 UpDataStructsPropertiesMapBoundedVec: 'BTreeMap<Bytes, Bytes>',2842 /**2843 * Lookup363: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>2844 **/2845 UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap<Bytes, UpDataStructsPropertyPermission>',2846 /**2847 * Lookup370: up_data_structs::CollectionStats2848 **/2849 UpDataStructsCollectionStats: {2850 created: 'u32',2851 destroyed: 'u32',2852 alive: 'u32'2853 },2854 /**2855 * Lookup371: up_data_structs::TokenChild2856 **/2857 UpDataStructsTokenChild: {2858 token: 'u32',2859 collection: 'u32'2860 },2861 /**2862 * Lookup372: PhantomType::up_data_structs<T>2863 **/2864 PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,RmrkTraitsCollectionCollectionInfo,RmrkTraitsNftNftInfo,RmrkTraitsResourceResourceInfo,RmrkTraitsPropertyPropertyInfo,RmrkTraitsBaseBaseInfo,RmrkTraitsPartPartType,RmrkTraitsTheme,RmrkTraitsNftNftChild);0]',2865 /**2866 * Lookup374: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2867 **/2868 UpDataStructsTokenData: {2869 properties: 'Vec<UpDataStructsProperty>',2870 owner: 'Option<PalletEvmAccountBasicCrossAccountIdRepr>',2871 pieces: 'u128'2872 },2873 /**2874 * Lookup376: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>2875 **/2876 UpDataStructsRpcCollection: {2877 owner: 'AccountId32',2878 mode: 'UpDataStructsCollectionMode',2879 name: 'Vec<u16>',2880 description: 'Vec<u16>',2881 tokenPrefix: 'Bytes',2882 sponsorship: 'UpDataStructsSponsorshipState',2883 limits: 'UpDataStructsCollectionLimits',2884 permissions: 'UpDataStructsCollectionPermissions',2885 tokenPropertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',2886 properties: 'Vec<UpDataStructsProperty>',2887 readOnly: 'bool'2888 },2889 /**2890 * Lookup377: rmrk_traits::collection::CollectionInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>2891 **/2892 RmrkTraitsCollectionCollectionInfo: {2893 issuer: 'AccountId32',2894 metadata: 'Bytes',2895 max: 'Option<u32>',2896 symbol: 'Bytes',2897 nftsCount: 'u32'2898 },2899 /**2900 * Lookup378: rmrk_traits::nft::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, frame_support::storage::bounded_vec::BoundedVec<T, S>>2901 **/2902 RmrkTraitsNftNftInfo: {2903 owner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2904 royalty: 'Option<RmrkTraitsNftRoyaltyInfo>',2905 metadata: 'Bytes',2906 equipped: 'bool',2907 pending: 'bool'2908 },2909 /**2910 * Lookup380: rmrk_traits::nft::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>2911 **/2912 RmrkTraitsNftRoyaltyInfo: {2913 recipient: 'AccountId32',2914 amount: 'Permill'2915 },2916 /**2917 * Lookup381: rmrk_traits::resource::ResourceInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>2918 **/2919 RmrkTraitsResourceResourceInfo: {2920 id: 'u32',2921 resource: 'RmrkTraitsResourceResourceTypes',2922 pending: 'bool',2923 pendingRemoval: 'bool'2924 },2925 /**2926 * Lookup382: rmrk_traits::property::PropertyInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>2927 **/2928 RmrkTraitsPropertyPropertyInfo: {2929 key: 'Bytes',2930 value: 'Bytes'2931 },2932 /**2933 * Lookup383: rmrk_traits::base::BaseInfo<sp_core::crypto::AccountId32, frame_support::storage::bounded_vec::BoundedVec<T, S>>2934 **/2935 RmrkTraitsBaseBaseInfo: {2936 issuer: 'AccountId32',2937 baseType: 'Bytes',2938 symbol: 'Bytes'2939 },2940 /**2941 * Lookup384: rmrk_traits::nft::NftChild2942 **/2943 RmrkTraitsNftNftChild: {2944 collectionId: 'u32',2945 nftId: 'u32'2946 },2947 /**2948 * Lookup386: pallet_common::pallet::Error<T>2949 **/2950 PalletCommonError: {2951 _enum: ['CollectionNotFound', 'MustBeTokenOwner', 'NoPermission', 'CantDestroyNotEmptyCollection', 'PublicMintingNotAllowed', 'AddressNotInAllowlist', 'CollectionNameLimitExceeded', 'CollectionDescriptionLimitExceeded', 'CollectionTokenPrefixLimitExceeded', 'TotalCollectionsLimitExceeded', 'CollectionAdminCountExceeded', 'CollectionLimitBoundsExceeded', 'OwnerPermissionsCantBeReverted', 'TransferNotAllowed', 'AccountTokenLimitExceeded', 'CollectionTokenLimitExceeded', 'MetadataFlagFrozen', 'TokenNotFound', 'TokenValueTooLow', 'ApprovedValueTooLow', 'CantApproveMoreThanOwned', 'AddressIsZero', 'UnsupportedOperation', 'NotSufficientFounds', 'UserIsNotAllowedToNest', 'SourceCollectionIsNotAllowedToNest', 'CollectionFieldSizeExceeded', 'NoSpaceForProperty', 'PropertyLimitReached', 'PropertyKeyIsTooLong', 'InvalidCharacterInPropertyKey', 'EmptyPropertyKey', 'CollectionIsExternal', 'CollectionIsInternal']2952 },2953 /**2954 * Lookup388: pallet_fungible::pallet::Error<T>2955 **/2956 PalletFungibleError: {2957 _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed']2958 },2959 /**2960 * Lookup389: pallet_refungible::ItemData2961 **/2962 PalletRefungibleItemData: {2963 constData: 'Bytes'2964 },2965 /**2966 * Lookup394: pallet_refungible::pallet::Error<T>2967 **/2968 PalletRefungibleError: {2969 _enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RepartitionWhileNotOwningAllPieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed']2970 },2971 /**2972 * Lookup395: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2973 **/2974 PalletNonfungibleItemData: {2975 owner: 'PalletEvmAccountBasicCrossAccountIdRepr'2976 },2977 /**2978 * Lookup397: up_data_structs::PropertyScope2979 **/2980 UpDataStructsPropertyScope: {2981 _enum: ['None', 'Rmrk']2982 },2983 /**2984 * Lookup399: pallet_nonfungible::pallet::Error<T>2985 **/2986 PalletNonfungibleError: {2987 _enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount', 'CantBurnNftWithChildren']2988 },2989 /**2990 * Lookup400: pallet_structure::pallet::Error<T>2991 **/2992 PalletStructureError: {2993 _enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound']2994 },2995 /**2996 * Lookup401: pallet_rmrk_core::pallet::Error<T>2997 **/2998 PalletRmrkCoreError: {2999 _enum: ['CorruptedCollectionType', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId']3000 },3001 /**3002 * Lookup403: pallet_rmrk_equip::pallet::Error<T>3003 **/3004 PalletRmrkEquipError: {3005 _enum: ['PermissionError', 'NoAvailableBaseId', 'NoAvailablePartId', 'BaseDoesntExist', 'NeedsDefaultThemeFirst', 'PartDoesntExist', 'NoEquippableOnFixedPart']3006 },3007 /**3008 * Lookup406: pallet_evm::pallet::Error<T>3009 **/3010 PalletEvmError: {3011 _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce']3012 },3013 /**3014 * Lookup409: fp_rpc::TransactionStatus3015 **/3016 FpRpcTransactionStatus: {3017 transactionHash: 'H256',3018 transactionIndex: 'u32',3019 from: 'H160',3020 to: 'Option<H160>',3021 contractAddress: 'Option<H160>',3022 logs: 'Vec<EthereumLog>',3023 logsBloom: 'EthbloomBloom'3024 },3025 /**3026 * Lookup411: ethbloom::Bloom3027 **/3028 EthbloomBloom: '[u8;256]',3029 /**3030 * Lookup413: ethereum::receipt::ReceiptV33031 **/3032 EthereumReceiptReceiptV3: {3033 _enum: {3034 Legacy: 'EthereumReceiptEip658ReceiptData',3035 EIP2930: 'EthereumReceiptEip658ReceiptData',3036 EIP1559: 'EthereumReceiptEip658ReceiptData'3037 }3038 },3039 /**3040 * Lookup414: ethereum::receipt::EIP658ReceiptData3041 **/3042 EthereumReceiptEip658ReceiptData: {3043 statusCode: 'u8',3044 usedGas: 'U256',3045 logsBloom: 'EthbloomBloom',3046 logs: 'Vec<EthereumLog>'3047 },3048 /**3049 * Lookup415: ethereum::block::Block<ethereum::transaction::TransactionV2>3050 **/3051 EthereumBlock: {3052 header: 'EthereumHeader',3053 transactions: 'Vec<EthereumTransactionTransactionV2>',3054 ommers: 'Vec<EthereumHeader>'3055 },3056 /**3057 * Lookup416: ethereum::header::Header3058 **/3059 EthereumHeader: {3060 parentHash: 'H256',3061 ommersHash: 'H256',3062 beneficiary: 'H160',3063 stateRoot: 'H256',3064 transactionsRoot: 'H256',3065 receiptsRoot: 'H256',3066 logsBloom: 'EthbloomBloom',3067 difficulty: 'U256',3068 number: 'U256',3069 gasLimit: 'U256',3070 gasUsed: 'U256',3071 timestamp: 'u64',3072 extraData: 'Bytes',3073 mixHash: 'H256',3074 nonce: 'EthereumTypesHashH64'3075 },3076 /**3077 * Lookup417: ethereum_types::hash::H643078 **/3079 EthereumTypesHashH64: '[u8;8]',3080 /**3081 * Lookup422: pallet_ethereum::pallet::Error<T>3082 **/3083 PalletEthereumError: {3084 _enum: ['InvalidSignature', 'PreLogExists']3085 },3086 /**3087 * Lookup423: pallet_evm_coder_substrate::pallet::Error<T>3088 **/3089 PalletEvmCoderSubstrateError: {3090 _enum: ['OutOfGas', 'OutOfFund']3091 },3092 /**3093 * Lookup424: pallet_evm_contract_helpers::SponsoringModeT3094 **/3095 PalletEvmContractHelpersSponsoringModeT: {3096 _enum: ['Disabled', 'Allowlisted', 'Generous']3097 },3098 /**3099 * Lookup426: pallet_evm_contract_helpers::pallet::Error<T>3100 **/3101 PalletEvmContractHelpersError: {3102 _enum: ['NoPermission']3103 },3104 /**3105 * Lookup427: pallet_evm_migration::pallet::Error<T>3106 **/3107 PalletEvmMigrationError: {3108 _enum: ['AccountNotEmpty', 'AccountIsNotMigrating']3109 },3110 /**3111 * Lookup429: sp_runtime::MultiSignature3112 **/3113 SpRuntimeMultiSignature: {3114 _enum: {3115 Ed25519: 'SpCoreEd25519Signature',3116 Sr25519: 'SpCoreSr25519Signature',3117 Ecdsa: 'SpCoreEcdsaSignature'3118 }3119 },3120 /**3121 * Lookup430: sp_core::ed25519::Signature3122 **/3123 SpCoreEd25519Signature: '[u8;64]',3124 /**3125 * Lookup432: sp_core::sr25519::Signature3126 **/3127 SpCoreSr25519Signature: '[u8;64]',3128 /**3129 * Lookup433: sp_core::ecdsa::Signature3130 **/3131 SpCoreEcdsaSignature: '[u8;65]',3132 /**3133 * Lookup436: frame_system::extensions::check_spec_version::CheckSpecVersion<T>3134 **/3135 FrameSystemExtensionsCheckSpecVersion: 'Null',3136 /**3137 * Lookup437: frame_system::extensions::check_genesis::CheckGenesis<T>3138 **/3139 FrameSystemExtensionsCheckGenesis: 'Null',3140 /**3141 * Lookup440: frame_system::extensions::check_nonce::CheckNonce<T>3142 **/3143 FrameSystemExtensionsCheckNonce: 'Compact<u32>',3144 /**3145 * Lookup441: frame_system::extensions::check_weight::CheckWeight<T>3146 **/3147 FrameSystemExtensionsCheckWeight: 'Null',3148 /**3149 * Lookup442: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>3150 **/3151 PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact<u128>',3152 /**3153 * Lookup443: opal_runtime::Runtime3154 **/3155 OpalRuntimeRuntime: 'Null',3156 /**3157 * Lookup444: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>3158 **/3159 PalletEthereumFakeTransactionFinalizer: 'Null'3160};1// Auto-generated via `yarn polkadot-types-from-defs`, do not edit2/* eslint-disable */34/* eslint-disable sort-keys */56export default {7 /**8 * Lookup2: polkadot_primitives::v2::PersistedValidationData<primitive_types::H256, N>9 **/10 PolkadotPrimitivesV2PersistedValidationData: {11 parentHead: 'Bytes',12 relayParentNumber: 'u32',13 relayParentStorageRoot: 'H256',14 maxPovSize: 'u32'15 },16 /**17 * Lookup9: polkadot_primitives::v2::UpgradeRestriction18 **/19 PolkadotPrimitivesV2UpgradeRestriction: {20 _enum: ['Present']21 },22 /**23 * Lookup10: sp_trie::storage_proof::StorageProof24 **/25 SpTrieStorageProof: {26 trieNodes: 'BTreeSet<Bytes>'27 },28 /**29 * Lookup13: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot30 **/31 CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: {32 dmqMqcHead: 'H256',33 relayDispatchQueueSize: '(u32,u32)',34 ingressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>',35 egressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>'36 },37 /**38 * Lookup18: polkadot_primitives::v2::AbridgedHrmpChannel39 **/40 PolkadotPrimitivesV2AbridgedHrmpChannel: {41 maxCapacity: 'u32',42 maxTotalSize: 'u32',43 maxMessageSize: 'u32',44 msgCount: 'u32',45 totalSize: 'u32',46 mqcHead: 'Option<H256>'47 },48 /**49 * Lookup20: polkadot_primitives::v2::AbridgedHostConfiguration50 **/51 PolkadotPrimitivesV2AbridgedHostConfiguration: {52 maxCodeSize: 'u32',53 maxHeadDataSize: 'u32',54 maxUpwardQueueCount: 'u32',55 maxUpwardQueueSize: 'u32',56 maxUpwardMessageSize: 'u32',57 maxUpwardMessageNumPerCandidate: 'u32',58 hrmpMaxMessageNumPerCandidate: 'u32',59 validationUpgradeCooldown: 'u32',60 validationUpgradeDelay: 'u32'61 },62 /**63 * Lookup26: polkadot_core_primitives::OutboundHrmpMessage<polkadot_parachain::primitives::Id>64 **/65 PolkadotCorePrimitivesOutboundHrmpMessage: {66 recipient: 'u32',67 data: 'Bytes'68 },69 /**70 * Lookup28: cumulus_pallet_parachain_system::pallet::Call<T>71 **/72 CumulusPalletParachainSystemCall: {73 _enum: {74 set_validation_data: {75 data: 'CumulusPrimitivesParachainInherentParachainInherentData',76 },77 sudo_send_upward_message: {78 message: 'Bytes',79 },80 authorize_upgrade: {81 codeHash: 'H256',82 },83 enact_authorized_upgrade: {84 code: 'Bytes'85 }86 }87 },88 /**89 * Lookup29: cumulus_primitives_parachain_inherent::ParachainInherentData90 **/91 CumulusPrimitivesParachainInherentParachainInherentData: {92 validationData: 'PolkadotPrimitivesV2PersistedValidationData',93 relayChainState: 'SpTrieStorageProof',94 downwardMessages: 'Vec<PolkadotCorePrimitivesInboundDownwardMessage>',95 horizontalMessages: 'BTreeMap<u32, Vec<PolkadotCorePrimitivesInboundHrmpMessage>>'96 },97 /**98 * Lookup31: polkadot_core_primitives::InboundDownwardMessage<BlockNumber>99 **/100 PolkadotCorePrimitivesInboundDownwardMessage: {101 sentAt: 'u32',102 msg: 'Bytes'103 },104 /**105 * Lookup34: polkadot_core_primitives::InboundHrmpMessage<BlockNumber>106 **/107 PolkadotCorePrimitivesInboundHrmpMessage: {108 sentAt: 'u32',109 data: 'Bytes'110 },111 /**112 * Lookup37: cumulus_pallet_parachain_system::pallet::Event<T>113 **/114 CumulusPalletParachainSystemEvent: {115 _enum: {116 ValidationFunctionStored: 'Null',117 ValidationFunctionApplied: {118 relayChainBlockNum: 'u32',119 },120 ValidationFunctionDiscarded: 'Null',121 UpgradeAuthorized: {122 codeHash: 'H256',123 },124 DownwardMessagesReceived: {125 count: 'u32',126 },127 DownwardMessagesProcessed: {128 weightUsed: 'u64',129 dmqHead: 'H256'130 }131 }132 },133 /**134 * Lookup38: cumulus_pallet_parachain_system::pallet::Error<T>135 **/136 CumulusPalletParachainSystemError: {137 _enum: ['OverlappingUpgrades', 'ProhibitedByPolkadot', 'TooBig', 'ValidationDataNotAvailable', 'HostConfigurationNotAvailable', 'NotScheduled', 'NothingAuthorized', 'Unauthorized']138 },139 /**140 * Lookup41: pallet_balances::AccountData<Balance>141 **/142 PalletBalancesAccountData: {143 free: 'u128',144 reserved: 'u128',145 miscFrozen: 'u128',146 feeFrozen: 'u128'147 },148 /**149 * Lookup43: pallet_balances::BalanceLock<Balance>150 **/151 PalletBalancesBalanceLock: {152 id: '[u8;8]',153 amount: 'u128',154 reasons: 'PalletBalancesReasons'155 },156 /**157 * Lookup45: pallet_balances::Reasons158 **/159 PalletBalancesReasons: {160 _enum: ['Fee', 'Misc', 'All']161 },162 /**163 * Lookup48: pallet_balances::ReserveData<ReserveIdentifier, Balance>164 **/165 PalletBalancesReserveData: {166 id: '[u8;16]',167 amount: 'u128'168 },169 /**170 * Lookup51: pallet_balances::Releases171 **/172 PalletBalancesReleases: {173 _enum: ['V1_0_0', 'V2_0_0']174 },175 /**176 * Lookup52: pallet_balances::pallet::Call<T, I>177 **/178 PalletBalancesCall: {179 _enum: {180 transfer: {181 dest: 'MultiAddress',182 value: 'Compact<u128>',183 },184 set_balance: {185 who: 'MultiAddress',186 newFree: 'Compact<u128>',187 newReserved: 'Compact<u128>',188 },189 force_transfer: {190 source: 'MultiAddress',191 dest: 'MultiAddress',192 value: 'Compact<u128>',193 },194 transfer_keep_alive: {195 dest: 'MultiAddress',196 value: 'Compact<u128>',197 },198 transfer_all: {199 dest: 'MultiAddress',200 keepAlive: 'bool',201 },202 force_unreserve: {203 who: 'MultiAddress',204 amount: 'u128'205 }206 }207 },208 /**209 * Lookup58: pallet_balances::pallet::Event<T, I>210 **/211 PalletBalancesEvent: {212 _enum: {213 Endowed: {214 account: 'AccountId32',215 freeBalance: 'u128',216 },217 DustLost: {218 account: 'AccountId32',219 amount: 'u128',220 },221 Transfer: {222 from: 'AccountId32',223 to: 'AccountId32',224 amount: 'u128',225 },226 BalanceSet: {227 who: 'AccountId32',228 free: 'u128',229 reserved: 'u128',230 },231 Reserved: {232 who: 'AccountId32',233 amount: 'u128',234 },235 Unreserved: {236 who: 'AccountId32',237 amount: 'u128',238 },239 ReserveRepatriated: {240 from: 'AccountId32',241 to: 'AccountId32',242 amount: 'u128',243 destinationStatus: 'FrameSupportTokensMiscBalanceStatus',244 },245 Deposit: {246 who: 'AccountId32',247 amount: 'u128',248 },249 Withdraw: {250 who: 'AccountId32',251 amount: 'u128',252 },253 Slashed: {254 who: 'AccountId32',255 amount: 'u128'256 }257 }258 },259 /**260 * Lookup59: frame_support::traits::tokens::misc::BalanceStatus261 **/262 FrameSupportTokensMiscBalanceStatus: {263 _enum: ['Free', 'Reserved']264 },265 /**266 * Lookup60: pallet_balances::pallet::Error<T, I>267 **/268 PalletBalancesError: {269 _enum: ['VestingBalance', 'LiquidityRestrictions', 'InsufficientBalance', 'ExistentialDeposit', 'KeepAlive', 'ExistingVestingSchedule', 'DeadAccount', 'TooManyReserves']270 },271 /**272 * Lookup63: pallet_timestamp::pallet::Call<T>273 **/274 PalletTimestampCall: {275 _enum: {276 set: {277 now: 'Compact<u64>'278 }279 }280 },281 /**282 * Lookup66: pallet_transaction_payment::Releases283 **/284 PalletTransactionPaymentReleases: {285 _enum: ['V1Ancient', 'V2']286 },287 /**288 * Lookup67: pallet_treasury::Proposal<sp_core::crypto::AccountId32, Balance>289 **/290 PalletTreasuryProposal: {291 proposer: 'AccountId32',292 value: 'u128',293 beneficiary: 'AccountId32',294 bond: 'u128'295 },296 /**297 * Lookup70: pallet_treasury::pallet::Call<T, I>298 **/299 PalletTreasuryCall: {300 _enum: {301 propose_spend: {302 value: 'Compact<u128>',303 beneficiary: 'MultiAddress',304 },305 reject_proposal: {306 proposalId: 'Compact<u32>',307 },308 approve_proposal: {309 proposalId: 'Compact<u32>',310 },311 remove_approval: {312 proposalId: 'Compact<u32>'313 }314 }315 },316 /**317 * Lookup72: pallet_treasury::pallet::Event<T, I>318 **/319 PalletTreasuryEvent: {320 _enum: {321 Proposed: {322 proposalIndex: 'u32',323 },324 Spending: {325 budgetRemaining: 'u128',326 },327 Awarded: {328 proposalIndex: 'u32',329 award: 'u128',330 account: 'AccountId32',331 },332 Rejected: {333 proposalIndex: 'u32',334 slashed: 'u128',335 },336 Burnt: {337 burntFunds: 'u128',338 },339 Rollover: {340 rolloverBalance: 'u128',341 },342 Deposit: {343 value: 'u128'344 }345 }346 },347 /**348 * Lookup75: frame_support::PalletId349 **/350 FrameSupportPalletId: '[u8;8]',351 /**352 * Lookup76: pallet_treasury::pallet::Error<T, I>353 **/354 PalletTreasuryError: {355 _enum: ['InsufficientProposersBalance', 'InvalidIndex', 'TooManyApprovals', 'ProposalNotApproved']356 },357 /**358 * Lookup77: pallet_sudo::pallet::Call<T>359 **/360 PalletSudoCall: {361 _enum: {362 sudo: {363 call: 'Call',364 },365 sudo_unchecked_weight: {366 call: 'Call',367 weight: 'u64',368 },369 set_key: {370 _alias: {371 new_: 'new',372 },373 new_: 'MultiAddress',374 },375 sudo_as: {376 who: 'MultiAddress',377 call: 'Call'378 }379 }380 },381 /**382 * Lookup79: frame_system::pallet::Call<T>383 **/384 FrameSystemCall: {385 _enum: {386 fill_block: {387 ratio: 'Perbill',388 },389 remark: {390 remark: 'Bytes',391 },392 set_heap_pages: {393 pages: 'u64',394 },395 set_code: {396 code: 'Bytes',397 },398 set_code_without_checks: {399 code: 'Bytes',400 },401 set_storage: {402 items: 'Vec<(Bytes,Bytes)>',403 },404 kill_storage: {405 _alias: {406 keys_: 'keys',407 },408 keys_: 'Vec<Bytes>',409 },410 kill_prefix: {411 prefix: 'Bytes',412 subkeys: 'u32',413 },414 remark_with_event: {415 remark: 'Bytes'416 }417 }418 },419 /**420 * Lookup83: orml_vesting::module::Call<T>421 **/422 OrmlVestingModuleCall: {423 _enum: {424 claim: 'Null',425 vested_transfer: {426 dest: 'MultiAddress',427 schedule: 'OrmlVestingVestingSchedule',428 },429 update_vesting_schedules: {430 who: 'MultiAddress',431 vestingSchedules: 'Vec<OrmlVestingVestingSchedule>',432 },433 claim_for: {434 dest: 'MultiAddress'435 }436 }437 },438 /**439 * Lookup84: orml_vesting::VestingSchedule<BlockNumber, Balance>440 **/441 OrmlVestingVestingSchedule: {442 start: 'u32',443 period: 'u32',444 periodCount: 'u32',445 perPeriod: 'Compact<u128>'446 },447 /**448 * Lookup86: cumulus_pallet_xcmp_queue::pallet::Call<T>449 **/450 CumulusPalletXcmpQueueCall: {451 _enum: {452 service_overweight: {453 index: 'u64',454 weightLimit: 'u64',455 },456 suspend_xcm_execution: 'Null',457 resume_xcm_execution: 'Null',458 update_suspend_threshold: {459 _alias: {460 new_: 'new',461 },462 new_: 'u32',463 },464 update_drop_threshold: {465 _alias: {466 new_: 'new',467 },468 new_: 'u32',469 },470 update_resume_threshold: {471 _alias: {472 new_: 'new',473 },474 new_: 'u32',475 },476 update_threshold_weight: {477 _alias: {478 new_: 'new',479 },480 new_: 'u64',481 },482 update_weight_restrict_decay: {483 _alias: {484 new_: 'new',485 },486 new_: 'u64',487 },488 update_xcmp_max_individual_weight: {489 _alias: {490 new_: 'new',491 },492 new_: 'u64'493 }494 }495 },496 /**497 * Lookup87: pallet_xcm::pallet::Call<T>498 **/499 PalletXcmCall: {500 _enum: {501 send: {502 dest: 'XcmVersionedMultiLocation',503 message: 'XcmVersionedXcm',504 },505 teleport_assets: {506 dest: 'XcmVersionedMultiLocation',507 beneficiary: 'XcmVersionedMultiLocation',508 assets: 'XcmVersionedMultiAssets',509 feeAssetItem: 'u32',510 },511 reserve_transfer_assets: {512 dest: 'XcmVersionedMultiLocation',513 beneficiary: 'XcmVersionedMultiLocation',514 assets: 'XcmVersionedMultiAssets',515 feeAssetItem: 'u32',516 },517 execute: {518 message: 'XcmVersionedXcm',519 maxWeight: 'u64',520 },521 force_xcm_version: {522 location: 'XcmV1MultiLocation',523 xcmVersion: 'u32',524 },525 force_default_xcm_version: {526 maybeXcmVersion: 'Option<u32>',527 },528 force_subscribe_version_notify: {529 location: 'XcmVersionedMultiLocation',530 },531 force_unsubscribe_version_notify: {532 location: 'XcmVersionedMultiLocation',533 },534 limited_reserve_transfer_assets: {535 dest: 'XcmVersionedMultiLocation',536 beneficiary: 'XcmVersionedMultiLocation',537 assets: 'XcmVersionedMultiAssets',538 feeAssetItem: 'u32',539 weightLimit: 'XcmV2WeightLimit',540 },541 limited_teleport_assets: {542 dest: 'XcmVersionedMultiLocation',543 beneficiary: 'XcmVersionedMultiLocation',544 assets: 'XcmVersionedMultiAssets',545 feeAssetItem: 'u32',546 weightLimit: 'XcmV2WeightLimit'547 }548 }549 },550 /**551 * Lookup88: xcm::VersionedMultiLocation552 **/553 XcmVersionedMultiLocation: {554 _enum: {555 V0: 'XcmV0MultiLocation',556 V1: 'XcmV1MultiLocation'557 }558 },559 /**560 * Lookup89: xcm::v0::multi_location::MultiLocation561 **/562 XcmV0MultiLocation: {563 _enum: {564 Null: 'Null',565 X1: 'XcmV0Junction',566 X2: '(XcmV0Junction,XcmV0Junction)',567 X3: '(XcmV0Junction,XcmV0Junction,XcmV0Junction)',568 X4: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',569 X5: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',570 X6: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',571 X7: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)',572 X8: '(XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction,XcmV0Junction)'573 }574 },575 /**576 * Lookup90: xcm::v0::junction::Junction577 **/578 XcmV0Junction: {579 _enum: {580 Parent: 'Null',581 Parachain: 'Compact<u32>',582 AccountId32: {583 network: 'XcmV0JunctionNetworkId',584 id: '[u8;32]',585 },586 AccountIndex64: {587 network: 'XcmV0JunctionNetworkId',588 index: 'Compact<u64>',589 },590 AccountKey20: {591 network: 'XcmV0JunctionNetworkId',592 key: '[u8;20]',593 },594 PalletInstance: 'u8',595 GeneralIndex: 'Compact<u128>',596 GeneralKey: 'Bytes',597 OnlyChild: 'Null',598 Plurality: {599 id: 'XcmV0JunctionBodyId',600 part: 'XcmV0JunctionBodyPart'601 }602 }603 },604 /**605 * Lookup91: xcm::v0::junction::NetworkId606 **/607 XcmV0JunctionNetworkId: {608 _enum: {609 Any: 'Null',610 Named: 'Bytes',611 Polkadot: 'Null',612 Kusama: 'Null'613 }614 },615 /**616 * Lookup92: xcm::v0::junction::BodyId617 **/618 XcmV0JunctionBodyId: {619 _enum: {620 Unit: 'Null',621 Named: 'Bytes',622 Index: 'Compact<u32>',623 Executive: 'Null',624 Technical: 'Null',625 Legislative: 'Null',626 Judicial: 'Null'627 }628 },629 /**630 * Lookup93: xcm::v0::junction::BodyPart631 **/632 XcmV0JunctionBodyPart: {633 _enum: {634 Voice: 'Null',635 Members: {636 count: 'Compact<u32>',637 },638 Fraction: {639 nom: 'Compact<u32>',640 denom: 'Compact<u32>',641 },642 AtLeastProportion: {643 nom: 'Compact<u32>',644 denom: 'Compact<u32>',645 },646 MoreThanProportion: {647 nom: 'Compact<u32>',648 denom: 'Compact<u32>'649 }650 }651 },652 /**653 * Lookup94: xcm::v1::multilocation::MultiLocation654 **/655 XcmV1MultiLocation: {656 parents: 'u8',657 interior: 'XcmV1MultilocationJunctions'658 },659 /**660 * Lookup95: xcm::v1::multilocation::Junctions661 **/662 XcmV1MultilocationJunctions: {663 _enum: {664 Here: 'Null',665 X1: 'XcmV1Junction',666 X2: '(XcmV1Junction,XcmV1Junction)',667 X3: '(XcmV1Junction,XcmV1Junction,XcmV1Junction)',668 X4: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',669 X5: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',670 X6: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',671 X7: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)',672 X8: '(XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction,XcmV1Junction)'673 }674 },675 /**676 * Lookup96: xcm::v1::junction::Junction677 **/678 XcmV1Junction: {679 _enum: {680 Parachain: 'Compact<u32>',681 AccountId32: {682 network: 'XcmV0JunctionNetworkId',683 id: '[u8;32]',684 },685 AccountIndex64: {686 network: 'XcmV0JunctionNetworkId',687 index: 'Compact<u64>',688 },689 AccountKey20: {690 network: 'XcmV0JunctionNetworkId',691 key: '[u8;20]',692 },693 PalletInstance: 'u8',694 GeneralIndex: 'Compact<u128>',695 GeneralKey: 'Bytes',696 OnlyChild: 'Null',697 Plurality: {698 id: 'XcmV0JunctionBodyId',699 part: 'XcmV0JunctionBodyPart'700 }701 }702 },703 /**704 * Lookup97: xcm::VersionedXcm<Call>705 **/706 XcmVersionedXcm: {707 _enum: {708 V0: 'XcmV0Xcm',709 V1: 'XcmV1Xcm',710 V2: 'XcmV2Xcm'711 }712 },713 /**714 * Lookup98: xcm::v0::Xcm<Call>715 **/716 XcmV0Xcm: {717 _enum: {718 WithdrawAsset: {719 assets: 'Vec<XcmV0MultiAsset>',720 effects: 'Vec<XcmV0Order>',721 },722 ReserveAssetDeposit: {723 assets: 'Vec<XcmV0MultiAsset>',724 effects: 'Vec<XcmV0Order>',725 },726 TeleportAsset: {727 assets: 'Vec<XcmV0MultiAsset>',728 effects: 'Vec<XcmV0Order>',729 },730 QueryResponse: {731 queryId: 'Compact<u64>',732 response: 'XcmV0Response',733 },734 TransferAsset: {735 assets: 'Vec<XcmV0MultiAsset>',736 dest: 'XcmV0MultiLocation',737 },738 TransferReserveAsset: {739 assets: 'Vec<XcmV0MultiAsset>',740 dest: 'XcmV0MultiLocation',741 effects: 'Vec<XcmV0Order>',742 },743 Transact: {744 originType: 'XcmV0OriginKind',745 requireWeightAtMost: 'u64',746 call: 'XcmDoubleEncoded',747 },748 HrmpNewChannelOpenRequest: {749 sender: 'Compact<u32>',750 maxMessageSize: 'Compact<u32>',751 maxCapacity: 'Compact<u32>',752 },753 HrmpChannelAccepted: {754 recipient: 'Compact<u32>',755 },756 HrmpChannelClosing: {757 initiator: 'Compact<u32>',758 sender: 'Compact<u32>',759 recipient: 'Compact<u32>',760 },761 RelayedFrom: {762 who: 'XcmV0MultiLocation',763 message: 'XcmV0Xcm'764 }765 }766 },767 /**768 * Lookup100: xcm::v0::multi_asset::MultiAsset769 **/770 XcmV0MultiAsset: {771 _enum: {772 None: 'Null',773 All: 'Null',774 AllFungible: 'Null',775 AllNonFungible: 'Null',776 AllAbstractFungible: {777 id: 'Bytes',778 },779 AllAbstractNonFungible: {780 class: 'Bytes',781 },782 AllConcreteFungible: {783 id: 'XcmV0MultiLocation',784 },785 AllConcreteNonFungible: {786 class: 'XcmV0MultiLocation',787 },788 AbstractFungible: {789 id: 'Bytes',790 amount: 'Compact<u128>',791 },792 AbstractNonFungible: {793 class: 'Bytes',794 instance: 'XcmV1MultiassetAssetInstance',795 },796 ConcreteFungible: {797 id: 'XcmV0MultiLocation',798 amount: 'Compact<u128>',799 },800 ConcreteNonFungible: {801 class: 'XcmV0MultiLocation',802 instance: 'XcmV1MultiassetAssetInstance'803 }804 }805 },806 /**807 * Lookup101: xcm::v1::multiasset::AssetInstance808 **/809 XcmV1MultiassetAssetInstance: {810 _enum: {811 Undefined: 'Null',812 Index: 'Compact<u128>',813 Array4: '[u8;4]',814 Array8: '[u8;8]',815 Array16: '[u8;16]',816 Array32: '[u8;32]',817 Blob: 'Bytes'818 }819 },820 /**821 * Lookup104: xcm::v0::order::Order<Call>822 **/823 XcmV0Order: {824 _enum: {825 Null: 'Null',826 DepositAsset: {827 assets: 'Vec<XcmV0MultiAsset>',828 dest: 'XcmV0MultiLocation',829 },830 DepositReserveAsset: {831 assets: 'Vec<XcmV0MultiAsset>',832 dest: 'XcmV0MultiLocation',833 effects: 'Vec<XcmV0Order>',834 },835 ExchangeAsset: {836 give: 'Vec<XcmV0MultiAsset>',837 receive: 'Vec<XcmV0MultiAsset>',838 },839 InitiateReserveWithdraw: {840 assets: 'Vec<XcmV0MultiAsset>',841 reserve: 'XcmV0MultiLocation',842 effects: 'Vec<XcmV0Order>',843 },844 InitiateTeleport: {845 assets: 'Vec<XcmV0MultiAsset>',846 dest: 'XcmV0MultiLocation',847 effects: 'Vec<XcmV0Order>',848 },849 QueryHolding: {850 queryId: 'Compact<u64>',851 dest: 'XcmV0MultiLocation',852 assets: 'Vec<XcmV0MultiAsset>',853 },854 BuyExecution: {855 fees: 'XcmV0MultiAsset',856 weight: 'u64',857 debt: 'u64',858 haltOnError: 'bool',859 xcm: 'Vec<XcmV0Xcm>'860 }861 }862 },863 /**864 * Lookup106: xcm::v0::Response865 **/866 XcmV0Response: {867 _enum: {868 Assets: 'Vec<XcmV0MultiAsset>'869 }870 },871 /**872 * Lookup107: xcm::v0::OriginKind873 **/874 XcmV0OriginKind: {875 _enum: ['Native', 'SovereignAccount', 'Superuser', 'Xcm']876 },877 /**878 * Lookup108: xcm::double_encoded::DoubleEncoded<T>879 **/880 XcmDoubleEncoded: {881 encoded: 'Bytes'882 },883 /**884 * Lookup109: xcm::v1::Xcm<Call>885 **/886 XcmV1Xcm: {887 _enum: {888 WithdrawAsset: {889 assets: 'XcmV1MultiassetMultiAssets',890 effects: 'Vec<XcmV1Order>',891 },892 ReserveAssetDeposited: {893 assets: 'XcmV1MultiassetMultiAssets',894 effects: 'Vec<XcmV1Order>',895 },896 ReceiveTeleportedAsset: {897 assets: 'XcmV1MultiassetMultiAssets',898 effects: 'Vec<XcmV1Order>',899 },900 QueryResponse: {901 queryId: 'Compact<u64>',902 response: 'XcmV1Response',903 },904 TransferAsset: {905 assets: 'XcmV1MultiassetMultiAssets',906 beneficiary: 'XcmV1MultiLocation',907 },908 TransferReserveAsset: {909 assets: 'XcmV1MultiassetMultiAssets',910 dest: 'XcmV1MultiLocation',911 effects: 'Vec<XcmV1Order>',912 },913 Transact: {914 originType: 'XcmV0OriginKind',915 requireWeightAtMost: 'u64',916 call: 'XcmDoubleEncoded',917 },918 HrmpNewChannelOpenRequest: {919 sender: 'Compact<u32>',920 maxMessageSize: 'Compact<u32>',921 maxCapacity: 'Compact<u32>',922 },923 HrmpChannelAccepted: {924 recipient: 'Compact<u32>',925 },926 HrmpChannelClosing: {927 initiator: 'Compact<u32>',928 sender: 'Compact<u32>',929 recipient: 'Compact<u32>',930 },931 RelayedFrom: {932 who: 'XcmV1MultilocationJunctions',933 message: 'XcmV1Xcm',934 },935 SubscribeVersion: {936 queryId: 'Compact<u64>',937 maxResponseWeight: 'Compact<u64>',938 },939 UnsubscribeVersion: 'Null'940 }941 },942 /**943 * Lookup110: xcm::v1::multiasset::MultiAssets944 **/945 XcmV1MultiassetMultiAssets: 'Vec<XcmV1MultiAsset>',946 /**947 * Lookup112: xcm::v1::multiasset::MultiAsset948 **/949 XcmV1MultiAsset: {950 id: 'XcmV1MultiassetAssetId',951 fun: 'XcmV1MultiassetFungibility'952 },953 /**954 * Lookup113: xcm::v1::multiasset::AssetId955 **/956 XcmV1MultiassetAssetId: {957 _enum: {958 Concrete: 'XcmV1MultiLocation',959 Abstract: 'Bytes'960 }961 },962 /**963 * Lookup114: xcm::v1::multiasset::Fungibility964 **/965 XcmV1MultiassetFungibility: {966 _enum: {967 Fungible: 'Compact<u128>',968 NonFungible: 'XcmV1MultiassetAssetInstance'969 }970 },971 /**972 * Lookup116: xcm::v1::order::Order<Call>973 **/974 XcmV1Order: {975 _enum: {976 Noop: 'Null',977 DepositAsset: {978 assets: 'XcmV1MultiassetMultiAssetFilter',979 maxAssets: 'u32',980 beneficiary: 'XcmV1MultiLocation',981 },982 DepositReserveAsset: {983 assets: 'XcmV1MultiassetMultiAssetFilter',984 maxAssets: 'u32',985 dest: 'XcmV1MultiLocation',986 effects: 'Vec<XcmV1Order>',987 },988 ExchangeAsset: {989 give: 'XcmV1MultiassetMultiAssetFilter',990 receive: 'XcmV1MultiassetMultiAssets',991 },992 InitiateReserveWithdraw: {993 assets: 'XcmV1MultiassetMultiAssetFilter',994 reserve: 'XcmV1MultiLocation',995 effects: 'Vec<XcmV1Order>',996 },997 InitiateTeleport: {998 assets: 'XcmV1MultiassetMultiAssetFilter',999 dest: 'XcmV1MultiLocation',1000 effects: 'Vec<XcmV1Order>',1001 },1002 QueryHolding: {1003 queryId: 'Compact<u64>',1004 dest: 'XcmV1MultiLocation',1005 assets: 'XcmV1MultiassetMultiAssetFilter',1006 },1007 BuyExecution: {1008 fees: 'XcmV1MultiAsset',1009 weight: 'u64',1010 debt: 'u64',1011 haltOnError: 'bool',1012 instructions: 'Vec<XcmV1Xcm>'1013 }1014 }1015 },1016 /**1017 * Lookup117: xcm::v1::multiasset::MultiAssetFilter1018 **/1019 XcmV1MultiassetMultiAssetFilter: {1020 _enum: {1021 Definite: 'XcmV1MultiassetMultiAssets',1022 Wild: 'XcmV1MultiassetWildMultiAsset'1023 }1024 },1025 /**1026 * Lookup118: xcm::v1::multiasset::WildMultiAsset1027 **/1028 XcmV1MultiassetWildMultiAsset: {1029 _enum: {1030 All: 'Null',1031 AllOf: {1032 id: 'XcmV1MultiassetAssetId',1033 fun: 'XcmV1MultiassetWildFungibility'1034 }1035 }1036 },1037 /**1038 * Lookup119: xcm::v1::multiasset::WildFungibility1039 **/1040 XcmV1MultiassetWildFungibility: {1041 _enum: ['Fungible', 'NonFungible']1042 },1043 /**1044 * Lookup121: xcm::v1::Response1045 **/1046 XcmV1Response: {1047 _enum: {1048 Assets: 'XcmV1MultiassetMultiAssets',1049 Version: 'u32'1050 }1051 },1052 /**1053 * Lookup122: xcm::v2::Xcm<Call>1054 **/1055 XcmV2Xcm: 'Vec<XcmV2Instruction>',1056 /**1057 * Lookup124: xcm::v2::Instruction<Call>1058 **/1059 XcmV2Instruction: {1060 _enum: {1061 WithdrawAsset: 'XcmV1MultiassetMultiAssets',1062 ReserveAssetDeposited: 'XcmV1MultiassetMultiAssets',1063 ReceiveTeleportedAsset: 'XcmV1MultiassetMultiAssets',1064 QueryResponse: {1065 queryId: 'Compact<u64>',1066 response: 'XcmV2Response',1067 maxWeight: 'Compact<u64>',1068 },1069 TransferAsset: {1070 assets: 'XcmV1MultiassetMultiAssets',1071 beneficiary: 'XcmV1MultiLocation',1072 },1073 TransferReserveAsset: {1074 assets: 'XcmV1MultiassetMultiAssets',1075 dest: 'XcmV1MultiLocation',1076 xcm: 'XcmV2Xcm',1077 },1078 Transact: {1079 originType: 'XcmV0OriginKind',1080 requireWeightAtMost: 'Compact<u64>',1081 call: 'XcmDoubleEncoded',1082 },1083 HrmpNewChannelOpenRequest: {1084 sender: 'Compact<u32>',1085 maxMessageSize: 'Compact<u32>',1086 maxCapacity: 'Compact<u32>',1087 },1088 HrmpChannelAccepted: {1089 recipient: 'Compact<u32>',1090 },1091 HrmpChannelClosing: {1092 initiator: 'Compact<u32>',1093 sender: 'Compact<u32>',1094 recipient: 'Compact<u32>',1095 },1096 ClearOrigin: 'Null',1097 DescendOrigin: 'XcmV1MultilocationJunctions',1098 ReportError: {1099 queryId: 'Compact<u64>',1100 dest: 'XcmV1MultiLocation',1101 maxResponseWeight: 'Compact<u64>',1102 },1103 DepositAsset: {1104 assets: 'XcmV1MultiassetMultiAssetFilter',1105 maxAssets: 'Compact<u32>',1106 beneficiary: 'XcmV1MultiLocation',1107 },1108 DepositReserveAsset: {1109 assets: 'XcmV1MultiassetMultiAssetFilter',1110 maxAssets: 'Compact<u32>',1111 dest: 'XcmV1MultiLocation',1112 xcm: 'XcmV2Xcm',1113 },1114 ExchangeAsset: {1115 give: 'XcmV1MultiassetMultiAssetFilter',1116 receive: 'XcmV1MultiassetMultiAssets',1117 },1118 InitiateReserveWithdraw: {1119 assets: 'XcmV1MultiassetMultiAssetFilter',1120 reserve: 'XcmV1MultiLocation',1121 xcm: 'XcmV2Xcm',1122 },1123 InitiateTeleport: {1124 assets: 'XcmV1MultiassetMultiAssetFilter',1125 dest: 'XcmV1MultiLocation',1126 xcm: 'XcmV2Xcm',1127 },1128 QueryHolding: {1129 queryId: 'Compact<u64>',1130 dest: 'XcmV1MultiLocation',1131 assets: 'XcmV1MultiassetMultiAssetFilter',1132 maxResponseWeight: 'Compact<u64>',1133 },1134 BuyExecution: {1135 fees: 'XcmV1MultiAsset',1136 weightLimit: 'XcmV2WeightLimit',1137 },1138 RefundSurplus: 'Null',1139 SetErrorHandler: 'XcmV2Xcm',1140 SetAppendix: 'XcmV2Xcm',1141 ClearError: 'Null',1142 ClaimAsset: {1143 assets: 'XcmV1MultiassetMultiAssets',1144 ticket: 'XcmV1MultiLocation',1145 },1146 Trap: 'Compact<u64>',1147 SubscribeVersion: {1148 queryId: 'Compact<u64>',1149 maxResponseWeight: 'Compact<u64>',1150 },1151 UnsubscribeVersion: 'Null'1152 }1153 },1154 /**1155 * Lookup125: xcm::v2::Response1156 **/1157 XcmV2Response: {1158 _enum: {1159 Null: 'Null',1160 Assets: 'XcmV1MultiassetMultiAssets',1161 ExecutionResult: 'Option<(u32,XcmV2TraitsError)>',1162 Version: 'u32'1163 }1164 },1165 /**1166 * Lookup128: xcm::v2::traits::Error1167 **/1168 XcmV2TraitsError: {1169 _enum: {1170 Overflow: 'Null',1171 Unimplemented: 'Null',1172 UntrustedReserveLocation: 'Null',1173 UntrustedTeleportLocation: 'Null',1174 MultiLocationFull: 'Null',1175 MultiLocationNotInvertible: 'Null',1176 BadOrigin: 'Null',1177 InvalidLocation: 'Null',1178 AssetNotFound: 'Null',1179 FailedToTransactAsset: 'Null',1180 NotWithdrawable: 'Null',1181 LocationCannotHold: 'Null',1182 ExceedsMaxMessageSize: 'Null',1183 DestinationUnsupported: 'Null',1184 Transport: 'Null',1185 Unroutable: 'Null',1186 UnknownClaim: 'Null',1187 FailedToDecode: 'Null',1188 MaxWeightInvalid: 'Null',1189 NotHoldingFees: 'Null',1190 TooExpensive: 'Null',1191 Trap: 'u64',1192 UnhandledXcmVersion: 'Null',1193 WeightLimitReached: 'u64',1194 Barrier: 'Null',1195 WeightNotComputable: 'Null'1196 }1197 },1198 /**1199 * Lookup129: xcm::v2::WeightLimit1200 **/1201 XcmV2WeightLimit: {1202 _enum: {1203 Unlimited: 'Null',1204 Limited: 'Compact<u64>'1205 }1206 },1207 /**1208 * Lookup130: xcm::VersionedMultiAssets1209 **/1210 XcmVersionedMultiAssets: {1211 _enum: {1212 V0: 'Vec<XcmV0MultiAsset>',1213 V1: 'XcmV1MultiassetMultiAssets'1214 }1215 },1216 /**1217 * Lookup145: cumulus_pallet_xcm::pallet::Call<T>1218 **/1219 CumulusPalletXcmCall: 'Null',1220 /**1221 * Lookup146: cumulus_pallet_dmp_queue::pallet::Call<T>1222 **/1223 CumulusPalletDmpQueueCall: {1224 _enum: {1225 service_overweight: {1226 index: 'u64',1227 weightLimit: 'u64'1228 }1229 }1230 },1231 /**1232 * Lookup147: pallet_inflation::pallet::Call<T>1233 **/1234 PalletInflationCall: {1235 _enum: {1236 start_inflation: {1237 inflationStartRelayBlock: 'u32'1238 }1239 }1240 },1241 /**1242 * Lookup148: pallet_unique::Call<T>1243 **/1244 PalletUniqueCall: {1245 _enum: {1246 create_collection: {1247 collectionName: 'Vec<u16>',1248 collectionDescription: 'Vec<u16>',1249 tokenPrefix: 'Bytes',1250 mode: 'UpDataStructsCollectionMode',1251 },1252 create_collection_ex: {1253 data: 'UpDataStructsCreateCollectionData',1254 },1255 destroy_collection: {1256 collectionId: 'u32',1257 },1258 add_to_allow_list: {1259 collectionId: 'u32',1260 address: 'PalletEvmAccountBasicCrossAccountIdRepr',1261 },1262 remove_from_allow_list: {1263 collectionId: 'u32',1264 address: 'PalletEvmAccountBasicCrossAccountIdRepr',1265 },1266 change_collection_owner: {1267 collectionId: 'u32',1268 newOwner: 'AccountId32',1269 },1270 add_collection_admin: {1271 collectionId: 'u32',1272 newAdmin: 'PalletEvmAccountBasicCrossAccountIdRepr',1273 },1274 remove_collection_admin: {1275 collectionId: 'u32',1276 accountId: 'PalletEvmAccountBasicCrossAccountIdRepr',1277 },1278 set_collection_sponsor: {1279 collectionId: 'u32',1280 newSponsor: 'AccountId32',1281 },1282 confirm_sponsorship: {1283 collectionId: 'u32',1284 },1285 remove_collection_sponsor: {1286 collectionId: 'u32',1287 },1288 create_item: {1289 collectionId: 'u32',1290 owner: 'PalletEvmAccountBasicCrossAccountIdRepr',1291 data: 'UpDataStructsCreateItemData',1292 },1293 create_multiple_items: {1294 collectionId: 'u32',1295 owner: 'PalletEvmAccountBasicCrossAccountIdRepr',1296 itemsData: 'Vec<UpDataStructsCreateItemData>',1297 },1298 set_collection_properties: {1299 collectionId: 'u32',1300 properties: 'Vec<UpDataStructsProperty>',1301 },1302 delete_collection_properties: {1303 collectionId: 'u32',1304 propertyKeys: 'Vec<Bytes>',1305 },1306 set_token_properties: {1307 collectionId: 'u32',1308 tokenId: 'u32',1309 properties: 'Vec<UpDataStructsProperty>',1310 },1311 delete_token_properties: {1312 collectionId: 'u32',1313 tokenId: 'u32',1314 propertyKeys: 'Vec<Bytes>',1315 },1316 set_token_property_permissions: {1317 collectionId: 'u32',1318 propertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',1319 },1320 create_multiple_items_ex: {1321 collectionId: 'u32',1322 data: 'UpDataStructsCreateItemExData',1323 },1324 set_transfers_enabled_flag: {1325 collectionId: 'u32',1326 value: 'bool',1327 },1328 burn_item: {1329 collectionId: 'u32',1330 itemId: 'u32',1331 value: 'u128',1332 },1333 burn_from: {1334 collectionId: 'u32',1335 from: 'PalletEvmAccountBasicCrossAccountIdRepr',1336 itemId: 'u32',1337 value: 'u128',1338 },1339 transfer: {1340 recipient: 'PalletEvmAccountBasicCrossAccountIdRepr',1341 collectionId: 'u32',1342 itemId: 'u32',1343 value: 'u128',1344 },1345 approve: {1346 spender: 'PalletEvmAccountBasicCrossAccountIdRepr',1347 collectionId: 'u32',1348 itemId: 'u32',1349 amount: 'u128',1350 },1351 transfer_from: {1352 from: 'PalletEvmAccountBasicCrossAccountIdRepr',1353 recipient: 'PalletEvmAccountBasicCrossAccountIdRepr',1354 collectionId: 'u32',1355 itemId: 'u32',1356 value: 'u128',1357 },1358 set_collection_limits: {1359 collectionId: 'u32',1360 newLimit: 'UpDataStructsCollectionLimits',1361 },1362 set_collection_permissions: {1363 collectionId: 'u32',1364 newPermission: 'UpDataStructsCollectionPermissions',1365 },1366 repartition: {1367 collectionId: 'u32',1368 tokenId: 'u32',1369 amount: 'u128'1370 }1371 }1372 },1373 /**1374 * Lookup154: up_data_structs::CollectionMode1375 **/1376 UpDataStructsCollectionMode: {1377 _enum: {1378 NFT: 'Null',1379 Fungible: 'u8',1380 ReFungible: 'Null'1381 }1382 },1383 /**1384 * Lookup155: up_data_structs::CreateCollectionData<sp_core::crypto::AccountId32>1385 **/1386 UpDataStructsCreateCollectionData: {1387 mode: 'UpDataStructsCollectionMode',1388 access: 'Option<UpDataStructsAccessMode>',1389 name: 'Vec<u16>',1390 description: 'Vec<u16>',1391 tokenPrefix: 'Bytes',1392 pendingSponsor: 'Option<AccountId32>',1393 limits: 'Option<UpDataStructsCollectionLimits>',1394 permissions: 'Option<UpDataStructsCollectionPermissions>',1395 tokenPropertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',1396 properties: 'Vec<UpDataStructsProperty>'1397 },1398 /**1399 * Lookup157: up_data_structs::AccessMode1400 **/1401 UpDataStructsAccessMode: {1402 _enum: ['Normal', 'AllowList']1403 },1404 /**1405 * Lookup160: up_data_structs::CollectionLimits1406 **/1407 UpDataStructsCollectionLimits: {1408 accountTokenOwnershipLimit: 'Option<u32>',1409 sponsoredDataSize: 'Option<u32>',1410 sponsoredDataRateLimit: 'Option<UpDataStructsSponsoringRateLimit>',1411 tokenLimit: 'Option<u32>',1412 sponsorTransferTimeout: 'Option<u32>',1413 sponsorApproveTimeout: 'Option<u32>',1414 ownerCanTransfer: 'Option<bool>',1415 ownerCanDestroy: 'Option<bool>',1416 transfersEnabled: 'Option<bool>'1417 },1418 /**1419 * Lookup162: up_data_structs::SponsoringRateLimit1420 **/1421 UpDataStructsSponsoringRateLimit: {1422 _enum: {1423 SponsoringDisabled: 'Null',1424 Blocks: 'u32'1425 }1426 },1427 /**1428 * Lookup165: up_data_structs::CollectionPermissions1429 **/1430 UpDataStructsCollectionPermissions: {1431 access: 'Option<UpDataStructsAccessMode>',1432 mintMode: 'Option<bool>',1433 nesting: 'Option<UpDataStructsNestingPermissions>'1434 },1435 /**1436 * Lookup167: up_data_structs::NestingPermissions1437 **/1438 UpDataStructsNestingPermissions: {1439 tokenOwner: 'bool',1440 collectionAdmin: 'bool',1441 restricted: 'Option<UpDataStructsOwnerRestrictedSet>'1442 },1443 /**1444 * Lookup169: up_data_structs::OwnerRestrictedSet1445 **/1446 UpDataStructsOwnerRestrictedSet: 'BTreeSet<u32>',1447 /**1448 * Lookup175: up_data_structs::PropertyKeyPermission1449 **/1450 UpDataStructsPropertyKeyPermission: {1451 key: 'Bytes',1452 permission: 'UpDataStructsPropertyPermission'1453 },1454 /**1455 * Lookup177: up_data_structs::PropertyPermission1456 **/1457 UpDataStructsPropertyPermission: {1458 mutable: 'bool',1459 collectionAdmin: 'bool',1460 tokenOwner: 'bool'1461 },1462 /**1463 * Lookup180: up_data_structs::Property1464 **/1465 UpDataStructsProperty: {1466 key: 'Bytes',1467 value: 'Bytes'1468 },1469 /**1470 * Lookup183: pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>1471 **/1472 PalletEvmAccountBasicCrossAccountIdRepr: {1473 _enum: {1474 Substrate: 'AccountId32',1475 Ethereum: 'H160'1476 }1477 },1478 /**1479 * Lookup185: up_data_structs::CreateItemData1480 **/1481 UpDataStructsCreateItemData: {1482 _enum: {1483 NFT: 'UpDataStructsCreateNftData',1484 Fungible: 'UpDataStructsCreateFungibleData',1485 ReFungible: 'UpDataStructsCreateReFungibleData'1486 }1487 },1488 /**1489 * Lookup186: up_data_structs::CreateNftData1490 **/1491 UpDataStructsCreateNftData: {1492 properties: 'Vec<UpDataStructsProperty>'1493 },1494 /**1495 * Lookup187: up_data_structs::CreateFungibleData1496 **/1497 UpDataStructsCreateFungibleData: {1498 value: 'u128'1499 },1500 /**1501 * Lookup188: up_data_structs::CreateReFungibleData1502 **/1503 UpDataStructsCreateReFungibleData: {1504 pieces: 'u128',1505 properties: 'Vec<UpDataStructsProperty>'1506 },1507 /**1508 * Lookup192: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>1509 **/1510 UpDataStructsCreateItemExData: {1511 _enum: {1512 NFT: 'Vec<UpDataStructsCreateNftExData>',1513 Fungible: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',1514 RefungibleMultipleItems: 'Vec<UpDataStructsCreateRefungibleExSingleOwner>',1515 RefungibleMultipleOwners: 'UpDataStructsCreateRefungibleExMultipleOwners'1516 }1517 },1518 /**1519 * Lookup194: up_data_structs::CreateNftExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>1520 **/1521 UpDataStructsCreateNftExData: {1522 properties: 'Vec<UpDataStructsProperty>',1523 owner: 'PalletEvmAccountBasicCrossAccountIdRepr'1524 },1525 /**1526 * Lookup201: up_data_structs::CreateRefungibleExSingleOwner<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>1527 **/1528 UpDataStructsCreateRefungibleExSingleOwner: {1529 user: 'PalletEvmAccountBasicCrossAccountIdRepr',1530 pieces: 'u128',1531 properties: 'Vec<UpDataStructsProperty>'1532 },1533 /**1534 * Lookup203: up_data_structs::CreateRefungibleExMultipleOwners<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>1535 **/1536 UpDataStructsCreateRefungibleExMultipleOwners: {1537 users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',1538 properties: 'Vec<UpDataStructsProperty>'1539 },1540 /**1541 * Lookup204: pallet_unique_scheduler::pallet::Call<T>1542 **/1543 PalletUniqueSchedulerCall: {1544 _enum: {1545 schedule_named: {1546 id: '[u8;16]',1547 when: 'u32',1548 maybePeriodic: 'Option<(u32,u32)>',1549 priority: 'u8',1550 call: 'FrameSupportScheduleMaybeHashed',1551 },1552 cancel_named: {1553 id: '[u8;16]',1554 },1555 schedule_named_after: {1556 id: '[u8;16]',1557 after: 'u32',1558 maybePeriodic: 'Option<(u32,u32)>',1559 priority: 'u8',1560 call: 'FrameSupportScheduleMaybeHashed'1561 }1562 }1563 },1564 /**1565 * Lookup206: frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>1566 **/1567 FrameSupportScheduleMaybeHashed: {1568 _enum: {1569 Value: 'Call',1570 Hash: 'H256'1571 }1572 },1573 /**1574 * Lookup207: pallet_configuration::pallet::Call<T>1575 **/1576 PalletConfigurationCall: {1577 _enum: {1578 set_weight_to_fee_coefficient_override: {1579 coeff: 'Option<u32>',1580 },1581 set_min_gas_price_override: {1582 coeff: 'Option<u64>'1583 }1584 }1585 },1586 /**1587 * Lookup209: pallet_template_transaction_payment::Call<T>1588 **/1589 PalletTemplateTransactionPaymentCall: 'Null',1590 /**1591 * Lookup210: pallet_structure::pallet::Call<T>1592 **/1593 PalletStructureCall: 'Null',1594 /**1595 * Lookup211: pallet_rmrk_core::pallet::Call<T>1596 **/1597 PalletRmrkCoreCall: {1598 _enum: {1599 create_collection: {1600 metadata: 'Bytes',1601 max: 'Option<u32>',1602 symbol: 'Bytes',1603 },1604 destroy_collection: {1605 collectionId: 'u32',1606 },1607 change_collection_issuer: {1608 collectionId: 'u32',1609 newIssuer: 'MultiAddress',1610 },1611 lock_collection: {1612 collectionId: 'u32',1613 },1614 mint_nft: {1615 owner: 'Option<AccountId32>',1616 collectionId: 'u32',1617 recipient: 'Option<AccountId32>',1618 royaltyAmount: 'Option<Permill>',1619 metadata: 'Bytes',1620 transferable: 'bool',1621 resources: 'Option<Vec<RmrkTraitsResourceResourceTypes>>',1622 },1623 burn_nft: {1624 collectionId: 'u32',1625 nftId: 'u32',1626 maxBurns: 'u32',1627 },1628 send: {1629 rmrkCollectionId: 'u32',1630 rmrkNftId: 'u32',1631 newOwner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',1632 },1633 accept_nft: {1634 rmrkCollectionId: 'u32',1635 rmrkNftId: 'u32',1636 newOwner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',1637 },1638 reject_nft: {1639 rmrkCollectionId: 'u32',1640 rmrkNftId: 'u32',1641 },1642 accept_resource: {1643 rmrkCollectionId: 'u32',1644 rmrkNftId: 'u32',1645 resourceId: 'u32',1646 },1647 accept_resource_removal: {1648 rmrkCollectionId: 'u32',1649 rmrkNftId: 'u32',1650 resourceId: 'u32',1651 },1652 set_property: {1653 rmrkCollectionId: 'Compact<u32>',1654 maybeNftId: 'Option<u32>',1655 key: 'Bytes',1656 value: 'Bytes',1657 },1658 set_priority: {1659 rmrkCollectionId: 'u32',1660 rmrkNftId: 'u32',1661 priorities: 'Vec<u32>',1662 },1663 add_basic_resource: {1664 rmrkCollectionId: 'u32',1665 nftId: 'u32',1666 resource: 'RmrkTraitsResourceBasicResource',1667 },1668 add_composable_resource: {1669 rmrkCollectionId: 'u32',1670 nftId: 'u32',1671 resource: 'RmrkTraitsResourceComposableResource',1672 },1673 add_slot_resource: {1674 rmrkCollectionId: 'u32',1675 nftId: 'u32',1676 resource: 'RmrkTraitsResourceSlotResource',1677 },1678 remove_resource: {1679 rmrkCollectionId: 'u32',1680 nftId: 'u32',1681 resourceId: 'u32'1682 }1683 }1684 },1685 /**1686 * Lookup217: rmrk_traits::resource::ResourceTypes<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>1687 **/1688 RmrkTraitsResourceResourceTypes: {1689 _enum: {1690 Basic: 'RmrkTraitsResourceBasicResource',1691 Composable: 'RmrkTraitsResourceComposableResource',1692 Slot: 'RmrkTraitsResourceSlotResource'1693 }1694 },1695 /**1696 * Lookup219: rmrk_traits::resource::BasicResource<frame_support::storage::bounded_vec::BoundedVec<T, S>>1697 **/1698 RmrkTraitsResourceBasicResource: {1699 src: 'Option<Bytes>',1700 metadata: 'Option<Bytes>',1701 license: 'Option<Bytes>',1702 thumb: 'Option<Bytes>'1703 },1704 /**1705 * Lookup221: rmrk_traits::resource::ComposableResource<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>1706 **/1707 RmrkTraitsResourceComposableResource: {1708 parts: 'Vec<u32>',1709 base: 'u32',1710 src: 'Option<Bytes>',1711 metadata: 'Option<Bytes>',1712 license: 'Option<Bytes>',1713 thumb: 'Option<Bytes>'1714 },1715 /**1716 * Lookup222: rmrk_traits::resource::SlotResource<frame_support::storage::bounded_vec::BoundedVec<T, S>>1717 **/1718 RmrkTraitsResourceSlotResource: {1719 base: 'u32',1720 src: 'Option<Bytes>',1721 metadata: 'Option<Bytes>',1722 slot: 'u32',1723 license: 'Option<Bytes>',1724 thumb: 'Option<Bytes>'1725 },1726 /**1727 * Lookup224: rmrk_traits::nft::AccountIdOrCollectionNftTuple<sp_core::crypto::AccountId32>1728 **/1729 RmrkTraitsNftAccountIdOrCollectionNftTuple: {1730 _enum: {1731 AccountId: 'AccountId32',1732 CollectionAndNftTuple: '(u32,u32)'1733 }1734 },1735 /**1736 * Lookup228: pallet_rmrk_equip::pallet::Call<T>1737 **/1738 PalletRmrkEquipCall: {1739 _enum: {1740 create_base: {1741 baseType: 'Bytes',1742 symbol: 'Bytes',1743 parts: 'Vec<RmrkTraitsPartPartType>',1744 },1745 theme_add: {1746 baseId: 'u32',1747 theme: 'RmrkTraitsTheme',1748 },1749 equippable: {1750 baseId: 'u32',1751 slotId: 'u32',1752 equippables: 'RmrkTraitsPartEquippableList'1753 }1754 }1755 },1756 /**1757 * Lookup231: rmrk_traits::part::PartType<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>1758 **/1759 RmrkTraitsPartPartType: {1760 _enum: {1761 FixedPart: 'RmrkTraitsPartFixedPart',1762 SlotPart: 'RmrkTraitsPartSlotPart'1763 }1764 },1765 /**1766 * Lookup233: rmrk_traits::part::FixedPart<frame_support::storage::bounded_vec::BoundedVec<T, S>>1767 **/1768 RmrkTraitsPartFixedPart: {1769 id: 'u32',1770 z: 'u32',1771 src: 'Bytes'1772 },1773 /**1774 * Lookup234: rmrk_traits::part::SlotPart<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>1775 **/1776 RmrkTraitsPartSlotPart: {1777 id: 'u32',1778 equippable: 'RmrkTraitsPartEquippableList',1779 src: 'Bytes',1780 z: 'u32'1781 },1782 /**1783 * Lookup235: rmrk_traits::part::EquippableList<frame_support::storage::bounded_vec::BoundedVec<T, S>>1784 **/1785 RmrkTraitsPartEquippableList: {1786 _enum: {1787 All: 'Null',1788 Empty: 'Null',1789 Custom: 'Vec<u32>'1790 }1791 },1792 /**1793 * Lookup237: rmrk_traits::theme::Theme<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<rmrk_traits::theme::ThemeProperty<frame_support::storage::bounded_vec::BoundedVec<T, S>>, S>>1794 **/1795 RmrkTraitsTheme: {1796 name: 'Bytes',1797 properties: 'Vec<RmrkTraitsThemeThemeProperty>',1798 inherit: 'bool'1799 },1800 /**1801 * Lookup239: rmrk_traits::theme::ThemeProperty<frame_support::storage::bounded_vec::BoundedVec<T, S>>1802 **/1803 RmrkTraitsThemeThemeProperty: {1804 key: 'Bytes',1805 value: 'Bytes'1806 },1807 /**1808 * Lookup241: pallet_evm::pallet::Call<T>1809 **/1810 PalletEvmCall: {1811 _enum: {1812 withdraw: {1813 address: 'H160',1814 value: 'u128',1815 },1816 call: {1817 source: 'H160',1818 target: 'H160',1819 input: 'Bytes',1820 value: 'U256',1821 gasLimit: 'u64',1822 maxFeePerGas: 'U256',1823 maxPriorityFeePerGas: 'Option<U256>',1824 nonce: 'Option<U256>',1825 accessList: 'Vec<(H160,Vec<H256>)>',1826 },1827 create: {1828 source: 'H160',1829 init: 'Bytes',1830 value: 'U256',1831 gasLimit: 'u64',1832 maxFeePerGas: 'U256',1833 maxPriorityFeePerGas: 'Option<U256>',1834 nonce: 'Option<U256>',1835 accessList: 'Vec<(H160,Vec<H256>)>',1836 },1837 create2: {1838 source: 'H160',1839 init: 'Bytes',1840 salt: 'H256',1841 value: 'U256',1842 gasLimit: 'u64',1843 maxFeePerGas: 'U256',1844 maxPriorityFeePerGas: 'Option<U256>',1845 nonce: 'Option<U256>',1846 accessList: 'Vec<(H160,Vec<H256>)>'1847 }1848 }1849 },1850 /**1851 * Lookup247: pallet_ethereum::pallet::Call<T>1852 **/1853 PalletEthereumCall: {1854 _enum: {1855 transact: {1856 transaction: 'EthereumTransactionTransactionV2'1857 }1858 }1859 },1860 /**1861 * Lookup248: ethereum::transaction::TransactionV21862 **/1863 EthereumTransactionTransactionV2: {1864 _enum: {1865 Legacy: 'EthereumTransactionLegacyTransaction',1866 EIP2930: 'EthereumTransactionEip2930Transaction',1867 EIP1559: 'EthereumTransactionEip1559Transaction'1868 }1869 },1870 /**1871 * Lookup249: ethereum::transaction::LegacyTransaction1872 **/1873 EthereumTransactionLegacyTransaction: {1874 nonce: 'U256',1875 gasPrice: 'U256',1876 gasLimit: 'U256',1877 action: 'EthereumTransactionTransactionAction',1878 value: 'U256',1879 input: 'Bytes',1880 signature: 'EthereumTransactionTransactionSignature'1881 },1882 /**1883 * Lookup250: ethereum::transaction::TransactionAction1884 **/1885 EthereumTransactionTransactionAction: {1886 _enum: {1887 Call: 'H160',1888 Create: 'Null'1889 }1890 },1891 /**1892 * Lookup251: ethereum::transaction::TransactionSignature1893 **/1894 EthereumTransactionTransactionSignature: {1895 v: 'u64',1896 r: 'H256',1897 s: 'H256'1898 },1899 /**1900 * Lookup253: ethereum::transaction::EIP2930Transaction1901 **/1902 EthereumTransactionEip2930Transaction: {1903 chainId: 'u64',1904 nonce: 'U256',1905 gasPrice: 'U256',1906 gasLimit: 'U256',1907 action: 'EthereumTransactionTransactionAction',1908 value: 'U256',1909 input: 'Bytes',1910 accessList: 'Vec<EthereumTransactionAccessListItem>',1911 oddYParity: 'bool',1912 r: 'H256',1913 s: 'H256'1914 },1915 /**1916 * Lookup255: ethereum::transaction::AccessListItem1917 **/1918 EthereumTransactionAccessListItem: {1919 address: 'H160',1920 storageKeys: 'Vec<H256>'1921 },1922 /**1923 * Lookup256: ethereum::transaction::EIP1559Transaction1924 **/1925 EthereumTransactionEip1559Transaction: {1926 chainId: 'u64',1927 nonce: 'U256',1928 maxPriorityFeePerGas: 'U256',1929 maxFeePerGas: 'U256',1930 gasLimit: 'U256',1931 action: 'EthereumTransactionTransactionAction',1932 value: 'U256',1933 input: 'Bytes',1934 accessList: 'Vec<EthereumTransactionAccessListItem>',1935 oddYParity: 'bool',1936 r: 'H256',1937 s: 'H256'1938 },1939 /**1940 * Lookup257: pallet_evm_migration::pallet::Call<T>1941 **/1942 PalletEvmMigrationCall: {1943 _enum: {1944 begin: {1945 address: 'H160',1946 },1947 set_data: {1948 address: 'H160',1949 data: 'Vec<(H256,H256)>',1950 },1951 finish: {1952 address: 'H160',1953 code: 'Bytes'1954 }1955 }1956 },1957 /**1958 * Lookup260: pallet_sudo::pallet::Event<T>1959 **/1960 PalletSudoEvent: {1961 _enum: {1962 Sudid: {1963 sudoResult: 'Result<Null, SpRuntimeDispatchError>',1964 },1965 KeyChanged: {1966 oldSudoer: 'Option<AccountId32>',1967 },1968 SudoAsDone: {1969 sudoResult: 'Result<Null, SpRuntimeDispatchError>'1970 }1971 }1972 },1973 /**1974 * Lookup262: sp_runtime::DispatchError1975 **/1976 SpRuntimeDispatchError: {1977 _enum: {1978 Other: 'Null',1979 CannotLookup: 'Null',1980 BadOrigin: 'Null',1981 Module: 'SpRuntimeModuleError',1982 ConsumerRemaining: 'Null',1983 NoProviders: 'Null',1984 TooManyConsumers: 'Null',1985 Token: 'SpRuntimeTokenError',1986 Arithmetic: 'SpRuntimeArithmeticError',1987 Transactional: 'SpRuntimeTransactionalError'1988 }1989 },1990 /**1991 * Lookup263: sp_runtime::ModuleError1992 **/1993 SpRuntimeModuleError: {1994 index: 'u8',1995 error: '[u8;4]'1996 },1997 /**1998 * Lookup264: sp_runtime::TokenError1999 **/2000 SpRuntimeTokenError: {2001 _enum: ['NoFunds', 'WouldDie', 'BelowMinimum', 'CannotCreate', 'UnknownAsset', 'Frozen', 'Unsupported']2002 },2003 /**2004 * Lookup265: sp_runtime::ArithmeticError2005 **/2006 SpRuntimeArithmeticError: {2007 _enum: ['Underflow', 'Overflow', 'DivisionByZero']2008 },2009 /**2010 * Lookup266: sp_runtime::TransactionalError2011 **/2012 SpRuntimeTransactionalError: {2013 _enum: ['LimitReached', 'NoLayer']2014 },2015 /**2016 * Lookup267: pallet_sudo::pallet::Error<T>2017 **/2018 PalletSudoError: {2019 _enum: ['RequireSudo']2020 },2021 /**2022 * Lookup268: frame_system::AccountInfo<Index, pallet_balances::AccountData<Balance>>2023 **/2024 FrameSystemAccountInfo: {2025 nonce: 'u32',2026 consumers: 'u32',2027 providers: 'u32',2028 sufficients: 'u32',2029 data: 'PalletBalancesAccountData'2030 },2031 /**2032 * Lookup269: frame_support::weights::PerDispatchClass<T>2033 **/2034 FrameSupportWeightsPerDispatchClassU64: {2035 normal: 'u64',2036 operational: 'u64',2037 mandatory: 'u64'2038 },2039 /**2040 * Lookup270: sp_runtime::generic::digest::Digest2041 **/2042 SpRuntimeDigest: {2043 logs: 'Vec<SpRuntimeDigestDigestItem>'2044 },2045 /**2046 * Lookup272: sp_runtime::generic::digest::DigestItem2047 **/2048 SpRuntimeDigestDigestItem: {2049 _enum: {2050 Other: 'Bytes',2051 __Unused1: 'Null',2052 __Unused2: 'Null',2053 __Unused3: 'Null',2054 Consensus: '([u8;4],Bytes)',2055 Seal: '([u8;4],Bytes)',2056 PreRuntime: '([u8;4],Bytes)',2057 __Unused7: 'Null',2058 RuntimeEnvironmentUpdated: 'Null'2059 }2060 },2061 /**2062 * Lookup274: frame_system::EventRecord<opal_runtime::Event, primitive_types::H256>2063 **/2064 FrameSystemEventRecord: {2065 phase: 'FrameSystemPhase',2066 event: 'Event',2067 topics: 'Vec<H256>'2068 },2069 /**2070 * Lookup276: frame_system::pallet::Event<T>2071 **/2072 FrameSystemEvent: {2073 _enum: {2074 ExtrinsicSuccess: {2075 dispatchInfo: 'FrameSupportWeightsDispatchInfo',2076 },2077 ExtrinsicFailed: {2078 dispatchError: 'SpRuntimeDispatchError',2079 dispatchInfo: 'FrameSupportWeightsDispatchInfo',2080 },2081 CodeUpdated: 'Null',2082 NewAccount: {2083 account: 'AccountId32',2084 },2085 KilledAccount: {2086 account: 'AccountId32',2087 },2088 Remarked: {2089 _alias: {2090 hash_: 'hash',2091 },2092 sender: 'AccountId32',2093 hash_: 'H256'2094 }2095 }2096 },2097 /**2098 * Lookup277: frame_support::weights::DispatchInfo2099 **/2100 FrameSupportWeightsDispatchInfo: {2101 weight: 'u64',2102 class: 'FrameSupportWeightsDispatchClass',2103 paysFee: 'FrameSupportWeightsPays'2104 },2105 /**2106 * Lookup278: frame_support::weights::DispatchClass2107 **/2108 FrameSupportWeightsDispatchClass: {2109 _enum: ['Normal', 'Operational', 'Mandatory']2110 },2111 /**2112 * Lookup279: frame_support::weights::Pays2113 **/2114 FrameSupportWeightsPays: {2115 _enum: ['Yes', 'No']2116 },2117 /**2118 * Lookup280: orml_vesting::module::Event<T>2119 **/2120 OrmlVestingModuleEvent: {2121 _enum: {2122 VestingScheduleAdded: {2123 from: 'AccountId32',2124 to: 'AccountId32',2125 vestingSchedule: 'OrmlVestingVestingSchedule',2126 },2127 Claimed: {2128 who: 'AccountId32',2129 amount: 'u128',2130 },2131 VestingSchedulesUpdated: {2132 who: 'AccountId32'2133 }2134 }2135 },2136 /**2137 * Lookup281: cumulus_pallet_xcmp_queue::pallet::Event<T>2138 **/2139 CumulusPalletXcmpQueueEvent: {2140 _enum: {2141 Success: 'Option<H256>',2142 Fail: '(Option<H256>,XcmV2TraitsError)',2143 BadVersion: 'Option<H256>',2144 BadFormat: 'Option<H256>',2145 UpwardMessageSent: 'Option<H256>',2146 XcmpMessageSent: 'Option<H256>',2147 OverweightEnqueued: '(u32,u32,u64,u64)',2148 OverweightServiced: '(u64,u64)'2149 }2150 },2151 /**2152 * Lookup282: pallet_xcm::pallet::Event<T>2153 **/2154 PalletXcmEvent: {2155 _enum: {2156 Attempted: 'XcmV2TraitsOutcome',2157 Sent: '(XcmV1MultiLocation,XcmV1MultiLocation,XcmV2Xcm)',2158 UnexpectedResponse: '(XcmV1MultiLocation,u64)',2159 ResponseReady: '(u64,XcmV2Response)',2160 Notified: '(u64,u8,u8)',2161 NotifyOverweight: '(u64,u8,u8,u64,u64)',2162 NotifyDispatchError: '(u64,u8,u8)',2163 NotifyDecodeFailed: '(u64,u8,u8)',2164 InvalidResponder: '(XcmV1MultiLocation,u64,Option<XcmV1MultiLocation>)',2165 InvalidResponderVersion: '(XcmV1MultiLocation,u64)',2166 ResponseTaken: 'u64',2167 AssetsTrapped: '(H256,XcmV1MultiLocation,XcmVersionedMultiAssets)',2168 VersionChangeNotified: '(XcmV1MultiLocation,u32)',2169 SupportedVersionChanged: '(XcmV1MultiLocation,u32)',2170 NotifyTargetSendFail: '(XcmV1MultiLocation,u64,XcmV2TraitsError)',2171 NotifyTargetMigrationFail: '(XcmVersionedMultiLocation,u64)'2172 }2173 },2174 /**2175 * Lookup283: xcm::v2::traits::Outcome2176 **/2177 XcmV2TraitsOutcome: {2178 _enum: {2179 Complete: 'u64',2180 Incomplete: '(u64,XcmV2TraitsError)',2181 Error: 'XcmV2TraitsError'2182 }2183 },2184 /**2185 * Lookup285: cumulus_pallet_xcm::pallet::Event<T>2186 **/2187 CumulusPalletXcmEvent: {2188 _enum: {2189 InvalidFormat: '[u8;8]',2190 UnsupportedVersion: '[u8;8]',2191 ExecutedDownward: '([u8;8],XcmV2TraitsOutcome)'2192 }2193 },2194 /**2195 * Lookup286: cumulus_pallet_dmp_queue::pallet::Event<T>2196 **/2197 CumulusPalletDmpQueueEvent: {2198 _enum: {2199 InvalidFormat: {2200 messageId: '[u8;32]',2201 },2202 UnsupportedVersion: {2203 messageId: '[u8;32]',2204 },2205 ExecutedDownward: {2206 messageId: '[u8;32]',2207 outcome: 'XcmV2TraitsOutcome',2208 },2209 WeightExhausted: {2210 messageId: '[u8;32]',2211 remainingWeight: 'u64',2212 requiredWeight: 'u64',2213 },2214 OverweightEnqueued: {2215 messageId: '[u8;32]',2216 overweightIndex: 'u64',2217 requiredWeight: 'u64',2218 },2219 OverweightServiced: {2220 overweightIndex: 'u64',2221 weightUsed: 'u64'2222 }2223 }2224 },2225 /**2226 * Lookup287: pallet_unique::RawEvent<sp_core::crypto::AccountId32, pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2227 **/2228 PalletUniqueRawEvent: {2229 _enum: {2230 CollectionSponsorRemoved: 'u32',2231 CollectionAdminAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',2232 CollectionOwnedChanged: '(u32,AccountId32)',2233 CollectionSponsorSet: '(u32,AccountId32)',2234 SponsorshipConfirmed: '(u32,AccountId32)',2235 CollectionAdminRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',2236 AllowListAddressRemoved: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',2237 AllowListAddressAdded: '(u32,PalletEvmAccountBasicCrossAccountIdRepr)',2238 CollectionLimitSet: 'u32',2239 CollectionPermissionSet: 'u32'2240 }2241 },2242 /**2243 * Lookup288: pallet_unique_scheduler::pallet::Event<T>2244 **/2245 PalletUniqueSchedulerEvent: {2246 _enum: {2247 Scheduled: {2248 when: 'u32',2249 index: 'u32',2250 },2251 Canceled: {2252 when: 'u32',2253 index: 'u32',2254 },2255 Dispatched: {2256 task: '(u32,u32)',2257 id: 'Option<[u8;16]>',2258 result: 'Result<Null, SpRuntimeDispatchError>',2259 },2260 CallLookupFailed: {2261 task: '(u32,u32)',2262 id: 'Option<[u8;16]>',2263 error: 'FrameSupportScheduleLookupError'2264 }2265 }2266 },2267 /**2268 * Lookup290: frame_support::traits::schedule::LookupError2269 **/2270 FrameSupportScheduleLookupError: {2271 _enum: ['Unknown', 'BadFormat']2272 },2273 /**2274 * Lookup291: pallet_common::pallet::Event<T>2275 **/2276 PalletCommonEvent: {2277 _enum: {2278 CollectionCreated: '(u32,u8,AccountId32)',2279 CollectionDestroyed: 'u32',2280 ItemCreated: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,u128)',2281 ItemDestroyed: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,u128)',2282 Transfer: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,u128)',2283 Approved: '(u32,u32,PalletEvmAccountBasicCrossAccountIdRepr,PalletEvmAccountBasicCrossAccountIdRepr,u128)',2284 CollectionPropertySet: '(u32,Bytes)',2285 CollectionPropertyDeleted: '(u32,Bytes)',2286 TokenPropertySet: '(u32,u32,Bytes)',2287 TokenPropertyDeleted: '(u32,u32,Bytes)',2288 PropertyPermissionSet: '(u32,Bytes)'2289 }2290 },2291 /**2292 * Lookup292: pallet_structure::pallet::Event<T>2293 **/2294 PalletStructureEvent: {2295 _enum: {2296 Executed: 'Result<Null, SpRuntimeDispatchError>'2297 }2298 },2299 /**2300 * Lookup293: pallet_rmrk_core::pallet::Event<T>2301 **/2302 PalletRmrkCoreEvent: {2303 _enum: {2304 CollectionCreated: {2305 issuer: 'AccountId32',2306 collectionId: 'u32',2307 },2308 CollectionDestroyed: {2309 issuer: 'AccountId32',2310 collectionId: 'u32',2311 },2312 IssuerChanged: {2313 oldIssuer: 'AccountId32',2314 newIssuer: 'AccountId32',2315 collectionId: 'u32',2316 },2317 CollectionLocked: {2318 issuer: 'AccountId32',2319 collectionId: 'u32',2320 },2321 NftMinted: {2322 owner: 'AccountId32',2323 collectionId: 'u32',2324 nftId: 'u32',2325 },2326 NFTBurned: {2327 owner: 'AccountId32',2328 nftId: 'u32',2329 },2330 NFTSent: {2331 sender: 'AccountId32',2332 recipient: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2333 collectionId: 'u32',2334 nftId: 'u32',2335 approvalRequired: 'bool',2336 },2337 NFTAccepted: {2338 sender: 'AccountId32',2339 recipient: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2340 collectionId: 'u32',2341 nftId: 'u32',2342 },2343 NFTRejected: {2344 sender: 'AccountId32',2345 collectionId: 'u32',2346 nftId: 'u32',2347 },2348 PropertySet: {2349 collectionId: 'u32',2350 maybeNftId: 'Option<u32>',2351 key: 'Bytes',2352 value: 'Bytes',2353 },2354 ResourceAdded: {2355 nftId: 'u32',2356 resourceId: 'u32',2357 },2358 ResourceRemoval: {2359 nftId: 'u32',2360 resourceId: 'u32',2361 },2362 ResourceAccepted: {2363 nftId: 'u32',2364 resourceId: 'u32',2365 },2366 ResourceRemovalAccepted: {2367 nftId: 'u32',2368 resourceId: 'u32',2369 },2370 PrioritySet: {2371 collectionId: 'u32',2372 nftId: 'u32'2373 }2374 }2375 },2376 /**2377 * Lookup294: pallet_rmrk_equip::pallet::Event<T>2378 **/2379 PalletRmrkEquipEvent: {2380 _enum: {2381 BaseCreated: {2382 issuer: 'AccountId32',2383 baseId: 'u32',2384 },2385 EquippablesUpdated: {2386 baseId: 'u32',2387 slotId: 'u32'2388 }2389 }2390 },2391 /**2392 * Lookup295: pallet_evm::pallet::Event<T>2393 **/2394 PalletEvmEvent: {2395 _enum: {2396 Log: 'EthereumLog',2397 Created: 'H160',2398 CreatedFailed: 'H160',2399 Executed: 'H160',2400 ExecutedFailed: 'H160',2401 BalanceDeposit: '(AccountId32,H160,U256)',2402 BalanceWithdraw: '(AccountId32,H160,U256)'2403 }2404 },2405 /**2406 * Lookup296: ethereum::log::Log2407 **/2408 EthereumLog: {2409 address: 'H160',2410 topics: 'Vec<H256>',2411 data: 'Bytes'2412 },2413 /**2414 * Lookup297: pallet_ethereum::pallet::Event2415 **/2416 PalletEthereumEvent: {2417 _enum: {2418 Executed: '(H160,H160,H256,EvmCoreErrorExitReason)'2419 }2420 },2421 /**2422 * Lookup298: evm_core::error::ExitReason2423 **/2424 EvmCoreErrorExitReason: {2425 _enum: {2426 Succeed: 'EvmCoreErrorExitSucceed',2427 Error: 'EvmCoreErrorExitError',2428 Revert: 'EvmCoreErrorExitRevert',2429 Fatal: 'EvmCoreErrorExitFatal'2430 }2431 },2432 /**2433 * Lookup299: evm_core::error::ExitSucceed2434 **/2435 EvmCoreErrorExitSucceed: {2436 _enum: ['Stopped', 'Returned', 'Suicided']2437 },2438 /**2439 * Lookup300: evm_core::error::ExitError2440 **/2441 EvmCoreErrorExitError: {2442 _enum: {2443 StackUnderflow: 'Null',2444 StackOverflow: 'Null',2445 InvalidJump: 'Null',2446 InvalidRange: 'Null',2447 DesignatedInvalid: 'Null',2448 CallTooDeep: 'Null',2449 CreateCollision: 'Null',2450 CreateContractLimit: 'Null',2451 OutOfOffset: 'Null',2452 OutOfGas: 'Null',2453 OutOfFund: 'Null',2454 PCUnderflow: 'Null',2455 CreateEmpty: 'Null',2456 Other: 'Text',2457 InvalidCode: 'Null'2458 }2459 },2460 /**2461 * Lookup303: evm_core::error::ExitRevert2462 **/2463 EvmCoreErrorExitRevert: {2464 _enum: ['Reverted']2465 },2466 /**2467 * Lookup304: evm_core::error::ExitFatal2468 **/2469 EvmCoreErrorExitFatal: {2470 _enum: {2471 NotSupported: 'Null',2472 UnhandledInterrupt: 'Null',2473 CallErrorAsFatal: 'EvmCoreErrorExitError',2474 Other: 'Text'2475 }2476 },2477 /**2478 * Lookup305: frame_system::Phase2479 **/2480 FrameSystemPhase: {2481 _enum: {2482 ApplyExtrinsic: 'u32',2483 Finalization: 'Null',2484 Initialization: 'Null'2485 }2486 },2487 /**2488 * Lookup307: frame_system::LastRuntimeUpgradeInfo2489 **/2490 FrameSystemLastRuntimeUpgradeInfo: {2491 specVersion: 'Compact<u32>',2492 specName: 'Text'2493 },2494 /**2495 * Lookup308: frame_system::limits::BlockWeights2496 **/2497 FrameSystemLimitsBlockWeights: {2498 baseBlock: 'u64',2499 maxBlock: 'u64',2500 perClass: 'FrameSupportWeightsPerDispatchClassWeightsPerClass'2501 },2502 /**2503 * Lookup309: frame_support::weights::PerDispatchClass<frame_system::limits::WeightsPerClass>2504 **/2505 FrameSupportWeightsPerDispatchClassWeightsPerClass: {2506 normal: 'FrameSystemLimitsWeightsPerClass',2507 operational: 'FrameSystemLimitsWeightsPerClass',2508 mandatory: 'FrameSystemLimitsWeightsPerClass'2509 },2510 /**2511 * Lookup310: frame_system::limits::WeightsPerClass2512 **/2513 FrameSystemLimitsWeightsPerClass: {2514 baseExtrinsic: 'u64',2515 maxExtrinsic: 'Option<u64>',2516 maxTotal: 'Option<u64>',2517 reserved: 'Option<u64>'2518 },2519 /**2520 * Lookup311: frame_system::limits::BlockLength2521 **/2522 FrameSystemLimitsBlockLength: {2523 max: 'FrameSupportWeightsPerDispatchClassU32'2524 },2525 /**2526 * Lookup312: frame_support::weights::PerDispatchClass<T>2527 **/2528 FrameSupportWeightsPerDispatchClassU32: {2529 normal: 'u32',2530 operational: 'u32',2531 mandatory: 'u32'2532 },2533 /**2534 * Lookup313: frame_support::weights::RuntimeDbWeight2535 **/2536 FrameSupportWeightsRuntimeDbWeight: {2537 read: 'u64',2538 write: 'u64'2539 },2540 /**2541 * Lookup314: sp_version::RuntimeVersion2542 **/2543 SpVersionRuntimeVersion: {2544 specName: 'Text',2545 implName: 'Text',2546 authoringVersion: 'u32',2547 specVersion: 'u32',2548 implVersion: 'u32',2549 apis: 'Vec<([u8;8],u32)>',2550 transactionVersion: 'u32',2551 stateVersion: 'u8'2552 },2553 /**2554 * Lookup318: frame_system::pallet::Error<T>2555 **/2556 FrameSystemError: {2557 _enum: ['InvalidSpecName', 'SpecVersionNeedsToIncrease', 'FailedToExtractRuntimeVersion', 'NonDefaultComposite', 'NonZeroRefCount', 'CallFiltered']2558 },2559 /**2560 * Lookup320: orml_vesting::module::Error<T>2561 **/2562 OrmlVestingModuleError: {2563 _enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded']2564 },2565 /**2566 * Lookup322: cumulus_pallet_xcmp_queue::InboundChannelDetails2567 **/2568 CumulusPalletXcmpQueueInboundChannelDetails: {2569 sender: 'u32',2570 state: 'CumulusPalletXcmpQueueInboundState',2571 messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>'2572 },2573 /**2574 * Lookup323: cumulus_pallet_xcmp_queue::InboundState2575 **/2576 CumulusPalletXcmpQueueInboundState: {2577 _enum: ['Ok', 'Suspended']2578 },2579 /**2580 * Lookup326: polkadot_parachain::primitives::XcmpMessageFormat2581 **/2582 PolkadotParachainPrimitivesXcmpMessageFormat: {2583 _enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals']2584 },2585 /**2586 * Lookup329: cumulus_pallet_xcmp_queue::OutboundChannelDetails2587 **/2588 CumulusPalletXcmpQueueOutboundChannelDetails: {2589 recipient: 'u32',2590 state: 'CumulusPalletXcmpQueueOutboundState',2591 signalsExist: 'bool',2592 firstIndex: 'u16',2593 lastIndex: 'u16'2594 },2595 /**2596 * Lookup330: cumulus_pallet_xcmp_queue::OutboundState2597 **/2598 CumulusPalletXcmpQueueOutboundState: {2599 _enum: ['Ok', 'Suspended']2600 },2601 /**2602 * Lookup332: cumulus_pallet_xcmp_queue::QueueConfigData2603 **/2604 CumulusPalletXcmpQueueQueueConfigData: {2605 suspendThreshold: 'u32',2606 dropThreshold: 'u32',2607 resumeThreshold: 'u32',2608 thresholdWeight: 'u64',2609 weightRestrictDecay: 'u64',2610 xcmpMaxIndividualWeight: 'u64'2611 },2612 /**2613 * Lookup334: cumulus_pallet_xcmp_queue::pallet::Error<T>2614 **/2615 CumulusPalletXcmpQueueError: {2616 _enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit']2617 },2618 /**2619 * Lookup335: pallet_xcm::pallet::Error<T>2620 **/2621 PalletXcmError: {2622 _enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed']2623 },2624 /**2625 * Lookup336: cumulus_pallet_xcm::pallet::Error<T>2626 **/2627 CumulusPalletXcmError: 'Null',2628 /**2629 * Lookup337: cumulus_pallet_dmp_queue::ConfigData2630 **/2631 CumulusPalletDmpQueueConfigData: {2632 maxIndividual: 'u64'2633 },2634 /**2635 * Lookup338: cumulus_pallet_dmp_queue::PageIndexData2636 **/2637 CumulusPalletDmpQueuePageIndexData: {2638 beginUsed: 'u32',2639 endUsed: 'u32',2640 overweightCount: 'u64'2641 },2642 /**2643 * Lookup341: cumulus_pallet_dmp_queue::pallet::Error<T>2644 **/2645 CumulusPalletDmpQueueError: {2646 _enum: ['Unknown', 'OverLimit']2647 },2648 /**2649 * Lookup345: pallet_unique::Error<T>2650 **/2651 PalletUniqueError: {2652 _enum: ['CollectionDecimalPointLimitExceeded', 'ConfirmUnsetSponsorFail', 'EmptyArgument', 'RepartitionCalledOnNonRefungibleCollection']2653 },2654 /**2655 * Lookup348: pallet_unique_scheduler::ScheduledV3<frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32>2656 **/2657 PalletUniqueSchedulerScheduledV3: {2658 maybeId: 'Option<[u8;16]>',2659 priority: 'u8',2660 call: 'FrameSupportScheduleMaybeHashed',2661 maybePeriodic: 'Option<(u32,u32)>',2662 origin: 'OpalRuntimeOriginCaller'2663 },2664 /**2665 * Lookup349: opal_runtime::OriginCaller2666 **/2667 OpalRuntimeOriginCaller: {2668 _enum: {2669 __Unused0: 'Null',2670 __Unused1: 'Null',2671 __Unused2: 'Null',2672 __Unused3: 'Null',2673 Void: 'SpCoreVoid',2674 __Unused5: 'Null',2675 __Unused6: 'Null',2676 __Unused7: 'Null',2677 __Unused8: 'Null',2678 __Unused9: 'Null',2679 __Unused10: 'Null',2680 __Unused11: 'Null',2681 __Unused12: 'Null',2682 __Unused13: 'Null',2683 __Unused14: 'Null',2684 __Unused15: 'Null',2685 __Unused16: 'Null',2686 __Unused17: 'Null',2687 __Unused18: 'Null',2688 __Unused19: 'Null',2689 __Unused20: 'Null',2690 __Unused21: 'Null',2691 __Unused22: 'Null',2692 __Unused23: 'Null',2693 __Unused24: 'Null',2694 __Unused25: 'Null',2695 __Unused26: 'Null',2696 __Unused27: 'Null',2697 __Unused28: 'Null',2698 __Unused29: 'Null',2699 __Unused30: 'Null',2700 __Unused31: 'Null',2701 __Unused32: 'Null',2702 __Unused33: 'Null',2703 __Unused34: 'Null',2704 __Unused35: 'Null',2705 system: 'FrameSupportDispatchRawOrigin',2706 __Unused37: 'Null',2707 __Unused38: 'Null',2708 __Unused39: 'Null',2709 __Unused40: 'Null',2710 __Unused41: 'Null',2711 __Unused42: 'Null',2712 __Unused43: 'Null',2713 __Unused44: 'Null',2714 __Unused45: 'Null',2715 __Unused46: 'Null',2716 __Unused47: 'Null',2717 __Unused48: 'Null',2718 __Unused49: 'Null',2719 __Unused50: 'Null',2720 PolkadotXcm: 'PalletXcmOrigin',2721 CumulusXcm: 'CumulusPalletXcmOrigin',2722 __Unused53: 'Null',2723 __Unused54: 'Null',2724 __Unused55: 'Null',2725 __Unused56: 'Null',2726 __Unused57: 'Null',2727 __Unused58: 'Null',2728 __Unused59: 'Null',2729 __Unused60: 'Null',2730 __Unused61: 'Null',2731 __Unused62: 'Null',2732 __Unused63: 'Null',2733 __Unused64: 'Null',2734 __Unused65: 'Null',2735 __Unused66: 'Null',2736 __Unused67: 'Null',2737 __Unused68: 'Null',2738 __Unused69: 'Null',2739 __Unused70: 'Null',2740 __Unused71: 'Null',2741 __Unused72: 'Null',2742 __Unused73: 'Null',2743 __Unused74: 'Null',2744 __Unused75: 'Null',2745 __Unused76: 'Null',2746 __Unused77: 'Null',2747 __Unused78: 'Null',2748 __Unused79: 'Null',2749 __Unused80: 'Null',2750 __Unused81: 'Null',2751 __Unused82: 'Null',2752 __Unused83: 'Null',2753 __Unused84: 'Null',2754 __Unused85: 'Null',2755 __Unused86: 'Null',2756 __Unused87: 'Null',2757 __Unused88: 'Null',2758 __Unused89: 'Null',2759 __Unused90: 'Null',2760 __Unused91: 'Null',2761 __Unused92: 'Null',2762 __Unused93: 'Null',2763 __Unused94: 'Null',2764 __Unused95: 'Null',2765 __Unused96: 'Null',2766 __Unused97: 'Null',2767 __Unused98: 'Null',2768 __Unused99: 'Null',2769 __Unused100: 'Null',2770 Ethereum: 'PalletEthereumRawOrigin'2771 }2772 },2773 /**2774 * Lookup350: frame_support::dispatch::RawOrigin<sp_core::crypto::AccountId32>2775 **/2776 FrameSupportDispatchRawOrigin: {2777 _enum: {2778 Root: 'Null',2779 Signed: 'AccountId32',2780 None: 'Null'2781 }2782 },2783 /**2784 * Lookup351: pallet_xcm::pallet::Origin2785 **/2786 PalletXcmOrigin: {2787 _enum: {2788 Xcm: 'XcmV1MultiLocation',2789 Response: 'XcmV1MultiLocation'2790 }2791 },2792 /**2793 * Lookup352: cumulus_pallet_xcm::pallet::Origin2794 **/2795 CumulusPalletXcmOrigin: {2796 _enum: {2797 Relay: 'Null',2798 SiblingParachain: 'u32'2799 }2800 },2801 /**2802 * Lookup353: pallet_ethereum::RawOrigin2803 **/2804 PalletEthereumRawOrigin: {2805 _enum: {2806 EthereumTransaction: 'H160'2807 }2808 },2809 /**2810 * Lookup354: sp_core::Void2811 **/2812 SpCoreVoid: 'Null',2813 /**2814 * Lookup355: pallet_unique_scheduler::pallet::Error<T>2815 **/2816 PalletUniqueSchedulerError: {2817 _enum: ['FailedToSchedule', 'NotFound', 'TargetBlockNumberInPast', 'RescheduleNoChange']2818 },2819 /**2820 * Lookup356: up_data_structs::Collection<sp_core::crypto::AccountId32>2821 **/2822 UpDataStructsCollection: {2823 owner: 'AccountId32',2824 mode: 'UpDataStructsCollectionMode',2825 name: 'Vec<u16>',2826 description: 'Vec<u16>',2827 tokenPrefix: 'Bytes',2828 sponsorship: 'UpDataStructsSponsorshipState',2829 limits: 'UpDataStructsCollectionLimits',2830 permissions: 'UpDataStructsCollectionPermissions',2831 externalCollection: 'bool'2832 },2833 /**2834 * Lookup357: up_data_structs::SponsorshipState<sp_core::crypto::AccountId32>2835 **/2836 UpDataStructsSponsorshipState: {2837 _enum: {2838 Disabled: 'Null',2839 Unconfirmed: 'AccountId32',2840 Confirmed: 'AccountId32'2841 }2842 },2843 /**2844 * Lookup358: up_data_structs::Properties2845 **/2846 UpDataStructsProperties: {2847 map: 'UpDataStructsPropertiesMapBoundedVec',2848 consumedSpace: 'u32',2849 spaceLimit: 'u32'2850 },2851 /**2852 * Lookup359: up_data_structs::PropertiesMap<frame_support::storage::bounded_vec::BoundedVec<T, S>>2853 **/2854 UpDataStructsPropertiesMapBoundedVec: 'BTreeMap<Bytes, Bytes>',2855 /**2856 * Lookup364: up_data_structs::PropertiesMap<up_data_structs::PropertyPermission>2857 **/2858 UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap<Bytes, UpDataStructsPropertyPermission>',2859 /**2860 * Lookup371: up_data_structs::CollectionStats2861 **/2862 UpDataStructsCollectionStats: {2863 created: 'u32',2864 destroyed: 'u32',2865 alive: 'u32'2866 },2867 /**2868 * Lookup372: up_data_structs::TokenChild2869 **/2870 UpDataStructsTokenChild: {2871 token: 'u32',2872 collection: 'u32'2873 },2874 /**2875 * Lookup373: PhantomType::up_data_structs<T>2876 **/2877 PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,RmrkTraitsCollectionCollectionInfo,RmrkTraitsNftNftInfo,RmrkTraitsResourceResourceInfo,RmrkTraitsPropertyPropertyInfo,RmrkTraitsBaseBaseInfo,RmrkTraitsPartPartType,RmrkTraitsTheme,RmrkTraitsNftNftChild);0]',2878 /**2879 * Lookup375: up_data_structs::TokenData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2880 **/2881 UpDataStructsTokenData: {2882 properties: 'Vec<UpDataStructsProperty>',2883 owner: 'Option<PalletEvmAccountBasicCrossAccountIdRepr>',2884 pieces: 'u128'2885 },2886 /**2887 * Lookup377: up_data_structs::RpcCollection<sp_core::crypto::AccountId32>2888 **/2889 UpDataStructsRpcCollection: {2890 owner: 'AccountId32',2891 mode: 'UpDataStructsCollectionMode',2892 name: 'Vec<u16>',2893 description: 'Vec<u16>',2894 tokenPrefix: 'Bytes',2895 sponsorship: 'UpDataStructsSponsorshipState',2896 limits: 'UpDataStructsCollectionLimits',2897 permissions: 'UpDataStructsCollectionPermissions',2898 tokenPropertyPermissions: 'Vec<UpDataStructsPropertyKeyPermission>',2899 properties: 'Vec<UpDataStructsProperty>',2900 readOnly: 'bool'2901 },2902 /**2903 * Lookup378: rmrk_traits::collection::CollectionInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>, sp_core::crypto::AccountId32>2904 **/2905 RmrkTraitsCollectionCollectionInfo: {2906 issuer: 'AccountId32',2907 metadata: 'Bytes',2908 max: 'Option<u32>',2909 symbol: 'Bytes',2910 nftsCount: 'u32'2911 },2912 /**2913 * Lookup379: rmrk_traits::nft::NftInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill, frame_support::storage::bounded_vec::BoundedVec<T, S>>2914 **/2915 RmrkTraitsNftNftInfo: {2916 owner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple',2917 royalty: 'Option<RmrkTraitsNftRoyaltyInfo>',2918 metadata: 'Bytes',2919 equipped: 'bool',2920 pending: 'bool'2921 },2922 /**2923 * Lookup381: rmrk_traits::nft::RoyaltyInfo<sp_core::crypto::AccountId32, sp_arithmetic::per_things::Permill>2924 **/2925 RmrkTraitsNftRoyaltyInfo: {2926 recipient: 'AccountId32',2927 amount: 'Permill'2928 },2929 /**2930 * Lookup382: rmrk_traits::resource::ResourceInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>2931 **/2932 RmrkTraitsResourceResourceInfo: {2933 id: 'u32',2934 resource: 'RmrkTraitsResourceResourceTypes',2935 pending: 'bool',2936 pendingRemoval: 'bool'2937 },2938 /**2939 * Lookup383: rmrk_traits::property::PropertyInfo<frame_support::storage::bounded_vec::BoundedVec<T, S>, frame_support::storage::bounded_vec::BoundedVec<T, S>>2940 **/2941 RmrkTraitsPropertyPropertyInfo: {2942 key: 'Bytes',2943 value: 'Bytes'2944 },2945 /**2946 * Lookup384: rmrk_traits::base::BaseInfo<sp_core::crypto::AccountId32, frame_support::storage::bounded_vec::BoundedVec<T, S>>2947 **/2948 RmrkTraitsBaseBaseInfo: {2949 issuer: 'AccountId32',2950 baseType: 'Bytes',2951 symbol: 'Bytes'2952 },2953 /**2954 * Lookup385: rmrk_traits::nft::NftChild2955 **/2956 RmrkTraitsNftNftChild: {2957 collectionId: 'u32',2958 nftId: 'u32'2959 },2960 /**2961 * Lookup387: pallet_common::pallet::Error<T>2962 **/2963 PalletCommonError: {2964 _enum: ['CollectionNotFound', 'MustBeTokenOwner', 'NoPermission', 'CantDestroyNotEmptyCollection', 'PublicMintingNotAllowed', 'AddressNotInAllowlist', 'CollectionNameLimitExceeded', 'CollectionDescriptionLimitExceeded', 'CollectionTokenPrefixLimitExceeded', 'TotalCollectionsLimitExceeded', 'CollectionAdminCountExceeded', 'CollectionLimitBoundsExceeded', 'OwnerPermissionsCantBeReverted', 'TransferNotAllowed', 'AccountTokenLimitExceeded', 'CollectionTokenLimitExceeded', 'MetadataFlagFrozen', 'TokenNotFound', 'TokenValueTooLow', 'ApprovedValueTooLow', 'CantApproveMoreThanOwned', 'AddressIsZero', 'UnsupportedOperation', 'NotSufficientFounds', 'UserIsNotAllowedToNest', 'SourceCollectionIsNotAllowedToNest', 'CollectionFieldSizeExceeded', 'NoSpaceForProperty', 'PropertyLimitReached', 'PropertyKeyIsTooLong', 'InvalidCharacterInPropertyKey', 'EmptyPropertyKey', 'CollectionIsExternal', 'CollectionIsInternal']2965 },2966 /**2967 * Lookup389: pallet_fungible::pallet::Error<T>2968 **/2969 PalletFungibleError: {2970 _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed']2971 },2972 /**2973 * Lookup390: pallet_refungible::ItemData2974 **/2975 PalletRefungibleItemData: {2976 constData: 'Bytes'2977 },2978 /**2979 * Lookup395: pallet_refungible::pallet::Error<T>2980 **/2981 PalletRefungibleError: {2982 _enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RepartitionWhileNotOwningAllPieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed']2983 },2984 /**2985 * Lookup396: pallet_nonfungible::ItemData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>2986 **/2987 PalletNonfungibleItemData: {2988 owner: 'PalletEvmAccountBasicCrossAccountIdRepr'2989 },2990 /**2991 * Lookup398: up_data_structs::PropertyScope2992 **/2993 UpDataStructsPropertyScope: {2994 _enum: ['None', 'Rmrk', 'Eth']2995 },2996 /**2997 * Lookup400: pallet_nonfungible::pallet::Error<T>2998 **/2999 PalletNonfungibleError: {3000 _enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount', 'CantBurnNftWithChildren']3001 },3002 /**3003 * Lookup401: pallet_structure::pallet::Error<T>3004 **/3005 PalletStructureError: {3006 _enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound']3007 },3008 /**3009 * Lookup402: pallet_rmrk_core::pallet::Error<T>3010 **/3011 PalletRmrkCoreError: {3012 _enum: ['CorruptedCollectionType', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId']3013 },3014 /**3015 * Lookup404: pallet_rmrk_equip::pallet::Error<T>3016 **/3017 PalletRmrkEquipError: {3018 _enum: ['PermissionError', 'NoAvailableBaseId', 'NoAvailablePartId', 'BaseDoesntExist', 'NeedsDefaultThemeFirst', 'PartDoesntExist', 'NoEquippableOnFixedPart']3019 },3020 /**3021 * Lookup407: pallet_evm::pallet::Error<T>3022 **/3023 PalletEvmError: {3024 _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce']3025 },3026 /**3027 * Lookup410: fp_rpc::TransactionStatus3028 **/3029 FpRpcTransactionStatus: {3030 transactionHash: 'H256',3031 transactionIndex: 'u32',3032 from: 'H160',3033 to: 'Option<H160>',3034 contractAddress: 'Option<H160>',3035 logs: 'Vec<EthereumLog>',3036 logsBloom: 'EthbloomBloom'3037 },3038 /**3039 * Lookup412: ethbloom::Bloom3040 **/3041 EthbloomBloom: '[u8;256]',3042 /**3043 * Lookup414: ethereum::receipt::ReceiptV33044 **/3045 EthereumReceiptReceiptV3: {3046 _enum: {3047 Legacy: 'EthereumReceiptEip658ReceiptData',3048 EIP2930: 'EthereumReceiptEip658ReceiptData',3049 EIP1559: 'EthereumReceiptEip658ReceiptData'3050 }3051 },3052 /**3053 * Lookup415: ethereum::receipt::EIP658ReceiptData3054 **/3055 EthereumReceiptEip658ReceiptData: {3056 statusCode: 'u8',3057 usedGas: 'U256',3058 logsBloom: 'EthbloomBloom',3059 logs: 'Vec<EthereumLog>'3060 },3061 /**3062 * Lookup416: ethereum::block::Block<ethereum::transaction::TransactionV2>3063 **/3064 EthereumBlock: {3065 header: 'EthereumHeader',3066 transactions: 'Vec<EthereumTransactionTransactionV2>',3067 ommers: 'Vec<EthereumHeader>'3068 },3069 /**3070 * Lookup417: ethereum::header::Header3071 **/3072 EthereumHeader: {3073 parentHash: 'H256',3074 ommersHash: 'H256',3075 beneficiary: 'H160',3076 stateRoot: 'H256',3077 transactionsRoot: 'H256',3078 receiptsRoot: 'H256',3079 logsBloom: 'EthbloomBloom',3080 difficulty: 'U256',3081 number: 'U256',3082 gasLimit: 'U256',3083 gasUsed: 'U256',3084 timestamp: 'u64',3085 extraData: 'Bytes',3086 mixHash: 'H256',3087 nonce: 'EthereumTypesHashH64'3088 },3089 /**3090 * Lookup418: ethereum_types::hash::H643091 **/3092 EthereumTypesHashH64: '[u8;8]',3093 /**3094 * Lookup423: pallet_ethereum::pallet::Error<T>3095 **/3096 PalletEthereumError: {3097 _enum: ['InvalidSignature', 'PreLogExists']3098 },3099 /**3100 * Lookup424: pallet_evm_coder_substrate::pallet::Error<T>3101 **/3102 PalletEvmCoderSubstrateError: {3103 _enum: ['OutOfGas', 'OutOfFund']3104 },3105 /**3106 * Lookup425: pallet_evm_contract_helpers::SponsoringModeT3107 **/3108 PalletEvmContractHelpersSponsoringModeT: {3109 _enum: ['Disabled', 'Allowlisted', 'Generous']3110 },3111 /**3112 * Lookup427: pallet_evm_contract_helpers::pallet::Error<T>3113 **/3114 PalletEvmContractHelpersError: {3115 _enum: ['NoPermission']3116 },3117 /**3118 * Lookup428: pallet_evm_migration::pallet::Error<T>3119 **/3120 PalletEvmMigrationError: {3121 _enum: ['AccountNotEmpty', 'AccountIsNotMigrating']3122 },3123 /**3124 * Lookup430: sp_runtime::MultiSignature3125 **/3126 SpRuntimeMultiSignature: {3127 _enum: {3128 Ed25519: 'SpCoreEd25519Signature',3129 Sr25519: 'SpCoreSr25519Signature',3130 Ecdsa: 'SpCoreEcdsaSignature'3131 }3132 },3133 /**3134 * Lookup431: sp_core::ed25519::Signature3135 **/3136 SpCoreEd25519Signature: '[u8;64]',3137 /**3138 * Lookup433: sp_core::sr25519::Signature3139 **/3140 SpCoreSr25519Signature: '[u8;64]',3141 /**3142 * Lookup434: sp_core::ecdsa::Signature3143 **/3144 SpCoreEcdsaSignature: '[u8;65]',3145 /**3146 * Lookup437: frame_system::extensions::check_spec_version::CheckSpecVersion<T>3147 **/3148 FrameSystemExtensionsCheckSpecVersion: 'Null',3149 /**3150 * Lookup438: frame_system::extensions::check_genesis::CheckGenesis<T>3151 **/3152 FrameSystemExtensionsCheckGenesis: 'Null',3153 /**3154 * Lookup441: frame_system::extensions::check_nonce::CheckNonce<T>3155 **/3156 FrameSystemExtensionsCheckNonce: 'Compact<u32>',3157 /**3158 * Lookup442: frame_system::extensions::check_weight::CheckWeight<T>3159 **/3160 FrameSystemExtensionsCheckWeight: 'Null',3161 /**3162 * Lookup443: pallet_template_transaction_payment::ChargeTransactionPayment<opal_runtime::Runtime>3163 **/3164 PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact<u128>',3165 /**3166 * Lookup444: opal_runtime::Runtime3167 **/3168 OpalRuntimeRuntime: 'Null',3169 /**3170 * Lookup445: pallet_ethereum::FakeTransactionFinalizer<opal_runtime::Runtime>3171 **/3172 PalletEthereumFakeTransactionFinalizer: 'Null'3173};tests/src/interfaces/registry.tsdiffbeforeafterboth--- a/tests/src/interfaces/registry.ts
+++ b/tests/src/interfaces/registry.ts
@@ -1,7 +1,7 @@
// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
/* eslint-disable */
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
+import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
declare module '@polkadot/types/types/registry' {
export interface InterfaceTypes {
@@ -89,6 +89,7 @@
PalletBalancesReserveData: PalletBalancesReserveData;
PalletCommonError: PalletCommonError;
PalletCommonEvent: PalletCommonEvent;
+ PalletConfigurationCall: PalletConfigurationCall;
PalletEthereumCall: PalletEthereumCall;
PalletEthereumError: PalletEthereumError;
PalletEthereumEvent: PalletEthereumEvent;
tests/src/interfaces/types-lookup.tsdiffbeforeafterboth--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -1697,13 +1697,26 @@
readonly type: 'Value' | 'Hash';
}
- /** @name PalletTemplateTransactionPaymentCall (207) */
+ /** @name PalletConfigurationCall (207) */
+ export interface PalletConfigurationCall extends Enum {
+ readonly isSetWeightToFeeCoefficientOverride: boolean;
+ readonly asSetWeightToFeeCoefficientOverride: {
+ readonly coeff: Option<u32>;
+ } & Struct;
+ readonly isSetMinGasPriceOverride: boolean;
+ readonly asSetMinGasPriceOverride: {
+ readonly coeff: Option<u64>;
+ } & Struct;
+ readonly type: 'SetWeightToFeeCoefficientOverride' | 'SetMinGasPriceOverride';
+ }
+
+ /** @name PalletTemplateTransactionPaymentCall (209) */
export type PalletTemplateTransactionPaymentCall = Null;
- /** @name PalletStructureCall (208) */
+ /** @name PalletStructureCall (210) */
export type PalletStructureCall = Null;
- /** @name PalletRmrkCoreCall (209) */
+ /** @name PalletRmrkCoreCall (211) */
export interface PalletRmrkCoreCall extends Enum {
readonly isCreateCollection: boolean;
readonly asCreateCollection: {
@@ -1809,7 +1822,7 @@
readonly type: 'CreateCollection' | 'DestroyCollection' | 'ChangeCollectionIssuer' | 'LockCollection' | 'MintNft' | 'BurnNft' | 'Send' | 'AcceptNft' | 'RejectNft' | 'AcceptResource' | 'AcceptResourceRemoval' | 'SetProperty' | 'SetPriority' | 'AddBasicResource' | 'AddComposableResource' | 'AddSlotResource' | 'RemoveResource';
}
- /** @name RmrkTraitsResourceResourceTypes (215) */
+ /** @name RmrkTraitsResourceResourceTypes (217) */
export interface RmrkTraitsResourceResourceTypes extends Enum {
readonly isBasic: boolean;
readonly asBasic: RmrkTraitsResourceBasicResource;
@@ -1820,7 +1833,7 @@
readonly type: 'Basic' | 'Composable' | 'Slot';
}
- /** @name RmrkTraitsResourceBasicResource (217) */
+ /** @name RmrkTraitsResourceBasicResource (219) */
export interface RmrkTraitsResourceBasicResource extends Struct {
readonly src: Option<Bytes>;
readonly metadata: Option<Bytes>;
@@ -1828,7 +1841,7 @@
readonly thumb: Option<Bytes>;
}
- /** @name RmrkTraitsResourceComposableResource (219) */
+ /** @name RmrkTraitsResourceComposableResource (221) */
export interface RmrkTraitsResourceComposableResource extends Struct {
readonly parts: Vec<u32>;
readonly base: u32;
@@ -1838,7 +1851,7 @@
readonly thumb: Option<Bytes>;
}
- /** @name RmrkTraitsResourceSlotResource (220) */
+ /** @name RmrkTraitsResourceSlotResource (222) */
export interface RmrkTraitsResourceSlotResource extends Struct {
readonly base: u32;
readonly src: Option<Bytes>;
@@ -1848,7 +1861,7 @@
readonly thumb: Option<Bytes>;
}
- /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (222) */
+ /** @name RmrkTraitsNftAccountIdOrCollectionNftTuple (224) */
export interface RmrkTraitsNftAccountIdOrCollectionNftTuple extends Enum {
readonly isAccountId: boolean;
readonly asAccountId: AccountId32;
@@ -1857,7 +1870,7 @@
readonly type: 'AccountId' | 'CollectionAndNftTuple';
}
- /** @name PalletRmrkEquipCall (226) */
+ /** @name PalletRmrkEquipCall (228) */
export interface PalletRmrkEquipCall extends Enum {
readonly isCreateBase: boolean;
readonly asCreateBase: {
@@ -1879,7 +1892,7 @@
readonly type: 'CreateBase' | 'ThemeAdd' | 'Equippable';
}
- /** @name RmrkTraitsPartPartType (229) */
+ /** @name RmrkTraitsPartPartType (231) */
export interface RmrkTraitsPartPartType extends Enum {
readonly isFixedPart: boolean;
readonly asFixedPart: RmrkTraitsPartFixedPart;
@@ -1888,14 +1901,14 @@
readonly type: 'FixedPart' | 'SlotPart';
}
- /** @name RmrkTraitsPartFixedPart (231) */
+ /** @name RmrkTraitsPartFixedPart (233) */
export interface RmrkTraitsPartFixedPart extends Struct {
readonly id: u32;
readonly z: u32;
readonly src: Bytes;
}
- /** @name RmrkTraitsPartSlotPart (232) */
+ /** @name RmrkTraitsPartSlotPart (234) */
export interface RmrkTraitsPartSlotPart extends Struct {
readonly id: u32;
readonly equippable: RmrkTraitsPartEquippableList;
@@ -1903,7 +1916,7 @@
readonly z: u32;
}
- /** @name RmrkTraitsPartEquippableList (233) */
+ /** @name RmrkTraitsPartEquippableList (235) */
export interface RmrkTraitsPartEquippableList extends Enum {
readonly isAll: boolean;
readonly isEmpty: boolean;
@@ -1912,20 +1925,20 @@
readonly type: 'All' | 'Empty' | 'Custom';
}
- /** @name RmrkTraitsTheme (235) */
+ /** @name RmrkTraitsTheme (237) */
export interface RmrkTraitsTheme extends Struct {
readonly name: Bytes;
readonly properties: Vec<RmrkTraitsThemeThemeProperty>;
readonly inherit: bool;
}
- /** @name RmrkTraitsThemeThemeProperty (237) */
+ /** @name RmrkTraitsThemeThemeProperty (239) */
export interface RmrkTraitsThemeThemeProperty extends Struct {
readonly key: Bytes;
readonly value: Bytes;
}
- /** @name PalletEvmCall (239) */
+ /** @name PalletEvmCall (241) */
export interface PalletEvmCall extends Enum {
readonly isWithdraw: boolean;
readonly asWithdraw: {
@@ -1970,7 +1983,7 @@
readonly type: 'Withdraw' | 'Call' | 'Create' | 'Create2';
}
- /** @name PalletEthereumCall (245) */
+ /** @name PalletEthereumCall (247) */
export interface PalletEthereumCall extends Enum {
readonly isTransact: boolean;
readonly asTransact: {
@@ -1979,7 +1992,7 @@
readonly type: 'Transact';
}
- /** @name EthereumTransactionTransactionV2 (246) */
+ /** @name EthereumTransactionTransactionV2 (248) */
export interface EthereumTransactionTransactionV2 extends Enum {
readonly isLegacy: boolean;
readonly asLegacy: EthereumTransactionLegacyTransaction;
@@ -1990,7 +2003,7 @@
readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
}
- /** @name EthereumTransactionLegacyTransaction (247) */
+ /** @name EthereumTransactionLegacyTransaction (249) */
export interface EthereumTransactionLegacyTransaction extends Struct {
readonly nonce: U256;
readonly gasPrice: U256;
@@ -2001,7 +2014,7 @@
readonly signature: EthereumTransactionTransactionSignature;
}
- /** @name EthereumTransactionTransactionAction (248) */
+ /** @name EthereumTransactionTransactionAction (250) */
export interface EthereumTransactionTransactionAction extends Enum {
readonly isCall: boolean;
readonly asCall: H160;
@@ -2009,14 +2022,14 @@
readonly type: 'Call' | 'Create';
}
- /** @name EthereumTransactionTransactionSignature (249) */
+ /** @name EthereumTransactionTransactionSignature (251) */
export interface EthereumTransactionTransactionSignature extends Struct {
readonly v: u64;
readonly r: H256;
readonly s: H256;
}
- /** @name EthereumTransactionEip2930Transaction (251) */
+ /** @name EthereumTransactionEip2930Transaction (253) */
export interface EthereumTransactionEip2930Transaction extends Struct {
readonly chainId: u64;
readonly nonce: U256;
@@ -2031,13 +2044,13 @@
readonly s: H256;
}
- /** @name EthereumTransactionAccessListItem (253) */
+ /** @name EthereumTransactionAccessListItem (255) */
export interface EthereumTransactionAccessListItem extends Struct {
readonly address: H160;
readonly storageKeys: Vec<H256>;
}
- /** @name EthereumTransactionEip1559Transaction (254) */
+ /** @name EthereumTransactionEip1559Transaction (256) */
export interface EthereumTransactionEip1559Transaction extends Struct {
readonly chainId: u64;
readonly nonce: U256;
@@ -2053,7 +2066,7 @@
readonly s: H256;
}
- /** @name PalletEvmMigrationCall (255) */
+ /** @name PalletEvmMigrationCall (257) */
export interface PalletEvmMigrationCall extends Enum {
readonly isBegin: boolean;
readonly asBegin: {
@@ -2072,7 +2085,7 @@
readonly type: 'Begin' | 'SetData' | 'Finish';
}
- /** @name PalletSudoEvent (258) */
+ /** @name PalletSudoEvent (260) */
export interface PalletSudoEvent extends Enum {
readonly isSudid: boolean;
readonly asSudid: {
@@ -2089,7 +2102,7 @@
readonly type: 'Sudid' | 'KeyChanged' | 'SudoAsDone';
}
- /** @name SpRuntimeDispatchError (260) */
+ /** @name SpRuntimeDispatchError (262) */
export interface SpRuntimeDispatchError extends Enum {
readonly isOther: boolean;
readonly isCannotLookup: boolean;
@@ -2108,13 +2121,13 @@
readonly type: 'Other' | 'CannotLookup' | 'BadOrigin' | 'Module' | 'ConsumerRemaining' | 'NoProviders' | 'TooManyConsumers' | 'Token' | 'Arithmetic' | 'Transactional';
}
- /** @name SpRuntimeModuleError (261) */
+ /** @name SpRuntimeModuleError (263) */
export interface SpRuntimeModuleError extends Struct {
readonly index: u8;
readonly error: U8aFixed;
}
- /** @name SpRuntimeTokenError (262) */
+ /** @name SpRuntimeTokenError (264) */
export interface SpRuntimeTokenError extends Enum {
readonly isNoFunds: boolean;
readonly isWouldDie: boolean;
@@ -2126,7 +2139,7 @@
readonly type: 'NoFunds' | 'WouldDie' | 'BelowMinimum' | 'CannotCreate' | 'UnknownAsset' | 'Frozen' | 'Unsupported';
}
- /** @name SpRuntimeArithmeticError (263) */
+ /** @name SpRuntimeArithmeticError (265) */
export interface SpRuntimeArithmeticError extends Enum {
readonly isUnderflow: boolean;
readonly isOverflow: boolean;
@@ -2134,20 +2147,20 @@
readonly type: 'Underflow' | 'Overflow' | 'DivisionByZero';
}
- /** @name SpRuntimeTransactionalError (264) */
+ /** @name SpRuntimeTransactionalError (266) */
export interface SpRuntimeTransactionalError extends Enum {
readonly isLimitReached: boolean;
readonly isNoLayer: boolean;
readonly type: 'LimitReached' | 'NoLayer';
}
- /** @name PalletSudoError (265) */
+ /** @name PalletSudoError (267) */
export interface PalletSudoError extends Enum {
readonly isRequireSudo: boolean;
readonly type: 'RequireSudo';
}
- /** @name FrameSystemAccountInfo (266) */
+ /** @name FrameSystemAccountInfo (268) */
export interface FrameSystemAccountInfo extends Struct {
readonly nonce: u32;
readonly consumers: u32;
@@ -2156,19 +2169,19 @@
readonly data: PalletBalancesAccountData;
}
- /** @name FrameSupportWeightsPerDispatchClassU64 (267) */
+ /** @name FrameSupportWeightsPerDispatchClassU64 (269) */
export interface FrameSupportWeightsPerDispatchClassU64 extends Struct {
readonly normal: u64;
readonly operational: u64;
readonly mandatory: u64;
}
- /** @name SpRuntimeDigest (268) */
+ /** @name SpRuntimeDigest (270) */
export interface SpRuntimeDigest extends Struct {
readonly logs: Vec<SpRuntimeDigestDigestItem>;
}
- /** @name SpRuntimeDigestDigestItem (270) */
+ /** @name SpRuntimeDigestDigestItem (272) */
export interface SpRuntimeDigestDigestItem extends Enum {
readonly isOther: boolean;
readonly asOther: Bytes;
@@ -2182,14 +2195,14 @@
readonly type: 'Other' | 'Consensus' | 'Seal' | 'PreRuntime' | 'RuntimeEnvironmentUpdated';
}
- /** @name FrameSystemEventRecord (272) */
+ /** @name FrameSystemEventRecord (274) */
export interface FrameSystemEventRecord extends Struct {
readonly phase: FrameSystemPhase;
readonly event: Event;
readonly topics: Vec<H256>;
}
- /** @name FrameSystemEvent (274) */
+ /** @name FrameSystemEvent (276) */
export interface FrameSystemEvent extends Enum {
readonly isExtrinsicSuccess: boolean;
readonly asExtrinsicSuccess: {
@@ -2217,14 +2230,14 @@
readonly type: 'ExtrinsicSuccess' | 'ExtrinsicFailed' | 'CodeUpdated' | 'NewAccount' | 'KilledAccount' | 'Remarked';
}
- /** @name FrameSupportWeightsDispatchInfo (275) */
+ /** @name FrameSupportWeightsDispatchInfo (277) */
export interface FrameSupportWeightsDispatchInfo extends Struct {
readonly weight: u64;
readonly class: FrameSupportWeightsDispatchClass;
readonly paysFee: FrameSupportWeightsPays;
}
- /** @name FrameSupportWeightsDispatchClass (276) */
+ /** @name FrameSupportWeightsDispatchClass (278) */
export interface FrameSupportWeightsDispatchClass extends Enum {
readonly isNormal: boolean;
readonly isOperational: boolean;
@@ -2232,14 +2245,14 @@
readonly type: 'Normal' | 'Operational' | 'Mandatory';
}
- /** @name FrameSupportWeightsPays (277) */
+ /** @name FrameSupportWeightsPays (279) */
export interface FrameSupportWeightsPays extends Enum {
readonly isYes: boolean;
readonly isNo: boolean;
readonly type: 'Yes' | 'No';
}
- /** @name OrmlVestingModuleEvent (278) */
+ /** @name OrmlVestingModuleEvent (280) */
export interface OrmlVestingModuleEvent extends Enum {
readonly isVestingScheduleAdded: boolean;
readonly asVestingScheduleAdded: {
@@ -2259,7 +2272,7 @@
readonly type: 'VestingScheduleAdded' | 'Claimed' | 'VestingSchedulesUpdated';
}
- /** @name CumulusPalletXcmpQueueEvent (279) */
+ /** @name CumulusPalletXcmpQueueEvent (281) */
export interface CumulusPalletXcmpQueueEvent extends Enum {
readonly isSuccess: boolean;
readonly asSuccess: Option<H256>;
@@ -2280,7 +2293,7 @@
readonly type: 'Success' | 'Fail' | 'BadVersion' | 'BadFormat' | 'UpwardMessageSent' | 'XcmpMessageSent' | 'OverweightEnqueued' | 'OverweightServiced';
}
- /** @name PalletXcmEvent (280) */
+ /** @name PalletXcmEvent (282) */
export interface PalletXcmEvent extends Enum {
readonly isAttempted: boolean;
readonly asAttempted: XcmV2TraitsOutcome;
@@ -2317,7 +2330,7 @@
readonly type: 'Attempted' | 'Sent' | 'UnexpectedResponse' | 'ResponseReady' | 'Notified' | 'NotifyOverweight' | 'NotifyDispatchError' | 'NotifyDecodeFailed' | 'InvalidResponder' | 'InvalidResponderVersion' | 'ResponseTaken' | 'AssetsTrapped' | 'VersionChangeNotified' | 'SupportedVersionChanged' | 'NotifyTargetSendFail' | 'NotifyTargetMigrationFail';
}
- /** @name XcmV2TraitsOutcome (281) */
+ /** @name XcmV2TraitsOutcome (283) */
export interface XcmV2TraitsOutcome extends Enum {
readonly isComplete: boolean;
readonly asComplete: u64;
@@ -2328,7 +2341,7 @@
readonly type: 'Complete' | 'Incomplete' | 'Error';
}
- /** @name CumulusPalletXcmEvent (283) */
+ /** @name CumulusPalletXcmEvent (285) */
export interface CumulusPalletXcmEvent extends Enum {
readonly isInvalidFormat: boolean;
readonly asInvalidFormat: U8aFixed;
@@ -2339,7 +2352,7 @@
readonly type: 'InvalidFormat' | 'UnsupportedVersion' | 'ExecutedDownward';
}
- /** @name CumulusPalletDmpQueueEvent (284) */
+ /** @name CumulusPalletDmpQueueEvent (286) */
export interface CumulusPalletDmpQueueEvent extends Enum {
readonly isInvalidFormat: boolean;
readonly asInvalidFormat: {
@@ -2374,7 +2387,7 @@
readonly type: 'InvalidFormat' | 'UnsupportedVersion' | 'ExecutedDownward' | 'WeightExhausted' | 'OverweightEnqueued' | 'OverweightServiced';
}
- /** @name PalletUniqueRawEvent (285) */
+ /** @name PalletUniqueRawEvent (287) */
export interface PalletUniqueRawEvent extends Enum {
readonly isCollectionSponsorRemoved: boolean;
readonly asCollectionSponsorRemoved: u32;
@@ -2399,7 +2412,7 @@
readonly type: 'CollectionSponsorRemoved' | 'CollectionAdminAdded' | 'CollectionOwnedChanged' | 'CollectionSponsorSet' | 'SponsorshipConfirmed' | 'CollectionAdminRemoved' | 'AllowListAddressRemoved' | 'AllowListAddressAdded' | 'CollectionLimitSet' | 'CollectionPermissionSet';
}
- /** @name PalletUniqueSchedulerEvent (286) */
+ /** @name PalletUniqueSchedulerEvent (288) */
export interface PalletUniqueSchedulerEvent extends Enum {
readonly isScheduled: boolean;
readonly asScheduled: {
@@ -2426,14 +2439,14 @@
readonly type: 'Scheduled' | 'Canceled' | 'Dispatched' | 'CallLookupFailed';
}
- /** @name FrameSupportScheduleLookupError (288) */
+ /** @name FrameSupportScheduleLookupError (290) */
export interface FrameSupportScheduleLookupError extends Enum {
readonly isUnknown: boolean;
readonly isBadFormat: boolean;
readonly type: 'Unknown' | 'BadFormat';
}
- /** @name PalletCommonEvent (289) */
+ /** @name PalletCommonEvent (291) */
export interface PalletCommonEvent extends Enum {
readonly isCollectionCreated: boolean;
readonly asCollectionCreated: ITuple<[u32, u8, AccountId32]>;
@@ -2460,14 +2473,14 @@
readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'ItemCreated' | 'ItemDestroyed' | 'Transfer' | 'Approved' | 'CollectionPropertySet' | 'CollectionPropertyDeleted' | 'TokenPropertySet' | 'TokenPropertyDeleted' | 'PropertyPermissionSet';
}
- /** @name PalletStructureEvent (290) */
+ /** @name PalletStructureEvent (292) */
export interface PalletStructureEvent extends Enum {
readonly isExecuted: boolean;
readonly asExecuted: Result<Null, SpRuntimeDispatchError>;
readonly type: 'Executed';
}
- /** @name PalletRmrkCoreEvent (291) */
+ /** @name PalletRmrkCoreEvent (293) */
export interface PalletRmrkCoreEvent extends Enum {
readonly isCollectionCreated: boolean;
readonly asCollectionCreated: {
@@ -2557,7 +2570,7 @@
readonly type: 'CollectionCreated' | 'CollectionDestroyed' | 'IssuerChanged' | 'CollectionLocked' | 'NftMinted' | 'NftBurned' | 'NftSent' | 'NftAccepted' | 'NftRejected' | 'PropertySet' | 'ResourceAdded' | 'ResourceRemoval' | 'ResourceAccepted' | 'ResourceRemovalAccepted' | 'PrioritySet';
}
- /** @name PalletRmrkEquipEvent (292) */
+ /** @name PalletRmrkEquipEvent (294) */
export interface PalletRmrkEquipEvent extends Enum {
readonly isBaseCreated: boolean;
readonly asBaseCreated: {
@@ -2572,7 +2585,7 @@
readonly type: 'BaseCreated' | 'EquippablesUpdated';
}
- /** @name PalletEvmEvent (293) */
+ /** @name PalletEvmEvent (295) */
export interface PalletEvmEvent extends Enum {
readonly isLog: boolean;
readonly asLog: EthereumLog;
@@ -2591,21 +2604,21 @@
readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed' | 'BalanceDeposit' | 'BalanceWithdraw';
}
- /** @name EthereumLog (294) */
+ /** @name EthereumLog (296) */
export interface EthereumLog extends Struct {
readonly address: H160;
readonly topics: Vec<H256>;
readonly data: Bytes;
}
- /** @name PalletEthereumEvent (295) */
+ /** @name PalletEthereumEvent (297) */
export interface PalletEthereumEvent extends Enum {
readonly isExecuted: boolean;
readonly asExecuted: ITuple<[H160, H160, H256, EvmCoreErrorExitReason]>;
readonly type: 'Executed';
}
- /** @name EvmCoreErrorExitReason (296) */
+ /** @name EvmCoreErrorExitReason (298) */
export interface EvmCoreErrorExitReason extends Enum {
readonly isSucceed: boolean;
readonly asSucceed: EvmCoreErrorExitSucceed;
@@ -2618,7 +2631,7 @@
readonly type: 'Succeed' | 'Error' | 'Revert' | 'Fatal';
}
- /** @name EvmCoreErrorExitSucceed (297) */
+ /** @name EvmCoreErrorExitSucceed (299) */
export interface EvmCoreErrorExitSucceed extends Enum {
readonly isStopped: boolean;
readonly isReturned: boolean;
@@ -2626,7 +2639,7 @@
readonly type: 'Stopped' | 'Returned' | 'Suicided';
}
- /** @name EvmCoreErrorExitError (298) */
+ /** @name EvmCoreErrorExitError (300) */
export interface EvmCoreErrorExitError extends Enum {
readonly isStackUnderflow: boolean;
readonly isStackOverflow: boolean;
@@ -2647,13 +2660,13 @@
readonly type: 'StackUnderflow' | 'StackOverflow' | 'InvalidJump' | 'InvalidRange' | 'DesignatedInvalid' | 'CallTooDeep' | 'CreateCollision' | 'CreateContractLimit' | 'OutOfOffset' | 'OutOfGas' | 'OutOfFund' | 'PcUnderflow' | 'CreateEmpty' | 'Other' | 'InvalidCode';
}
- /** @name EvmCoreErrorExitRevert (301) */
+ /** @name EvmCoreErrorExitRevert (303) */
export interface EvmCoreErrorExitRevert extends Enum {
readonly isReverted: boolean;
readonly type: 'Reverted';
}
- /** @name EvmCoreErrorExitFatal (302) */
+ /** @name EvmCoreErrorExitFatal (304) */
export interface EvmCoreErrorExitFatal extends Enum {
readonly isNotSupported: boolean;
readonly isUnhandledInterrupt: boolean;
@@ -2664,7 +2677,7 @@
readonly type: 'NotSupported' | 'UnhandledInterrupt' | 'CallErrorAsFatal' | 'Other';
}
- /** @name FrameSystemPhase (303) */
+ /** @name FrameSystemPhase (305) */
export interface FrameSystemPhase extends Enum {
readonly isApplyExtrinsic: boolean;
readonly asApplyExtrinsic: u32;
@@ -2673,27 +2686,27 @@
readonly type: 'ApplyExtrinsic' | 'Finalization' | 'Initialization';
}
- /** @name FrameSystemLastRuntimeUpgradeInfo (305) */
+ /** @name FrameSystemLastRuntimeUpgradeInfo (307) */
export interface FrameSystemLastRuntimeUpgradeInfo extends Struct {
readonly specVersion: Compact<u32>;
readonly specName: Text;
}
- /** @name FrameSystemLimitsBlockWeights (306) */
+ /** @name FrameSystemLimitsBlockWeights (308) */
export interface FrameSystemLimitsBlockWeights extends Struct {
readonly baseBlock: u64;
readonly maxBlock: u64;
readonly perClass: FrameSupportWeightsPerDispatchClassWeightsPerClass;
}
- /** @name FrameSupportWeightsPerDispatchClassWeightsPerClass (307) */
+ /** @name FrameSupportWeightsPerDispatchClassWeightsPerClass (309) */
export interface FrameSupportWeightsPerDispatchClassWeightsPerClass extends Struct {
readonly normal: FrameSystemLimitsWeightsPerClass;
readonly operational: FrameSystemLimitsWeightsPerClass;
readonly mandatory: FrameSystemLimitsWeightsPerClass;
}
- /** @name FrameSystemLimitsWeightsPerClass (308) */
+ /** @name FrameSystemLimitsWeightsPerClass (310) */
export interface FrameSystemLimitsWeightsPerClass extends Struct {
readonly baseExtrinsic: u64;
readonly maxExtrinsic: Option<u64>;
@@ -2701,25 +2714,25 @@
readonly reserved: Option<u64>;
}
- /** @name FrameSystemLimitsBlockLength (310) */
+ /** @name FrameSystemLimitsBlockLength (311) */
export interface FrameSystemLimitsBlockLength extends Struct {
readonly max: FrameSupportWeightsPerDispatchClassU32;
}
- /** @name FrameSupportWeightsPerDispatchClassU32 (311) */
+ /** @name FrameSupportWeightsPerDispatchClassU32 (312) */
export interface FrameSupportWeightsPerDispatchClassU32 extends Struct {
readonly normal: u32;
readonly operational: u32;
readonly mandatory: u32;
}
- /** @name FrameSupportWeightsRuntimeDbWeight (312) */
+ /** @name FrameSupportWeightsRuntimeDbWeight (313) */
export interface FrameSupportWeightsRuntimeDbWeight extends Struct {
readonly read: u64;
readonly write: u64;
}
- /** @name SpVersionRuntimeVersion (313) */
+ /** @name SpVersionRuntimeVersion (314) */
export interface SpVersionRuntimeVersion extends Struct {
readonly specName: Text;
readonly implName: Text;
@@ -2731,7 +2744,7 @@
readonly stateVersion: u8;
}
- /** @name FrameSystemError (317) */
+ /** @name FrameSystemError (318) */
export interface FrameSystemError extends Enum {
readonly isInvalidSpecName: boolean;
readonly isSpecVersionNeedsToIncrease: boolean;
@@ -2742,7 +2755,7 @@
readonly type: 'InvalidSpecName' | 'SpecVersionNeedsToIncrease' | 'FailedToExtractRuntimeVersion' | 'NonDefaultComposite' | 'NonZeroRefCount' | 'CallFiltered';
}
- /** @name OrmlVestingModuleError (319) */
+ /** @name OrmlVestingModuleError (320) */
export interface OrmlVestingModuleError extends Enum {
readonly isZeroVestingPeriod: boolean;
readonly isZeroVestingPeriodCount: boolean;
@@ -2753,21 +2766,21 @@
readonly type: 'ZeroVestingPeriod' | 'ZeroVestingPeriodCount' | 'InsufficientBalanceToLock' | 'TooManyVestingSchedules' | 'AmountLow' | 'MaxVestingSchedulesExceeded';
}
- /** @name CumulusPalletXcmpQueueInboundChannelDetails (321) */
+ /** @name CumulusPalletXcmpQueueInboundChannelDetails (322) */
export interface CumulusPalletXcmpQueueInboundChannelDetails extends Struct {
readonly sender: u32;
readonly state: CumulusPalletXcmpQueueInboundState;
readonly messageMetadata: Vec<ITuple<[u32, PolkadotParachainPrimitivesXcmpMessageFormat]>>;
}
- /** @name CumulusPalletXcmpQueueInboundState (322) */
+ /** @name CumulusPalletXcmpQueueInboundState (323) */
export interface CumulusPalletXcmpQueueInboundState extends Enum {
readonly isOk: boolean;
readonly isSuspended: boolean;
readonly type: 'Ok' | 'Suspended';
}
- /** @name PolkadotParachainPrimitivesXcmpMessageFormat (325) */
+ /** @name PolkadotParachainPrimitivesXcmpMessageFormat (326) */
export interface PolkadotParachainPrimitivesXcmpMessageFormat extends Enum {
readonly isConcatenatedVersionedXcm: boolean;
readonly isConcatenatedEncodedBlob: boolean;
@@ -2775,7 +2788,7 @@
readonly type: 'ConcatenatedVersionedXcm' | 'ConcatenatedEncodedBlob' | 'Signals';
}
- /** @name CumulusPalletXcmpQueueOutboundChannelDetails (328) */
+ /** @name CumulusPalletXcmpQueueOutboundChannelDetails (329) */
export interface CumulusPalletXcmpQueueOutboundChannelDetails extends Struct {
readonly recipient: u32;
readonly state: CumulusPalletXcmpQueueOutboundState;
@@ -2784,14 +2797,14 @@
readonly lastIndex: u16;
}
- /** @name CumulusPalletXcmpQueueOutboundState (329) */
+ /** @name CumulusPalletXcmpQueueOutboundState (330) */
export interface CumulusPalletXcmpQueueOutboundState extends Enum {
readonly isOk: boolean;
readonly isSuspended: boolean;
readonly type: 'Ok' | 'Suspended';
}
- /** @name CumulusPalletXcmpQueueQueueConfigData (331) */
+ /** @name CumulusPalletXcmpQueueQueueConfigData (332) */
export interface CumulusPalletXcmpQueueQueueConfigData extends Struct {
readonly suspendThreshold: u32;
readonly dropThreshold: u32;
@@ -2801,7 +2814,7 @@
readonly xcmpMaxIndividualWeight: u64;
}
- /** @name CumulusPalletXcmpQueueError (333) */
+ /** @name CumulusPalletXcmpQueueError (334) */
export interface CumulusPalletXcmpQueueError extends Enum {
readonly isFailedToSend: boolean;
readonly isBadXcmOrigin: boolean;
@@ -2811,7 +2824,7 @@
readonly type: 'FailedToSend' | 'BadXcmOrigin' | 'BadXcm' | 'BadOverweightIndex' | 'WeightOverLimit';
}
- /** @name PalletXcmError (334) */
+ /** @name PalletXcmError (335) */
export interface PalletXcmError extends Enum {
readonly isUnreachable: boolean;
readonly isSendFailure: boolean;
@@ -2829,29 +2842,29 @@
readonly type: 'Unreachable' | 'SendFailure' | 'Filtered' | 'UnweighableMessage' | 'DestinationNotInvertible' | 'Empty' | 'CannotReanchor' | 'TooManyAssets' | 'InvalidOrigin' | 'BadVersion' | 'BadLocation' | 'NoSubscription' | 'AlreadySubscribed';
}
- /** @name CumulusPalletXcmError (335) */
+ /** @name CumulusPalletXcmError (336) */
export type CumulusPalletXcmError = Null;
- /** @name CumulusPalletDmpQueueConfigData (336) */
+ /** @name CumulusPalletDmpQueueConfigData (337) */
export interface CumulusPalletDmpQueueConfigData extends Struct {
readonly maxIndividual: u64;
}
- /** @name CumulusPalletDmpQueuePageIndexData (337) */
+ /** @name CumulusPalletDmpQueuePageIndexData (338) */
export interface CumulusPalletDmpQueuePageIndexData extends Struct {
readonly beginUsed: u32;
readonly endUsed: u32;
readonly overweightCount: u64;
}
- /** @name CumulusPalletDmpQueueError (340) */
+ /** @name CumulusPalletDmpQueueError (341) */
export interface CumulusPalletDmpQueueError extends Enum {
readonly isUnknown: boolean;
readonly isOverLimit: boolean;
readonly type: 'Unknown' | 'OverLimit';
}
- /** @name PalletUniqueError (344) */
+ /** @name PalletUniqueError (345) */
export interface PalletUniqueError extends Enum {
readonly isCollectionDecimalPointLimitExceeded: boolean;
readonly isConfirmUnsetSponsorFail: boolean;
@@ -2860,7 +2873,7 @@
readonly type: 'CollectionDecimalPointLimitExceeded' | 'ConfirmUnsetSponsorFail' | 'EmptyArgument' | 'RepartitionCalledOnNonRefungibleCollection';
}
- /** @name PalletUniqueSchedulerScheduledV3 (347) */
+ /** @name PalletUniqueSchedulerScheduledV3 (348) */
export interface PalletUniqueSchedulerScheduledV3 extends Struct {
readonly maybeId: Option<U8aFixed>;
readonly priority: u8;
@@ -2869,7 +2882,7 @@
readonly origin: OpalRuntimeOriginCaller;
}
- /** @name OpalRuntimeOriginCaller (348) */
+ /** @name OpalRuntimeOriginCaller (349) */
export interface OpalRuntimeOriginCaller extends Enum {
readonly isVoid: boolean;
readonly isSystem: boolean;
@@ -2883,7 +2896,7 @@
readonly type: 'Void' | 'System' | 'PolkadotXcm' | 'CumulusXcm' | 'Ethereum';
}
- /** @name FrameSupportDispatchRawOrigin (349) */
+ /** @name FrameSupportDispatchRawOrigin (350) */
export interface FrameSupportDispatchRawOrigin extends Enum {
readonly isRoot: boolean;
readonly isSigned: boolean;
@@ -2892,7 +2905,7 @@
readonly type: 'Root' | 'Signed' | 'None';
}
- /** @name PalletXcmOrigin (350) */
+ /** @name PalletXcmOrigin (351) */
export interface PalletXcmOrigin extends Enum {
readonly isXcm: boolean;
readonly asXcm: XcmV1MultiLocation;
@@ -2901,7 +2914,7 @@
readonly type: 'Xcm' | 'Response';
}
- /** @name CumulusPalletXcmOrigin (351) */
+ /** @name CumulusPalletXcmOrigin (352) */
export interface CumulusPalletXcmOrigin extends Enum {
readonly isRelay: boolean;
readonly isSiblingParachain: boolean;
@@ -2909,17 +2922,17 @@
readonly type: 'Relay' | 'SiblingParachain';
}
- /** @name PalletEthereumRawOrigin (352) */
+ /** @name PalletEthereumRawOrigin (353) */
export interface PalletEthereumRawOrigin extends Enum {
readonly isEthereumTransaction: boolean;
readonly asEthereumTransaction: H160;
readonly type: 'EthereumTransaction';
}
- /** @name SpCoreVoid (353) */
+ /** @name SpCoreVoid (354) */
export type SpCoreVoid = Null;
- /** @name PalletUniqueSchedulerError (354) */
+ /** @name PalletUniqueSchedulerError (355) */
export interface PalletUniqueSchedulerError extends Enum {
readonly isFailedToSchedule: boolean;
readonly isNotFound: boolean;
@@ -2928,7 +2941,7 @@
readonly type: 'FailedToSchedule' | 'NotFound' | 'TargetBlockNumberInPast' | 'RescheduleNoChange';
}
- /** @name UpDataStructsCollection (355) */
+ /** @name UpDataStructsCollection (356) */
export interface UpDataStructsCollection extends Struct {
readonly owner: AccountId32;
readonly mode: UpDataStructsCollectionMode;
@@ -2941,7 +2954,7 @@
readonly externalCollection: bool;
}
- /** @name UpDataStructsSponsorshipState (356) */
+ /** @name UpDataStructsSponsorshipState (357) */
export interface UpDataStructsSponsorshipState extends Enum {
readonly isDisabled: boolean;
readonly isUnconfirmed: boolean;
@@ -2951,43 +2964,43 @@
readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed';
}
- /** @name UpDataStructsProperties (357) */
+ /** @name UpDataStructsProperties (358) */
export interface UpDataStructsProperties extends Struct {
readonly map: UpDataStructsPropertiesMapBoundedVec;
readonly consumedSpace: u32;
readonly spaceLimit: u32;
}
- /** @name UpDataStructsPropertiesMapBoundedVec (358) */
+ /** @name UpDataStructsPropertiesMapBoundedVec (359) */
export interface UpDataStructsPropertiesMapBoundedVec extends BTreeMap<Bytes, Bytes> {}
- /** @name UpDataStructsPropertiesMapPropertyPermission (363) */
+ /** @name UpDataStructsPropertiesMapPropertyPermission (364) */
export interface UpDataStructsPropertiesMapPropertyPermission extends BTreeMap<Bytes, UpDataStructsPropertyPermission> {}
- /** @name UpDataStructsCollectionStats (370) */
+ /** @name UpDataStructsCollectionStats (371) */
export interface UpDataStructsCollectionStats extends Struct {
readonly created: u32;
readonly destroyed: u32;
readonly alive: u32;
}
- /** @name UpDataStructsTokenChild (371) */
+ /** @name UpDataStructsTokenChild (372) */
export interface UpDataStructsTokenChild extends Struct {
readonly token: u32;
readonly collection: u32;
}
- /** @name PhantomTypeUpDataStructs (372) */
+ /** @name PhantomTypeUpDataStructs (373) */
export interface PhantomTypeUpDataStructs extends Vec<ITuple<[UpDataStructsTokenData, UpDataStructsRpcCollection, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftNftInfo, RmrkTraitsResourceResourceInfo, RmrkTraitsPropertyPropertyInfo, RmrkTraitsBaseBaseInfo, RmrkTraitsPartPartType, RmrkTraitsTheme, RmrkTraitsNftNftChild]>> {}
- /** @name UpDataStructsTokenData (374) */
+ /** @name UpDataStructsTokenData (375) */
export interface UpDataStructsTokenData extends Struct {
readonly properties: Vec<UpDataStructsProperty>;
readonly owner: Option<PalletEvmAccountBasicCrossAccountIdRepr>;
readonly pieces: u128;
}
- /** @name UpDataStructsRpcCollection (376) */
+ /** @name UpDataStructsRpcCollection (377) */
export interface UpDataStructsRpcCollection extends Struct {
readonly owner: AccountId32;
readonly mode: UpDataStructsCollectionMode;
@@ -3002,7 +3015,7 @@
readonly readOnly: bool;
}
- /** @name RmrkTraitsCollectionCollectionInfo (377) */
+ /** @name RmrkTraitsCollectionCollectionInfo (378) */
export interface RmrkTraitsCollectionCollectionInfo extends Struct {
readonly issuer: AccountId32;
readonly metadata: Bytes;
@@ -3011,7 +3024,7 @@
readonly nftsCount: u32;
}
- /** @name RmrkTraitsNftNftInfo (378) */
+ /** @name RmrkTraitsNftNftInfo (379) */
export interface RmrkTraitsNftNftInfo extends Struct {
readonly owner: RmrkTraitsNftAccountIdOrCollectionNftTuple;
readonly royalty: Option<RmrkTraitsNftRoyaltyInfo>;
@@ -3020,13 +3033,13 @@
readonly pending: bool;
}
- /** @name RmrkTraitsNftRoyaltyInfo (380) */
+ /** @name RmrkTraitsNftRoyaltyInfo (381) */
export interface RmrkTraitsNftRoyaltyInfo extends Struct {
readonly recipient: AccountId32;
readonly amount: Permill;
}
- /** @name RmrkTraitsResourceResourceInfo (381) */
+ /** @name RmrkTraitsResourceResourceInfo (382) */
export interface RmrkTraitsResourceResourceInfo extends Struct {
readonly id: u32;
readonly resource: RmrkTraitsResourceResourceTypes;
@@ -3034,26 +3047,26 @@
readonly pendingRemoval: bool;
}
- /** @name RmrkTraitsPropertyPropertyInfo (382) */
+ /** @name RmrkTraitsPropertyPropertyInfo (383) */
export interface RmrkTraitsPropertyPropertyInfo extends Struct {
readonly key: Bytes;
readonly value: Bytes;
}
- /** @name RmrkTraitsBaseBaseInfo (383) */
+ /** @name RmrkTraitsBaseBaseInfo (384) */
export interface RmrkTraitsBaseBaseInfo extends Struct {
readonly issuer: AccountId32;
readonly baseType: Bytes;
readonly symbol: Bytes;
}
- /** @name RmrkTraitsNftNftChild (384) */
+ /** @name RmrkTraitsNftNftChild (385) */
export interface RmrkTraitsNftNftChild extends Struct {
readonly collectionId: u32;
readonly nftId: u32;
}
- /** @name PalletCommonError (386) */
+ /** @name PalletCommonError (387) */
export interface PalletCommonError extends Enum {
readonly isCollectionNotFound: boolean;
readonly isMustBeTokenOwner: boolean;
@@ -3092,7 +3105,7 @@
readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'CantDestroyNotEmptyCollection' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal';
}
- /** @name PalletFungibleError (388) */
+ /** @name PalletFungibleError (389) */
export interface PalletFungibleError extends Enum {
readonly isNotFungibleDataUsedToMintFungibleCollectionToken: boolean;
readonly isFungibleItemsHaveNoId: boolean;
@@ -3102,12 +3115,12 @@
readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
}
- /** @name PalletRefungibleItemData (389) */
+ /** @name PalletRefungibleItemData (390) */
export interface PalletRefungibleItemData extends Struct {
readonly constData: Bytes;
}
- /** @name PalletRefungibleError (394) */
+ /** @name PalletRefungibleError (395) */
export interface PalletRefungibleError extends Enum {
readonly isNotRefungibleDataUsedToMintFungibleCollectionToken: boolean;
readonly isWrongRefungiblePieces: boolean;
@@ -3117,19 +3130,20 @@
readonly type: 'NotRefungibleDataUsedToMintFungibleCollectionToken' | 'WrongRefungiblePieces' | 'RepartitionWhileNotOwningAllPieces' | 'RefungibleDisallowsNesting' | 'SettingPropertiesNotAllowed';
}
- /** @name PalletNonfungibleItemData (395) */
+ /** @name PalletNonfungibleItemData (396) */
export interface PalletNonfungibleItemData extends Struct {
readonly owner: PalletEvmAccountBasicCrossAccountIdRepr;
}
- /** @name UpDataStructsPropertyScope (397) */
+ /** @name UpDataStructsPropertyScope (398) */
export interface UpDataStructsPropertyScope extends Enum {
readonly isNone: boolean;
readonly isRmrk: boolean;
- readonly type: 'None' | 'Rmrk';
+ readonly isEth: boolean;
+ readonly type: 'None' | 'Rmrk' | 'Eth';
}
- /** @name PalletNonfungibleError (399) */
+ /** @name PalletNonfungibleError (400) */
export interface PalletNonfungibleError extends Enum {
readonly isNotNonfungibleDataUsedToMintFungibleCollectionToken: boolean;
readonly isNonfungibleItemsHaveNoAmount: boolean;
@@ -3137,7 +3151,7 @@
readonly type: 'NotNonfungibleDataUsedToMintFungibleCollectionToken' | 'NonfungibleItemsHaveNoAmount' | 'CantBurnNftWithChildren';
}
- /** @name PalletStructureError (400) */
+ /** @name PalletStructureError (401) */
export interface PalletStructureError extends Enum {
readonly isOuroborosDetected: boolean;
readonly isDepthLimit: boolean;
@@ -3146,7 +3160,7 @@
readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound';
}
- /** @name PalletRmrkCoreError (401) */
+ /** @name PalletRmrkCoreError (402) */
export interface PalletRmrkCoreError extends Enum {
readonly isCorruptedCollectionType: boolean;
readonly isRmrkPropertyKeyIsTooLong: boolean;
@@ -3170,7 +3184,7 @@
readonly type: 'CorruptedCollectionType' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId';
}
- /** @name PalletRmrkEquipError (403) */
+ /** @name PalletRmrkEquipError (404) */
export interface PalletRmrkEquipError extends Enum {
readonly isPermissionError: boolean;
readonly isNoAvailableBaseId: boolean;
@@ -3182,7 +3196,7 @@
readonly type: 'PermissionError' | 'NoAvailableBaseId' | 'NoAvailablePartId' | 'BaseDoesntExist' | 'NeedsDefaultThemeFirst' | 'PartDoesntExist' | 'NoEquippableOnFixedPart';
}
- /** @name PalletEvmError (406) */
+ /** @name PalletEvmError (407) */
export interface PalletEvmError extends Enum {
readonly isBalanceLow: boolean;
readonly isFeeOverflow: boolean;
@@ -3193,7 +3207,7 @@
readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce';
}
- /** @name FpRpcTransactionStatus (409) */
+ /** @name FpRpcTransactionStatus (410) */
export interface FpRpcTransactionStatus extends Struct {
readonly transactionHash: H256;
readonly transactionIndex: u32;
@@ -3204,10 +3218,10 @@
readonly logsBloom: EthbloomBloom;
}
- /** @name EthbloomBloom (411) */
+ /** @name EthbloomBloom (412) */
export interface EthbloomBloom extends U8aFixed {}
- /** @name EthereumReceiptReceiptV3 (413) */
+ /** @name EthereumReceiptReceiptV3 (414) */
export interface EthereumReceiptReceiptV3 extends Enum {
readonly isLegacy: boolean;
readonly asLegacy: EthereumReceiptEip658ReceiptData;
@@ -3218,7 +3232,7 @@
readonly type: 'Legacy' | 'Eip2930' | 'Eip1559';
}
- /** @name EthereumReceiptEip658ReceiptData (414) */
+ /** @name EthereumReceiptEip658ReceiptData (415) */
export interface EthereumReceiptEip658ReceiptData extends Struct {
readonly statusCode: u8;
readonly usedGas: U256;
@@ -3226,14 +3240,14 @@
readonly logs: Vec<EthereumLog>;
}
- /** @name EthereumBlock (415) */
+ /** @name EthereumBlock (416) */
export interface EthereumBlock extends Struct {
readonly header: EthereumHeader;
readonly transactions: Vec<EthereumTransactionTransactionV2>;
readonly ommers: Vec<EthereumHeader>;
}
- /** @name EthereumHeader (416) */
+ /** @name EthereumHeader (417) */
export interface EthereumHeader extends Struct {
readonly parentHash: H256;
readonly ommersHash: H256;
@@ -3252,24 +3266,24 @@
readonly nonce: EthereumTypesHashH64;
}
- /** @name EthereumTypesHashH64 (417) */
+ /** @name EthereumTypesHashH64 (418) */
export interface EthereumTypesHashH64 extends U8aFixed {}
- /** @name PalletEthereumError (422) */
+ /** @name PalletEthereumError (423) */
export interface PalletEthereumError extends Enum {
readonly isInvalidSignature: boolean;
readonly isPreLogExists: boolean;
readonly type: 'InvalidSignature' | 'PreLogExists';
}
- /** @name PalletEvmCoderSubstrateError (423) */
+ /** @name PalletEvmCoderSubstrateError (424) */
export interface PalletEvmCoderSubstrateError extends Enum {
readonly isOutOfGas: boolean;
readonly isOutOfFund: boolean;
readonly type: 'OutOfGas' | 'OutOfFund';
}
- /** @name PalletEvmContractHelpersSponsoringModeT (424) */
+ /** @name PalletEvmContractHelpersSponsoringModeT (425) */
export interface PalletEvmContractHelpersSponsoringModeT extends Enum {
readonly isDisabled: boolean;
readonly isAllowlisted: boolean;
@@ -3277,20 +3291,20 @@
readonly type: 'Disabled' | 'Allowlisted' | 'Generous';
}
- /** @name PalletEvmContractHelpersError (426) */
+ /** @name PalletEvmContractHelpersError (427) */
export interface PalletEvmContractHelpersError extends Enum {
readonly isNoPermission: boolean;
readonly type: 'NoPermission';
}
- /** @name PalletEvmMigrationError (427) */
+ /** @name PalletEvmMigrationError (428) */
export interface PalletEvmMigrationError extends Enum {
readonly isAccountNotEmpty: boolean;
readonly isAccountIsNotMigrating: boolean;
readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating';
}
- /** @name SpRuntimeMultiSignature (429) */
+ /** @name SpRuntimeMultiSignature (430) */
export interface SpRuntimeMultiSignature extends Enum {
readonly isEd25519: boolean;
readonly asEd25519: SpCoreEd25519Signature;
@@ -3301,34 +3315,34 @@
readonly type: 'Ed25519' | 'Sr25519' | 'Ecdsa';
}
- /** @name SpCoreEd25519Signature (430) */
+ /** @name SpCoreEd25519Signature (431) */
export interface SpCoreEd25519Signature extends U8aFixed {}
- /** @name SpCoreSr25519Signature (432) */
+ /** @name SpCoreSr25519Signature (433) */
export interface SpCoreSr25519Signature extends U8aFixed {}
- /** @name SpCoreEcdsaSignature (433) */
+ /** @name SpCoreEcdsaSignature (434) */
export interface SpCoreEcdsaSignature extends U8aFixed {}
- /** @name FrameSystemExtensionsCheckSpecVersion (436) */
+ /** @name FrameSystemExtensionsCheckSpecVersion (437) */
export type FrameSystemExtensionsCheckSpecVersion = Null;
- /** @name FrameSystemExtensionsCheckGenesis (437) */
+ /** @name FrameSystemExtensionsCheckGenesis (438) */
export type FrameSystemExtensionsCheckGenesis = Null;
- /** @name FrameSystemExtensionsCheckNonce (440) */
+ /** @name FrameSystemExtensionsCheckNonce (441) */
export interface FrameSystemExtensionsCheckNonce extends Compact<u32> {}
- /** @name FrameSystemExtensionsCheckWeight (441) */
+ /** @name FrameSystemExtensionsCheckWeight (442) */
export type FrameSystemExtensionsCheckWeight = Null;
- /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (442) */
+ /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (443) */
export interface PalletTemplateTransactionPaymentChargeTransactionPayment extends Compact<u128> {}
- /** @name OpalRuntimeRuntime (443) */
+ /** @name OpalRuntimeRuntime (444) */
export type OpalRuntimeRuntime = Null;
- /** @name PalletEthereumFakeTransactionFinalizer (444) */
+ /** @name PalletEthereumFakeTransactionFinalizer (445) */
export type PalletEthereumFakeTransactionFinalizer = Null;
} // declare module
tests/src/limits.test.tsdiffbeforeafterboth--- a/tests/src/limits.test.ts
+++ b/tests/src/limits.test.ts
@@ -27,6 +27,8 @@
transferExpectSuccess,
getFreeBalance,
waitNewBlocks, burnItemExpectSuccess,
+ requirePallets,
+ Pallets,
} from './util/helpers';
import {expect} from 'chai';
@@ -67,7 +69,9 @@
describe('Number of tokens per address (ReFungible)', () => {
let alice: IKeyringPair;
- before(async () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async (api, privateKeyWrapper) => {
alice = privateKeyWrapper('//Alice');
});
@@ -367,7 +371,9 @@
let bob: IKeyringPair;
let charlie: IKeyringPair;
- before(async () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async (api, privateKeyWrapper) => {
alice = privateKeyWrapper('//Alice');
bob = privateKeyWrapper('//Bob');
tests/src/nesting/nest.test.tsdiffbeforeafterboth--- a/tests/src/nesting/nest.test.ts
+++ b/tests/src/nesting/nest.test.ts
@@ -17,6 +17,8 @@
transferExpectSuccess,
transferFromExpectSuccess,
setCollectionLimitsExpectSuccess,
+ requirePallets,
+ Pallets,
} from '../util/helpers';
import {IKeyringPair} from '@polkadot/types/types';
@@ -311,7 +313,9 @@
// ---------- Re-Fungible ----------
- it('ReFungible: allows an Owner to nest/unnest their token', async () => {
+ it('ReFungible: allows an Owner to nest/unnest their token', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async api => {
const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});
@@ -333,7 +337,9 @@
});
});
- it('ReFungible: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {
+ it('ReFungible: allows an Owner to nest/unnest their token (Restricted nesting)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async api => {
const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
const targetToken = await createItemExpectSuccess(alice, collectionNFT, 'NFT', {Substrate: alice.address});
@@ -715,7 +721,9 @@
// ---------- Re-Fungible ----------
- it('ReFungible: disallows to nest token if nesting is disabled', async () => {
+ it('ReFungible: disallows to nest token if nesting is disabled', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async api => {
const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {}});
@@ -745,7 +753,9 @@
});
});
- it('ReFungible: disallows a non-Owner to nest someone else\'s token', async () => {
+ it('ReFungible: disallows a non-Owner to nest someone else\'s token', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async api => {
const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true}});
@@ -773,7 +783,9 @@
});
});
- it('ReFungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {
+ it('ReFungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async api => {
const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await addToAllowListExpectSuccess(alice, collectionNFT, bob.address);
@@ -800,7 +812,9 @@
});
});
- it('ReFungible: disallows to nest token to an unlisted collection', async () => {
+ it('ReFungible: disallows to nest token to an unlisted collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async api => {
const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await setCollectionPermissionsExpectSuccess(alice, collectionNFT, {nesting: {tokenOwner: true, restricted:[]}});
tests/src/nesting/properties.test.tsdiffbeforeafterboth--- a/tests/src/nesting/properties.test.ts
+++ b/tests/src/nesting/properties.test.ts
@@ -8,6 +8,8 @@
createItemExpectSuccess,
getCreateCollectionResult,
transferExpectSuccess,
+ requirePallets,
+ Pallets,
} from '../util/helpers';
import {IKeyringPair} from '@polkadot/types/types';
import {tokenIdToAddress} from '../eth/util/helpers';
@@ -64,7 +66,9 @@
await testMakeSureSuppliesRequired({type: 'NFT'});
});
- it('Makes sure collectionById supplies required fields for ReFungible', async () => {
+ it('Makes sure collectionById supplies required fields for ReFungible', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testMakeSureSuppliesRequired({type: 'ReFungible'});
});
});
@@ -120,7 +124,9 @@
it('Sets properties for a NFT collection', async () => {
await testSetsPropertiesForCollection('NFT');
});
- it('Sets properties for a ReFungible collection', async () => {
+ it('Sets properties for a ReFungible collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testSetsPropertiesForCollection('ReFungible');
});
@@ -178,7 +184,9 @@
it('Check valid names for NFT collection properties keys', async () => {
await testCheckValidNames('NFT');
});
- it('Check valid names for ReFungible collection properties keys', async () => {
+ it('Check valid names for ReFungible collection properties keys', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testCheckValidNames('ReFungible');
});
@@ -209,7 +217,9 @@
it('Changes properties of a NFT collection', async () => {
await testChangesProperties({type: 'NFT'});
});
- it('Changes properties of a ReFungible collection', async () => {
+ it('Changes properties of a ReFungible collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testChangesProperties({type: 'ReFungible'});
});
@@ -238,7 +248,9 @@
it('Deletes properties of a NFT collection', async () => {
await testDeleteProperties({type: 'NFT'});
});
- it('Deletes properties of a ReFungible collection', async () => {
+ it('Deletes properties of a ReFungible collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testDeleteProperties({type: 'ReFungible'});
});
});
@@ -269,7 +281,9 @@
it('Fails to set properties in a NFT collection if not its onwer/administrator', async () => {
await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'NFT'});
});
- it('Fails to set properties in a ReFungible collection if not its onwer/administrator', async () => {
+ it('Fails to set properties in a ReFungible collection if not its onwer/administrator', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'ReFungible'});
});
@@ -307,7 +321,9 @@
it('Fails to set properties that exceed the limits (NFT)', async () => {
await testFailsSetPropertiesThatExeedLimits({type: 'NFT'});
});
- it('Fails to set properties that exceed the limits (ReFungible)', async () => {
+ it('Fails to set properties that exceed the limits (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testFailsSetPropertiesThatExeedLimits({type: 'ReFungible'});
});
@@ -337,7 +353,9 @@
it('Fails to set more properties than it is allowed (NFT)', async () => {
await testFailsSetMorePropertiesThanAllowed({type: 'NFT'});
});
- it('Fails to set more properties than it is allowed (ReFungible)', async () => {
+ it('Fails to set more properties than it is allowed (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testFailsSetMorePropertiesThanAllowed({type: 'ReFungible'});
});
@@ -392,7 +410,9 @@
it('Fails to set properties with invalid names (NFT)', async () => {
await testFailsSetPropertiesWithInvalidNames({type: 'NFT'});
});
- it('Fails to set properties with invalid names (ReFungible)', async () => {
+ it('Fails to set properties with invalid names (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testFailsSetPropertiesWithInvalidNames({type: 'ReFungible'});
});
});
@@ -443,7 +463,9 @@
it('Sets access rights to properties of a collection (NFT)', async () => {
await testSetsAccessRightsToProperties({type: 'NFT'});
});
- it('Sets access rights to properties of a collection (ReFungible)', async () => {
+ it('Sets access rights to properties of a collection (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testSetsAccessRightsToProperties({type: 'ReFungible'});
});
@@ -472,7 +494,9 @@
it('Changes access rights to properties of a NFT collection', async () => {
await testChangesAccessRightsToProperty({type: 'NFT'});
});
- it('Changes access rights to properties of a ReFungible collection', async () => {
+ it('Changes access rights to properties of a ReFungible collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testChangesAccessRightsToProperty({type: 'ReFungible'});
});
});
@@ -502,7 +526,9 @@
it('Prevents from setting access rights to properties of a NFT collection if not an onwer/admin', async () => {
await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'NFT'});
});
- it('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', async () => {
+ it('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'ReFungible'});
});
@@ -531,7 +557,9 @@
it('Prevents from adding too many possible properties (NFT)', async () => {
await testPreventFromAddingTooManyPossibleProperties({type: 'NFT'});
});
- it('Prevents from adding too many possible properties (ReFungible)', async () => {
+ it('Prevents from adding too many possible properties (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testPreventFromAddingTooManyPossibleProperties({type: 'ReFungible'});
});
@@ -560,7 +588,9 @@
it('Prevents access rights to be modified if constant (NFT)', async () => {
await testPreventAccessRightsModifiedIfConstant({type: 'NFT'});
});
- it('Prevents access rights to be modified if constant (ReFungible)', async () => {
+ it('Prevents access rights to be modified if constant (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testPreventAccessRightsModifiedIfConstant({type: 'ReFungible'});
});
@@ -608,7 +638,9 @@
it('Prevents adding properties with invalid names (NFT)', async () => {
await testPreventsAddingPropertiesWithInvalidNames({type: 'NFT'});
});
- it('Prevents adding properties with invalid names (ReFungible)', async () => {
+ it('Prevents adding properties with invalid names (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testPreventsAddingPropertiesWithInvalidNames({type: 'ReFungible'});
});
});
@@ -651,7 +683,9 @@
it('Reads yet empty properties of a token (NFT)', async () => {
await testReadsYetEmptyProperties({type: 'NFT'});
});
- it('Reads yet empty properties of a token (ReFungible)', async () => {
+ it('Reads yet empty properties of a token (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testReadsYetEmptyProperties({type: 'ReFungible'});
});
@@ -696,7 +730,9 @@
it('Assigns properties to a token according to permissions (NFT)', async () => {
await testAssignPropertiesAccordingToPermissions({type: 'NFT'}, 1);
});
- it('Assigns properties to a token according to permissions (ReFungible)', async () => {
+ it('Assigns properties to a token according to permissions (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testAssignPropertiesAccordingToPermissions({type: 'ReFungible'}, 100);
});
@@ -749,7 +785,9 @@
it('Changes properties of a token according to permissions (NFT)', async () => {
await testChangesPropertiesAccordingPermission({type: 'NFT'}, 1);
});
- it('Changes properties of a token according to permissions (ReFungible)', async () => {
+ it('Changes properties of a token according to permissions (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testChangesPropertiesAccordingPermission({type: 'ReFungible'}, 100);
});
@@ -802,7 +840,9 @@
it('Deletes properties of a token according to permissions (NFT)', async () => {
await testDeletePropertiesAccordingPermission({type: 'NFT'}, 1);
});
- it('Deletes properties of a token according to permissions (ReFungible)', async () => {
+ it('Deletes properties of a token according to permissions (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testDeletePropertiesAccordingPermission({type: 'ReFungible'}, 100);
});
@@ -1029,7 +1069,9 @@
it('Forbids changing/deleting properties of a token if the user is outside of permissions (NFT)', async () => {
await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'NFT'}, 1);
});
- it('Forbids changing/deleting properties of a token if the user is outside of permissions (ReFungible)', async () => {
+ it('Forbids changing/deleting properties of a token if the user is outside of permissions (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'ReFungible'}, 100);
});
@@ -1062,7 +1104,9 @@
it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (NFT)', async () => {
await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'NFT'}, 1);
});
- it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (ReFungible)', async () => {
+ it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'ReFungible'}, 100);
});
@@ -1096,7 +1140,9 @@
it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (NFT)', async () => {
await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'NFT'}, 1);
});
- it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (ReFungible)', async () => {
+ it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'ReFungible'}, 100);
});
@@ -1140,7 +1186,9 @@
it('Forbids adding too many properties to a token (NFT)', async () => {
await testForbidsAddingTooManyProperties({type: 'NFT'}, 1);
});
- it('Forbids adding too many properties to a token (ReFungible)', async () => {
+ it('Forbids adding too many properties to a token (ReFungible)', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await testForbidsAddingTooManyProperties({type: 'ReFungible'}, 100);
});
});
@@ -1149,7 +1197,9 @@
let collection: number;
let token: number;
- before(async () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async (api, privateKeyWrapper) => {
alice = privateKeyWrapper('//Alice');
bob = privateKeyWrapper('//Bob');
tests/src/nesting/rules-smoke.test.tsdiffbeforeafterboth--- a/tests/src/nesting/rules-smoke.test.ts
+++ b/tests/src/nesting/rules-smoke.test.ts
@@ -1,7 +1,7 @@
import {expect} from 'chai';
import {tokenIdToAddress} from '../eth/util/helpers';
import usingApi, {executeTransaction} from '../substrate/substrate-api';
-import {createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, CrossAccountId, getCreateCollectionResult} from '../util/helpers';
+import {createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, CrossAccountId, getCreateCollectionResult, requirePallets, Pallets} from '../util/helpers';
import {IKeyringPair} from '@polkadot/types/types';
describe('nesting check', () => {
@@ -47,7 +47,9 @@
});
});
- it('called for refungible', async () => {
+ it('called for refungible', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async api => {
const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await expect(executeTransaction(api, alice, api.tx.unique.createItem(collection, nestTarget, {ReFungible: {}})))
tests/src/nesting/unnest.test.tsdiffbeforeafterboth--- a/tests/src/nesting/unnest.test.ts
+++ b/tests/src/nesting/unnest.test.ts
@@ -10,6 +10,8 @@
setCollectionPermissionsExpectSuccess,
transferExpectSuccess,
transferFromExpectSuccess,
+ requirePallets,
+ Pallets,
} from '../util/helpers';
import {IKeyringPair} from '@polkadot/types/types';
@@ -80,7 +82,9 @@
});
});
- it('ReFungible: allows the owner to successfully unnest a token', async () => {
+ it('ReFungible: allows the owner to successfully unnest a token', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async api => {
const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
tests/src/nextSponsoring.test.tsdiffbeforeafterboth--- a/tests/src/nextSponsoring.test.ts
+++ b/tests/src/nextSponsoring.test.ts
@@ -27,6 +27,8 @@
transferExpectSuccess,
normalizeAccountId,
getNextSponsored,
+ requirePallets,
+ Pallets,
} from './util/helpers';
chai.use(chaiAsPromised);
@@ -89,7 +91,9 @@
});
});
- it('ReFungible', async () => {
+ it('ReFungible', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async (api: ApiPromise) => {
const createMode = 'ReFungible';
tests/src/pallet-presence.test.tsdiffbeforeafterboth--- a/tests/src/pallet-presence.test.ts
+++ b/tests/src/pallet-presence.test.ts
@@ -49,9 +49,8 @@
'inflation',
'unique',
'nonfungible',
- 'refungible',
- 'scheduler',
'charging',
+ 'configuration',
];
// Pallets that depend on consensus and governance configuration
@@ -66,8 +65,16 @@
await usingApi(async api => {
const chain = await api.rpc.system.chain();
- if (!chain.eq('UNIQUE')) {
- requiredPallets.push(...['rmrkcore', 'rmrkequip']);
+ const refungible = 'refungible';
+ const scheduler = 'scheduler';
+ const rmrkPallets = ['rmrkcore', 'rmrkequip'];
+
+ if (chain.eq('OPAL by UNIQUE')) {
+ requiredPallets.push(refungible, scheduler, ...rmrkPallets);
+ } else if (chain.eq('QUARTZ by UNIQUE')) {
+ // Insert Quartz additional pallets here
+ } else if (chain.eq('UNIQUE')) {
+ // Insert Unique additional pallets here
}
});
});
tests/src/refungible.test.tsdiffbeforeafterboth--- a/tests/src/refungible.test.ts
+++ b/tests/src/refungible.test.ts
@@ -14,28 +14,13 @@
// 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 {default as usingApi, submitTransactionAsync} from './substrate/substrate-api';
import {IKeyringPair} from '@polkadot/types/types';
+
+import {usingPlaygrounds} from './util/playgrounds';
import {
- createCollectionExpectSuccess,
- getBalance,
- createMultipleItemsExpectSuccess,
- isTokenExists,
- getLastTokenId,
- getAllowance,
- approve,
- transferFrom,
- createCollection,
- createRefungibleToken,
- transfer,
- burnItem,
- repartitionRFT,
- createCollectionWithPropsExpectSuccess,
- getDetailedCollectionInfo,
- normalizeAccountId,
- CrossAccountId,
- getCreateItemsResult,
- getDestroyItemsResult,
+ getModuleNames,
+ Pallets,
+ requirePallets,
} from './util/helpers';
import chai from 'chai';
@@ -45,250 +30,259 @@
let alice: IKeyringPair;
let bob: IKeyringPair;
+const MAX_REFUNGIBLE_PIECES = 1_000_000_000_000_000_000_000n;
+
+describe('integration test: Refungible functionality:', async () => {
+ before(async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
-describe('integration test: Refungible functionality:', () => {
- before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
+ 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 usingApi(async api => {
- const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});
- expect(createCollectionResult.success).to.be.true;
- const collectionId = createCollectionResult.collectionId;
-
- const itemCountBefore = await getLastTokenId(api, collectionId);
- const result = await createRefungibleToken(api, alice, collectionId, 100n);
+ await usingPlaygrounds(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 getLastTokenId(api, collectionId);
+ const itemCountAfter = await collection.getLastTokenId();
// What to expect
- // tslint:disable-next-line:no-unused-expression
- expect(result.success).to.be.true;
+ expect(token?.tokenId).to.be.gte(itemCountBefore);
expect(itemCountAfter).to.be.equal(itemCountBefore + 1);
- expect(collectionId).to.be.equal(result.collectionId);
- expect(itemCountAfter.toString()).to.be.equal(result.itemId.toString());
+ expect(itemCountAfter.toString()).to.be.equal(token?.tokenId.toString());
});
});
- it('RPC method tokenOnewrs for refungible 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())));
+ 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 createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});
- const collectionId = createCollectionResult.collectionId;
+ const token = await collection.mintToken(alice, {Substrate: alice.address}, MAX_REFUNGIBLE_PIECES);
- const result = await createRefungibleToken(api, alice, collectionId, 10_000n);
- const aliceTokenId = result.itemId;
+ 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 transfer(api, collectionId, aliceTokenId, alice, bob, 1000n);
- await transfer(api, collectionId, aliceTokenId, alice, ethAcc, 900n);
+ await expect(collection.mintToken(alice, {Substrate: alice.address}, MAX_REFUNGIBLE_PIECES + 1n)).to.eventually.be.rejected;
+ });
+ });
+
+ 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}));
+
+ const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+
+ const token = await collection.mintToken(alice, {Substrate: alice.address}, 10_000n);
+
+ await token.transfer(alice, {Substrate: bob.address}, 1000n);
+ await token.transfer(alice, ethAcc, 900n);
for (let i = 0; i < 7; i++) {
- await transfer(api, collectionId, aliceTokenId, alice, facelessCrowd[i], 50*(i+1));
+ await token.transfer(alice, facelessCrowd[i], 50n * BigInt(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);
-
+
+ const owners = await token.getTop10Owners();
+
// What to expect
- // tslint:disable-next-line:no-unused-expression
- expect(ids).to.deep.include.members([aliceID, ethAcc, bobId, ...facelessCrowd]);
+ expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]);
expect(owners.length).to.be.equal(10);
- 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);
+ 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 usingApi(async api => {
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;
+ 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 getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);
- expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;
-
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n);
- expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);
- await expect(transfer(api, collectionId, tokenId, alice, bob, 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.rejected;
});
});
it('Create multiple tokens', async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- const args = [
- {ReFungible: {pieces: 1}},
- {ReFungible: {pieces: 2}},
- {ReFungible: {pieces: 100}},
- ];
- await createMultipleItemsExpectSuccess(alice, collectionId, args);
-
- await usingApi(async api => {
- const tokenId = await getLastTokenId(api, collectionId);
- expect(tokenId).to.be.equal(3);
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);
+ 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);
});
});
it('Burn some pieces', async () => {
- await usingApi(async api => {
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;
- expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);
- expect(await burnItem(api, alice, collectionId, tokenId, 99n)).to.be.true;
- expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(1n);
+ 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);
});
});
it('Burn all pieces', async () => {
- await usingApi(async api => {
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;
- expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);
- expect(await burnItem(api, alice, collectionId, tokenId, 100n)).to.be.true;
- expect(await isTokenExists(api, collectionId, tokenId)).to.be.false;
+ 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, 100n)).success).to.be.true;
+ expect(await collection.isTokenExists(token.tokenId)).to.be.false;
});
});
it('Burn some pieces for multiple users', async () => {
- await usingApi(async api => {
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;
- expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;
+ 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.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.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 getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);
- expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;
+ expect((await token.burn(bob, 59n)).success).to.be.true;
-
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n);
- expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);
- expect(await burnItem(api, alice, collectionId, tokenId, 40n)).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 getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);
- expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;
- expect(await burnItem(api, bob, collectionId, tokenId, 59n)).to.be.true;
+ expect((await token.burn(bob, 1n)).success).to.be.true;
- expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(1n);
- expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;
- expect(await burnItem(api, bob, collectionId, tokenId, 1n)).to.be.true;
-
- expect(await isTokenExists(api, collectionId, tokenId)).to.be.false;
+ expect(await collection.isTokenExists(token.tokenId)).to.be.false;
});
});
it('Set allowance for token', async () => {
- await usingApi(async api => {
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;
-
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);
+ 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);
- expect(await approve(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;
- expect(await getAllowance(api, collectionId, alice, bob, tokenId)).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 transferFrom(api, collectionId, tokenId, bob, alice, bob, 20n)).to.be.true;
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(80n);
- expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(20n);
- expect(await getAllowance(api, collectionId, alice, bob, tokenId)).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 usingApi(async api => {
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;
-
- expect(await repartitionRFT(api, collectionId, alice, tokenId, 200n)).to.be.true;
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(200n);
-
- expect(await transfer(api, collectionId, tokenId, alice, bob, 110n)).to.be.true;
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(90n);
- expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(110n);
+ 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 expect(repartitionRFT(api, collectionId, alice, tokenId, 80n)).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.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 transfer(api, collectionId, tokenId, alice, bob, 90n)).to.be.true;
- expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);
- expect(await getBalance(api, collectionId, bob, tokenId)).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 repartitionRFT(api, collectionId, bob, tokenId, 150n)).to.be.true;
- await expect(transfer(api, collectionId, tokenId, bob, alice, 160n)).to.eventually.be.rejected;
});
});
it('Repartition with increased amount', async () => {
- await usingApi(async api => {
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;
-
- const tx = api.tx.unique.repartition(collectionId, tokenId, 200n);
- const events = await submitTransactionAsync(alice, tx);
- const substrateEvents = getCreateItemsResult(events);
- expect(substrateEvents).to.include.deep.members([
- {
- success: true,
- collectionId,
- itemId: tokenId,
- recipient: {Substrate: alice.address},
- amount: 100,
- },
- ]);
+ 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: [
+ collection.collectionId.toString(),
+ token.tokenId.toString(),
+ {Substrate: alice.address},
+ '100',
+ ],
+ }]);
});
});
it('Repartition with decreased amount', async () => {
- await usingApi(async api => {
- const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;
- const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;
-
- const tx = api.tx.unique.repartition(collectionId, tokenId, 50n);
- const events = await submitTransactionAsync(alice, tx);
- const substrateEvents = getDestroyItemsResult(events);
- expect(substrateEvents).to.include.deep.members([
- {
- success: true,
- collectionId,
- itemId: tokenId,
- owner: {Substrate: alice.address},
- amount: 50,
- },
- ]);
- });
- });
-});
-
-describe('Test Refungible properties:', () => {
- before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
+ 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: [
+ collection.collectionId.toString(),
+ token.tokenId.toString(),
+ {Substrate: alice.address},
+ '50',
+ ],
+ }]);
});
});
- it('Сreate new collection with properties', async () => {
- await usingApi(async api => {
+ it('Create new collection with properties', async () => {
+ await usingPlaygrounds(async helper => {
const properties = [{key: 'key1', value: 'val1'}];
- const propertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}];
- const collectionId = await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'ReFungible'},
- properties: properties,
- propPerm: propertyPermissions,
- });
- const collection = (await getDetailedCollectionInfo(api, collectionId))!;
- expect(collection.properties.toHuman()).to.be.deep.equal(properties);
- expect(collection.tokenPropertyPermissions.toHuman()).to.be.deep.equal(propertyPermissions);
+ 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
@@ -16,123 +16,112 @@
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
-import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';
-import {createCollectionExpectSuccess, destroyCollectionExpectSuccess, getAdminList, normalizeAccountId, queryCollectionExpectSuccess} from './util/helpers';
+import {usingPlaygrounds} from './util/playgrounds';
chai.use(chaiAsPromised);
const expect = chai.expect;
describe('Integration Test removeCollectionAdmin(collection_id, account_id):', () => {
it('Remove collection admin.', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- const collectionId = await createCollectionExpectSuccess();
- const alice = privateKeyWrapper('//Alice');
- const bob = privateKeyWrapper('//Bob');
- const collection = await queryCollectionExpectSuccess(api, collectionId);
- expect(collection.owner.toString()).to.be.deep.eq(alice.address);
+ 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
- const addAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
- await submitTransactionAsync(alice, addAdminTx);
+ await collection.addAdmin(alice, {Substrate: bob.address});
- const adminListAfterAddAdmin = await getAdminList(api, collectionId);
- expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+ const adminListAfterAddAdmin = await collection.getAdmins();
+ expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)});
// then remove bob from admins of collection
- const removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
- await submitTransactionAsync(alice, removeAdminTx);
+ await collection.removeAdmin(alice, {Substrate: bob.address});
- const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);
- expect(adminListAfterRemoveAdmin).not.to.be.deep.contains(normalizeAccountId(bob.address));
+ const adminListAfterRemoveAdmin = await collection.getAdmins();
+ expect(adminListAfterRemoveAdmin).not.to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)});
});
});
it('Remove admin from collection that has no admins', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- const alice = privateKeyWrapper('//Alice');
- const collectionId = await createCollectionExpectSuccess();
+ await usingPlaygrounds(async (helper, privateKey) => {
+ const alice = privateKey('//Alice');
+ const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
- const adminListBeforeAddAdmin = await getAdminList(api, collectionId);
+ const adminListBeforeAddAdmin = await collection.getAdmins();
expect(adminListBeforeAddAdmin).to.have.lengthOf(0);
- const tx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(alice.address));
- await submitTransactionAsync(alice, tx);
+ // await expect(collection.removeAdmin(alice, {Substrate: alice.address})).to.be.rejectedWith('Unable to remove collection admin');
+ 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 () => {
- await usingApi(async (api, privateKeyWrapper) => {
+ await usingPlaygrounds(async (helper, privateKey) => {
// tslint:disable-next-line: no-bitwise
const collectionId = (1 << 32) - 1;
- const alice = privateKeyWrapper('//Alice');
- const bob = privateKeyWrapper('//Bob');
+ const alice = privateKey('//Alice');
+ const bob = privateKey('//Bob');
- const changeOwnerTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
- await expect(submitTransactionExpectFailAsync(alice, changeOwnerTx)).to.be.rejected;
+ await expect(helper.collection.removeAdmin(alice, collectionId, {Substrate: bob.address})).to.be.rejected;
// Verifying that nothing bad happened (network is live, new collections can be created, etc.)
- await createCollectionExpectSuccess();
+ await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
});
});
it('Can\'t remove collection admin from deleted collection', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- // tslint:disable-next-line: no-bitwise
- const collectionId = await createCollectionExpectSuccess();
- const alice = privateKeyWrapper('//Alice');
- const bob = privateKeyWrapper('//Bob');
+ 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'});
- await destroyCollectionExpectSuccess(collectionId);
+ expect(await collection.burn(alice)).to.be.true;
- const changeOwnerTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
- await expect(submitTransactionExpectFailAsync(alice, changeOwnerTx)).to.be.rejected;
+ 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 createCollectionExpectSuccess();
+ await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
});
});
it('Regular user can\'t remove collection admin', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- const collectionId = await createCollectionExpectSuccess();
- const alice = privateKeyWrapper('//Alice');
- const bob = privateKeyWrapper('//Bob');
- const charlie = privateKeyWrapper('//Charlie');
+ 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'});
- const addAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
- await submitTransactionAsync(alice, addAdminTx);
+ await collection.addAdmin(alice, {Substrate: bob.address});
- const changeOwnerTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
- await expect(submitTransactionExpectFailAsync(charlie, changeOwnerTx)).to.be.rejected;
+ 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 createCollectionExpectSuccess();
+ await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
});
});
it('Admin can\'t remove collection admin.', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- const collectionId = await createCollectionExpectSuccess();
- const alice = privateKeyWrapper('//Alice');
- const bob = privateKeyWrapper('//Bob');
- const charlie = privateKeyWrapper('//Charlie');
-
- const addBobAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
- await submitTransactionAsync(alice, addBobAdminTx);
- const addCharlieAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
- await submitTransactionAsync(alice, addCharlieAdminTx);
+ 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});
- const adminListAfterAddAdmin = await getAdminList(api, collectionId);
- expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
- expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(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 removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
- await expect(submitTransactionExpectFailAsync(charlie, removeAdminTx)).to.be.rejected;
+ await expect(collection.removeAdmin(charlie, {Substrate: bob.address})).to.be.rejected;
- const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);
- expect(adminListAfterRemoveAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
- expect(adminListAfterRemoveAdmin).to.be.deep.contains(normalizeAccountId(charlie.address));
+ 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)});
});
});
});
tests/src/rmrk/acceptNft.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/acceptNft.test.ts
+++ b/tests/src/rmrk/acceptNft.test.ts
@@ -8,14 +8,19 @@
} from './util/tx';
import {NftIdTuple} from './util/fetch';
import {isNftChildOfAnother, expectTxFailure} from './util/helpers';
+import {requirePallets, Pallets} from '../util/helpers';
describe('integration test: accept NFT', () => {
let api: any;
- before(async () => { api = await getApiConnection(); });
-
+ before(async function() {
+ api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
+ });
+
+
const alice = '//Alice';
const bob = '//Bob';
-
+
const createTestCollection = async (issuerUri: string) => {
return await createCollection(
api,
tests/src/rmrk/addResource.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/addResource.test.ts
+++ b/tests/src/rmrk/addResource.test.ts
@@ -12,6 +12,7 @@
addNftComposableResource,
} from './util/tx';
import {RmrkTraitsResourceResourceInfo as ResourceInfo} from '@polkadot/types/lookup';
+import {requirePallets, Pallets} from '../util/helpers';
describe('integration test: add NFT resource', () => {
const Alice = '//Alice';
@@ -24,8 +25,9 @@
const nonexistentId = 99999;
let api: any;
- before(async () => {
+ before(async function() {
api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
});
it('add resource', async () => {
tests/src/rmrk/addTheme.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/addTheme.test.ts
+++ b/tests/src/rmrk/addTheme.test.ts
@@ -3,10 +3,14 @@
import {createBase, addTheme} from './util/tx';
import {expectTxFailure} from './util/helpers';
import {getThemeNames} from './util/fetch';
+import {requirePallets, Pallets} from '../util/helpers';
describe('integration test: add Theme to Base', () => {
let api: any;
- before(async () => { api = await getApiConnection(); });
+ before(async function() {
+ api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkEquip]);
+ });
const alice = '//Alice';
const bob = '//Bob';
tests/src/rmrk/burnNft.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/burnNft.test.ts
+++ b/tests/src/rmrk/burnNft.test.ts
@@ -5,6 +5,7 @@
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
+import {requirePallets, Pallets} from '../util/helpers';
chai.use(chaiAsPromised);
const expect = chai.expect;
@@ -14,10 +15,12 @@
const Bob = '//Bob';
let api: any;
- before(async () => {
+ before(async function() {
api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
});
+
it('burn nft', async () => {
await createCollection(
api,
tests/src/rmrk/changeCollectionIssuer.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/changeCollectionIssuer.test.ts
+++ b/tests/src/rmrk/changeCollectionIssuer.test.ts
@@ -1,4 +1,5 @@
import {getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {expectTxFailure} from './util/helpers';
import {
changeIssuer,
@@ -10,10 +11,13 @@
const Bob = '//Bob';
let api: any;
- before(async () => {
+ before(async function() {
api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
});
+
+
it('change collection issuer', async () => {
await createCollection(
api,
tests/src/rmrk/createBase.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/createBase.test.ts
+++ b/tests/src/rmrk/createBase.test.ts
@@ -1,9 +1,13 @@
import {getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {createCollection, createBase} from './util/tx';
describe('integration test: create new Base', () => {
let api: any;
- before(async () => { api = await getApiConnection(); });
+ before(async function() {
+ api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore, Pallets.RmrkEquip]);
+ });
const alice = '//Alice';
tests/src/rmrk/createCollection.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/createCollection.test.ts
+++ b/tests/src/rmrk/createCollection.test.ts
@@ -1,9 +1,15 @@
import {getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {createCollection} from './util/tx';
describe('Integration test: create new collection', () => {
let api: any;
- before(async () => { api = await getApiConnection(); });
+ before(async function () {
+ api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
+ });
+
+
const alice = '//Alice';
tests/src/rmrk/deleteCollection.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/deleteCollection.test.ts
+++ b/tests/src/rmrk/deleteCollection.test.ts
@@ -1,11 +1,13 @@
import {getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {expectTxFailure} from './util/helpers';
import {createCollection, deleteCollection} from './util/tx';
describe('integration test: delete collection', () => {
let api: any;
- before(async () => {
+ before(async function () {
api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
});
const Alice = '//Alice';
tests/src/rmrk/equipNft.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/equipNft.test.ts
+++ b/tests/src/rmrk/equipNft.test.ts
@@ -1,6 +1,7 @@
import {ApiPromise} from '@polkadot/api';
import {expect} from 'chai';
import {getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {getNft, getParts, NftIdTuple} from './util/fetch';
import {expectTxFailure} from './util/helpers';
import {
@@ -122,8 +123,10 @@
describe.skip('integration test: Equip NFT', () => {
let api: any;
- before(async () => {
+
+ before(async function () {
api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore, Pallets.RmrkEquip]);
});
it('equip nft', async () => {
tests/src/rmrk/getOwnedNfts.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/getOwnedNfts.test.ts
+++ b/tests/src/rmrk/getOwnedNfts.test.ts
@@ -1,11 +1,17 @@
import {expect} from 'chai';
import {getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {getOwnedNfts} from './util/fetch';
import {mintNft, createCollection} from './util/tx';
describe('integration test: get owned NFTs', () => {
let api: any;
- before(async () => { api = await getApiConnection(); });
+
+ before(async function () {
+ api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
+ });
+
const alice = '//Alice';
tests/src/rmrk/lockCollection.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/lockCollection.test.ts
+++ b/tests/src/rmrk/lockCollection.test.ts
@@ -1,4 +1,5 @@
import {getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {expectTxFailure} from './util/helpers';
import {createCollection, lockCollection, mintNft} from './util/tx';
@@ -8,8 +9,9 @@
const Max = 5;
let api: any;
- before(async () => {
+ before(async function () {
api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
});
it('lock collection', async () => {
tests/src/rmrk/mintNft.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/mintNft.test.ts
+++ b/tests/src/rmrk/mintNft.test.ts
@@ -1,12 +1,18 @@
import {expect} from 'chai';
import {getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {getNft} from './util/fetch';
import {expectTxFailure} from './util/helpers';
import {createCollection, mintNft} from './util/tx';
describe('integration test: mint new NFT', () => {
let api: any;
- before(async () => { api = await getApiConnection(); });
+
+ before(async function () {
+ api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
+ });
+
const alice = '//Alice';
const bob = '//Bob';
tests/src/rmrk/rejectNft.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/rejectNft.test.ts
+++ b/tests/src/rmrk/rejectNft.test.ts
@@ -8,10 +8,16 @@
} from './util/tx';
import {getChildren, NftIdTuple} from './util/fetch';
import {isNftChildOfAnother, expectTxFailure} from './util/helpers';
+import {requirePallets, Pallets} from '../util/helpers';
describe('integration test: reject NFT', () => {
let api: any;
- before(async () => { api = await getApiConnection(); });
+ before(async function () {
+ api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
+ });
+
+
const alice = '//Alice';
const bob = '//Bob';
tests/src/rmrk/removeResource.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/removeResource.test.ts
+++ b/tests/src/rmrk/removeResource.test.ts
@@ -1,6 +1,7 @@
import {expect} from 'chai';
import privateKey from '../substrate/privateKey';
import {executeTransaction, getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {getNft, NftIdTuple} from './util/fetch';
import {expectTxFailure} from './util/helpers';
import {
@@ -16,9 +17,10 @@
describe('Integration test: remove nft resource', () => {
let api: any;
let ss58Format: string;
- before(async () => {
+ before(async function() {
api = await getApiConnection();
ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
+ await requirePallets(this, [Pallets.RmrkCore]);
});
const Alice = '//Alice';
tests/src/rmrk/rmrkIsolation.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/rmrkIsolation.test.ts
+++ b/tests/src/rmrk/rmrkIsolation.test.ts
@@ -6,7 +6,9 @@
getCreateCollectionResult,
getDetailedCollectionInfo,
getGenericResult,
+ requirePallets,
normalizeAccountId,
+ Pallets,
} from '../util/helpers';
import {IKeyringPair} from '@polkadot/types/types';
import {ApiPromise} from '@polkadot/api';
@@ -59,11 +61,10 @@
describe('RMRK External Integration Test', async () => {
const it_rmrk = (await isUnique() ? it : it.skip);
- before(async () => {
+ before(async function() {
await usingApi(async (api, privateKeyWrapper) => {
alice = privateKeyWrapper('//Alice');
-
-
+ await requirePallets(this, [Pallets.RmrkCore]);
});
});
tests/src/rmrk/sendNft.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/sendNft.test.ts
+++ b/tests/src/rmrk/sendNft.test.ts
@@ -3,10 +3,14 @@
import {createCollection, mintNft, sendNft} from './util/tx';
import {NftIdTuple} from './util/fetch';
import {isNftChildOfAnother, expectTxFailure} from './util/helpers';
+import {requirePallets, Pallets} from '../util/helpers';
describe('integration test: send NFT', () => {
let api: any;
- before(async () => { api = await getApiConnection(); });
+ before(async function () {
+ api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
+ });
const maxNftId = 0xFFFFFFFF;
tests/src/rmrk/setCollectionProperty.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/setCollectionProperty.test.ts
+++ b/tests/src/rmrk/setCollectionProperty.test.ts
@@ -1,4 +1,5 @@
import {getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {expectTxFailure} from './util/helpers';
import {createCollection, setPropertyCollection} from './util/tx';
@@ -7,8 +8,9 @@
const Bob = '//Bob';
let api: any;
- before(async () => {
+ before(async function () {
api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
});
it('set collection property', async () => {
tests/src/rmrk/setEquippableList.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/setEquippableList.test.ts
+++ b/tests/src/rmrk/setEquippableList.test.ts
@@ -1,10 +1,14 @@
import {getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {expectTxFailure} from './util/helpers';
import {createCollection, createBase, setEquippableList} from './util/tx';
describe("integration test: set slot's Equippable List", () => {
let api: any;
- before(async () => { api = await getApiConnection(); });
+ before(async function () {
+ api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
+ });
const alice = '//Alice';
const bob = '//Bob';
tests/src/rmrk/setNftProperty.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/setNftProperty.test.ts
+++ b/tests/src/rmrk/setNftProperty.test.ts
@@ -1,11 +1,15 @@
import {getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {NftIdTuple} from './util/fetch';
import {expectTxFailure} from './util/helpers';
import {createCollection, mintNft, sendNft, setNftProperty} from './util/tx';
describe('integration test: set NFT property', () => {
let api: any;
- before(async () => { api = await getApiConnection(); });
+ before(async function () {
+ api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
+ });
const alice = '//Alice';
const bob = '//Bob';
tests/src/rmrk/setResourcePriorities.test.tsdiffbeforeafterboth--- a/tests/src/rmrk/setResourcePriorities.test.ts
+++ b/tests/src/rmrk/setResourcePriorities.test.ts
@@ -1,10 +1,14 @@
import {getApiConnection} from '../substrate/substrate-api';
+import {requirePallets, Pallets} from '../util/helpers';
import {expectTxFailure} from './util/helpers';
import {mintNft, createCollection, setResourcePriorities} from './util/tx';
describe('integration test: set NFT resource priorities', () => {
let api: any;
- before(async () => { api = await getApiConnection(); });
+ before(async function () {
+ api = await getApiConnection();
+ await requirePallets(this, [Pallets.RmrkCore]);
+ });
const alice = '//Alice';
const bob = '//Bob';
tests/src/setCollectionSponsor.test.tsdiffbeforeafterboth--- a/tests/src/setCollectionSponsor.test.ts
+++ b/tests/src/setCollectionSponsor.test.ts
@@ -23,6 +23,8 @@
setCollectionSponsorExpectFailure,
addCollectionAdminExpectSuccess,
getCreatedCollectionCount,
+ requirePallets,
+ Pallets,
} from './util/helpers';
import {IKeyringPair} from '@polkadot/types/types';
@@ -50,7 +52,9 @@
const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
});
- it('Set ReFungible collection sponsor', async () => {
+ it('Set ReFungible collection sponsor', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
});
tests/src/transfer.test.tsdiffbeforeafterboth--- a/tests/src/transfer.test.ts
+++ b/tests/src/transfer.test.ts
@@ -35,11 +35,14 @@
getBalance as getTokenBalance,
transferFromExpectSuccess,
transferFromExpectFail,
+ requirePallets,
+ Pallets,
} from './util/helpers';
import {
subToEth,
itWeb3,
} from './eth/util/helpers';
+import {request} from 'https';
let alice: IKeyringPair;
let bob: IKeyringPair;
@@ -89,56 +92,61 @@
});
});
- it('User can transfer owned token', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- // nft
- const nftCollectionId = await createCollectionExpectSuccess();
- const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
- await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 'NFT');
- // fungible
- const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
- await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob, 1, 'Fungible');
- // reFungible
- const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
- await transferExpectSuccess(
- reFungibleCollectionId,
- newReFungibleTokenId,
- alice,
- bob,
- 100,
- 'ReFungible',
- );
- });
+ it('[nft] User can transfer owned token', async () => {
+ const nftCollectionId = await createCollectionExpectSuccess();
+ const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
+ await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 'NFT');
+ });
+
+ it('[fungible] User can transfer owned token', async () => {
+ const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+ const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
+ await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob, 1, 'Fungible');
+ });
+
+ it('[refungible] User can transfer owned token', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
+ const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+ const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
+ await transferExpectSuccess(
+ reFungibleCollectionId,
+ newReFungibleTokenId,
+ alice,
+ bob,
+ 100,
+ 'ReFungible',
+ );
+ });
+
+ it('[nft] Collection admin can transfer owned token', async () => {
+ const nftCollectionId = await createCollectionExpectSuccess();
+ await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);
+ const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT', bob.address);
+ await transferExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, 1, 'NFT');
+ });
+
+ it('[fungible] Collection admin can transfer owned token', async () => {
+ const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+ await addCollectionAdminExpectSuccess(alice, fungibleCollectionId, bob.address);
+ const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible', bob.address);
+ await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, 1, 'Fungible');
});
- it('Collection admin can transfer owned token', async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- // nft
- const nftCollectionId = await createCollectionExpectSuccess();
- await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);
- const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT', bob.address);
- await transferExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, 1, 'NFT');
- // fungible
- const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- await addCollectionAdminExpectSuccess(alice, fungibleCollectionId, bob.address);
- const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible', bob.address);
- await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, 1, 'Fungible');
- // reFungible
- const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- await addCollectionAdminExpectSuccess(alice, reFungibleCollectionId, bob.address);
- const newReFungibleTokenId = await createItemExpectSuccess(bob, reFungibleCollectionId, 'ReFungible', bob.address);
- await transferExpectSuccess(
- reFungibleCollectionId,
- newReFungibleTokenId,
- bob,
- alice,
- 100,
- 'ReFungible',
- );
- });
+ it('[refungible] Collection admin can transfer owned token', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
+ const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+ await addCollectionAdminExpectSuccess(alice, reFungibleCollectionId, bob.address);
+ const newReFungibleTokenId = await createItemExpectSuccess(bob, reFungibleCollectionId, 'ReFungible', bob.address);
+ await transferExpectSuccess(
+ reFungibleCollectionId,
+ newReFungibleTokenId,
+ bob,
+ alice,
+ 100,
+ 'ReFungible',
+ );
});
});
@@ -150,33 +158,49 @@
charlie = privateKeyWrapper('//Charlie');
});
});
- it('Transfer with not existed collection_id', async () => {
+
+ it('[nft] Transfer with not existed collection_id', async () => {
await usingApi(async (api) => {
- // nft
const nftCollectionCount = await getCreatedCollectionCount(api);
await transferExpectFailure(nftCollectionCount + 1, 1, alice, bob, 1);
- // fungible
+ });
+ });
+
+ it('[fungible] Transfer with not existed collection_id', async () => {
+ await usingApi(async (api) => {
const fungibleCollectionCount = await getCreatedCollectionCount(api);
await transferExpectFailure(fungibleCollectionCount + 1, 0, alice, bob, 1);
- // reFungible
+ });
+ });
+
+ it('[refungible] Transfer with not existed collection_id', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
+ await usingApi(async (api) => {
const reFungibleCollectionCount = await getCreatedCollectionCount(api);
await transferExpectFailure(reFungibleCollectionCount + 1, 1, alice, bob, 1);
});
});
- it('Transfer with deleted collection_id', async () => {
- // nft
+
+ it('[nft] Transfer with deleted collection_id', async () => {
const nftCollectionId = await createCollectionExpectSuccess();
const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId);
await destroyCollectionExpectSuccess(nftCollectionId);
await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);
- // fungible
+ });
+
+ it('[fungible] Transfer with deleted collection_id', async () => {
const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);
await destroyCollectionExpectSuccess(fungibleCollectionId);
await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);
- // reFungible
+ });
+
+ it('[refungible] Transfer with deleted collection_id', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const reFungibleCollectionId = await
createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
@@ -190,16 +214,21 @@
1,
);
});
- it('Transfer with not existed item_id', async () => {
- // nft
+
+ it('[nft] Transfer with not existed item_id', async () => {
const nftCollectionId = await createCollectionExpectSuccess();
await transferExpectFailure(nftCollectionId, 2, alice, bob, 1);
- // fungible
+ });
+
+ it('[fungible] Transfer with not existed item_id', async () => {
const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
await transferExpectFailure(fungibleCollectionId, 2, alice, bob, 1);
- // reFungible
- const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+ });
+
+ it('[refungible] Transfer with not existed item_id', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
+ const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await transferExpectFailure(
reFungibleCollectionId,
2,
@@ -208,18 +237,24 @@
1,
);
});
- it('Transfer with deleted item_id', async () => {
- // nft
+
+ it('[nft] Transfer with deleted item_id', async () => {
const nftCollectionId = await createCollectionExpectSuccess();
const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);
await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);
- // fungible
+ });
+
+ it('[fungible] Transfer with deleted item_id', async () => {
const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);
await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);
- // reFungible
+ });
+
+ it('[refungible] Transfer with deleted item_id', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
const reFungibleCollectionId = await
createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
@@ -232,18 +267,23 @@
1,
);
});
- it('Transfer with recipient that is not owner', async () => {
- // nft
+
+ it('[nft] Transfer with recipient that is not owner', async () => {
const nftCollectionId = await createCollectionExpectSuccess();
const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
await transferExpectFailure(nftCollectionId, newNftTokenId, charlie, bob, 1);
- // fungible
+ });
+
+ it('[fungible] Transfer with recipient that is not owner', async () => {
const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, charlie, bob, 1);
- // reFungible
- const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+ });
+
+ it('[refungible] Transfer with recipient that is not owner', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
+ const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
await transferExpectFailure(
reFungibleCollectionId,
@@ -276,7 +316,9 @@
});
});
- it('RFT', async () => {
+ it('RFT', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async (api: ApiPromise) => {
const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
tests/src/transferFrom.test.tsdiffbeforeafterboth--- a/tests/src/transferFrom.test.ts
+++ b/tests/src/transferFrom.test.ts
@@ -31,6 +31,8 @@
burnItemExpectSuccess,
setCollectionLimitsExpectSuccess,
getCreatedCollectionCount,
+ requirePallets,
+ Pallets,
} from './util/helpers';
chai.use(chaiAsPromised);
@@ -49,36 +51,36 @@
});
});
- it('Execute the extrinsic and check nftItemList - owner of token', async () => {
- await usingApi(async () => {
- // nft
- const nftCollectionId = await createCollectionExpectSuccess();
- const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
- await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
+ 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);
- await transferFromExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, charlie, 1, 'NFT');
+ await transferFromExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, charlie, 1, 'NFT');
+ });
- // fungible
- 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');
+ 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');
+ });
- // 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',
- );
- });
+ 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',
+ );
});
it('Should reduce allowance if value is big', async () => {
@@ -119,20 +121,28 @@
});
});
- it('transferFrom for a collection that does not exist', async () => {
+ it('[nft] transferFrom for a collection that does not exist', async () => {
await usingApi(async (api: ApiPromise) => {
- // nft
const nftCollectionCount = await getCreatedCollectionCount(api);
await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);
await transferFromExpectFail(nftCollectionCount + 1, 1, bob, alice, charlie, 1);
+ });
+ });
- // fungible
+ 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);
await transferFromExpectFail(fungibleCollectionCount + 1, 0, bob, alice, charlie, 1);
- // reFungible
+ });
+ });
+
+ it('[refungible] transferFrom for a collection that does not exist', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
+ await usingApi(async (api: ApiPromise) => {
const reFungibleCollectionCount = await getCreatedCollectionCount(api);
await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);
@@ -158,67 +168,70 @@
});
}); */
- it('transferFrom for not approved address', async () => {
- await usingApi(async () => {
- // nft
- const nftCollectionId = await createCollectionExpectSuccess();
- const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
+ it('[nft] transferFrom for not approved address', async () => {
+ const nftCollectionId = await createCollectionExpectSuccess();
+ const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
- await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1);
+ await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1);
+ });
- // fungible
- const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
- const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
- await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1);
- // reFungible
- const reFungibleCollectionId = await
- createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
- const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
- await transferFromExpectFail(
- reFungibleCollectionId,
- newReFungibleTokenId,
- bob,
- alice,
- charlie,
- 1,
- );
- });
+ 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);
+ });
+
+ it('[refungible] transferFrom for not approved address', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
+ const reFungibleCollectionId = await
+ createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+ const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
+ await transferFromExpectFail(
+ reFungibleCollectionId,
+ newReFungibleTokenId,
+ bob,
+ alice,
+ charlie,
+ 1,
+ );
+ });
+
+ 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);
+
+ await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 2);
});
- it('transferFrom incorrect token count', async () => {
- await usingApi(async () => {
- // nft
- const nftCollectionId = await createCollectionExpectSuccess();
- const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
- await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
+ 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 transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 2);
+ it('[refungible] transferFrom incorrect token count', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
- // fungible
- 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);
- // reFungible
- 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,
- bob,
- alice,
- charlie,
- 2,
- );
- });
+ 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,
+ bob,
+ alice,
+ charlie,
+ 2,
+ );
});
- it('execute transferFrom from account that is not owner of collection', async () => {
+ it('[nft] execute transferFrom from account that is not owner of collection', async () => {
await usingApi(async (api, privateKeyWrapper) => {
const dave = privateKeyWrapper('//Dave');
- // nft
const nftCollectionId = await createCollectionExpectSuccess();
const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
try {
@@ -230,8 +243,13 @@
}
// await transferFromExpectFail(nftCollectionId, newNftTokenId, Dave, Alice, Charlie, 1);
+ });
+ });
- // fungible
+ it('[fungible] execute transferFrom from account that is not owner of collection', async () => {
+ await usingApi(async (api, privateKeyWrapper) => {
+ const dave = privateKeyWrapper('//Dave');
+
const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
try {
@@ -241,7 +259,14 @@
// tslint:disable-next-line:no-unused-expression
expect(e).to.be.exist;
}
- // reFungible
+ });
+ });
+
+ it('[refungible] execute transferFrom from account that is not owner of collection', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
+ await usingApi(async (api, privateKeyWrapper) => {
+ const dave = privateKeyWrapper('//Dave');
const reFungibleCollectionId = await
createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
@@ -276,7 +301,9 @@
});
});
- it('transferFrom burnt token before approve ReFungible', async () => {
+ it('transferFrom burnt token before approve ReFungible', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async () => {
const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
await setCollectionLimitsExpectSuccess(alice, reFungibleCollectionId, {ownerCanTransfer: true});
@@ -308,7 +335,9 @@
});
});
- it('transferFrom burnt token after approve ReFungible', async () => {
+ it('transferFrom burnt token after approve ReFungible', async function() {
+ await requirePallets(this, [Pallets.ReFungible]);
+
await usingApi(async () => {
const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
tests/src/util/helpers.tsdiffbeforeafterboth--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -28,6 +28,7 @@
import {hexToStr, strToUTF16, utf16ToStr} from './util';
import {UpDataStructsRpcCollection, UpDataStructsCreateItemData, UpDataStructsProperty} from '@polkadot/types/lookup';
import {UpDataStructsTokenChild} from '../interfaces';
+import {Context} from 'mocha';
chai.use(chaiAsPromised);
const expect = chai.expect;
@@ -38,6 +39,66 @@
Ethereum: string,
};
+
+export enum Pallets {
+ Inflation = 'inflation',
+ RmrkCore = 'rmrkcore',
+ RmrkEquip = 'rmrkequip',
+ ReFungible = 'refungible',
+ Fungible = 'fungible',
+ NFT = 'nonfungible',
+ Scheduler = 'scheduler',
+}
+
+export async function isUnique(): Promise<boolean> {
+ return usingApi(async api => {
+ const chain = await api.rpc.system.chain();
+
+ return chain.eq('UNIQUE');
+ });
+}
+
+export async function isQuartz(): Promise<boolean> {
+ return usingApi(async api => {
+ const chain = await api.rpc.system.chain();
+
+ return chain.eq('QUARTZ');
+ });
+}
+
+let modulesNames: any;
+export function getModuleNames(api: ApiPromise): string[] {
+ if (typeof modulesNames === 'undefined')
+ modulesNames = api.runtimeMetadata.asLatest.pallets.map(m => m.name.toString().toLowerCase());
+ return modulesNames;
+}
+
+export async function missingRequiredPallets(requiredPallets: string[]): Promise<string[]> {
+ return await usingApi(async api => {
+ const pallets = getModuleNames(api);
+
+ return requiredPallets.filter(p => !pallets.includes(p));
+ });
+}
+
+export async function checkPalletsPresence(requiredPallets: string[]): Promise<boolean> {
+ return (await missingRequiredPallets(requiredPallets)).length == 0;
+}
+
+export async function requirePallets(mocha: Context, requiredPallets: string[]) {
+ const missingPallets = await missingRequiredPallets(requiredPallets);
+
+ if (missingPallets.length > 0) {
+ const skippingTestMsg = `\tSkipping test "${mocha.test?.title}".`;
+ const missingPalletsMsg = `\tThe following pallets are missing:\n\t- ${missingPallets.join('\n\t- ')}`;
+ const skipMsg = `${skippingTestMsg}\n${missingPalletsMsg}`;
+
+ console.error('\x1b[38:5:208m%s\x1b[0m', skipMsg);
+
+ mocha.skip();
+ }
+}
+
export function normalizeAccountId(input: string | AccountId | CrossAccountId | IKeyringPair): CrossAccountId {
if (typeof input === 'string') {
if (input.length >= 47) {
tests/src/util/playgrounds/index.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/util/playgrounds/index.ts
@@ -0,0 +1,93 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+import {IKeyringPair} from '@polkadot/types/types';
+import {UniqueHelper} from './unique';
+import config from '../../config';
+import '../../interfaces/augment-api-events';
+import * as defs from '../../interfaces/definitions';
+import {ApiPromise, WsProvider} from '@polkadot/api';
+
+
+class SilentLogger {
+ log(msg: any, level: any): void {}
+ level = {
+ ERROR: 'ERROR' as const,
+ WARNING: 'WARNING' as const,
+ INFO: 'INFO' as const,
+ };
+}
+
+
+class DevUniqueHelper extends UniqueHelper {
+ async connect(wsEndpoint: string, listeners?: any): Promise<void> {
+ const wsProvider = new WsProvider(wsEndpoint);
+ this.api = new ApiPromise({
+ provider: wsProvider,
+ signedExtensions: {
+ ContractHelpers: {
+ extrinsic: {},
+ payload: {},
+ },
+ FakeTransactionFinalizer: {
+ extrinsic: {},
+ payload: {},
+ },
+ },
+ rpc: {
+ unique: defs.unique.rpc,
+ rmrk: defs.rmrk.rpc,
+ eth: {
+ feeHistory: {
+ description: 'Dummy',
+ params: [],
+ type: 'u8',
+ },
+ maxPriorityFeePerGas: {
+ description: 'Dummy',
+ params: [],
+ type: 'u8',
+ },
+ },
+ },
+ });
+ await this.api.isReadyOrError;
+ this.network = await UniqueHelper.detectNetwork(this.api);
+ }
+}
+
+export const usingPlaygrounds = async (code: (helper: UniqueHelper, privateKey: (seed: string) => IKeyringPair) => Promise<void>) => {
+ // TODO: Remove, this is temporary: Filter unneeded API output
+ // (Jaco promised it will be removed in the next version)
+ const consoleErr = console.error;
+ const consoleLog = console.log;
+ const consoleWarn = console.warn;
+
+ const outFn = (printer: any) => (...args: any[]) => {
+ for (const arg of args) {
+ if (typeof arg !== 'string')
+ continue;
+ if (arg.includes('1000:: Normal connection closure' || arg === 'Normal connection closure'))
+ return;
+ }
+ printer(...args);
+ };
+
+ console.error = outFn(consoleErr.bind(console));
+ console.log = outFn(consoleLog.bind(console));
+ console.warn = outFn(consoleWarn.bind(console));
+ const helper = new DevUniqueHelper(new SilentLogger());
+
+ try {
+ await helper.connect(config.substrateUrl);
+ const ss58Format = helper.chain.getChainProperties().ss58Format;
+ const privateKey = (seed: string) => helper.util.fromSeed(seed, ss58Format);
+ await code(helper, privateKey);
+ }
+ finally {
+ await helper.disconnect();
+ console.error = consoleErr;
+ console.log = consoleLog;
+ console.warn = consoleWarn;
+ }
+};
\ No newline at end of file
tests/src/util/playgrounds/unique.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/util/playgrounds/unique.ts
@@ -0,0 +1,2490 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+/* eslint-disable @typescript-eslint/no-var-requires */
+/* eslint-disable function-call-argument-newline */
+/* eslint-disable no-prototype-builtins */
+
+import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';
+import {ApiInterfaceEvents} from '@polkadot/api/types';
+import {IKeyringPair} from '@polkadot/types/types';
+import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';
+
+
+const crossAccountIdFromLower = (lowerAddress: ICrossAccountIdLower): ICrossAccountId => {
+ const address = {} as ICrossAccountId;
+ if(lowerAddress.substrate) address.Substrate = lowerAddress.substrate;
+ if(lowerAddress.ethereum) address.Ethereum = lowerAddress.ethereum;
+ return address;
+};
+
+
+const nesting = {
+ toChecksumAddress(address: string): string {
+ if (typeof address === 'undefined') return '';
+
+ if(!/^(0x)?[0-9a-f]{40}$/i.test(address)) throw new Error(`Given address "${address}" is not a valid Ethereum address.`);
+
+ address = address.toLowerCase().replace(/^0x/i,'');
+ const addressHash = keccakAsHex(address).replace(/^0x/i,'');
+ const checksumAddress = ['0x'];
+
+ for (let i = 0; i < address.length; i++) {
+ // If ith character is 8 to f then make it uppercase
+ if (parseInt(addressHash[i], 16) > 7) {
+ checksumAddress.push(address[i].toUpperCase());
+ } else {
+ checksumAddress.push(address[i]);
+ }
+ }
+ return checksumAddress.join('');
+ },
+ tokenIdToAddress(collectionId: number, tokenId: number) {
+ return this.toChecksumAddress(`0xf8238ccfff8ed887463fd5e0${collectionId.toString(16).padStart(8, '0')}${tokenId.toString(16).padStart(8, '0')}`);
+ },
+};
+
+
+interface IChainEvent {
+ data: any;
+ method: string;
+ section: string;
+}
+
+interface ITransactionResult {
+ status: 'Fail' | 'Success';
+ result: {
+ events: {
+ event: IChainEvent
+ }[];
+ },
+ moduleError?: string;
+}
+
+interface ILogger {
+ log: (msg: any, level?: string) => void;
+ level: {
+ ERROR: 'ERROR';
+ WARNING: 'WARNING';
+ INFO: 'INFO';
+ [key: string]: string;
+ }
+}
+
+interface IUniqueHelperLog {
+ executedAt: number;
+ executionTime: number;
+ type: 'extrinsic' | 'rpc';
+ status: 'Fail' | 'Success';
+ call: string;
+ params: any[];
+ moduleError?: string;
+ events?: any;
+}
+
+interface IApiListeners {
+ connected?: (...args: any[]) => any;
+ disconnected?: (...args: any[]) => any;
+ error?: (...args: any[]) => any;
+ ready?: (...args: any[]) => any;
+ decorated?: (...args: any[]) => any;
+}
+
+interface ICrossAccountId {
+ Substrate?: TSubstrateAccount;
+ Ethereum?: TEthereumAccount;
+}
+
+interface ICrossAccountIdLower {
+ substrate?: TSubstrateAccount;
+ ethereum?: TEthereumAccount;
+}
+
+interface ICollectionLimits {
+ accountTokenOwnershipLimit?: number | null;
+ sponsoredDataSize?: number | null;
+ sponsoredDataRateLimit?: {blocks: number} | {sponsoringDisabled: null} | null;
+ tokenLimit?: number | null;
+ sponsorTransferTimeout?: number | null;
+ sponsorApproveTimeout?: number | null;
+ ownerCanTransfer?: boolean | null;
+ ownerCanDestroy?: boolean | null;
+ transfersEnabled?: boolean | null;
+}
+
+interface INestingPermissions {
+ tokenOwner?: boolean;
+ collectionAdmin?: boolean;
+ restricted?: number[] | null;
+}
+
+interface ICollectionPermissions {
+ access?: 'Normal' | 'AllowList';
+ mintMode?: boolean;
+ nesting?: INestingPermissions;
+}
+
+interface IProperty {
+ key: string;
+ value: string;
+}
+
+interface ITokenPropertyPermission {
+ key: string;
+ permission: {
+ mutable: boolean;
+ tokenOwner: boolean;
+ collectionAdmin: boolean;
+ }
+}
+
+interface IToken {
+ collectionId: number;
+ tokenId: number;
+}
+
+interface ICollectionCreationOptions {
+ name: string | number[];
+ description: string | number[];
+ tokenPrefix: string | number[];
+ mode?: {
+ nft?: null;
+ refungible?: null;
+ fungible?: number;
+ }
+ permissions?: ICollectionPermissions;
+ properties?: IProperty[];
+ tokenPropertyPermissions?: ITokenPropertyPermission[];
+ limits?: ICollectionLimits;
+ pendingSponsor?: TSubstrateAccount;
+}
+
+interface IChainProperties {
+ ss58Format: number;
+ tokenDecimals: number[];
+ tokenSymbol: string[]
+}
+
+type TSubstrateAccount = string;
+type TEthereumAccount = string;
+type TApiAllowedListeners = 'connected' | 'disconnected' | 'error' | 'ready' | 'decorated';
+type TUniqueNetworks = 'opal' | 'quartz' | 'unique';
+type TSigner = IKeyringPair; // | 'string'
+
+class UniqueUtil {
+ static transactionStatus = {
+ NOT_READY: 'NotReady',
+ FAIL: 'Fail',
+ SUCCESS: 'Success',
+ };
+
+ static chainLogType = {
+ EXTRINSIC: 'extrinsic',
+ RPC: 'rpc',
+ };
+
+ static getNestingTokenAddress(collectionId: number, tokenId: number) {
+ return nesting.tokenIdToAddress(collectionId, tokenId);
+ }
+
+ static getDefaultLogger(): ILogger {
+ return {
+ log(msg: any, level = 'INFO') {
+ console[level.toLocaleLowerCase() === 'error' ? 'error' : 'log'](...(Array.isArray(msg) ? msg : [msg]));
+ },
+ level: {
+ ERROR: 'ERROR',
+ WARNING: 'WARNING',
+ INFO: 'INFO',
+ },
+ };
+ }
+
+ static vec2str(arr: string[] | number[]) {
+ return arr.map(x => String.fromCharCode(parseInt(x.toString()))).join('');
+ }
+
+ static str2vec(string: string) {
+ if (typeof string !== 'string') return string;
+ return Array.from(string).map(x => x.charCodeAt(0));
+ }
+
+ static fromSeed(seed: string, ss58Format = 42) {
+ const keyring = new Keyring({type: 'sr25519', ss58Format});
+ return keyring.addFromUri(seed);
+ }
+
+ static normalizeSubstrateAddress(address: string, ss58Format = 42) {
+ return encodeAddress(decodeAddress(address), ss58Format);
+ }
+
+ static extractCollectionIdFromCreationResult(creationResult: ITransactionResult, label = 'new collection') {
+ if (creationResult.status !== this.transactionStatus.SUCCESS) {
+ throw Error(`Unable to create collection for ${label}`);
+ }
+
+ let collectionId = null;
+ creationResult.result.events.forEach(({event: {data, method, section}}) => {
+ if ((section === 'common') && (method === 'CollectionCreated')) {
+ collectionId = parseInt(data[0].toString(), 10);
+ }
+ });
+
+ if (collectionId === null) {
+ throw Error(`No CollectionCreated event for ${label}`);
+ }
+
+ return collectionId;
+ }
+
+ static extractTokensFromCreationResult(creationResult: ITransactionResult, label = 'new tokens') {
+ if (creationResult.status !== this.transactionStatus.SUCCESS) {
+ throw Error(`Unable to create tokens for ${label}`);
+ }
+ let success = false;
+ const tokens = [] as any;
+ creationResult.result.events.forEach(({event: {data, method, section}}) => {
+ if (method === 'ExtrinsicSuccess') {
+ success = true;
+ } else if ((section === 'common') && (method === 'ItemCreated')) {
+ tokens.push({
+ collectionId: parseInt(data[0].toString(), 10),
+ tokenId: parseInt(data[1].toString(), 10),
+ owner: data[2].toJSON(),
+ });
+ }
+ });
+ return {success, tokens};
+ }
+
+ static extractTokensFromBurnResult(burnResult: ITransactionResult, label = 'burned tokens') {
+ if (burnResult.status !== this.transactionStatus.SUCCESS) {
+ throw Error(`Unable to burn tokens for ${label}`);
+ }
+ let success = false;
+ const tokens = [] as any;
+ burnResult.result.events.forEach(({event: {data, method, section}}) => {
+ if (method === 'ExtrinsicSuccess') {
+ success = true;
+ } else if ((section === 'common') && (method === 'ItemDestroyed')) {
+ tokens.push({
+ collectionId: parseInt(data[0].toString(), 10),
+ tokenId: parseInt(data[1].toString(), 10),
+ owner: data[2].toJSON(),
+ });
+ }
+ });
+ return {success, tokens};
+ }
+
+ static findCollectionInEvents(events: {event: IChainEvent}[], collectionId: number, expectedSection: string, expectedMethod: string, label?: string) {
+ let eventId = null;
+ events.forEach(({event: {data, method, section}}) => {
+ if ((section === expectedSection) && (method === expectedMethod)) {
+ eventId = parseInt(data[0].toString(), 10);
+ }
+ });
+
+ if (eventId === null) {
+ throw Error(`No ${expectedMethod} event for ${label}`);
+ }
+ return eventId === collectionId;
+ }
+
+ static isTokenTransferSuccess(events: {event: IChainEvent}[], collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n) {
+ const normalizeAddress = (address: string | ICrossAccountId) => {
+ if(typeof address === 'string') return address;
+ const obj = {} as any;
+ Object.keys(address).forEach(k => {
+ obj[k.toLocaleLowerCase()] = address[k as 'Substrate' | 'Ethereum'];
+ });
+ if(obj.substrate) return {Substrate: this.normalizeSubstrateAddress(obj.substrate)};
+ if(obj.ethereum) return {Ethereum: obj.ethereum.toLocaleLowerCase()};
+ return address;
+ };
+ let transfer = {collectionId: null, tokenId: null, from: null, to: null, amount: 1} as any;
+ events.forEach(({event: {data, method, section}}) => {
+ if ((section === 'common') && (method === 'Transfer')) {
+ const hData = (data as any).toJSON();
+ transfer = {
+ collectionId: hData[0],
+ tokenId: hData[1],
+ from: normalizeAddress(hData[2]),
+ to: normalizeAddress(hData[3]),
+ amount: BigInt(hData[4]),
+ };
+ }
+ });
+ let isSuccess = parseInt(collectionId.toString()) === transfer.collectionId && parseInt(tokenId.toString()) === transfer.tokenId;
+ isSuccess = isSuccess && JSON.stringify(normalizeAddress(fromAddressObj)) === JSON.stringify(transfer.from);
+ isSuccess = isSuccess && JSON.stringify(normalizeAddress(toAddressObj)) === JSON.stringify(transfer.to);
+ isSuccess = isSuccess && amount === transfer.amount;
+ return isSuccess;
+ }
+}
+
+
+class ChainHelperBase {
+ transactionStatus = UniqueUtil.transactionStatus;
+ chainLogType = UniqueUtil.chainLogType;
+ util: typeof UniqueUtil;
+ logger: ILogger;
+ api: ApiPromise | null;
+ forcedNetwork: TUniqueNetworks | null;
+ network: TUniqueNetworks | null;
+ chainLog: IUniqueHelperLog[];
+
+ constructor(logger?: ILogger) {
+ this.util = UniqueUtil;
+ if (typeof logger == 'undefined') logger = this.util.getDefaultLogger();
+ this.logger = logger;
+ this.api = null;
+ this.forcedNetwork = null;
+ this.network = null;
+ this.chainLog = [];
+ }
+
+ clearChainLog(): void {
+ this.chainLog = [];
+ }
+
+ forceNetwork(value: TUniqueNetworks): void {
+ this.forcedNetwork = value;
+ }
+
+ async connect(wsEndpoint: string, listeners?: IApiListeners) {
+ if (this.api !== null) throw Error('Already connected');
+ const {api, network} = await ChainHelperBase.createConnection(wsEndpoint, listeners, this.forcedNetwork);
+ this.api = api;
+ this.network = network;
+ }
+
+ async disconnect() {
+ if (this.api === null) return;
+ await this.api.disconnect();
+ this.api = null;
+ this.network = null;
+ }
+
+ static async detectNetwork(api: ApiPromise): Promise<TUniqueNetworks> {
+ const spec = (await api.query.system.lastRuntimeUpgrade()).toJSON() as any;
+ if(['quartz', 'unique'].indexOf(spec.specName) > -1) return spec.specName;
+ return 'opal';
+ }
+
+ static async detectNetworkByWsEndpoint(wsEndpoint: string): Promise<TUniqueNetworks> {
+ const api = new ApiPromise({provider: new WsProvider(wsEndpoint)});
+ await api.isReady;
+
+ const network = await this.detectNetwork(api);
+
+ await api.disconnect();
+
+ return network;
+ }
+
+ static async createConnection(wsEndpoint: string, listeners?: IApiListeners, network?: TUniqueNetworks | null): Promise<{
+ api: ApiPromise;
+ network: TUniqueNetworks;
+ }> {
+ if(typeof network === 'undefined' || network === null) network = 'opal';
+ const supportedRPC = {
+ opal: {
+ unique: require('@unique-nft/opal-testnet-types/definitions').unique.rpc,
+ },
+ quartz: {
+ unique: require('@unique-nft/quartz-mainnet-types/definitions').unique.rpc,
+ },
+ unique: {
+ unique: require('@unique-nft/unique-mainnet-types/definitions').unique.rpc,
+ },
+ };
+ if(!supportedRPC.hasOwnProperty(network)) network = await this.detectNetworkByWsEndpoint(wsEndpoint);
+ const rpc = supportedRPC[network];
+
+ // TODO: investigate how to replace rpc in runtime
+ // api._rpcCore.addUserInterfaces(rpc);
+
+ const api = new ApiPromise({provider: new WsProvider(wsEndpoint), rpc});
+
+ await api.isReadyOrError;
+
+ if (typeof listeners === 'undefined') listeners = {};
+ for (const event of ['connected', 'disconnected', 'error', 'ready', 'decorated']) {
+ if (!listeners.hasOwnProperty(event) || typeof listeners[event as TApiAllowedListeners] === 'undefined') continue;
+ api.on(event as ApiInterfaceEvents, listeners[event as TApiAllowedListeners] as (...args: any[]) => any);
+ }
+
+ return {api, network};
+ }
+
+ getTransactionStatus(data: {events: {event: IChainEvent}[], status: any}) {
+ const {events, status} = data;
+ if (status.isReady) {
+ return this.transactionStatus.NOT_READY;
+ }
+ if (status.isBroadcast) {
+ return this.transactionStatus.NOT_READY;
+ }
+ if (status.isInBlock || status.isFinalized) {
+ const errors = events.filter(e => e.event.data.method === 'ExtrinsicFailed');
+ if (errors.length > 0) {
+ return this.transactionStatus.FAIL;
+ }
+ if (events.filter(e => e.event.data.method === 'ExtrinsicSuccess').length > 0) {
+ return this.transactionStatus.SUCCESS;
+ }
+ }
+
+ return this.transactionStatus.FAIL;
+ }
+
+ signTransaction(sender: TSigner, transaction: any, label = 'transaction', options = null) {
+ const sign = (callback: any) => {
+ if(options !== null) return transaction.signAndSend(sender, options, callback);
+ return transaction.signAndSend(sender, callback);
+ };
+ return new Promise(async (resolve, reject) => {
+ try {
+ const unsub = await sign((result: any) => {
+ const status = this.getTransactionStatus(result);
+
+ if (status === this.transactionStatus.SUCCESS) {
+ this.logger.log(`${label} successful`);
+ unsub();
+ resolve({result, status});
+ } else if (status === this.transactionStatus.FAIL) {
+ let moduleError = null;
+
+ if (result.hasOwnProperty('dispatchError')) {
+ const dispatchError = result['dispatchError'];
+
+ if (dispatchError && dispatchError.isModule) {
+ const modErr = dispatchError.asModule;
+ const errorMeta = dispatchError.registry.findMetaError(modErr);
+
+ moduleError = `${errorMeta.section}.${errorMeta.name}`;
+ }
+ else {
+ this.logger.log(result, this.logger.level.ERROR);
+ }
+ }
+
+ this.logger.log(`Something went wrong with ${label}. Status: ${status}`, this.logger.level.ERROR);
+ unsub();
+ reject({status, moduleError, result});
+ }
+ });
+ } catch (e) {
+ this.logger.log(e, this.logger.level.ERROR);
+ reject(e);
+ }
+ });
+ }
+
+ constructApiCall(apiCall: string, params: any[]) {
+ if(!apiCall.startsWith('api.')) throw Error(`Invalid api call: ${apiCall}`);
+ let call = this.api as any;
+ for(const part of apiCall.slice(4).split('.')) {
+ call = call[part];
+ }
+ return call(...params);
+ }
+
+ async executeExtrinsic(sender: TSigner, extrinsic: string, params: any[], expectSuccess=false, failureMessage='expected success') {
+ if(this.api === null) throw Error('API not initialized');
+ if(!extrinsic.startsWith('api.tx.')) throw Error(`${extrinsic} is not transaction`);
+
+ const startTime = (new Date()).getTime();
+ let result: ITransactionResult;
+ let events = [];
+ try {
+ result = await this.signTransaction(sender, this.constructApiCall(extrinsic, params), extrinsic) as ITransactionResult;
+ events = result.result.events.map((x: any) => x.toHuman());
+ }
+ catch(e) {
+ if(!(e as object).hasOwnProperty('status')) throw e;
+ result = e as ITransactionResult;
+ }
+
+ const endTime = (new Date()).getTime();
+
+ const log = {
+ executedAt: endTime,
+ executionTime: endTime - startTime,
+ type: this.chainLogType.EXTRINSIC,
+ status: result.status,
+ call: extrinsic,
+ params,
+ } as IUniqueHelperLog;
+
+ if(result.status !== this.transactionStatus.SUCCESS && result.moduleError) log.moduleError = result.moduleError;
+ if(events.length > 0) log.events = events;
+
+ this.chainLog.push(log);
+
+ if(expectSuccess && result.status !== this.transactionStatus.SUCCESS) throw Error(failureMessage);
+ return result;
+ }
+
+ async callRpc(rpc: string, params?: any[]) {
+ if(typeof params === 'undefined') params = [];
+ if(this.api === null) throw Error('API not initialized');
+ if(!rpc.startsWith('api.rpc.') && !rpc.startsWith('api.query.')) throw Error(`${rpc} is not RPC call`);
+
+ const startTime = (new Date()).getTime();
+ let result;
+ let error = null;
+ const log = {
+ type: this.chainLogType.RPC,
+ call: rpc,
+ params,
+ } as IUniqueHelperLog;
+
+ try {
+ result = await this.constructApiCall(rpc, params);
+ }
+ catch(e) {
+ error = e;
+ }
+
+ const endTime = (new Date()).getTime();
+
+ log.executedAt = endTime;
+ log.status = (error === null ? this.transactionStatus.SUCCESS : this.transactionStatus.FAIL) as 'Fail' | 'Success';
+ log.executionTime = endTime - startTime;
+
+ this.chainLog.push(log);
+
+ if(error !== null) throw error;
+
+ return result;
+ }
+
+ getSignerAddress(signer: IKeyringPair | string): string {
+ if(typeof signer === 'string') return signer;
+ return signer.address;
+ }
+}
+
+
+class HelperGroup {
+ helper: UniqueHelper;
+
+ constructor(uniqueHelper: UniqueHelper) {
+ this.helper = uniqueHelper;
+ }
+}
+
+
+class CollectionGroup extends HelperGroup {
+ /**
+ * Get number of blocks when sponsored transaction is available.
+ *
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param addressObj address for which the sponsorship is checked
+ * @example await getTokenNextSponsored(1, 2, {Substrate: '5DfhbVfww7ThF8q6f3...'});
+ * @returns number of blocks or null if sponsorship hasn't been set
+ */
+ async getTokenNextSponsored(collectionId: number, tokenId: number, addressObj: ICrossAccountId): Promise<number | null> {
+ return (await this.helper.callRpc('api.rpc.unique.nextSponsored', [collectionId, addressObj, tokenId])).toJSON();
+ }
+
+ /**
+ * Get the number of created collections.
+ *
+ * @returns number of created collections
+ */
+ async getTotalCount(): Promise<number> {
+ return (await this.helper.callRpc('api.rpc.unique.collectionStats')).created.toNumber();
+ }
+
+ /**
+ * Get information about the collection with additional data, including the number of tokens it contains, its administrators, the normalized address of the collection's owner, and decoded name and description.
+ *
+ * @param collectionId ID of collection
+ * @example await getData(2)
+ * @returns collection information object
+ */
+ async getData(collectionId: number): Promise<{
+ id: number;
+ name: string;
+ description: string;
+ tokensCount: number;
+ admins: ICrossAccountId[];
+ normalizedOwner: TSubstrateAccount;
+ raw: any
+ } | null> {
+ const collection = await this.helper.callRpc('api.rpc.unique.collectionById', [collectionId]);
+ const humanCollection = collection.toHuman(), collectionData = {
+ id: collectionId, name: null, description: null, tokensCount: 0, admins: [],
+ raw: humanCollection,
+ } as any, jsonCollection = collection.toJSON();
+ if (humanCollection === null) return null;
+ collectionData.raw.limits = jsonCollection.limits;
+ collectionData.raw.permissions = jsonCollection.permissions;
+ collectionData.normalizedOwner = this.helper.address.normalizeSubstrate(collectionData.raw.owner);
+ for (const key of ['name', 'description']) {
+ collectionData[key] = this.helper.util.vec2str(humanCollection[key]);
+ }
+
+ collectionData.tokensCount = (['RFT', 'NFT'].includes(humanCollection.mode)) ? await this.helper[humanCollection.mode.toLocaleLowerCase() as 'nft' | 'rft'].getLastTokenId(collectionId) : 0;
+ collectionData.admins = await this.getAdmins(collectionId);
+
+ return collectionData;
+ }
+
+ /**
+ * Get the normalized addresses of the collection's administrators.
+ *
+ * @param collectionId ID of collection
+ * @example await getAdmins(1)
+ * @returns array of administrators
+ */
+ async getAdmins(collectionId: number): Promise<ICrossAccountId[]> {
+ const normalized = [];
+ for(const admin of (await this.helper.callRpc('api.rpc.unique.adminlist', [collectionId])).toHuman()) {
+ if(admin.Substrate) normalized.push({Substrate: this.helper.address.normalizeSubstrate(admin.Substrate)});
+ else normalized.push(admin);
+ }
+ return normalized;
+ }
+
+ /**
+ * Get the effective limits of the collection instead of null for default values
+ *
+ * @param collectionId ID of collection
+ * @example await getEffectiveLimits(2)
+ * @returns object of collection limits
+ */
+ async getEffectiveLimits(collectionId: number): Promise<ICollectionLimits> {
+ return (await this.helper.callRpc('api.rpc.unique.effectiveCollectionLimits', [collectionId])).toJSON();
+ }
+
+ /**
+ * Burns the collection if the signer has sufficient permissions and collection is empty.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param label extra label for log
+ * @example await helper.collection.burn(aliceKeyring, 3);
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async burn(signer: TSigner, collectionId: number, label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.destroyCollection', [collectionId],
+ true, `Unable to burn collection for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionDestroyed', label);
+ }
+
+ /**
+ * Sets the sponsor for the collection (Requires the Substrate address).
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param sponsorAddress Sponsor substrate address
+ * @param label extra label for log
+ * @example setSponsor(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...")
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async setSponsor(signer: TSigner, collectionId: number, sponsorAddress: TSubstrateAccount, label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.setCollectionSponsor', [collectionId, sponsorAddress],
+ true, `Unable to set collection sponsor for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionSponsorSet', label);
+ }
+
+ /**
+ * Confirms consent to sponsor the collection on behalf of the signer.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param label extra label for log
+ * @example confirmSponsorship(aliceKeyring, 10)
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async confirmSponsorship(signer: TSigner, collectionId: number, label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.confirmSponsorship', [collectionId],
+ true, `Unable to confirm collection sponsorship for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'SponsorshipConfirmed', label);
+ }
+
+ /**
+ * Sets the limits of the collection. At least one limit must be specified for a correct call.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param limits collection limits object
+ * @param label extra label for log
+ * @example
+ * await setLimits(
+ * aliceKeyring,
+ * 10,
+ * {
+ * sponsorTransferTimeout: 0,
+ * ownerCanDestroy: false
+ * }
+ * )
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async setLimits(signer: TSigner, collectionId: number, limits: ICollectionLimits, label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.setCollectionLimits', [collectionId, limits],
+ true, `Unable to set collection limits for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionLimitSet', label);
+ }
+
+ /**
+ * Changes the owner of the collection to the new Substrate address.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param ownerAddress substrate address of new owner
+ * @param label extra label for log
+ * @example changeOwner(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...")
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async changeOwner(signer: TSigner, collectionId: number, ownerAddress: TSubstrateAccount, label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.changeCollectionOwner', [collectionId, ownerAddress],
+ true, `Unable to change collection owner for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionOwnedChanged', label);
+ }
+
+ /**
+ * Adds a collection administrator.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param adminAddressObj Administrator address (substrate or ethereum)
+ * @param label extra label for log
+ * @example addAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async addAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId, label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.addCollectionAdmin', [collectionId, adminAddressObj],
+ true, `Unable to add collection admin for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminAdded', label);
+ }
+
+ /**
+ * Removes a collection administrator.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param adminAddressObj Administrator address (substrate or ethereum)
+ * @param label extra label for log
+ * @example removeAdmin(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."})
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async removeAdmin(signer: TSigner, collectionId: number, adminAddressObj: ICrossAccountId, label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.removeCollectionAdmin', [collectionId, adminAddressObj],
+ true, `Unable to remove collection admin for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminRemoved', label);
+ }
+
+ /**
+ * Sets onchain permissions for selected collection.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param permissions collection permissions object
+ * @param label extra label for log
+ * @example setPermissions(aliceKeyring, 10, {access:'AllowList', mintMode: true, nesting: {collectionAdmin: true, tokenOwner: true}});
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async setPermissions(signer: TSigner, collectionId: number, permissions: ICollectionPermissions, label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.setCollectionPermissions', [collectionId, permissions],
+ true, `Unable to set collection permissions for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionPermissionSet', label);
+ }
+
+ /**
+ * Enables nesting for selected collection. If `restricted` set, you can nest only tokens from specified collections.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param permissions nesting permissions object
+ * @param label extra label for log
+ * @example enableNesting(aliceKeyring, 10, {collectionAdmin: true, tokenOwner: true});
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async enableNesting(signer: TSigner, collectionId: number, permissions: INestingPermissions, label?: string): Promise<boolean> {
+ return await this.setPermissions(signer, collectionId, {nesting: permissions}, label);
+ }
+
+ /**
+ * Disables nesting for selected collection.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param label extra label for log
+ * @example disableNesting(aliceKeyring, 10);
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async disableNesting(signer: TSigner, collectionId: number, label?: string): Promise<boolean> {
+ return await this.setPermissions(signer, collectionId, {nesting: {tokenOwner: false, collectionAdmin: false}}, label);
+ }
+
+ /**
+ * Sets onchain properties to the collection.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param properties array of property objects
+ * @param label extra label for log
+ * @example setProperties(aliceKeyring, 10, [{key: "gender", value: "male"}]);
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async setProperties(signer: TSigner, collectionId: number, properties: IProperty[], label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.setCollectionProperties', [collectionId, properties],
+ true, `Unable to set collection properties for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertySet', label);
+ }
+
+ /**
+ * Deletes onchain properties from the collection.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param propertyKeys array of property keys to delete
+ * @param label
+ * @example deleteProperties(aliceKeyring, 10, ["gender", "age"]);
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async deleteProperties(signer: TSigner, collectionId: number, propertyKeys: string[], label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.deleteCollectionProperties', [collectionId, propertyKeys],
+ true, `Unable to delete collection properties for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertyDeleted', label);
+ }
+
+ /**
+ * Changes the owner of the token.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param addressObj address of a new owner
+ * @param amount amount of tokens to be transfered. For NFT must be set to 1n
+ * @example transferToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})
+ * @returns true if the token success, otherwise false
+ */
+ async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId, amount=1n): Promise<boolean> {
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.transfer', [addressObj, collectionId, tokenId, amount],
+ true, `Unable to transfer token #${tokenId} from collection #${collectionId}`,
+ );
+
+ return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, {Substrate: typeof signer === 'string' ? signer : signer.address}, addressObj, amount);
+ }
+
+ /**
+ *
+ * Change ownership of a token(s) on behalf of the owner.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param fromAddressObj address on behalf of which the token will be sent
+ * @param toAddressObj new token owner
+ * @param amount amount of tokens to be transfered. For NFT must be set to 1n
+ * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg"}, {Ethereum: "0x9F0583DbB85..."})
+ * @returns true if the token success, otherwise false
+ */
+ async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=1n): Promise<boolean> {
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.transferFrom', [fromAddressObj, toAddressObj, collectionId, tokenId, amount],
+ true, `Unable to transfer token #${tokenId} from collection #${collectionId}`,
+ );
+ return this.helper.util.isTokenTransferSuccess(result.result.events, collectionId, tokenId, fromAddressObj, toAddressObj, amount);
+ }
+
+ /**
+ *
+ * Destroys a concrete instance of NFT/RFT or burns a specified amount of fungible tokens.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param label
+ * @param amount amount of tokens to be burned. For NFT must be set to 1n
+ * @example burnToken(aliceKeyring, 10, 5);
+ * @returns ```true``` and burnt token number is extrinsic success. Otherwise ```false``` and ```null```
+ */
+ async burnToken(signer: TSigner, collectionId: number, tokenId: number, label?: string, amount=1n): Promise<{
+ success: boolean,
+ token: number | null
+ }> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const burnResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.burnItem', [collectionId, tokenId, amount],
+ true, `Unable to burn token for ${label}`,
+ );
+ const burnedTokens = this.helper.util.extractTokensFromBurnResult(burnResult, label);
+ if (burnedTokens.tokens.length > 1) throw Error('Burned multiple tokens');
+ return {success: burnedTokens.success, token: burnedTokens.tokens.length > 0 ? burnedTokens.tokens[0] : null};
+ }
+
+ /**
+ * Destroys a concrete instance of NFT on behalf of the owner
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param fromAddressObj address on behalf of which the token will be burnt
+ * @param tokenId ID of token
+ * @param label
+ * @param amount amount of tokens to be burned. For NFT must be set to 1n
+ * @example burnTokenFrom(aliceKeyring, 10, {Substrate: "5DyN4Y92vZCjv38fg..."}, 5, {Ethereum: "0x9F0583DbB85..."})
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async burnTokenFrom(signer: TSigner, collectionId: number, fromAddressObj: ICrossAccountId, tokenId: number, label?: string, amount=1n): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const burnResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.burnFrom', [collectionId, fromAddressObj, tokenId, amount],
+ true, `Unable to burn token from for ${label}`,
+ );
+ const burnedTokens = this.helper.util.extractTokensFromBurnResult(burnResult, label);
+ return burnedTokens.success && burnedTokens.tokens.length > 0;
+ }
+
+ /**
+ * Set, change, or remove approved address to transfer the ownership of the NFT.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param toAddressObj
+ * @param label
+ * @param amount amount of token to be approved. For NFT must be set to 1n
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, label?: string, amount=1n) {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const approveResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.approve', [toAddressObj, collectionId, tokenId, amount],
+ true, `Unable to approve token for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(approveResult.result.events, collectionId, 'common', 'Approved', label);
+ }
+
+ /**
+ * Get the amount of token pieces approved to transfer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param toAccountObj
+ * @param fromAccountObj
+ * @example getTokenApprovedPieces(10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Substrate: "5ERZNF88Mm7UGfPP3mdG..."})
+ * @returns number of approved to transfer pieces
+ */
+ async getTokenApprovedPieces(collectionId: number, tokenId: number, toAccountObj: ICrossAccountId, fromAccountObj: ICrossAccountId): Promise<bigint> {
+ return (await this.helper.callRpc('api.rpc.unique.allowance', [collectionId, fromAccountObj, toAccountObj, tokenId])).toBigInt();
+ }
+
+ /**
+ * Get the last created token id
+ * @param collectionId ID of collection
+ * @example getLastTokenId(10);
+ * @returns id of the last created token
+ */
+ async getLastTokenId(collectionId: number): Promise<number> {
+ return (await this.helper.callRpc('api.rpc.unique.lastTokenId', [collectionId])).toNumber();
+ }
+
+ /**
+ * Check if token exists
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @example isTokenExists(10, 20);
+ * @returns true if the token exists, otherwise false
+ */
+ async isTokenExists(collectionId: number, tokenId: number): Promise<boolean> {
+ return (await this.helper.callRpc('api.rpc.unique.tokenExists', [collectionId, tokenId])).toJSON();
+ }
+}
+
+class NFTnRFT extends CollectionGroup {
+ /**
+ * Get tokens owned by account
+ *
+ * @param collectionId ID of collection
+ * @param addressObj tokens owner
+ * @example getTokensByAddress(10, {Substrate: "5DyN4Y92vZCjv38fg..."})
+ * @returns array of token ids owned by account
+ */
+ async getTokensByAddress(collectionId: number, addressObj: ICrossAccountId): Promise<number[]> {
+ return (await this.helper.callRpc('api.rpc.unique.accountTokens', [collectionId, addressObj])).toJSON();
+ }
+
+ /**
+ * Get token data
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param blockHashAt
+ * @param propertyKeys
+ * @example getToken(10, 5);
+ * @returns human readable token data
+ */
+ async getToken(collectionId: number, tokenId: number, blockHashAt?: string, propertyKeys?: string[]): Promise<{
+ properties: IProperty[];
+ owner: ICrossAccountId;
+ normalizedOwner: ICrossAccountId;
+ }| null> {
+ let tokenData;
+ if(typeof blockHashAt === 'undefined') {
+ tokenData = await this.helper.callRpc('api.rpc.unique.tokenData', [collectionId, tokenId]);
+ }
+ else {
+ if(typeof propertyKeys === 'undefined') {
+ const collection = (await this.helper.callRpc('api.rpc.unique.collectionById', [collectionId])).toHuman();
+ if(!collection) return null;
+ propertyKeys = collection.tokenPropertyPermissions.map((x: ITokenPropertyPermission) => x.key);
+ }
+ tokenData = await this.helper.callRpc('api.rpc.unique.tokenData', [collectionId, tokenId, propertyKeys, blockHashAt]);
+ }
+ tokenData = tokenData.toHuman();
+ if (tokenData === null || tokenData.owner === null) return null;
+ const owner = {} as any;
+ for (const key of Object.keys(tokenData.owner)) {
+ owner[key.toLocaleLowerCase()] = key.toLocaleLowerCase() === 'substrate' ? this.helper.address.normalizeSubstrate(tokenData.owner[key]) : tokenData.owner[key];
+ }
+ tokenData.normalizedOwner = crossAccountIdFromLower(owner);
+ return tokenData;
+ }
+
+ /**
+ * Set permissions to change token properties
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param permissions permissions to change a property by the collection owner or admin
+ * @param label
+ * @example setTokenPropertyPermissions(
+ * aliceKeyring, 10, [{key: "gender", permission: {tokenOwner: true, mutable: true, collectionAdmin: true}}]
+ * )
+ * @returns true if extrinsic success otherwise false
+ */
+ async setTokenPropertyPermissions(signer: TSigner, collectionId: number, permissions: ITokenPropertyPermission[], label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.setTokenPropertyPermissions', [collectionId, permissions],
+ true, `Unable to set token property permissions for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'PropertyPermissionSet', label);
+ }
+
+ /**
+ * Set token properties
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param properties
+ * @param label
+ * @example setTokenProperties(aliceKeyring, 10, 5, [{key: "gender", value: "female"}, {key: "age", value: "23"}])
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async setTokenProperties(signer: TSigner, collectionId: number, tokenId: number, properties: IProperty[], label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `token #${tokenId} from collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.setTokenProperties', [collectionId, tokenId, properties],
+ true, `Unable to set token properties for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertySet', label);
+ }
+
+ /**
+ * Delete the provided properties of a token
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param propertyKeys property keys to be deleted
+ * @param label
+ * @example deleteTokenProperties(aliceKeyring, 10, 5, ["gender", "age"])
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async deleteTokenProperties(signer: TSigner, collectionId: number, tokenId: number, propertyKeys: string[], label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `token #${tokenId} from collection #${collectionId}`;
+ const result = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.deleteTokenProperties', [collectionId, tokenId, propertyKeys],
+ true, `Unable to delete token properties for ${label}`,
+ );
+
+ return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertyDeleted', label);
+ }
+
+ /**
+ * Mint new collection
+ * @param signer keyring of signer
+ * @param collectionOptions basic collection options and properties
+ * @param mode NFT or RFT type of a collection
+ * @param errorLabel
+ * @example mintCollection(aliceKeyring, {name: 'New', description: "New collection", tokenPrefix: "NEW"}, "NFT")
+ * @returns object of the created collection
+ */
+ async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, mode: 'NFT' | 'RFT', errorLabel = 'Unable to mint collection'): Promise<UniqueCollectionBase> {
+ collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object
+ collectionOptions.mode = (mode === 'NFT') ? {nft: null} : {refungible: null};
+ for (const key of ['name', 'description', 'tokenPrefix']) {
+ if (typeof collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] === 'string') collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] = this.helper.util.str2vec(collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] as string);
+ }
+ const creationResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.createCollectionEx', [collectionOptions],
+ true, errorLabel,
+ );
+ return this.getCollectionObject(this.helper.util.extractCollectionIdFromCreationResult(creationResult, errorLabel));
+ }
+
+ getCollectionObject(collectionId: number): any {
+ return null;
+ }
+
+ getTokenObject(collectionId: number, tokenId: number): any {
+ return null;
+ }
+}
+
+
+class NFTGroup extends NFTnRFT {
+ /**
+ * Get collection object
+ * @param collectionId ID of collection
+ * @example getCollectionObject(2);
+ * @returns instance of UniqueNFTCollection
+ */
+ getCollectionObject(collectionId: number): UniqueNFTCollection {
+ return new UniqueNFTCollection(collectionId, this.helper);
+ }
+
+ /**
+ * Get token object
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @example getTokenObject(10, 5);
+ * @returns instance of UniqueNFTToken
+ */
+ getTokenObject(collectionId: number, tokenId: number): UniqueNFTToken {
+ return new UniqueNFTToken(tokenId, this.getCollectionObject(collectionId));
+ }
+
+ /**
+ * Get token's owner
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param blockHashAt
+ * @example getTokenOwner(10, 5);
+ * @returns Address in CrossAccountId format, e.g. {Substrate: "5DnSF6RRjwteE3BrCj..."}
+ */
+ async getTokenOwner(collectionId: number, tokenId: number, blockHashAt?: string): Promise<ICrossAccountId> {
+ let owner;
+ if (typeof blockHashAt === 'undefined') {
+ owner = await this.helper.callRpc('api.rpc.unique.tokenOwner', [collectionId, tokenId]);
+ } else {
+ owner = await this.helper.callRpc('api.rpc.unique.tokenOwner', [collectionId, tokenId, blockHashAt]);
+ }
+ return crossAccountIdFromLower(owner.toJSON());
+ }
+
+ /**
+ * Is token approved to transfer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param toAccountObj address to be approved
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async isTokenApproved(collectionId: number, tokenId: number, toAccountObj: ICrossAccountId): Promise<boolean> {
+ return (await this.getTokenApprovedPieces(collectionId, tokenId, toAccountObj, await this.getTokenOwner(collectionId, tokenId))) === 1n;
+ }
+
+ /**
+ * Changes the owner of the token.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param addressObj address of a new owner
+ * @example transferToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId): Promise<boolean> {
+ return await super.transferToken(signer, collectionId, tokenId, addressObj, 1n);
+ }
+
+ /**
+ *
+ * Change ownership of a NFT on behalf of the owner.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param fromAddressObj address on behalf of which the token will be sent
+ * @param toAddressObj new token owner
+ * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Ethereum: "0x9F0583DbB85..."})
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId): Promise<boolean> {
+ return await super.transferTokenFrom(signer, collectionId, tokenId, fromAddressObj, toAddressObj, 1n);
+ }
+
+ /**
+ * Recursively find the address that owns the token
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param blockHashAt
+ * @example getTokenTopmostOwner(10, 5);
+ * @returns address in CrossAccountId format, e.g. {Substrate: "5DyN4Y92vZCjv38fg..."}
+ */
+ async getTokenTopmostOwner(collectionId: number, tokenId: number, blockHashAt?: string): Promise<ICrossAccountId | null> {
+ let owner;
+ if (typeof blockHashAt === 'undefined') {
+ owner = await this.helper.callRpc('api.rpc.unique.topmostTokenOwner', [collectionId, tokenId]);
+ } else {
+ owner = await this.helper.callRpc('api.rpc.unique.topmostTokenOwner', [collectionId, tokenId, blockHashAt]);
+ }
+
+ if (owner === null) return null;
+
+ owner = owner.toHuman();
+
+ return owner.Substrate ? {Substrate: this.helper.address.normalizeSubstrate(owner.Substrate)} : owner;
+ }
+
+ /**
+ * Get tokens nested in the provided token
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param blockHashAt
+ * @example getTokenChildren(10, 5);
+ * @returns tokens whose depth of nesting is <= 5
+ */
+ async getTokenChildren(collectionId: number, tokenId: number, blockHashAt?: string): Promise<IToken[]> {
+ let children;
+ if(typeof blockHashAt === 'undefined') {
+ children = await this.helper.callRpc('api.rpc.unique.tokenChildren', [collectionId, tokenId]);
+ } else {
+ children = await this.helper.callRpc('api.rpc.unique.tokenChildren', [collectionId, tokenId, blockHashAt]);
+ }
+
+ return children.toJSON().map((x: any) => {
+ return {collectionId: x.collection, tokenId: x.token};
+ });
+ }
+
+ /**
+ * Nest one token into another
+ * @param signer keyring of signer
+ * @param tokenObj token to be nested
+ * @param rootTokenObj token to be parent
+ * @param label
+ * @example nestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4});
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async nestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken, label='nest token'): Promise<boolean> {
+ const rootTokenAddress = {Ethereum: this.helper.util.getNestingTokenAddress(rootTokenObj.collectionId, rootTokenObj.tokenId)};
+ const result = await this.transferToken(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress);
+ if(!result) {
+ throw Error(`Unable to nest token for ${label}`);
+ }
+ return result;
+ }
+
+ /**
+ * Remove token from nested state
+ * @param signer keyring of signer
+ * @param tokenObj token to unnest
+ * @param rootTokenObj parent of a token
+ * @param toAddressObj address of a new token owner
+ * @param label
+ * @example unnestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4}, {Substrate: "5DyN4Y92vZCjv38fg..."});
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async unnestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken, toAddressObj: ICrossAccountId, label='unnest token'): Promise<boolean> {
+ const rootTokenAddress = {Ethereum: this.helper.util.getNestingTokenAddress(rootTokenObj.collectionId, rootTokenObj.tokenId)};
+ const result = await this.transferTokenFrom(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress, toAddressObj);
+ if(!result) {
+ throw Error(`Unable to unnest token for ${label}`);
+ }
+ return result;
+ }
+
+ /**
+ * Mint new collection
+ * @param signer keyring of signer
+ * @param collectionOptions Collection options
+ * @param label
+ * @example
+ * mintCollection(aliceKeyring, {
+ * name: 'New',
+ * description: 'New collection',
+ * tokenPrefix: 'NEW',
+ * })
+ * @returns object of the created collection
+ */
+ async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, label = 'new collection'): Promise<UniqueNFTCollection> {
+ return await super.mintCollection(signer, collectionOptions, 'NFT', `Unable to mint NFT collection for ${label}`) as UniqueNFTCollection;
+ }
+
+ /**
+ * Mint new token
+ * @param signer keyring of signer
+ * @param data token data
+ * @param label
+ * @returns created token object
+ */
+ async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; properties?: IProperty[]; }, label?: string): Promise<UniqueNFTToken> {
+ if(typeof label === 'undefined') label = `collection #${data.collectionId}`;
+ const creationResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {
+ nft: {
+ properties: data.properties,
+ },
+ }],
+ true, `Unable to mint NFT token for ${label}`,
+ );
+ const createdTokens = this.helper.util.extractTokensFromCreationResult(creationResult, label);
+ if (createdTokens.tokens.length > 1) throw Error('Minted multiple tokens');
+ if (createdTokens.tokens.length < 1) throw Error('No tokens minted');
+ return this.getTokenObject(data.collectionId, createdTokens.tokens[0].tokenId);
+ }
+
+ /**
+ * Mint multiple NFT tokens
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokens array of tokens with owner and properties
+ * @param label
+ * @example
+ * mintMultipleTokens(aliceKeyring, 10, [{
+ * owner: {Substrate: "5DyN4Y92vZCjv38fg..."},
+ * properties: [{key: "gender", value: "male"},{key: "age", value: "45"}],
+ * },{
+ * owner: {Ethereum: "0x9F0583DbB855d..."},
+ * properties: [{key: "gender", value: "female"},{key: "age", value: "22"}],
+ * }]);
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[], label?: string): Promise<UniqueNFTToken[]> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const creationResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.createMultipleItemsEx', [collectionId, {NFT: tokens}],
+ true, `Unable to mint NFT tokens for ${label}`,
+ );
+ const collection = this.getCollectionObject(collectionId);
+ return this.helper.util.extractTokensFromCreationResult(creationResult, label).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
+ }
+
+ /**
+ * Mint multiple NFT tokens with one owner
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param owner tokens owner
+ * @param tokens array of tokens with owner and properties
+ * @param label
+ * @example
+ * mintMultipleTokensWithOneOwner(aliceKeyring, 10, "5DyN4Y92vZCjv38fg...", [{
+ * properties: [{
+ * key: "gender",
+ * value: "female",
+ * },{
+ * key: "age",
+ * value: "33",
+ * }],
+ * }]);
+ * @returns array of newly created tokens
+ */
+ async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {properties?: IProperty[]}[], label?: string): Promise<UniqueNFTToken[]> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const rawTokens = [];
+ for (const token of tokens) {
+ const raw = {NFT: {properties: token.properties}};
+ rawTokens.push(raw);
+ }
+ const creationResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.createMultipleItems', [collectionId, owner, rawTokens],
+ true, `Unable to mint NFT tokens for ${label}`,
+ );
+ const collection = this.getCollectionObject(collectionId);
+ return this.helper.util.extractTokensFromCreationResult(creationResult, label).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
+ }
+
+ /**
+ * Destroys a concrete instance of NFT.
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param label
+ * @example burnToken(aliceKeyring, 10, 5);
+ * @returns ```true``` and burnt token number is extrinsic success. Otherwise ```false``` and ```null```
+ */
+ async burnToken(signer: IKeyringPair, collectionId: number, tokenId: number, label?: string): Promise<{ success: boolean; token: number | null; }> {
+ return await super.burnToken(signer, collectionId, tokenId, label, 1n);
+ }
+
+ /**
+ * Set, change, or remove approved address to transfer the ownership of the NFT.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param toAddressObj address to approve
+ * @param label
+ * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."})
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, label?: string) {
+ return super.approveToken(signer, collectionId, tokenId, toAddressObj, label, 1n);
+ }
+}
+
+
+class RFTGroup extends NFTnRFT {
+ /**
+ * Get collection object
+ * @param collectionId ID of collection
+ * @example getCollectionObject(2);
+ * @returns instance of UniqueRFTCollection
+ */
+ getCollectionObject(collectionId: number): UniqueRFTCollection {
+ return new UniqueRFTCollection(collectionId, this.helper);
+ }
+
+ /**
+ * Get token object
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @example getTokenObject(10, 5);
+ * @returns instance of UniqueNFTToken
+ */
+ getTokenObject(collectionId: number, tokenId: number): UniqueRFTToken {
+ return new UniqueRFTToken(tokenId, this.getCollectionObject(collectionId));
+ }
+
+ /**
+ * Get top 10 token owners with the largest number of pieces
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @example getTokenTop10Owners(10, 5);
+ * @returns array of top 10 owners
+ */
+ async getTokenTop10Owners(collectionId: number, tokenId: number): Promise<ICrossAccountId[]> {
+ return (await this.helper.callRpc('api.rpc.unique.tokenOwners', [collectionId, tokenId])).toJSON().map(crossAccountIdFromLower);
+ }
+
+ /**
+ * Get number of pieces owned by address
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param addressObj address token owner
+ * @example getTokenBalance(10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."});
+ * @returns number of pieces ownerd by address
+ */
+ async getTokenBalance(collectionId: number, tokenId: number, addressObj: ICrossAccountId): Promise<bigint> {
+ return (await this.helper.callRpc('api.rpc.unique.balance', [collectionId, addressObj, tokenId])).toBigInt();
+ }
+
+ /**
+ * Transfer pieces of token to another address
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param addressObj address of a new owner
+ * @param amount number of pieces to be transfered
+ * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, 2000n)
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async transferToken(signer: TSigner, collectionId: number, tokenId: number, addressObj: ICrossAccountId, amount=100n): Promise<boolean> {
+ return await super.transferToken(signer, collectionId, tokenId, addressObj, amount);
+ }
+
+ /**
+ * Change ownership of some pieces of RFT on behalf of the owner.
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param fromAddressObj address on behalf of which the token will be sent
+ * @param toAddressObj new token owner
+ * @param amount number of pieces to be transfered
+ * @example transferTokenFrom(aliceKeyring, 10, 5, {Substrate: "5DyN4Y92vZCjv38fg..."}, {Substrate: "5DfhbVfww7ThF8q6f3i..."}, 2000n)
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async transferTokenFrom(signer: TSigner, collectionId: number, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=100n): Promise<boolean> {
+ return await super.transferTokenFrom(signer, collectionId, tokenId, fromAddressObj, toAddressObj, amount);
+ }
+
+ /**
+ * Mint new collection
+ * @param signer keyring of signer
+ * @param collectionOptions Collection options
+ * @param label
+ * @example
+ * mintCollection(aliceKeyring, {
+ * name: 'New',
+ * description: 'New collection',
+ * tokenPrefix: 'NEW',
+ * })
+ * @returns object of the created collection
+ */
+ async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, label = 'new collection'): Promise<UniqueRFTCollection> {
+ return await super.mintCollection(signer, collectionOptions, 'RFT', `Unable to mint RFT collection for ${label}`) as UniqueRFTCollection;
+ }
+
+ /**
+ * Mint new token
+ * @param signer keyring of signer
+ * @param data token data
+ * @param label
+ * @example mintToken(aliceKeyring, {collectionId: 10, owner: {Substrate: '5GHoZe9c73RYbVzq...'}, pieces: 10000n});
+ * @returns created token object
+ */
+ async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; pieces: bigint; properties?: IProperty[]; }, label?: string): Promise<UniqueRFTToken> {
+ if(typeof label === 'undefined') label = `collection #${data.collectionId}`;
+ const creationResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {
+ refungible: {
+ pieces: data.pieces,
+ properties: data.properties,
+ },
+ }],
+ true, `Unable to mint RFT token for ${label}`,
+ );
+ const createdTokens = this.helper.util.extractTokensFromCreationResult(creationResult, label);
+ if (createdTokens.tokens.length > 1) throw Error('Minted multiple tokens');
+ if (createdTokens.tokens.length < 1) throw Error('No tokens minted');
+ return this.getTokenObject(data.collectionId, createdTokens.tokens[0].tokenId);
+ }
+
+ async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, pieces: bigint, properties?: IProperty[]}[], label?: string): Promise<UniqueRFTToken[]> {
+ throw Error('Not implemented');
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const creationResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.createMultipleItemsEx', [collectionId, {RefungibleMultipleOwners: tokens}],
+ true, `Unable to mint RFT tokens for ${label}`,
+ );
+ const collection = this.getCollectionObject(collectionId);
+ return this.helper.util.extractTokensFromCreationResult(creationResult, label).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
+ }
+
+ /**
+ * Mint multiple RFT tokens with one owner
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param owner tokens owner
+ * @param tokens array of tokens with properties and pieces
+ * @param label
+ * @example mintMultipleTokensWithOneOwner(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, [{pieces: 100000n, properties: [{key: "gender", value: "male"}]}]);
+ * @returns array of newly created RFT tokens
+ */
+ async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {pieces: bigint, properties?: IProperty[]}[], label?: string): Promise<UniqueRFTToken[]> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const rawTokens = [];
+ for (const token of tokens) {
+ const raw = {ReFungible: {pieces: token.pieces, properties: token.properties}};
+ rawTokens.push(raw);
+ }
+ const creationResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.createMultipleItems', [collectionId, owner, rawTokens],
+ true, `Unable to mint RFT tokens for ${label}`,
+ );
+ const collection = this.getCollectionObject(collectionId);
+ return this.helper.util.extractTokensFromCreationResult(creationResult, label).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
+ }
+
+ /**
+ * Destroys a concrete instance of RFT.
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param label
+ * @param amount number of pieces to be burnt
+ * @example burnToken(aliceKeyring, 10, 5);
+ * @returns ```true``` and burnt token number is extrinsic success. Otherwise ```false``` and ```null```
+ */
+ async burnToken(signer: IKeyringPair, collectionId: number, tokenId: number, label?: string, amount=100n): Promise<{ success: boolean; token: number | null; }> {
+ return await super.burnToken(signer, collectionId, tokenId, label, amount);
+ }
+
+ /**
+ * Set, change, or remove approved address to transfer the ownership of the RFT.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param toAddressObj address to approve
+ * @param label
+ * @param amount number of pieces to be approved
+ * @example approveToken(aliceKeyring, 10, 5, {Substrate: "5GHoZe9c73RYbVzq..."}, "", 10000n);
+ * @returns true if the token success, otherwise false
+ */
+ async approveToken(signer: IKeyringPair, collectionId: number, tokenId: number, toAddressObj: ICrossAccountId, label?: string, amount=100n) {
+ return super.approveToken(signer, collectionId, tokenId, toAddressObj, label, amount);
+ }
+
+ /**
+ * Get total number of pieces
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @example getTokenTotalPieces(10, 5);
+ * @returns number of pieces
+ */
+ async getTokenTotalPieces(collectionId: number, tokenId: number): Promise<bigint> {
+ return (await this.helper.callRpc('api.rpc.unique.totalPieces', [collectionId, tokenId])).unwrap().toBigInt();
+ }
+
+ /**
+ * Change number of token pieces. Signer must be the owner of all token pieces.
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param tokenId ID of token
+ * @param amount new number of pieces
+ * @param label
+ * @example repartitionToken(aliceKeyring, 10, 5, 12345n);
+ * @returns true if the repartion was success, otherwise false
+ */
+ async repartitionToken(signer: TSigner, collectionId: number, tokenId: number, amount: bigint, label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const currentAmount = await this.getTokenTotalPieces(collectionId, tokenId);
+ const repartitionResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.repartition', [collectionId, tokenId, amount],
+ true, `Unable to repartition RFT token for ${label}`,
+ );
+ if(currentAmount < amount) return this.helper.util.findCollectionInEvents(repartitionResult.result.events, collectionId, 'common', 'ItemCreated', label);
+ return this.helper.util.findCollectionInEvents(repartitionResult.result.events, collectionId, 'common', 'ItemDestroyed', label);
+ }
+}
+
+
+class FTGroup extends CollectionGroup {
+ /**
+ * Get collection object
+ * @param collectionId ID of collection
+ * @example getCollectionObject(2);
+ * @returns instance of UniqueFTCollection
+ */
+ getCollectionObject(collectionId: number): UniqueFTCollection {
+ return new UniqueFTCollection(collectionId, this.helper);
+ }
+
+ /**
+ * Mint new fungible collection
+ * @param signer keyring of signer
+ * @param collectionOptions Collection options
+ * @param decimalPoints number of token decimals
+ * @param errorLabel
+ * @example
+ * mintCollection(aliceKeyring, {
+ * name: 'New',
+ * description: 'New collection',
+ * tokenPrefix: 'NEW',
+ * }, 18)
+ * @returns newly created fungible collection
+ */
+ async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, decimalPoints = 0, errorLabel = 'Unable to mint collection'): Promise<UniqueFTCollection> {
+ collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object
+ if(collectionOptions.tokenPropertyPermissions) throw Error('Fungible collections has no tokenPropertyPermissions');
+ collectionOptions.mode = {fungible: decimalPoints};
+ for (const key of ['name', 'description', 'tokenPrefix']) {
+ if (typeof collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] === 'string') collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] = this.helper.util.str2vec(collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] as string);
+ }
+ const creationResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.createCollectionEx', [collectionOptions],
+ true, errorLabel,
+ );
+ return this.getCollectionObject(this.helper.util.extractCollectionIdFromCreationResult(creationResult, errorLabel));
+ }
+
+ /**
+ * Mint tokens
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param owner address owner of new tokens
+ * @param amount amount of tokens to be meanted
+ * @param label
+ * @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, label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const creationResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.createItem', [collectionId, (typeof owner === 'string') ? {Substrate: owner} : owner, {
+ fungible: {
+ value: amount,
+ },
+ }],
+ true, `Unable to mint fungible tokens for ${label}`,
+ );
+ return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated', label);
+ }
+
+ /**
+ * Mint multiple Fungible tokens with one owner
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param owner tokens owner
+ * @param tokens array of tokens with properties and pieces
+ * @param label
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {value: bigint}[], label?: string): Promise<boolean> {
+ if(typeof label === 'undefined') label = `collection #${collectionId}`;
+ const rawTokens = [];
+ for (const token of tokens) {
+ const raw = {Fungible: {Value: token.value}};
+ rawTokens.push(raw);
+ }
+ const creationResult = await this.helper.executeExtrinsic(
+ signer,
+ 'api.tx.unique.createMultipleItems', [collectionId, owner, rawTokens],
+ true, `Unable to mint RFT tokens for ${label}`,
+ );
+ return this.helper.util.findCollectionInEvents(creationResult.result.events, collectionId, 'common', 'ItemCreated', label);
+ }
+
+ /**
+ * Get the top 10 owners with the largest balance for the Fungible collection
+ * @param collectionId ID of collection
+ * @example getTop10Owners(10);
+ * @returns array of ```ICrossAccountId```
+ */
+ async getTop10Owners(collectionId: number): Promise<ICrossAccountId[]> {
+ return (await this.helper.callRpc('api.rpc.unique.tokenOwners', [collectionId, 0])).toJSON().map(crossAccountIdFromLower);
+ }
+
+ /**
+ * Get account balance
+ * @param collectionId ID of collection
+ * @param addressObj address of owner
+ * @example getBalance(10, {Substrate: "5GHoZe9c73RYbVzq..."})
+ * @returns amount of fungible tokens owned by address
+ */
+ async getBalance(collectionId: number, addressObj: ICrossAccountId): Promise<bigint> {
+ return (await this.helper.callRpc('api.rpc.unique.balance', [collectionId, addressObj, 0])).toBigInt();
+ }
+
+ /**
+ * Transfer tokens to address
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param toAddressObj address recepient
+ * @param amount amount of tokens to be sent
+ * @example transfer(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n);
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async transfer(signer: TSigner, collectionId: number, toAddressObj: ICrossAccountId, amount: bigint) {
+ return await super.transferToken(signer, collectionId, 0, toAddressObj, amount);
+ }
+
+ /**
+ * Transfer some tokens on behalf of the owner.
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param fromAddressObj address on behalf of which tokens will be sent
+ * @param toAddressObj address where token to be sent
+ * @param amount number of tokens to be sent
+ * @example transferFrom(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, {Substrate: "5DfhbVfww7ThF8q6f3ij..."}, 10000n);
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async transferFrom(signer: TSigner, collectionId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount: bigint) {
+ return await super.transferTokenFrom(signer, collectionId, 0, fromAddressObj, toAddressObj, amount);
+ }
+
+ /**
+ * Destroy some amount of tokens
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param amount amount of tokens to be destroyed
+ * @param label
+ * @example burnTokens(aliceKeyring, 10, 1000n);
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async burnTokens(signer: IKeyringPair, collectionId: number, amount=100n, label?: string): Promise<boolean> {
+ return (await super.burnToken(signer, collectionId, 0, label, amount)).success;
+ }
+
+ /**
+ * Burn some tokens on behalf of the owner.
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param fromAddressObj address on behalf of which tokens will be burnt
+ * @param amount amount of tokens to be burnt
+ * @param label
+ * @example burnTokensFrom(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n);
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async burnTokensFrom(signer: IKeyringPair, collectionId: number, fromAddressObj: ICrossAccountId, amount=100n, label?: string): Promise<boolean> {
+ return await super.burnTokenFrom(signer, collectionId, fromAddressObj, 0, label, amount);
+ }
+
+ /**
+ * Get total collection supply
+ * @param collectionId
+ * @returns
+ */
+ async getTotalPieces(collectionId: number): Promise<bigint> {
+ return (await this.helper.callRpc('api.rpc.unique.totalPieces', [collectionId, 0])).unwrap().toBigInt();
+ }
+
+ /**
+ * Set, change, or remove approved address to transfer tokens.
+ *
+ * @param signer keyring of signer
+ * @param collectionId ID of collection
+ * @param toAddressObj address to be approved
+ * @param amount amount of tokens to be approved
+ * @param label
+ * @example approveTokens(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, 1000n)
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async approveTokens(signer: IKeyringPair, collectionId: number, toAddressObj: ICrossAccountId, amount=100n, label?: string) {
+ return super.approveToken(signer, collectionId, 0, toAddressObj, label, amount);
+ }
+
+ /**
+ * Get amount of fungible tokens approved to transfer
+ * @param collectionId ID of collection
+ * @param fromAddressObj owner of tokens
+ * @param toAddressObj the address approved for the transfer of tokens on behalf of the owner
+ * @returns number of tokens approved for the transfer
+ */
+ async getApprovedTokens(collectionId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {
+ return super.getTokenApprovedPieces(collectionId, 0, toAddressObj, fromAddressObj);
+ }
+}
+
+
+class ChainGroup extends HelperGroup {
+ /**
+ * Get system properties of a chain
+ * @example getChainProperties();
+ * @returns ss58Format, token decimals, and token symbol
+ */
+ getChainProperties(): IChainProperties {
+ const properties = (this.helper.api as any).registry.getChainProperties().toJSON();
+ return {
+ ss58Format: properties.ss58Format.toJSON(),
+ tokenDecimals: properties.tokenDecimals.toJSON(),
+ tokenSymbol: properties.tokenSymbol.toJSON(),
+ };
+ }
+
+ /**
+ * Get chain header
+ * @example getLatestBlockNumber();
+ * @returns the number of the last block
+ */
+ async getLatestBlockNumber(): Promise<number> {
+ return (await this.helper.callRpc('api.rpc.chain.getHeader')).number.toNumber();
+ }
+
+ /**
+ * Get block hash by block number
+ * @param blockNumber number of block
+ * @example getBlockHashByNumber(12345);
+ * @returns hash of a block
+ */
+ async getBlockHashByNumber(blockNumber: number): Promise<string | null> {
+ const blockHash = (await this.helper.callRpc('api.rpc.chain.getBlockHash', [blockNumber])).toJSON();
+ if(blockHash === '0x0000000000000000000000000000000000000000000000000000000000000000') return null;
+ return blockHash;
+ }
+
+ /**
+ * Get account nonce
+ * @param address substrate address
+ * @example getNonce("5GrwvaEF5zXb26Fz...");
+ * @returns number, account's nonce
+ */
+ async getNonce(address: TSubstrateAccount): Promise<number> {
+ return (await (this.helper.api as any).query.system.account(address)).nonce.toNumber();
+ }
+}
+
+
+class BalanceGroup extends HelperGroup {
+ /**
+ * Representation of the native token in the smallest unit
+ * @example getOneTokenNominal()
+ * @returns ```BigInt``` representation of the native token in the smallest unit, e.g. ```1_000_000_000_000_000_000n``` for QTZ.
+ */
+ getOneTokenNominal(): bigint {
+ const chainProperties = this.helper.chain.getChainProperties();
+ return 10n ** BigInt((chainProperties.tokenDecimals || [18])[0]);
+ }
+
+ /**
+ * Get substrate address balance
+ * @param address substrate address
+ * @example getSubstrate("5GrwvaEF5zXb26Fz...")
+ * @returns amount of tokens on address
+ */
+ async getSubstrate(address: TSubstrateAccount): Promise<bigint> {
+ return (await this.helper.callRpc('api.query.system.account', [address])).data.free.toBigInt();
+ }
+
+ /**
+ * Get ethereum address balance
+ * @param address ethereum address
+ * @example getEthereum("0x9F0583DbB855d...")
+ * @returns amount of tokens on address
+ */
+ async getEthereum(address: TEthereumAccount): Promise<bigint> {
+ return (await this.helper.callRpc('api.rpc.eth.getBalance', [address])).toBigInt();
+ }
+
+ /**
+ * Transfer tokens to substrate address
+ * @param signer keyring of signer
+ * @param address substrate address of a recepient
+ * @param amount amount of tokens to be transfered
+ * @example transferToSubstrate(aliceKeyring, "5GrwvaEF5zXb26Fz...", 100_000_000_000n);
+ * @returns ```true``` if extrinsic success, otherwise ```false```
+ */
+ async transferToSubstrate(signer: TSigner, address: TSubstrateAccount, amount: bigint | string): Promise<boolean> {
+ const result = await this.helper.executeExtrinsic(signer, 'api.tx.balances.transfer', [address, amount], true, `Unable to transfer balance from ${this.helper.getSignerAddress(signer)} to ${address}`);
+
+ let transfer = {from: null, to: null, amount: 0n} as any;
+ result.result.events.forEach(({event: {data, method, section}}) => {
+ if ((section === 'balances') && (method === 'Transfer')) {
+ transfer = {
+ from: this.helper.address.normalizeSubstrate(data[0]),
+ to: this.helper.address.normalizeSubstrate(data[1]),
+ amount: BigInt(data[2]),
+ };
+ }
+ });
+ let isSuccess = this.helper.address.normalizeSubstrate(typeof signer === 'string' ? signer : signer.address) === transfer.from;
+ isSuccess = isSuccess && this.helper.address.normalizeSubstrate(address) === transfer.to;
+ isSuccess = isSuccess && BigInt(amount) === transfer.amount;
+ return isSuccess;
+ }
+}
+
+
+class AddressGroup extends HelperGroup {
+ /**
+ * Normalizes the address to the specified ss58 format, by default ```42```.
+ * @param address substrate address
+ * @param ss58Format format for address conversion, by default ```42```
+ * @example normalizeSubstrate("unjKJQJrRd238pkUZZvzDQrfKuM39zBSnQ5zjAGAGcdRhaJTx") // returns 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
+ * @returns substrate address converted to normalized (i.e., starting with 5) or specified explicitly representation
+ */
+ normalizeSubstrate(address: TSubstrateAccount, ss58Format = 42): TSubstrateAccount {
+ return this.helper.util.normalizeSubstrateAddress(address, ss58Format);
+ }
+
+ /**
+ * Get address in the connected chain format
+ * @param address substrate address
+ * @example normalizeSubstrateToChainFormat("5GrwvaEF5zXb26Fz...") // returns unjKJQJrRd238pkUZZ... for Unique Network
+ * @returns address in chain format
+ */
+ async normalizeSubstrateToChainFormat(address: TSubstrateAccount): Promise<TSubstrateAccount> {
+ const info = this.helper.chain.getChainProperties();
+ return encodeAddress(decodeAddress(address), info.ss58Format);
+ }
+
+ /**
+ * Get substrate mirror of an ethereum address
+ * @param ethAddress ethereum address
+ * @param toChainFormat false for normalized account
+ * @example ethToSubstrate('0x9F0583DbB855d...')
+ * @returns substrate mirror of a provided ethereum address
+ */
+ async ethToSubstrate(ethAddress: TEthereumAccount, toChainFormat=false): Promise<TSubstrateAccount> {
+ if(!toChainFormat) return evmToAddress(ethAddress);
+ const info = this.helper.chain.getChainProperties();
+ return evmToAddress(ethAddress, info.ss58Format);
+ }
+
+ /**
+ * Get ethereum mirror of a substrate address
+ * @param subAddress substrate account
+ * @example substrateToEth("5DnSF6RRjwteE3BrC...")
+ * @returns ethereum mirror of a provided substrate address
+ */
+ substrateToEth(subAddress: TSubstrateAccount): TEthereumAccount {
+ return nesting.toChecksumAddress('0x' + Array.from(addressToEvm(subAddress), i => i.toString(16).padStart(2, '0')).join(''));
+ }
+}
+
+
+export class UniqueHelper extends ChainHelperBase {
+ chain: ChainGroup;
+ balance: BalanceGroup;
+ address: AddressGroup;
+ collection: CollectionGroup;
+ nft: NFTGroup;
+ rft: RFTGroup;
+ ft: FTGroup;
+
+ constructor(logger?: ILogger) {
+ super(logger);
+ this.chain = new ChainGroup(this);
+ this.balance = new BalanceGroup(this);
+ this.address = new AddressGroup(this);
+ this.collection = new CollectionGroup(this);
+ this.nft = new NFTGroup(this);
+ this.rft = new RFTGroup(this);
+ this.ft = new FTGroup(this);
+ }
+}
+
+
+class UniqueCollectionBase {
+ helper: UniqueHelper;
+ collectionId: number;
+
+ constructor(collectionId: number, uniqueHelper: UniqueHelper) {
+ this.collectionId = collectionId;
+ this.helper = uniqueHelper;
+ }
+
+ async getData() {
+ return await this.helper.collection.getData(this.collectionId);
+ }
+
+ async getLastTokenId() {
+ return await this.helper.collection.getLastTokenId(this.collectionId);
+ }
+
+ async isTokenExists(tokenId: number) {
+ return await this.helper.collection.isTokenExists(this.collectionId, tokenId);
+ }
+
+ async getAdmins() {
+ return await this.helper.collection.getAdmins(this.collectionId);
+ }
+
+ async getEffectiveLimits() {
+ return await this.helper.collection.getEffectiveLimits(this.collectionId);
+ }
+
+ async setSponsor(signer: TSigner, sponsorAddress: TSubstrateAccount, label?: string) {
+ return await this.helper.collection.setSponsor(signer, this.collectionId, sponsorAddress, label);
+ }
+
+ async confirmSponsorship(signer: TSigner, label?: string) {
+ return await this.helper.collection.confirmSponsorship(signer, this.collectionId, label);
+ }
+
+ async setLimits(signer: TSigner, limits: ICollectionLimits, label?: string) {
+ return await this.helper.collection.setLimits(signer, this.collectionId, limits, label);
+ }
+
+ async changeOwner(signer: TSigner, ownerAddress: TSubstrateAccount, label?: string) {
+ return await this.helper.collection.changeOwner(signer, this.collectionId, ownerAddress, label);
+ }
+
+ async addAdmin(signer: TSigner, adminAddressObj: ICrossAccountId, label?: string) {
+ return await this.helper.collection.addAdmin(signer, this.collectionId, adminAddressObj, label);
+ }
+
+ async removeAdmin(signer: TSigner, adminAddressObj: ICrossAccountId, label?: string) {
+ return await this.helper.collection.removeAdmin(signer, this.collectionId, adminAddressObj, label);
+ }
+
+ async setProperties(signer: TSigner, properties: IProperty[], label?: string) {
+ return await this.helper.collection.setProperties(signer, this.collectionId, properties, label);
+ }
+
+ async deleteProperties(signer: TSigner, propertyKeys: string[], label?: string) {
+ return await this.helper.collection.deleteProperties(signer, this.collectionId, propertyKeys, label);
+ }
+
+ async getTokenNextSponsored(tokenId: number, addressObj: ICrossAccountId) {
+ return await this.helper.collection.getTokenNextSponsored(this.collectionId, tokenId, addressObj);
+ }
+
+ async setPermissions(signer: TSigner, permissions: ICollectionPermissions, label?: string) {
+ return await this.helper.collection.setPermissions(signer, this.collectionId, permissions, label);
+ }
+
+ async enableNesting(signer: TSigner, permissions: INestingPermissions, label?: string) {
+ return await this.helper.collection.enableNesting(signer, this.collectionId, permissions, label);
+ }
+
+ async disableNesting(signer: TSigner, label?: string) {
+ return await this.helper.collection.disableNesting(signer, this.collectionId, label);
+ }
+
+ async burn(signer: TSigner, label?: string) {
+ return await this.helper.collection.burn(signer, this.collectionId, label);
+ }
+}
+
+
+class UniqueNFTCollection extends UniqueCollectionBase {
+ getTokenObject(tokenId: number) {
+ return new UniqueNFTToken(tokenId, this);
+ }
+
+ async getTokensByAddress(addressObj: ICrossAccountId) {
+ return await this.helper.nft.getTokensByAddress(this.collectionId, addressObj);
+ }
+
+ async getToken(tokenId: number, blockHashAt?: string) {
+ return await this.helper.nft.getToken(this.collectionId, tokenId, blockHashAt);
+ }
+
+ async getTokenOwner(tokenId: number, blockHashAt?: string) {
+ return await this.helper.nft.getTokenOwner(this.collectionId, tokenId, blockHashAt);
+ }
+
+ async getTokenTopmostOwner(tokenId: number, blockHashAt?: string) {
+ return await this.helper.nft.getTokenTopmostOwner(this.collectionId, tokenId, blockHashAt);
+ }
+
+ async getTokenChildren(tokenId: number, blockHashAt?: string) {
+ return await this.helper.nft.getTokenChildren(this.collectionId, tokenId, blockHashAt);
+ }
+
+ async transferToken(signer: TSigner, tokenId: number, addressObj: ICrossAccountId) {
+ return await this.helper.nft.transferToken(signer, this.collectionId, tokenId, addressObj);
+ }
+
+ async transferTokenFrom(signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {
+ return await this.helper.nft.transferTokenFrom(signer, this.collectionId, tokenId, fromAddressObj, toAddressObj);
+ }
+
+ async approveToken(signer: TSigner, tokenId: number, toAddressObj: ICrossAccountId, label?: string) {
+ return await this.helper.nft.approveToken(signer, this.collectionId, tokenId, toAddressObj, label);
+ }
+
+ async isTokenApproved(tokenId: number, toAddressObj: ICrossAccountId) {
+ return await this.helper.nft.isTokenApproved(this.collectionId, tokenId, toAddressObj);
+ }
+
+ async mintToken(signer: TSigner, owner: ICrossAccountId, properties?: IProperty[], label?: string) {
+ return await this.helper.nft.mintToken(signer, {collectionId: this.collectionId, owner, properties}, label);
+ }
+
+ async mintMultipleTokens(signer: TSigner, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[], label?: string) {
+ return await this.helper.nft.mintMultipleTokens(signer, this.collectionId, tokens, label);
+ }
+
+ async burnToken(signer: TSigner, tokenId: number, label?: string) {
+ return await this.helper.nft.burnToken(signer, this.collectionId, tokenId, label);
+ }
+
+ async setTokenProperties(signer: TSigner, tokenId: number, properties: IProperty[], label?: string) {
+ return await this.helper.nft.setTokenProperties(signer, this.collectionId, tokenId, properties, label);
+ }
+
+ async deleteTokenProperties(signer: TSigner, tokenId: number, propertyKeys: string[], label?: string) {
+ return await this.helper.nft.deleteTokenProperties(signer, this.collectionId, tokenId, propertyKeys, label);
+ }
+
+ async setTokenPropertyPermissions(signer: TSigner, permissions: ITokenPropertyPermission[], label?: string) {
+ return await this.helper.nft.setTokenPropertyPermissions(signer, this.collectionId, permissions, label);
+ }
+
+ async nestToken(signer: TSigner, tokenId: number, toTokenObj: IToken, label?: string) {
+ return await this.helper.nft.nestToken(signer, {collectionId: this.collectionId, tokenId}, toTokenObj, label);
+ }
+
+ async unnestToken(signer: TSigner, tokenId: number, fromTokenObj: IToken, toAddressObj: ICrossAccountId, label?: string) {
+ return await this.helper.nft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj, label);
+ }
+}
+
+
+class UniqueRFTCollection extends UniqueCollectionBase {
+ getTokenObject(tokenId: number) {
+ return new UniqueRFTToken(tokenId, this);
+ }
+
+ async getTokensByAddress(addressObj: ICrossAccountId) {
+ return await this.helper.rft.getTokensByAddress(this.collectionId, addressObj);
+ }
+
+ async getTop10TokenOwners(tokenId: number) {
+ return await this.helper.rft.getTokenTop10Owners(this.collectionId, tokenId);
+ }
+
+ async getTokenBalance(tokenId: number, addressObj: ICrossAccountId) {
+ return await this.helper.rft.getTokenBalance(this.collectionId, tokenId, addressObj);
+ }
+
+ async getTokenTotalPieces(tokenId: number) {
+ return await this.helper.rft.getTokenTotalPieces(this.collectionId, tokenId);
+ }
+
+ async transferToken(signer: TSigner, tokenId: number, addressObj: ICrossAccountId, amount=100n) {
+ return await this.helper.rft.transferToken(signer, this.collectionId, tokenId, addressObj, amount);
+ }
+
+ async transferTokenFrom(signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=100n) {
+ return await this.helper.rft.transferTokenFrom(signer, this.collectionId, tokenId, fromAddressObj, toAddressObj, amount);
+ }
+
+ async approveToken(signer: TSigner, tokenId: number, toAddressObj: ICrossAccountId, amount=100n, label?: string) {
+ return await this.helper.rft.approveToken(signer, this.collectionId, tokenId, toAddressObj, label, amount);
+ }
+
+ async getTokenApprovedPieces(tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {
+ return await this.helper.rft.getTokenApprovedPieces(this.collectionId, tokenId, toAddressObj, fromAddressObj);
+ }
+
+ async repartitionToken(signer: TSigner, tokenId: number, amount: bigint, label?: string) {
+ return await this.helper.rft.repartitionToken(signer, this.collectionId, tokenId, amount, label);
+ }
+
+ async mintToken(signer: TSigner, owner: ICrossAccountId, pieces=100n, properties?: IProperty[], label?: string) {
+ return await this.helper.rft.mintToken(signer, {collectionId: this.collectionId, owner, pieces, properties}, label);
+ }
+
+ async mintMultipleTokens(signer: TSigner, tokens: {owner: ICrossAccountId, pieces: bigint, properties?: IProperty[]}[], label?: string) {
+ return await this.helper.rft.mintMultipleTokens(signer, this.collectionId, tokens, label);
+ }
+
+ async burnToken(signer: TSigner, tokenId: number, amount=100n, label?: string) {
+ return await this.helper.rft.burnToken(signer, this.collectionId, tokenId, label, amount);
+ }
+
+ async setTokenProperties(signer: TSigner, tokenId: number, properties: IProperty[], label?: string) {
+ return await this.helper.rft.setTokenProperties(signer, this.collectionId, tokenId, properties, label);
+ }
+
+ async deleteTokenProperties(signer: TSigner, tokenId: number, propertyKeys: string[], label?: string) {
+ return await this.helper.rft.deleteTokenProperties(signer, this.collectionId, tokenId, propertyKeys, label);
+ }
+
+ async setTokenPropertyPermissions(signer: TSigner, permissions: ITokenPropertyPermission[], label?: string) {
+ return await this.helper.rft.setTokenPropertyPermissions(signer, this.collectionId, permissions, label);
+ }
+}
+
+
+class UniqueFTCollection extends UniqueCollectionBase {
+ async mint(signer: TSigner, owner: ICrossAccountId, amount: bigint, label?: string) {
+ return await this.helper.ft.mintTokens(signer, this.collectionId, owner, amount, label);
+ }
+
+ async mintWithOneOwner(signer: TSigner, owner: ICrossAccountId, tokens: {value: bigint}[], label?: string) {
+ return await this.helper.ft.mintMultipleTokensWithOneOwner(signer, this.collectionId, owner, tokens, label);
+ }
+
+ async getBalance(addressObj: ICrossAccountId) {
+ return await this.helper.ft.getBalance(this.collectionId, addressObj);
+ }
+
+ async getTop10Owners() {
+ return await this.helper.ft.getTop10Owners(this.collectionId);
+ }
+
+ async transfer(signer: TSigner, toAddressObj: ICrossAccountId, amount: bigint) {
+ return await this.helper.ft.transfer(signer, this.collectionId, toAddressObj, amount);
+ }
+
+ async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount: bigint) {
+ return await this.helper.ft.transferFrom(signer, this.collectionId, fromAddressObj, toAddressObj, amount);
+ }
+
+ async burnTokens(signer: TSigner, amount: bigint, label?: string) {
+ return await this.helper.ft.burnTokens(signer, this.collectionId, amount, label);
+ }
+
+ async burnTokensFrom(signer: TSigner, fromAddressObj: ICrossAccountId, amount: bigint, label?: string) {
+ return await this.helper.ft.burnTokensFrom(signer, this.collectionId, fromAddressObj, amount, label);
+ }
+
+ async getTotalPieces() {
+ return await this.helper.ft.getTotalPieces(this.collectionId);
+ }
+
+ async approveTokens(signer: TSigner, toAddressObj: ICrossAccountId, amount=100n, label?: string) {
+ return await this.helper.ft.approveTokens(signer, this.collectionId, toAddressObj, amount, label);
+ }
+
+ async getApprovedTokens(fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {
+ return await this.helper.ft.getApprovedTokens(this.collectionId, fromAddressObj, toAddressObj);
+ }
+}
+
+
+class UniqueTokenBase implements IToken {
+ collection: UniqueNFTCollection | UniqueRFTCollection;
+ collectionId: number;
+ tokenId: number;
+
+ constructor(tokenId: number, collection: UniqueNFTCollection | UniqueRFTCollection) {
+ this.collection = collection;
+ this.collectionId = collection.collectionId;
+ this.tokenId = tokenId;
+ }
+
+ async getNextSponsored(addressObj: ICrossAccountId) {
+ return await this.collection.getTokenNextSponsored(this.tokenId, addressObj);
+ }
+
+ async setProperties(signer: TSigner, properties: IProperty[], label?: string) {
+ return await this.collection.setTokenProperties(signer, this.tokenId, properties, label);
+ }
+
+ async deleteProperties(signer: TSigner, propertyKeys: string[], label?: string) {
+ return await this.collection.deleteTokenProperties(signer, this.tokenId, propertyKeys, label);
+ }
+}
+
+
+class UniqueNFTToken extends UniqueTokenBase {
+ collection: UniqueNFTCollection;
+
+ constructor(tokenId: number, collection: UniqueNFTCollection) {
+ super(tokenId, collection);
+ this.collection = collection;
+ }
+
+ async getData(blockHashAt?: string) {
+ return await this.collection.getToken(this.tokenId, blockHashAt);
+ }
+
+ async getOwner(blockHashAt?: string) {
+ return await this.collection.getTokenOwner(this.tokenId, blockHashAt);
+ }
+
+ async getTopmostOwner(blockHashAt?: string) {
+ return await this.collection.getTokenTopmostOwner(this.tokenId, blockHashAt);
+ }
+
+ async getChildren(blockHashAt?: string) {
+ return await this.collection.getTokenChildren(this.tokenId, blockHashAt);
+ }
+
+ async nest(signer: TSigner, toTokenObj: IToken, label?: string) {
+ return await this.collection.nestToken(signer, this.tokenId, toTokenObj, label);
+ }
+
+ async unnest(signer: TSigner, fromTokenObj: IToken, toAddressObj: ICrossAccountId, label?: string) {
+ return await this.collection.unnestToken(signer, this.tokenId, fromTokenObj, toAddressObj, label);
+ }
+
+ async transfer(signer: TSigner, addressObj: ICrossAccountId) {
+ return await this.collection.transferToken(signer, this.tokenId, addressObj);
+ }
+
+ async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {
+ return await this.collection.transferTokenFrom(signer, this.tokenId, fromAddressObj, toAddressObj);
+ }
+
+ async approve(signer: TSigner, toAddressObj: ICrossAccountId, label?: string) {
+ return await this.collection.approveToken(signer, this.tokenId, toAddressObj, label);
+ }
+
+ async isApproved(toAddressObj: ICrossAccountId) {
+ return await this.collection.isTokenApproved(this.tokenId, toAddressObj);
+ }
+
+ async burn(signer: TSigner, label?: string) {
+ return await this.collection.burnToken(signer, this.tokenId, label);
+ }
+}
+
+class UniqueRFTToken extends UniqueTokenBase {
+ collection: UniqueRFTCollection;
+
+ constructor(tokenId: number, collection: UniqueRFTCollection) {
+ super(tokenId, collection);
+ this.collection = collection;
+ }
+
+ async getTop10Owners() {
+ return await this.collection.getTop10TokenOwners(this.tokenId);
+ }
+
+ async getBalance(addressObj: ICrossAccountId) {
+ return await this.collection.getTokenBalance(this.tokenId, addressObj);
+ }
+
+ async getTotalPieces() {
+ return await this.collection.getTokenTotalPieces(this.tokenId);
+ }
+
+ async transfer(signer: TSigner, addressObj: ICrossAccountId, amount=100n) {
+ return await this.collection.transferToken(signer, this.tokenId, addressObj, amount);
+ }
+
+ async transferFrom(signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount=100n) {
+ return await this.collection.transferTokenFrom(signer, this.tokenId, fromAddressObj, toAddressObj, amount);
+ }
+
+ async approve(signer: TSigner, toAddressObj: ICrossAccountId, amount=100n, label?: string) {
+ return await this.collection.approveToken(signer, this.tokenId, toAddressObj, amount, label);
+ }
+
+ async getApprovedPieces(fromAddressObj: ICrossAccountId, toAccountObj: ICrossAccountId) {
+ return await this.collection.getTokenApprovedPieces(this.tokenId, fromAddressObj, toAccountObj);
+ }
+
+ async repartition(signer: TSigner, amount: bigint, label?: string) {
+ return await this.collection.repartitionToken(signer, this.tokenId, amount, label);
+ }
+
+ async burn(signer: TSigner, amount=100n, label?: string) {
+ return await this.collection.burnToken(signer, this.tokenId, amount, label);
+ }
+}
\ No newline at end of file
tests/yarn.lockdiffbeforeafterboth--- a/tests/yarn.lock
+++ b/tests/yarn.lock
@@ -963,6 +963,13 @@
dependencies:
"@types/chai" "*"
+"@types/chai-like@^1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@types/chai-like/-/chai-like-1.1.1.tgz#c454039b0a2f92664fb5b7b7a2a66c3358783ae7"
+ integrity sha512-s46EZsupBuVhLn66DbRee5B0SELLmL4nFXVrBiV29BxLGm9Sh7Bful623j3AfiQRu2zAP4cnlZ3ETWB3eWc4bA==
+ dependencies:
+ "@types/chai" "*"
+
"@types/chai@*", "@types/chai@^4.3.1":
version "4.3.1"
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.1.tgz#e2c6e73e0bdeb2521d00756d099218e9f5d90a04"
@@ -1545,6 +1552,11 @@
dependencies:
check-error "^1.0.2"
+chai-like@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/chai-like/-/chai-like-1.1.1.tgz#8c558a414c34514e814d497c772547ceb7958f64"
+ integrity sha512-VKa9z/SnhXhkT1zIjtPACFWSoWsqVoaz1Vg+ecrKo5DCKVlgL30F/pEyEvXPBOVwCgLZcWUleCM/C1okaKdTTA==
+
chai@^4.3.6:
version "4.3.6"
resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c"